From 974a04c12939068b23b62ee6ebb1e7fc2e830eec Mon Sep 17 00:00:00 2001 From: dkanada Date: Wed, 26 Feb 2020 01:58:39 +0900 Subject: [PATCH 01/83] update plugin classes for nightly builds --- .../Activity/ActivityLogEntryPoint.cs | 8 +- .../ApplicationHost.cs | 10 +- .../Updates/InstallationManager.cs | 68 +++++------ MediaBrowser.Api/PackageService.cs | 36 +----- .../Extensions/BaseExtensions.cs | 1 - MediaBrowser.Common/IApplicationHost.cs | 4 +- MediaBrowser.Common/Plugins/BasePlugin.cs | 8 +- .../Updates/IInstallationManager.cs | 22 ++-- .../Updates/InstallationEventArgs.cs | 2 +- MediaBrowser.Model/MediaBrowser.Model.csproj | 2 +- MediaBrowser.Model/System/SystemInfo.cs | 2 +- .../Updates/CheckForUpdateResult.cs | 4 +- .../Updates/InstallationInfo.cs | 2 +- MediaBrowser.Model/Updates/PackageInfo.cs | 106 +----------------- .../Updates/PackageTargetSystem.cs | 23 ---- .../Updates/PackageVersionInfo.cs | 97 ---------------- ...ckageVersionClass.cs => ReleaseChannel.cs} | 15 +-- MediaBrowser.Model/Updates/VersionInfo.cs | 73 ++++++++++++ 18 files changed, 150 insertions(+), 333 deletions(-) delete mode 100644 MediaBrowser.Model/Updates/PackageTargetSystem.cs delete mode 100644 MediaBrowser.Model/Updates/PackageVersionInfo.cs rename MediaBrowser.Model/Updates/{PackageVersionClass.cs => ReleaseChannel.cs} (51%) create mode 100644 MediaBrowser.Model/Updates/VersionInfo.cs diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index ac8af66a2..0f0b8b97b 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -421,7 +421,7 @@ namespace Emby.Server.Implementations.Activity }); } - private void OnPluginUpdated(object sender, GenericEventArgs<(IPlugin, PackageVersionInfo)> e) + private void OnPluginUpdated(object sender, GenericEventArgs<(IPlugin, VersionInfo)> e) { CreateLogEntry(new ActivityLogEntry { @@ -433,7 +433,7 @@ namespace Emby.Server.Implementations.Activity ShortOverview = string.Format( CultureInfo.InvariantCulture, _localization.GetLocalizedString("VersionNumber"), - e.Argument.Item2.versionStr), + e.Argument.Item2.versionString), Overview = e.Argument.Item2.description }); } @@ -450,7 +450,7 @@ namespace Emby.Server.Implementations.Activity }); } - private void OnPluginInstalled(object sender, GenericEventArgs e) + private void OnPluginInstalled(object sender, GenericEventArgs e) { CreateLogEntry(new ActivityLogEntry { @@ -462,7 +462,7 @@ namespace Emby.Server.Implementations.Activity ShortOverview = string.Format( CultureInfo.InvariantCulture, _localization.GetLocalizedString("VersionNumber"), - e.Argument.versionStr) + e.Argument.versionString) }); } diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index dee0edd26..ad77ab8b4 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -212,14 +212,14 @@ namespace Emby.Server.Implementations public IFileSystem FileSystemManager { get; set; } /// - public PackageVersionClass SystemUpdateLevel + public ReleaseChannel SystemUpdateLevel { get { -#if BETA - return PackageVersionClass.Beta; +#if NIGHTLY + return PackageChannel.Nightly; #else - return PackageVersionClass.Release; + return ReleaseChannel.Stable; #endif } } @@ -1003,7 +1003,7 @@ namespace Emby.Server.Implementations AuthenticatedAttribute.AuthService = AuthService; } - private async void PluginInstalled(object sender, GenericEventArgs args) + private async void PluginInstalled(object sender, GenericEventArgs args) { string dir = Path.Combine(ApplicationPaths.PluginsPath, args.Argument.name); var types = Directory.EnumerateFiles(dir, "*.dll", SearchOption.AllDirectories) diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index c897036eb..1450c74d2 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -23,12 +23,12 @@ using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.Updates { /// - /// Manages all install, uninstall and update operations (both plugins and system). + /// Manages all install, uninstall, and update operations for the system and individual plugins. /// public class InstallationManager : IInstallationManager { /// - /// The _logger. + /// The logger. /// private readonly ILogger _logger; private readonly IApplicationPaths _appPaths; @@ -101,10 +101,10 @@ namespace Emby.Server.Implementations.Updates public event EventHandler> PluginUninstalled; /// - public event EventHandler> PluginUpdated; + public event EventHandler> PluginUpdated; /// - public event EventHandler> PluginInstalled; + public event EventHandler> PluginInstalled; /// public IEnumerable CompletedInstallations => _completedInstallationsInternal; @@ -115,7 +115,7 @@ namespace Emby.Server.Implementations.Updates using (var response = await _httpClient.SendAsync( new HttpRequestOptions { - Url = "https://repo.jellyfin.org/releases/plugin/manifest.json", + Url = "https://repo.jellyfin.org/releases/plugin/manifest-water.json", CancellationToken = cancellationToken, CacheMode = CacheMode.Unconditional, CacheLength = TimeSpan.FromMinutes(3) @@ -148,48 +148,48 @@ namespace Emby.Server.Implementations.Updates } /// - public IEnumerable GetCompatibleVersions( - IEnumerable availableVersions, + public IEnumerable GetCompatibleVersions( + IEnumerable availableVersions, Version minVersion = null, - PackageVersionClass classification = PackageVersionClass.Release) + ReleaseChannel releaseChannel = ReleaseChannel.Stable) { var appVer = _applicationHost.ApplicationVersion; availableVersions = availableVersions - .Where(x => x.classification == classification - && Version.Parse(x.requiredVersionStr) <= appVer); + .Where(x => x.channel == releaseChannel + && Version.Parse(x.minimumServerVersion) <= appVer); if (minVersion != null) { - availableVersions = availableVersions.Where(x => x.Version >= minVersion); + availableVersions = availableVersions.Where(x => x.versionCode >= minVersion); } - return availableVersions.OrderByDescending(x => x.Version); + return availableVersions.OrderByDescending(x => x.versionCode); } /// - public IEnumerable GetCompatibleVersions( + public IEnumerable GetCompatibleVersions( IEnumerable availablePackages, string name = null, Guid guid = default, Version minVersion = null, - PackageVersionClass classification = PackageVersionClass.Release) + ReleaseChannel releaseChannel = ReleaseChannel.Stable) { var package = FilterPackages(availablePackages, name, guid).FirstOrDefault(); - // Package not found. + // Package not found in repository if (package == null) { - return Enumerable.Empty(); + return Enumerable.Empty(); } return GetCompatibleVersions( package.versions, minVersion, - classification); + releaseChannel); } /// - public async IAsyncEnumerable GetAvailablePluginUpdates([EnumeratorCancellation] CancellationToken cancellationToken = default) + public async IAsyncEnumerable GetAvailablePluginUpdates([EnumeratorCancellation] CancellationToken cancellationToken = default) { var catalog = await GetAvailablePackages(cancellationToken).ConfigureAwait(false); @@ -198,8 +198,8 @@ namespace Emby.Server.Implementations.Updates // Figure out what needs to be installed foreach (var plugin in _applicationHost.Plugins) { - var compatibleversions = GetCompatibleVersions(catalog, plugin.Name, plugin.Id, plugin.Version, systemUpdateLevel); - var version = compatibleversions.FirstOrDefault(y => y.Version > plugin.Version); + var compatibleVersions = GetCompatibleVersions(catalog, plugin.Name, plugin.Id, plugin.Version, systemUpdateLevel); + var version = compatibleVersions.FirstOrDefault(y => y.versionCode > plugin.Version); if (version != null && !CompletedInstallations.Any(x => string.Equals(x.AssemblyGuid, version.guid, StringComparison.OrdinalIgnoreCase))) { @@ -209,7 +209,7 @@ namespace Emby.Server.Implementations.Updates } /// - public async Task InstallPackage(PackageVersionInfo package, CancellationToken cancellationToken) + public async Task InstallPackage(VersionInfo package, CancellationToken cancellationToken) { if (package == null) { @@ -221,8 +221,8 @@ namespace Emby.Server.Implementations.Updates Id = Guid.NewGuid(), Name = package.name, AssemblyGuid = package.guid, - UpdateClass = package.classification, - Version = package.versionStr + UpdateClass = package.channel, + Version = package.versionString }; var innerCancellationTokenSource = new CancellationTokenSource(); @@ -240,7 +240,7 @@ namespace Emby.Server.Implementations.Updates var installationEventArgs = new InstallationEventArgs { InstallationInfo = installationInfo, - PackageVersionInfo = package + VersionInfo = package }; PackageInstalling?.Invoke(this, installationEventArgs); @@ -265,7 +265,7 @@ namespace Emby.Server.Implementations.Updates _currentInstallations.Remove(tuple); } - _logger.LogInformation("Package installation cancelled: {0} {1}", package.name, package.versionStr); + _logger.LogInformation("Package installation cancelled: {0} {1}", package.name, package.versionString); PackageInstallationCancelled?.Invoke(this, installationEventArgs); @@ -301,7 +301,7 @@ namespace Emby.Server.Implementations.Updates /// The package. /// The cancellation token. /// . - private async Task InstallPackageInternal(PackageVersionInfo package, CancellationToken cancellationToken) + private async Task InstallPackageInternal(VersionInfo package, CancellationToken cancellationToken) { // Set last update time if we were installed before IPlugin plugin = _applicationHost.Plugins.FirstOrDefault(p => string.Equals(p.Id.ToString(), package.guid, StringComparison.OrdinalIgnoreCase)) @@ -313,26 +313,26 @@ namespace Emby.Server.Implementations.Updates // Do plugin-specific processing if (plugin == null) { - _logger.LogInformation("New plugin installed: {0} {1} {2}", package.name, package.versionStr ?? string.Empty, package.classification); + _logger.LogInformation("New plugin installed: {0} {1} {2}", package.name, package.versionString ?? string.Empty, package.channel); - PluginInstalled?.Invoke(this, new GenericEventArgs(package)); + PluginInstalled?.Invoke(this, new GenericEventArgs(package)); } else { - _logger.LogInformation("Plugin updated: {0} {1} {2}", package.name, package.versionStr ?? string.Empty, package.classification); + _logger.LogInformation("Plugin updated: {0} {1} {2}", package.name, package.versionString ?? string.Empty, package.channel); - PluginUpdated?.Invoke(this, new GenericEventArgs<(IPlugin, PackageVersionInfo)>((plugin, package))); + PluginUpdated?.Invoke(this, new GenericEventArgs<(IPlugin, VersionInfo)>((plugin, package))); } _applicationHost.NotifyPendingRestart(); } - private async Task PerformPackageInstallation(PackageVersionInfo package, CancellationToken cancellationToken) + private async Task PerformPackageInstallation(VersionInfo package, CancellationToken cancellationToken) { - var extension = Path.GetExtension(package.targetFilename); + var extension = Path.GetExtension(package.filename); if (!string.Equals(extension, ".zip", StringComparison.OrdinalIgnoreCase)) { - _logger.LogError("Only zip packages are supported. {Filename} is not a zip archive.", package.targetFilename); + _logger.LogError("Only zip packages are supported. {Filename} is not a zip archive.", package.filename); return; } @@ -379,7 +379,7 @@ namespace Emby.Server.Implementations.Updates } /// - /// Uninstalls a plugin + /// Uninstalls a plugin. /// /// The plugin. public void UninstallPlugin(IPlugin plugin) diff --git a/MediaBrowser.Api/PackageService.cs b/MediaBrowser.Api/PackageService.cs index afc3e026a..ccc978295 100644 --- a/MediaBrowser.Api/PackageService.cs +++ b/MediaBrowser.Api/PackageService.cs @@ -42,23 +42,6 @@ namespace MediaBrowser.Api [Authenticated] public class GetPackages : IReturn { - /// - /// Gets or sets the name. - /// - /// The name. - [ApiMember(Name = "PackageType", Description = "Optional package type filter (System/UserInstalled)", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] - public string PackageType { get; set; } - - [ApiMember(Name = "TargetSystems", Description = "Optional. Filter by target system type. Allows multiple, comma delimited.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] - public string TargetSystems { get; set; } - - [ApiMember(Name = "IsPremium", Description = "Optional. Filter by premium status", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")] - public bool? IsPremium { get; set; } - - [ApiMember(Name = "IsAdult", Description = "Optional. Filter by package that contain adult content.", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")] - public bool? IsAdult { get; set; } - - public bool? IsAppStoreEnabled { get; set; } } /// @@ -94,7 +77,7 @@ namespace MediaBrowser.Api /// /// The update class. [ApiMember(Name = "UpdateClass", Description = "Optional update class (Dev, Beta, Release). Defaults to Release.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] - public PackageVersionClass UpdateClass { get; set; } + public ReleaseChannel UpdateClass { get; set; } } /// @@ -154,23 +137,6 @@ namespace MediaBrowser.Api { IEnumerable packages = await _installationManager.GetAvailablePackages().ConfigureAwait(false); - if (!string.IsNullOrEmpty(request.TargetSystems)) - { - var apps = request.TargetSystems.Split(',').Select(i => (PackageTargetSystem)Enum.Parse(typeof(PackageTargetSystem), i, true)); - - packages = packages.Where(p => apps.Contains(p.targetSystem)); - } - - if (request.IsAdult.HasValue) - { - packages = packages.Where(p => p.adult == request.IsAdult.Value); - } - - if (request.IsAppStoreEnabled.HasValue) - { - packages = packages.Where(p => p.enableInAppStore == request.IsAppStoreEnabled.Value); - } - return ToOptimizedResult(packages.ToArray()); } diff --git a/MediaBrowser.Common/Extensions/BaseExtensions.cs b/MediaBrowser.Common/Extensions/BaseExtensions.cs index 08964420e..bc002e523 100644 --- a/MediaBrowser.Common/Extensions/BaseExtensions.cs +++ b/MediaBrowser.Common/Extensions/BaseExtensions.cs @@ -35,7 +35,6 @@ namespace MediaBrowser.Common.Extensions { return new Guid(provider.ComputeHash(Encoding.Unicode.GetBytes(str))); } - #pragma warning restore CA5351 } } diff --git a/MediaBrowser.Common/IApplicationHost.cs b/MediaBrowser.Common/IApplicationHost.cs index 68a24aaba..c88eac27a 100644 --- a/MediaBrowser.Common/IApplicationHost.cs +++ b/MediaBrowser.Common/IApplicationHost.cs @@ -50,8 +50,8 @@ namespace MediaBrowser.Common /// /// Gets the version class of the system. /// - /// or . - PackageVersionClass SystemUpdateLevel { get; } + /// or . + ReleaseChannel SystemUpdateLevel { get; } /// /// Gets the application version. diff --git a/MediaBrowser.Common/Plugins/BasePlugin.cs b/MediaBrowser.Common/Plugins/BasePlugin.cs index b24d10ff1..9e4a360c3 100644 --- a/MediaBrowser.Common/Plugins/BasePlugin.cs +++ b/MediaBrowser.Common/Plugins/BasePlugin.cs @@ -67,7 +67,7 @@ namespace MediaBrowser.Common.Plugins } /// - /// Called when just before the plugin is uninstalled from the server. + /// Called just before the plugin is uninstalled from the server. /// public virtual void OnUninstalling() { @@ -101,7 +101,7 @@ namespace MediaBrowser.Common.Plugins private readonly object _configurationSyncLock = new object(); /// - /// The save lock. + /// The configuration save lock. /// private readonly object _configurationSaveLock = new object(); @@ -148,7 +148,7 @@ namespace MediaBrowser.Common.Plugins protected string AssemblyFileName => Path.GetFileName(AssemblyFilePath); /// - /// Gets or sets the plugin's configuration. + /// Gets or sets the plugin configuration. /// /// The configuration. public TConfigurationType Configuration @@ -186,7 +186,7 @@ namespace MediaBrowser.Common.Plugins public string ConfigurationFilePath => Path.Combine(ApplicationPaths.PluginConfigurationsPath, ConfigurationFileName); /// - /// Gets the plugin's configuration. + /// Gets the plugin configuration. /// /// The configuration. BasePluginConfiguration IHasPluginConfiguration.Configuration => Configuration; diff --git a/MediaBrowser.Common/Updates/IInstallationManager.cs b/MediaBrowser.Common/Updates/IInstallationManager.cs index a09c1916c..284e418d9 100644 --- a/MediaBrowser.Common/Updates/IInstallationManager.cs +++ b/MediaBrowser.Common/Updates/IInstallationManager.cs @@ -29,12 +29,12 @@ namespace MediaBrowser.Common.Updates /// /// Occurs when a plugin is updated. /// - event EventHandler> PluginUpdated; + event EventHandler> PluginUpdated; /// /// Occurs when a plugin is installed. /// - event EventHandler> PluginInstalled; + event EventHandler> PluginInstalled; /// /// Gets the completed installations. @@ -65,12 +65,12 @@ namespace MediaBrowser.Common.Updates /// /// The available version of the plugin. /// The minimum required version of the plugin. - /// The classification of updates. + /// The classification of updates. /// All compatible versions ordered from newest to oldest. - IEnumerable GetCompatibleVersions( - IEnumerable availableVersions, + IEnumerable GetCompatibleVersions( + IEnumerable availableVersions, Version minVersion = null, - PackageVersionClass classification = PackageVersionClass.Release); + ReleaseChannel releaseChannel = ReleaseChannel.Stable); /// /// Returns all compatible versions ordered from newest to oldest. @@ -79,21 +79,21 @@ namespace MediaBrowser.Common.Updates /// The name. /// The guid of the plugin. /// The minimum required version of the plugin. - /// The classification. + /// The classification. /// All compatible versions ordered from newest to oldest. - IEnumerable GetCompatibleVersions( + IEnumerable GetCompatibleVersions( IEnumerable availablePackages, string name = null, Guid guid = default, Version minVersion = null, - PackageVersionClass classification = PackageVersionClass.Release); + ReleaseChannel releaseChannel = ReleaseChannel.Stable); /// /// Returns the available plugin updates. /// /// The cancellation token. /// The available plugin updates. - IAsyncEnumerable GetAvailablePluginUpdates(CancellationToken cancellationToken = default); + IAsyncEnumerable GetAvailablePluginUpdates(CancellationToken cancellationToken = default); /// /// Installs the package. @@ -101,7 +101,7 @@ namespace MediaBrowser.Common.Updates /// The package. /// The cancellation token. /// . - Task InstallPackage(PackageVersionInfo package, CancellationToken cancellationToken = default); + Task InstallPackage(VersionInfo package, CancellationToken cancellationToken = default); /// /// Uninstalls a plugin. diff --git a/MediaBrowser.Common/Updates/InstallationEventArgs.cs b/MediaBrowser.Common/Updates/InstallationEventArgs.cs index 8bbb231ce..f459fd825 100644 --- a/MediaBrowser.Common/Updates/InstallationEventArgs.cs +++ b/MediaBrowser.Common/Updates/InstallationEventArgs.cs @@ -9,6 +9,6 @@ namespace MediaBrowser.Common.Updates { public InstallationInfo InstallationInfo { get; set; } - public PackageVersionInfo PackageVersionInfo { get; set; } + public VersionInfo VersionInfo { get; set; } } } diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 657665766..41644ad33 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -11,7 +11,7 @@ netstandard2.1 false true - true + true diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs index 190411c9b..da39ee208 100644 --- a/MediaBrowser.Model/System/SystemInfo.cs +++ b/MediaBrowser.Model/System/SystemInfo.cs @@ -27,7 +27,7 @@ namespace MediaBrowser.Model.System /// public class SystemInfo : PublicSystemInfo { - public PackageVersionClass SystemUpdateLevel { get; set; } + public ReleaseChannel SystemUpdateLevel { get; set; } /// /// Gets or sets the display name of the operating system. diff --git a/MediaBrowser.Model/Updates/CheckForUpdateResult.cs b/MediaBrowser.Model/Updates/CheckForUpdateResult.cs index be1b08223..883fc636b 100644 --- a/MediaBrowser.Model/Updates/CheckForUpdateResult.cs +++ b/MediaBrowser.Model/Updates/CheckForUpdateResult.cs @@ -17,13 +17,13 @@ namespace MediaBrowser.Model.Updates /// The available version. public string AvailableVersion { - get => Package != null ? Package.versionStr : "0.0.0.1"; + get => Package != null ? Package.versionString : "0.0.0.1"; set { } // need this for the serializer } /// /// Get or sets package information for an available update /// - public PackageVersionInfo Package { get; set; } + public VersionInfo Package { get; set; } } } diff --git a/MediaBrowser.Model/Updates/InstallationInfo.cs b/MediaBrowser.Model/Updates/InstallationInfo.cs index 42c2105f5..870bf8c0b 100644 --- a/MediaBrowser.Model/Updates/InstallationInfo.cs +++ b/MediaBrowser.Model/Updates/InstallationInfo.cs @@ -35,6 +35,6 @@ namespace MediaBrowser.Model.Updates /// Gets or sets the update class. /// /// The update class. - public PackageVersionClass UpdateClass { get; set; } + public ReleaseChannel UpdateClass { get; set; } } } diff --git a/MediaBrowser.Model/Updates/PackageInfo.cs b/MediaBrowser.Model/Updates/PackageInfo.cs index abbe91eff..d06ffe1e6 100644 --- a/MediaBrowser.Model/Updates/PackageInfo.cs +++ b/MediaBrowser.Model/Updates/PackageInfo.cs @@ -8,12 +8,6 @@ namespace MediaBrowser.Model.Updates /// public class PackageInfo { - /// - /// The internal id of this package. - /// - /// The id. - public string id { get; set; } - /// /// Gets or sets the name. /// @@ -32,24 +26,6 @@ namespace MediaBrowser.Model.Updates /// The overview. public string overview { get; set; } - /// - /// Gets or sets a value indicating whether this instance is premium. - /// - /// true if this instance is premium; otherwise, false. - public bool isPremium { get; set; } - - /// - /// Gets or sets a value indicating whether this instance is adult only content. - /// - /// true if this instance is adult; otherwise, false. - public bool adult { get; set; } - - /// - /// Gets or sets the rich desc URL. - /// - /// The rich desc URL. - public string richDescUrl { get; set; } - /// /// Gets or sets the thumb image. /// @@ -63,16 +39,10 @@ namespace MediaBrowser.Model.Updates public string previewImage { get; set; } /// - /// Gets or sets the type. - /// - /// The type. - public string type { get; set; } - - /// - /// Gets or sets the target filename. + /// Gets or sets the target filename for the downloaded binary. /// /// The target filename. - public string targetFilename { get; set; } + public string filename { get; set; } /// /// Gets or sets the owner. @@ -87,90 +57,24 @@ namespace MediaBrowser.Model.Updates public string category { get; set; } /// - /// Gets or sets the catalog tile color. - /// - /// The owner. - public string tileColor { get; set; } - - /// - /// Gets or sets the feature id of this package (if premium). - /// - /// The feature id. - public string featureId { get; set; } - - /// - /// Gets or sets the registration info for this package (if premium). - /// - /// The registration info. - public string regInfo { get; set; } - - /// - /// Gets or sets the price for this package (if premium). - /// - /// The price. - public float price { get; set; } - - /// - /// Gets or sets the target system for this plug-in (Server, MBTheater, MBClassic). - /// - /// The target system. - public PackageTargetSystem targetSystem { get; set; } - - /// - /// The guid of the assembly associated with this package (if a plug-in). + /// The guid of the assembly associated with this plugin. /// This is used to identify the proper item for automatic updates. /// /// The name. public string guid { get; set; } - /// - /// Gets or sets the total number of ratings for this package. - /// - /// The total ratings. - public int? totalRatings { get; set; } - - /// - /// Gets or sets the average rating for this package . - /// - /// The rating. - public float avgRating { get; set; } - - /// - /// Gets or sets whether or not this package is registered. - /// - /// True if registered. - public bool isRegistered { get; set; } - - /// - /// Gets or sets the expiration date for this package. - /// - /// Expiration Date. - public DateTime expDate { get; set; } - /// /// Gets or sets the versions. /// /// The versions. - public IReadOnlyList versions { get; set; } - - /// - /// Gets or sets a value indicating whether [enable in application store]. - /// - /// true if [enable in application store]; otherwise, false. - public bool enableInAppStore { get; set; } - - /// - /// Gets or sets the installs. - /// - /// The installs. - public int installs { get; set; } + public IReadOnlyList versions { get; set; } /// /// Initializes a new instance of the class. /// public PackageInfo() { - versions = Array.Empty(); + versions = Array.Empty(); } } } diff --git a/MediaBrowser.Model/Updates/PackageTargetSystem.cs b/MediaBrowser.Model/Updates/PackageTargetSystem.cs deleted file mode 100644 index 11af7f02d..000000000 --- a/MediaBrowser.Model/Updates/PackageTargetSystem.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace MediaBrowser.Model.Updates -{ - /// - /// Enum PackageType. - /// - public enum PackageTargetSystem - { - /// - /// Server. - /// - Server, - - /// - /// MB Theater. - /// - MBTheater, - - /// - /// MB Classic. - /// - MBClassic - } -} diff --git a/MediaBrowser.Model/Updates/PackageVersionInfo.cs b/MediaBrowser.Model/Updates/PackageVersionInfo.cs deleted file mode 100644 index 85d8fde86..000000000 --- a/MediaBrowser.Model/Updates/PackageVersionInfo.cs +++ /dev/null @@ -1,97 +0,0 @@ -#pragma warning disable CS1591 -#pragma warning disable SA1600 - -using System; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Model.Updates -{ - /// - /// Class PackageVersionInfo. - /// - public class PackageVersionInfo - { - /// - /// Gets or sets the name. - /// - /// The name. - public string name { get; set; } - - /// - /// Gets or sets the guid. - /// - /// The guid. - public string guid { get; set; } - - /// - /// Gets or sets the version STR. - /// - /// The version STR. - public string versionStr { get; set; } - - /// - /// The _version - /// - private Version _version; - - /// - /// Gets or sets the version. - /// Had to make this an interpreted property since Protobuf can't handle Version - /// - /// The version. - [JsonIgnore] - public Version Version - { - get - { - if (_version == null) - { - var ver = versionStr; - _version = new Version(string.IsNullOrEmpty(ver) ? "0.0.0.1" : ver); - } - - return _version; - } - } - - /// - /// Gets or sets the classification. - /// - /// The classification. - public PackageVersionClass classification { get; set; } - - /// - /// Gets or sets the description. - /// - /// The description. - public string description { get; set; } - - /// - /// Gets or sets the required version STR. - /// - /// The required version STR. - public string requiredVersionStr { get; set; } - - /// - /// Gets or sets the source URL. - /// - /// The source URL. - public string sourceUrl { get; set; } - - /// - /// Gets or sets the source URL. - /// - /// The source URL. - public string checksum { get; set; } - - /// - /// Gets or sets the target filename. - /// - /// The target filename. - public string targetFilename { get; set; } - - public string infoUrl { get; set; } - - public string runtimes { get; set; } - } -} diff --git a/MediaBrowser.Model/Updates/PackageVersionClass.cs b/MediaBrowser.Model/Updates/ReleaseChannel.cs similarity index 51% rename from MediaBrowser.Model/Updates/PackageVersionClass.cs rename to MediaBrowser.Model/Updates/ReleaseChannel.cs index f813f2c97..ed4a774a7 100644 --- a/MediaBrowser.Model/Updates/PackageVersionClass.cs +++ b/MediaBrowser.Model/Updates/ReleaseChannel.cs @@ -3,21 +3,16 @@ namespace MediaBrowser.Model.Updates /// /// Enum PackageVersionClass. /// - public enum PackageVersionClass + public enum ReleaseChannel { /// - /// The release. + /// The stable. /// - Release = 0, + Stable = 0, /// - /// The beta. + /// The nightly. /// - Beta = 1, - - /// - /// The dev. - /// - Dev = 2 + Nightly = 1 } } diff --git a/MediaBrowser.Model/Updates/VersionInfo.cs b/MediaBrowser.Model/Updates/VersionInfo.cs new file mode 100644 index 000000000..ad893db2e --- /dev/null +++ b/MediaBrowser.Model/Updates/VersionInfo.cs @@ -0,0 +1,73 @@ +#pragma warning disable CS1591 +#pragma warning disable SA1600 + +using System; + +namespace MediaBrowser.Model.Updates +{ + /// + /// Class PackageVersionInfo. + /// + public class VersionInfo + { + /// + /// Gets or sets the name. + /// + /// The name. + public string name { get; set; } + + /// + /// Gets or sets the guid. + /// + /// The guid. + public string guid { get; set; } + + /// + /// Gets or sets the version string. + /// + /// The version string. + public string versionString { get; set; } + + /// + /// Gets or sets the version. + /// + /// The version. + public Version versionCode { get; set; } + + /// + /// Gets or sets the release channel. + /// + /// The release channel for a given package version. + public ReleaseChannel channel { get; set; } + + /// + /// Gets or sets the description. + /// + /// The description. + public string description { get; set; } + + /// + /// Gets or sets the minimum required version for the server. + /// + /// The minimum required version. + public string minimumServerVersion { get; set; } + + /// + /// Gets or sets the source URL. + /// + /// The source URL. + public string sourceUrl { get; set; } + + /// + /// Gets or sets a checksum for the binary. + /// + /// The checksum. + public string checksum { get; set; } + + /// + /// Gets or sets the target filename for the downloaded binary. + /// + /// The target filename. + public string filename { get; set; } + } +} From e9e12b8eb97947f3387dcfac00fe9aa5e845d9e9 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 12:26:24 -0400 Subject: [PATCH 02/83] Register ISubtitleEncoder correctly --- Emby.Server.Implementations/ApplicationHost.cs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index c959cc974..27dd0ec1a 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -845,16 +845,7 @@ namespace Emby.Server.Implementations AuthService = new AuthService(LoggerFactory.CreateLogger(), authContext, ServerConfigurationManager, SessionManager, NetworkManager); serviceCollection.AddSingleton(AuthService); - SubtitleEncoder = new MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder( - LibraryManager, - LoggerFactory.CreateLogger(), - ApplicationPaths, - FileSystemManager, - MediaEncoder, - HttpClient, - MediaSourceManager, - ProcessFactory); - serviceCollection.AddSingleton(SubtitleEncoder); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(typeof(IResourceFileManager), typeof(ResourceFileManager)); serviceCollection.AddSingleton(); @@ -880,6 +871,7 @@ namespace Emby.Server.Implementations public void InitializeServices() { HttpServer = Resolve(); + SubtitleEncoder = Resolve(); } public static void LogEnvironmentInfo(ILogger logger, IApplicationPaths appPaths) From 92b0d40ad40cdf0e35ecd1a9e1680fd5b8e6ef2f Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 12:33:25 -0400 Subject: [PATCH 03/83] Move service initializations into correct method --- .../ApplicationHost.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 27dd0ec1a..f98532035 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -851,6 +851,16 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(); serviceCollection.AddSingleton(typeof(IAttachmentExtractor), typeof(MediaBrowser.MediaEncoding.Attachments.AttachmentExtractor)); + } + + /// + /// Create services registered with the service container that need to be initialized at application startup. + /// + public void InitializeServices() + { + HttpServer = Resolve(); + AuthService = Resolve(); + SubtitleEncoder = Resolve(); _displayPreferencesRepository.Initialize(); @@ -865,15 +875,6 @@ namespace Emby.Server.Implementations ((LibraryManager)LibraryManager).ItemRepository = ItemRepository; } - /// - /// Create services registered with the service container that need to be initialized at application startup. - /// - public void InitializeServices() - { - HttpServer = Resolve(); - SubtitleEncoder = Resolve(); - } - public static void LogEnvironmentInfo(ILogger logger, IApplicationPaths appPaths) { // Distinct these to prevent users from reporting problems that aren't actually problems From 314711147181ae26af4857b113b0e2acdcf10931 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 12:34:01 -0400 Subject: [PATCH 04/83] Register IAuthService correctly --- Emby.Server.Implementations/ApplicationHost.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index f98532035..00700a306 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -842,8 +842,7 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(authContext); serviceCollection.AddSingleton(new SessionContext(UserManager, authContext, SessionManager)); - AuthService = new AuthService(LoggerFactory.CreateLogger(), authContext, ServerConfigurationManager, SessionManager, NetworkManager); - serviceCollection.AddSingleton(AuthService); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); From 358deecf52370ef764b65d56f83a21d0eebcd91a Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 12:38:59 -0400 Subject: [PATCH 05/83] Register ISessionContext correctly --- Emby.Server.Implementations/ApplicationHost.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 00700a306..a90f14b1f 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -840,7 +840,7 @@ namespace Emby.Server.Implementations var authContext = new AuthorizationContext(AuthenticationRepository, UserManager); serviceCollection.AddSingleton(authContext); - serviceCollection.AddSingleton(new SessionContext(UserManager, authContext, SessionManager)); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); From 18c1823cead357ada7094675175b20b3399cafcb Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 12:40:33 -0400 Subject: [PATCH 06/83] Register IAuthorizationContext correctly --- Emby.Server.Implementations/ApplicationHost.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index a90f14b1f..c17798911 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -838,8 +838,7 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(activityLogRepo); serviceCollection.AddSingleton(new ActivityManager(LoggerFactory, activityLogRepo, UserManager)); - var authContext = new AuthorizationContext(AuthenticationRepository, UserManager); - serviceCollection.AddSingleton(authContext); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); From 3dbbe54f6c94ae279aa74eff3bfa380a665e02a9 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 12:42:21 -0400 Subject: [PATCH 07/83] Register IResourceFileManager correctly --- Emby.Server.Implementations/ApplicationHost.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index c17798911..46fa4d4b4 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -845,7 +845,7 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(typeof(IResourceFileManager), typeof(ResourceFileManager)); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(typeof(IAttachmentExtractor), typeof(MediaBrowser.MediaEncoding.Attachments.AttachmentExtractor)); From 4ba07b114d78b042dce111e2345f87b375d8da6e Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 12:46:35 -0400 Subject: [PATCH 08/83] Register and initialize IActivityRepository correctly --- Emby.Server.Implementations/ApplicationHost.cs | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 46fa4d4b4..3209ab3b7 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -834,9 +834,8 @@ namespace Emby.Server.Implementations LibraryManager); serviceCollection.AddSingleton(EncodingManager); - var activityLogRepo = GetActivityLogRepository(); - serviceCollection.AddSingleton(activityLogRepo); - serviceCollection.AddSingleton(new ActivityManager(LoggerFactory, activityLogRepo, UserManager)); + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); @@ -860,6 +859,7 @@ namespace Emby.Server.Implementations AuthService = Resolve(); SubtitleEncoder = Resolve(); + ((ActivityRepository)Resolve()).Initialize(); _displayPreferencesRepository.Initialize(); var userDataRepo = new SqliteUserDataRepository(LoggerFactory.CreateLogger(), ApplicationPaths); @@ -963,15 +963,6 @@ namespace Emby.Server.Implementations return repo; } - private IActivityRepository GetActivityLogRepository() - { - var repo = new ActivityRepository(LoggerFactory, ServerConfigurationManager.ApplicationPaths, FileSystemManager); - - repo.Initialize(); - - return repo; - } - /// /// Dirty hacks. /// From 7884c3813d682ca6ae8d7df4a6ba11f61e1d8ae0 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 12:51:56 -0400 Subject: [PATCH 09/83] Register IEncodingManager correctly; remove unnecessary properties in ApplicationHost --- .../ApplicationHost.cs | 20 +++---------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 3209ab3b7..7d72b8e08 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -282,16 +282,12 @@ namespace Emby.Server.Implementations /// The media encoder. private IMediaEncoder MediaEncoder { get; set; } - private ISubtitleEncoder SubtitleEncoder { get; set; } - private ISessionManager SessionManager { get; set; } private ILiveTvManager LiveTvManager { get; set; } public LocalizationManager LocalizationManager { get; set; } - private IEncodingManager EncodingManager { get; set; } - private IChannelManager ChannelManager { get; set; } /// @@ -326,8 +322,6 @@ namespace Emby.Server.Implementations /// The installation manager. protected IInstallationManager InstallationManager { get; private set; } - protected IAuthService AuthService { get; private set; } - public IStartupOptions StartupOptions { get; } internal IImageEncoder ImageEncoder { get; private set; } @@ -740,7 +734,7 @@ namespace Emby.Server.Implementations FileSystemManager, ProcessFactory, LocalizationManager, - () => SubtitleEncoder, + ServiceProvider.GetRequiredService, startupConfig, StartupOptions.FFmpegPath); serviceCollection.AddSingleton(MediaEncoder); @@ -826,13 +820,7 @@ namespace Emby.Server.Implementations ChapterManager = new ChapterManager(ItemRepository); serviceCollection.AddSingleton(ChapterManager); - EncodingManager = new MediaEncoder.EncodingManager( - LoggerFactory.CreateLogger(), - FileSystemManager, - MediaEncoder, - ChapterManager, - LibraryManager); - serviceCollection.AddSingleton(EncodingManager); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); @@ -856,8 +844,6 @@ namespace Emby.Server.Implementations public void InitializeServices() { HttpServer = Resolve(); - AuthService = Resolve(); - SubtitleEncoder = Resolve(); ((ActivityRepository)Resolve()).Initialize(); _displayPreferencesRepository.Initialize(); @@ -989,7 +975,7 @@ namespace Emby.Server.Implementations CollectionFolder.XmlSerializer = XmlSerializer; CollectionFolder.JsonSerializer = JsonSerializer; CollectionFolder.ApplicationHost = this; - AuthenticatedAttribute.AuthService = AuthService; + AuthenticatedAttribute.AuthService = ServiceProvider.GetRequiredService(); } private async void PluginInstalled(object sender, GenericEventArgs args) From 78370911c20d83b4f7fc9ca1fb89e5fdd978f0ef Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 12:56:36 -0400 Subject: [PATCH 10/83] Register IDeviceDiscovery, IChapterManager, IAttachmentExtractor correctly --- Emby.Server.Implementations/ApplicationHost.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 7d72b8e08..777c12eae 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -302,8 +302,6 @@ namespace Emby.Server.Implementations private ISubtitleManager SubtitleManager { get; set; } - private IChapterManager ChapterManager { get; set; } - private IDeviceManager DeviceManager { get; set; } internal IUserViewManager UserViewManager { get; set; } @@ -815,10 +813,9 @@ namespace Emby.Server.Implementations ServerConfigurationManager); serviceCollection.AddSingleton(NotificationManager); - serviceCollection.AddSingleton(new DeviceDiscovery(ServerConfigurationManager)); + serviceCollection.AddSingleton(); - ChapterManager = new ChapterManager(ItemRepository); - serviceCollection.AddSingleton(ChapterManager); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); @@ -835,7 +832,7 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(typeof(IAttachmentExtractor), typeof(MediaBrowser.MediaEncoding.Attachments.AttachmentExtractor)); + serviceCollection.AddSingleton(); } /// From f1d0fb1edb56e488bb1ef8f7b4ca2cd9b878f312 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 13:03:32 -0400 Subject: [PATCH 11/83] Register INotificationManager correctly; resolve services correctly --- Emby.Server.Implementations/ApplicationHost.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 777c12eae..0fcfedd6b 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -732,7 +732,7 @@ namespace Emby.Server.Implementations FileSystemManager, ProcessFactory, LocalizationManager, - ServiceProvider.GetRequiredService, + Resolve, startupConfig, StartupOptions.FFmpegPath); serviceCollection.AddSingleton(MediaEncoder); @@ -807,11 +807,7 @@ namespace Emby.Server.Implementations UserViewManager = new UserViewManager(LibraryManager, LocalizationManager, UserManager, ChannelManager, LiveTvManager, ServerConfigurationManager); serviceCollection.AddSingleton(UserViewManager); - NotificationManager = new NotificationManager( - LoggerFactory.CreateLogger(), - UserManager, - ServerConfigurationManager); - serviceCollection.AddSingleton(NotificationManager); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); @@ -840,6 +836,7 @@ namespace Emby.Server.Implementations /// public void InitializeServices() { + NotificationManager = Resolve(); HttpServer = Resolve(); ((ActivityRepository)Resolve()).Initialize(); @@ -972,7 +969,7 @@ namespace Emby.Server.Implementations CollectionFolder.XmlSerializer = XmlSerializer; CollectionFolder.JsonSerializer = JsonSerializer; CollectionFolder.ApplicationHost = this; - AuthenticatedAttribute.AuthService = ServiceProvider.GetRequiredService(); + AuthenticatedAttribute.AuthService = Resolve(); } private async void PluginInstalled(object sender, GenericEventArgs args) From 14563654113192fbf162c5238c79a0f908587c05 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 13:10:39 -0400 Subject: [PATCH 12/83] Register IUserViewManager correctly --- Emby.Server.Implementations/ApplicationHost.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 0fcfedd6b..aa1e9ab9d 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -304,8 +304,6 @@ namespace Emby.Server.Implementations private IDeviceManager DeviceManager { get; set; } - internal IUserViewManager UserViewManager { get; set; } - private IAuthenticationRepository AuthenticationRepository { get; set; } private ITVSeriesManager TVSeriesManager { get; set; } @@ -737,7 +735,7 @@ namespace Emby.Server.Implementations StartupOptions.FFmpegPath); serviceCollection.AddSingleton(MediaEncoder); - LibraryManager = new LibraryManager(this, LoggerFactory, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, () => ProviderManager, () => UserViewManager, MediaEncoder); + LibraryManager = new LibraryManager(this, LoggerFactory, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, () => ProviderManager, Resolve, MediaEncoder); serviceCollection.AddSingleton(LibraryManager); var musicManager = new MusicManager(LibraryManager); @@ -804,8 +802,7 @@ namespace Emby.Server.Implementations LiveTvManager = new LiveTvManager(this, ServerConfigurationManager, LoggerFactory, ItemRepository, ImageProcessor, UserDataManager, DtoService, UserManager, LibraryManager, TaskManager, LocalizationManager, JsonSerializer, FileSystemManager, () => ChannelManager); serviceCollection.AddSingleton(LiveTvManager); - UserViewManager = new UserViewManager(LibraryManager, LocalizationManager, UserManager, ChannelManager, LiveTvManager, ServerConfigurationManager); - serviceCollection.AddSingleton(UserViewManager); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); @@ -962,7 +959,7 @@ namespace Emby.Server.Implementations BaseItem.UserDataManager = UserDataManager; BaseItem.ChannelManager = ChannelManager; Video.LiveTvManager = LiveTvManager; - Folder.UserViewManager = UserViewManager; + Folder.UserViewManager = Resolve(); UserView.TVSeriesManager = TVSeriesManager; UserView.CollectionManager = CollectionManager; BaseItem.MediaSourceManager = MediaSourceManager; From 3d5b4f869c9edb1e297b89b82221ee837ac6330e Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 13:16:41 -0400 Subject: [PATCH 13/83] Register ILiveTvManager and IPlaylistManager correctly --- Emby.Server.Implementations/ApplicationHost.cs | 6 +++--- Emby.Server.Implementations/LiveTv/LiveTvManager.cs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index aa1e9ab9d..94d656e16 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -797,10 +797,9 @@ namespace Emby.Server.Implementations CollectionManager = new CollectionManager(LibraryManager, ApplicationPaths, LocalizationManager, FileSystemManager, LibraryMonitor, LoggerFactory, ProviderManager); serviceCollection.AddSingleton(CollectionManager); - serviceCollection.AddSingleton(typeof(IPlaylistManager), typeof(PlaylistManager)); + serviceCollection.AddSingleton(); - LiveTvManager = new LiveTvManager(this, ServerConfigurationManager, LoggerFactory, ItemRepository, ImageProcessor, UserDataManager, DtoService, UserManager, LibraryManager, TaskManager, LocalizationManager, JsonSerializer, FileSystemManager, () => ChannelManager); - serviceCollection.AddSingleton(LiveTvManager); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); @@ -833,6 +832,7 @@ namespace Emby.Server.Implementations /// public void InitializeServices() { + LiveTvManager = Resolve(); NotificationManager = Resolve(); HttpServer = Resolve(); diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index b64fe8634..eabc20786 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -49,7 +49,7 @@ namespace Emby.Server.Implementations.LiveTv private readonly ILibraryManager _libraryManager; private readonly ITaskManager _taskManager; private readonly IJsonSerializer _jsonSerializer; - private readonly Func _channelManager; + private readonly IChannelManager _channelManager; private readonly IDtoService _dtoService; private readonly ILocalizationManager _localization; @@ -76,7 +76,7 @@ namespace Emby.Server.Implementations.LiveTv ILocalizationManager localization, IJsonSerializer jsonSerializer, IFileSystem fileSystem, - Func channelManager) + IChannelManager channelManager) { _config = config; _logger = loggerFactory.CreateLogger(nameof(LiveTvManager)); @@ -2482,7 +2482,7 @@ namespace Emby.Server.Implementations.LiveTv .OrderBy(i => i.SortName) .ToList(); - folders.AddRange(_channelManager().GetChannelsInternal(new MediaBrowser.Model.Channels.ChannelQuery + folders.AddRange(_channelManager.GetChannelsInternal(new MediaBrowser.Model.Channels.ChannelQuery { UserId = user.Id, IsRecordingsFolder = true, From bb3db9e845208984a9b2093d81642cc0efc844a0 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 13:56:01 -0400 Subject: [PATCH 14/83] Register ISessionManager, IDlnaManager and ICollectionManager correctly; replace private properties with fields --- .../ApplicationHost.cs | 69 +++++++------------ 1 file changed, 25 insertions(+), 44 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 94d656e16..48414e26e 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -120,6 +120,10 @@ namespace Emby.Server.Implementations { private SqliteUserRepository _userRepository; private SqliteDisplayPreferencesRepository _displayPreferencesRepository; + private ISessionManager _sessionManager; + private ILiveTvManager _liveTvManager; + private INotificationManager _notificationManager; + private IHttpServer _httpServer; /// /// Gets a value indicating whether this instance can self restart. @@ -266,11 +270,7 @@ namespace Emby.Server.Implementations /// The provider manager. private IProviderManager ProviderManager { get; set; } - /// - /// Gets or sets the HTTP server. - /// - /// The HTTP server. - private IHttpServer HttpServer { get; set; } + private IDtoService DtoService { get; set; } @@ -282,10 +282,6 @@ namespace Emby.Server.Implementations /// The media encoder. private IMediaEncoder MediaEncoder { get; set; } - private ISessionManager SessionManager { get; set; } - - private ILiveTvManager LiveTvManager { get; set; } - public LocalizationManager LocalizationManager { get; set; } private IChannelManager ChannelManager { get; set; } @@ -298,7 +294,7 @@ namespace Emby.Server.Implementations internal SqliteItemRepository ItemRepository { get; set; } - private INotificationManager NotificationManager { get; set; } + private ISubtitleManager SubtitleManager { get; set; } @@ -308,8 +304,6 @@ namespace Emby.Server.Implementations private ITVSeriesManager TVSeriesManager { get; set; } - private ICollectionManager CollectionManager { get; set; } - private IMediaSourceManager MediaSourceManager { get; set; } /// @@ -541,7 +535,7 @@ namespace Emby.Server.Implementations Logger.LogInformation("Executed all pre-startup entry points in {Elapsed:g}", stopWatch.Elapsed); Logger.LogInformation("Core startup complete"); - HttpServer.GlobalResponse = null; + _httpServer.GlobalResponse = null; stopWatch.Restart(); await Task.WhenAll(StartEntryPoints(entryPoints, false)).ConfigureAwait(false); @@ -609,7 +603,7 @@ namespace Emby.Server.Implementations return; } - await HttpServer.ProcessWebSocketRequest(context).ConfigureAwait(false); + await _httpServer.ProcessWebSocketRequest(context).ConfigureAwait(false); } public async Task ExecuteHttpHandlerAsync(HttpContext context, Func next) @@ -625,7 +619,7 @@ namespace Emby.Server.Implementations var localPath = context.Request.Path.ToString(); var req = new WebSocketSharpRequest(request, response, request.Path, LoggerFactory.CreateLogger()); - await HttpServer.RequestHandler(req, request.GetDisplayUrl(), request.Host.ToString(), localPath, context.RequestAborted).ConfigureAwait(false); + await _httpServer.RequestHandler(req, request.GetDisplayUrl(), request.Host.ToString(), localPath, context.RequestAborted).ConfigureAwait(false); } /// @@ -771,31 +765,17 @@ namespace Emby.Server.Implementations ProviderManager = new ProviderManager(HttpClient, SubtitleManager, ServerConfigurationManager, LibraryMonitor, LoggerFactory, FileSystemManager, ApplicationPaths, () => LibraryManager, JsonSerializer); serviceCollection.AddSingleton(ProviderManager); - DtoService = new DtoService(LoggerFactory, LibraryManager, UserDataManager, ItemRepository, ImageProcessor, ProviderManager, this, () => MediaSourceManager, () => LiveTvManager); + DtoService = new DtoService(LoggerFactory, LibraryManager, UserDataManager, ItemRepository, ImageProcessor, ProviderManager, this, () => MediaSourceManager, () => _liveTvManager); serviceCollection.AddSingleton(DtoService); ChannelManager = new ChannelManager(UserManager, DtoService, LibraryManager, LoggerFactory, ServerConfigurationManager, FileSystemManager, UserDataManager, JsonSerializer, ProviderManager); serviceCollection.AddSingleton(ChannelManager); - SessionManager = new SessionManager( - LoggerFactory.CreateLogger(), - UserDataManager, - LibraryManager, - UserManager, - musicManager, - DtoService, - ImageProcessor, - this, - AuthenticationRepository, - DeviceManager, - MediaSourceManager); - serviceCollection.AddSingleton(SessionManager); + serviceCollection.AddSingleton(); - serviceCollection.AddSingleton( - new DlnaManager(XmlSerializer, FileSystemManager, ApplicationPaths, LoggerFactory, JsonSerializer, this)); + serviceCollection.AddSingleton(); - CollectionManager = new CollectionManager(LibraryManager, ApplicationPaths, LocalizationManager, FileSystemManager, LibraryMonitor, LoggerFactory, ProviderManager); - serviceCollection.AddSingleton(CollectionManager); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); @@ -832,9 +812,10 @@ namespace Emby.Server.Implementations /// public void InitializeServices() { - LiveTvManager = Resolve(); - NotificationManager = Resolve(); - HttpServer = Resolve(); + _sessionManager = Resolve(); + _liveTvManager = Resolve(); + _notificationManager = Resolve(); + _httpServer = Resolve(); ((ActivityRepository)Resolve()).Initialize(); _displayPreferencesRepository.Initialize(); @@ -958,10 +939,10 @@ namespace Emby.Server.Implementations BaseItem.FileSystem = FileSystemManager; BaseItem.UserDataManager = UserDataManager; BaseItem.ChannelManager = ChannelManager; - Video.LiveTvManager = LiveTvManager; + Video.LiveTvManager = _liveTvManager; Folder.UserViewManager = Resolve(); UserView.TVSeriesManager = TVSeriesManager; - UserView.CollectionManager = CollectionManager; + UserView.CollectionManager = Resolve(); BaseItem.MediaSourceManager = MediaSourceManager; CollectionFolder.XmlSerializer = XmlSerializer; CollectionFolder.JsonSerializer = JsonSerializer; @@ -1024,7 +1005,7 @@ namespace Emby.Server.Implementations .Where(i => i != null) .ToArray(); - HttpServer.Init(GetExportTypes(), GetExports(), GetUrlPrefixes()); + _httpServer.Init(GetExportTypes(), GetExports(), GetUrlPrefixes()); LibraryManager.AddParts( GetExports(), @@ -1040,7 +1021,7 @@ namespace Emby.Server.Implementations GetExports(), GetExports()); - LiveTvManager.AddParts(GetExports(), GetExports(), GetExports()); + _liveTvManager.AddParts(GetExports(), GetExports(), GetExports()); SubtitleManager.AddParts(GetExports()); @@ -1048,7 +1029,7 @@ namespace Emby.Server.Implementations MediaSourceManager.AddParts(GetExports()); - NotificationManager.AddParts(GetExports(), GetExports()); + _notificationManager.AddParts(GetExports(), GetExports()); UserManager.AddParts(GetExports(), GetExports()); IsoManager.AddParts(GetExports()); @@ -1194,7 +1175,7 @@ namespace Emby.Server.Implementations } } - if (!HttpServer.UrlPrefixes.SequenceEqual(GetUrlPrefixes(), StringComparer.OrdinalIgnoreCase)) + if (!_httpServer.UrlPrefixes.SequenceEqual(GetUrlPrefixes(), StringComparer.OrdinalIgnoreCase)) { requiresRestart = true; } @@ -1254,7 +1235,7 @@ namespace Emby.Server.Implementations { try { - await SessionManager.SendServerRestartNotification(CancellationToken.None).ConfigureAwait(false); + await _sessionManager.SendServerRestartNotification(CancellationToken.None).ConfigureAwait(false); } catch (Exception ex) { @@ -1618,7 +1599,7 @@ namespace Emby.Server.Implementations try { - await SessionManager.SendServerShutdownNotification(CancellationToken.None).ConfigureAwait(false); + await _sessionManager.SendServerShutdownNotification(CancellationToken.None).ConfigureAwait(false); } catch (Exception ex) { From f78423bd494d2439191e57705ec4031cb211e4d4 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 14:32:35 -0400 Subject: [PATCH 15/83] Register IChannerManager correctly --- Emby.Server.Implementations/ApplicationHost.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 48414e26e..f437390c0 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -120,6 +120,7 @@ namespace Emby.Server.Implementations { private SqliteUserRepository _userRepository; private SqliteDisplayPreferencesRepository _displayPreferencesRepository; + private IChannelManager _channelManager; private ISessionManager _sessionManager; private ILiveTvManager _liveTvManager; private INotificationManager _notificationManager; @@ -284,7 +285,7 @@ namespace Emby.Server.Implementations public LocalizationManager LocalizationManager { get; set; } - private IChannelManager ChannelManager { get; set; } + /// /// Gets or sets the user data repository. @@ -768,8 +769,7 @@ namespace Emby.Server.Implementations DtoService = new DtoService(LoggerFactory, LibraryManager, UserDataManager, ItemRepository, ImageProcessor, ProviderManager, this, () => MediaSourceManager, () => _liveTvManager); serviceCollection.AddSingleton(DtoService); - ChannelManager = new ChannelManager(UserManager, DtoService, LibraryManager, LoggerFactory, ServerConfigurationManager, FileSystemManager, UserDataManager, JsonSerializer, ProviderManager); - serviceCollection.AddSingleton(ChannelManager); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); @@ -812,6 +812,7 @@ namespace Emby.Server.Implementations /// public void InitializeServices() { + _channelManager = Resolve(); _sessionManager = Resolve(); _liveTvManager = Resolve(); _notificationManager = Resolve(); @@ -938,7 +939,7 @@ namespace Emby.Server.Implementations User.UserManager = UserManager; BaseItem.FileSystem = FileSystemManager; BaseItem.UserDataManager = UserDataManager; - BaseItem.ChannelManager = ChannelManager; + BaseItem.ChannelManager = _channelManager; Video.LiveTvManager = _liveTvManager; Folder.UserViewManager = Resolve(); UserView.TVSeriesManager = TVSeriesManager; @@ -1025,7 +1026,7 @@ namespace Emby.Server.Implementations SubtitleManager.AddParts(GetExports()); - ChannelManager.AddParts(GetExports()); + _channelManager.AddParts(GetExports()); MediaSourceManager.AddParts(GetExports()); From cb2d99e8318d6831b8c7ba80997c172e72a6ee95 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 14:40:04 -0400 Subject: [PATCH 16/83] Construct LiveTvDtoService and LiveTvManager correctly --- .../ApplicationHost.cs | 1 + .../LiveTv/LiveTvDtoService.cs | 5 ++-- .../LiveTv/LiveTvManager.cs | 23 ++++++++----------- 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index f437390c0..e10627ad1 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -779,6 +779,7 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); diff --git a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs index 6e903a18e..55300c967 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs @@ -24,7 +24,6 @@ namespace Emby.Server.Implementations.LiveTv { private readonly ILogger _logger; private readonly IImageProcessor _imageProcessor; - private readonly IDtoService _dtoService; private readonly IApplicationHost _appHost; private readonly ILibraryManager _libraryManager; @@ -32,13 +31,13 @@ namespace Emby.Server.Implementations.LiveTv public LiveTvDtoService( IDtoService dtoService, IImageProcessor imageProcessor, - ILoggerFactory loggerFactory, + ILogger logger, IApplicationHost appHost, ILibraryManager libraryManager) { _dtoService = dtoService; _imageProcessor = imageProcessor; - _logger = loggerFactory.CreateLogger(nameof(LiveTvDtoService)); + _logger = logger; _appHost = appHost; _libraryManager = libraryManager; } diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index eabc20786..d8ff8a72f 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -45,29 +45,24 @@ namespace Emby.Server.Implementations.LiveTv private readonly ILogger _logger; private readonly IItemRepository _itemRepo; private readonly IUserManager _userManager; + private readonly IDtoService _dtoService; private readonly IUserDataManager _userDataManager; private readonly ILibraryManager _libraryManager; private readonly ITaskManager _taskManager; - private readonly IJsonSerializer _jsonSerializer; - private readonly IChannelManager _channelManager; - - private readonly IDtoService _dtoService; private readonly ILocalizationManager _localization; - + private readonly IJsonSerializer _jsonSerializer; + private readonly IFileSystem _fileSystem; + private readonly IChannelManager _channelManager; private readonly LiveTvDtoService _tvDtoService; private ILiveTvService[] _services = Array.Empty(); - private ITunerHost[] _tunerHosts = Array.Empty(); private IListingsProvider[] _listingProviders = Array.Empty(); - private readonly IFileSystem _fileSystem; public LiveTvManager( - IServerApplicationHost appHost, IServerConfigurationManager config, - ILoggerFactory loggerFactory, + ILogger logger, IItemRepository itemRepo, - IImageProcessor imageProcessor, IUserDataManager userDataManager, IDtoService dtoService, IUserManager userManager, @@ -76,10 +71,11 @@ namespace Emby.Server.Implementations.LiveTv ILocalizationManager localization, IJsonSerializer jsonSerializer, IFileSystem fileSystem, - IChannelManager channelManager) + IChannelManager channelManager, + LiveTvDtoService liveTvDtoService) { _config = config; - _logger = loggerFactory.CreateLogger(nameof(LiveTvManager)); + _logger = logger; _itemRepo = itemRepo; _userManager = userManager; _libraryManager = libraryManager; @@ -90,8 +86,7 @@ namespace Emby.Server.Implementations.LiveTv _dtoService = dtoService; _userDataManager = userDataManager; _channelManager = channelManager; - - _tvDtoService = new LiveTvDtoService(dtoService, imageProcessor, loggerFactory, appHost, _libraryManager); + _tvDtoService = liveTvDtoService; } public event EventHandler> SeriesTimerCancelled; From 75b05ca1e6dce73c2d419dd83cbc5f9693688faa Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 14:41:03 -0400 Subject: [PATCH 17/83] Register and construct DtoService correctly --- .../ApplicationHost.cs | 11 +++---- Emby.Server.Implementations/Dto/DtoService.cs | 30 ++++++++++--------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index e10627ad1..44056dc9e 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -271,10 +271,6 @@ namespace Emby.Server.Implementations /// The provider manager. private IProviderManager ProviderManager { get; set; } - - - private IDtoService DtoService { get; set; } - public IImageProcessor ImageProcessor { get; set; } /// @@ -711,7 +707,7 @@ namespace Emby.Server.Implementations XmlSerializer, NetworkManager, () => ImageProcessor, - () => DtoService, + Resolve, this, JsonSerializer, FileSystemManager, @@ -766,8 +762,9 @@ namespace Emby.Server.Implementations ProviderManager = new ProviderManager(HttpClient, SubtitleManager, ServerConfigurationManager, LibraryMonitor, LoggerFactory, FileSystemManager, ApplicationPaths, () => LibraryManager, JsonSerializer); serviceCollection.AddSingleton(ProviderManager); - DtoService = new DtoService(LoggerFactory, LibraryManager, UserDataManager, ItemRepository, ImageProcessor, ProviderManager, this, () => MediaSourceManager, () => _liveTvManager); - serviceCollection.AddSingleton(DtoService); + // TODO: Refactor to eliminate circular dependency here so Lazy<> isn't required + serviceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 65711e89d..001cfe5db 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -38,21 +38,23 @@ namespace Emby.Server.Implementations.Dto private readonly IProviderManager _providerManager; private readonly IApplicationHost _appHost; - private readonly Func _mediaSourceManager; - private readonly Func _livetvManager; + private readonly IMediaSourceManager _mediaSourceManager; + private readonly Lazy _livetvManagerLazy; + + private ILiveTvManager LivetvManager => _livetvManagerLazy.Value; public DtoService( - ILoggerFactory loggerFactory, + ILogger logger, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IImageProcessor imageProcessor, IProviderManager providerManager, IApplicationHost appHost, - Func mediaSourceManager, - Func livetvManager) + IMediaSourceManager mediaSourceManager, + Lazy livetvManager) { - _logger = loggerFactory.CreateLogger(nameof(DtoService)); + _logger = logger; _libraryManager = libraryManager; _userDataRepository = userDataRepository; _itemRepo = itemRepo; @@ -60,7 +62,7 @@ namespace Emby.Server.Implementations.Dto _providerManager = providerManager; _appHost = appHost; _mediaSourceManager = mediaSourceManager; - _livetvManager = livetvManager; + _livetvManagerLazy = livetvManager; } /// @@ -125,12 +127,12 @@ namespace Emby.Server.Implementations.Dto if (programTuples.Count > 0) { - _livetvManager().AddInfoToProgramDto(programTuples, options.Fields, user).GetAwaiter().GetResult(); + LivetvManager.AddInfoToProgramDto(programTuples, options.Fields, user).GetAwaiter().GetResult(); } if (channelTuples.Count > 0) { - _livetvManager().AddChannelInfo(channelTuples, options, user); + LivetvManager.AddChannelInfo(channelTuples, options, user); } return returnItems; @@ -142,12 +144,12 @@ namespace Emby.Server.Implementations.Dto if (item is LiveTvChannel tvChannel) { var list = new List<(BaseItemDto, LiveTvChannel)>(1) { (dto, tvChannel) }; - _livetvManager().AddChannelInfo(list, options, user); + LivetvManager.AddChannelInfo(list, options, user); } else if (item is LiveTvProgram) { var list = new List<(BaseItem, BaseItemDto)>(1) { (item, dto) }; - var task = _livetvManager().AddInfoToProgramDto(list, options.Fields, user); + var task = LivetvManager.AddInfoToProgramDto(list, options.Fields, user); Task.WaitAll(task); } @@ -223,7 +225,7 @@ namespace Emby.Server.Implementations.Dto if (item is IHasMediaSources && options.ContainsField(ItemFields.MediaSources)) { - dto.MediaSources = _mediaSourceManager().GetStaticMediaSources(item, true, user).ToArray(); + dto.MediaSources = _mediaSourceManager.GetStaticMediaSources(item, true, user).ToArray(); NormalizeMediaSourceContainers(dto); } @@ -254,7 +256,7 @@ namespace Emby.Server.Implementations.Dto dto.Etag = item.GetEtag(user); } - var liveTvManager = _livetvManager(); + var liveTvManager = LivetvManager; var activeRecording = liveTvManager.GetActiveRecordingInfo(item.Path); if (activeRecording != null) { @@ -1045,7 +1047,7 @@ namespace Emby.Server.Implementations.Dto } else { - mediaStreams = _mediaSourceManager().GetStaticMediaSources(item, true)[0].MediaStreams.ToArray(); + mediaStreams = _mediaSourceManager.GetStaticMediaSources(item, true)[0].MediaStreams.ToArray(); } dto.MediaStreams = mediaStreams; From 51b9a6e94b06db6ae4b21cf2372287a98778a075 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 14:56:50 -0400 Subject: [PATCH 18/83] Register IProviderManager correctly --- .../ApplicationHost.cs | 15 ++-- Emby.Server.Implementations/Dto/DtoService.cs | 8 +-- .../Manager/ProviderManager.cs | 71 ++++++++----------- 3 files changed, 39 insertions(+), 55 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 44056dc9e..8a3398e01 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -265,12 +265,6 @@ namespace Emby.Server.Implementations /// The directory watchers. private ILibraryMonitor LibraryMonitor { get; set; } - /// - /// Gets or sets the provider manager. - /// - /// The provider manager. - private IProviderManager ProviderManager { get; set; } - public IImageProcessor ImageProcessor { get; set; } /// @@ -726,7 +720,7 @@ namespace Emby.Server.Implementations StartupOptions.FFmpegPath); serviceCollection.AddSingleton(MediaEncoder); - LibraryManager = new LibraryManager(this, LoggerFactory, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, () => ProviderManager, Resolve, MediaEncoder); + LibraryManager = new LibraryManager(this, LoggerFactory, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, Resolve, Resolve, MediaEncoder); serviceCollection.AddSingleton(LibraryManager); var musicManager = new MusicManager(LibraryManager); @@ -759,8 +753,7 @@ namespace Emby.Server.Implementations SubtitleManager = new SubtitleManager(LoggerFactory, FileSystemManager, LibraryMonitor, MediaSourceManager, LocalizationManager); serviceCollection.AddSingleton(SubtitleManager); - ProviderManager = new ProviderManager(HttpClient, SubtitleManager, ServerConfigurationManager, LibraryMonitor, LoggerFactory, FileSystemManager, ApplicationPaths, () => LibraryManager, JsonSerializer); - serviceCollection.AddSingleton(ProviderManager); + serviceCollection.AddSingleton(); // TODO: Refactor to eliminate circular dependency here so Lazy<> isn't required serviceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); @@ -931,7 +924,7 @@ namespace Emby.Server.Implementations BaseItem.Logger = LoggerFactory.CreateLogger("BaseItem"); BaseItem.ConfigurationManager = ServerConfigurationManager; BaseItem.LibraryManager = LibraryManager; - BaseItem.ProviderManager = ProviderManager; + BaseItem.ProviderManager = Resolve(); BaseItem.LocalizationManager = LocalizationManager; BaseItem.ItemRepository = ItemRepository; User.UserManager = UserManager; @@ -1013,7 +1006,7 @@ namespace Emby.Server.Implementations GetExports(), GetExports()); - ProviderManager.AddParts( + Resolve().AddParts( GetExports(), GetExports(), GetExports(), diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 001cfe5db..c8ea861ce 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -39,9 +39,9 @@ namespace Emby.Server.Implementations.Dto private readonly IApplicationHost _appHost; private readonly IMediaSourceManager _mediaSourceManager; - private readonly Lazy _livetvManagerLazy; + private readonly Lazy _livetvManagerFactory; - private ILiveTvManager LivetvManager => _livetvManagerLazy.Value; + private ILiveTvManager LivetvManager => _livetvManagerFactory.Value; public DtoService( ILogger logger, @@ -52,7 +52,7 @@ namespace Emby.Server.Implementations.Dto IProviderManager providerManager, IApplicationHost appHost, IMediaSourceManager mediaSourceManager, - Lazy livetvManager) + Lazy livetvManagerFactory) { _logger = logger; _libraryManager = libraryManager; @@ -62,7 +62,7 @@ namespace Emby.Server.Implementations.Dto _providerManager = providerManager; _appHost = appHost; _mediaSourceManager = mediaSourceManager; - _livetvManagerLazy = livetvManager; + _livetvManagerFactory = livetvManagerFactory; } /// diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 7125f34c5..337bc37eb 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -36,60 +36,51 @@ namespace MediaBrowser.Providers.Manager /// public class ProviderManager : IProviderManager, IDisposable { - /// - /// The _logger - /// private readonly ILogger _logger; - - /// - /// The _HTTP client - /// private readonly IHttpClient _httpClient; - - /// - /// The _directory watchers - /// private readonly ILibraryMonitor _libraryMonitor; - - /// - /// Gets or sets the configuration manager. - /// - /// The configuration manager. - private IServerConfigurationManager ConfigurationManager { get; set; } + private readonly IFileSystem _fileSystem; + private readonly IServerApplicationPaths _appPaths; + private readonly IJsonSerializer _json; + private readonly ILibraryManager _libraryManager; + private readonly ISubtitleManager _subtitleManager; + private readonly IServerConfigurationManager _configurationManager; private IImageProvider[] ImageProviders { get; set; } - private readonly IFileSystem _fileSystem; - private IMetadataService[] _metadataServices = { }; private IMetadataProvider[] _metadataProviders = { }; private IEnumerable _savers; - private readonly IServerApplicationPaths _appPaths; - private readonly IJsonSerializer _json; private IExternalId[] _externalIds; - private readonly Func _libraryManagerFactory; private CancellationTokenSource _disposeCancellationTokenSource = new CancellationTokenSource(); public event EventHandler> RefreshStarted; public event EventHandler> RefreshCompleted; public event EventHandler>> RefreshProgress; - private ISubtitleManager _subtitleManager; - /// /// Initializes a new instance of the class. /// - public ProviderManager(IHttpClient httpClient, ISubtitleManager subtitleManager, IServerConfigurationManager configurationManager, ILibraryMonitor libraryMonitor, ILoggerFactory loggerFactory, IFileSystem fileSystem, IServerApplicationPaths appPaths, Func libraryManagerFactory, IJsonSerializer json) + public ProviderManager( + IHttpClient httpClient, + ISubtitleManager subtitleManager, + IServerConfigurationManager configurationManager, + ILibraryMonitor libraryMonitor, + ILogger logger, + IFileSystem fileSystem, + IServerApplicationPaths appPaths, + ILibraryManager libraryManager, + IJsonSerializer json) { - _logger = loggerFactory.CreateLogger("ProviderManager"); + _logger = logger; _httpClient = httpClient; - ConfigurationManager = configurationManager; + _configurationManager = configurationManager; _libraryMonitor = libraryMonitor; _fileSystem = fileSystem; _appPaths = appPaths; - _libraryManagerFactory = libraryManagerFactory; + _libraryManager = libraryManager; _json = json; _subtitleManager = subtitleManager; } @@ -176,7 +167,7 @@ namespace MediaBrowser.Providers.Manager public Task SaveImage(BaseItem item, Stream source, string mimeType, ImageType type, int? imageIndex, CancellationToken cancellationToken) { - return new ImageSaver(ConfigurationManager, _libraryMonitor, _fileSystem, _logger).SaveImage(item, source, mimeType, type, imageIndex, cancellationToken); + return new ImageSaver(_configurationManager, _libraryMonitor, _fileSystem, _logger).SaveImage(item, source, mimeType, type, imageIndex, cancellationToken); } public Task SaveImage(BaseItem item, string source, string mimeType, ImageType type, int? imageIndex, bool? saveLocallyWithMedia, CancellationToken cancellationToken) @@ -188,7 +179,7 @@ namespace MediaBrowser.Providers.Manager var fileStream = new FileStream(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, true); - return new ImageSaver(ConfigurationManager, _libraryMonitor, _fileSystem, _logger).SaveImage(item, fileStream, mimeType, type, imageIndex, saveLocallyWithMedia, cancellationToken); + return new ImageSaver(_configurationManager, _libraryMonitor, _fileSystem, _logger).SaveImage(item, fileStream, mimeType, type, imageIndex, saveLocallyWithMedia, cancellationToken); } public async Task> GetAvailableRemoteImages(BaseItem item, RemoteImageQuery query, CancellationToken cancellationToken) @@ -273,7 +264,7 @@ namespace MediaBrowser.Providers.Manager public IEnumerable GetImageProviders(BaseItem item, ImageRefreshOptions refreshOptions) { - return GetImageProviders(item, _libraryManagerFactory().GetLibraryOptions(item), GetMetadataOptions(item), refreshOptions, false); + return GetImageProviders(item, _libraryManager.GetLibraryOptions(item), GetMetadataOptions(item), refreshOptions, false); } private IEnumerable GetImageProviders(BaseItem item, LibraryOptions libraryOptions, MetadataOptions options, ImageRefreshOptions refreshOptions, bool includeDisabled) @@ -328,7 +319,7 @@ namespace MediaBrowser.Providers.Manager private IEnumerable GetRemoteImageProviders(BaseItem item, bool includeDisabled) { var options = GetMetadataOptions(item); - var libraryOptions = _libraryManagerFactory().GetLibraryOptions(item); + var libraryOptions = _libraryManager.GetLibraryOptions(item); return GetImageProviders(item, libraryOptions, options, new ImageRefreshOptions( @@ -593,7 +584,7 @@ namespace MediaBrowser.Providers.Manager { var type = item.GetType().Name; - return ConfigurationManager.Configuration.MetadataOptions + return _configurationManager.Configuration.MetadataOptions .FirstOrDefault(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase)) ?? new MetadataOptions(); } @@ -623,7 +614,7 @@ namespace MediaBrowser.Providers.Manager /// Task. private void SaveMetadata(BaseItem item, ItemUpdateType updateType, IEnumerable savers) { - var libraryOptions = _libraryManagerFactory().GetLibraryOptions(item); + var libraryOptions = _libraryManager.GetLibraryOptions(item); foreach (var saver in savers.Where(i => IsSaverEnabledForItem(i, item, libraryOptions, updateType, false))) { @@ -743,7 +734,7 @@ namespace MediaBrowser.Providers.Manager if (!searchInfo.ItemId.Equals(Guid.Empty)) { - referenceItem = _libraryManagerFactory().GetItemById(searchInfo.ItemId); + referenceItem = _libraryManager.GetItemById(searchInfo.ItemId); } return GetRemoteSearchResults(searchInfo, referenceItem, cancellationToken); @@ -771,7 +762,7 @@ namespace MediaBrowser.Providers.Manager } else { - libraryOptions = _libraryManagerFactory().GetLibraryOptions(referenceItem); + libraryOptions = _libraryManager.GetLibraryOptions(referenceItem); } var options = GetMetadataOptions(referenceItem); @@ -786,11 +777,11 @@ namespace MediaBrowser.Providers.Manager if (string.IsNullOrWhiteSpace(searchInfo.SearchInfo.MetadataLanguage)) { - searchInfo.SearchInfo.MetadataLanguage = ConfigurationManager.Configuration.PreferredMetadataLanguage; + searchInfo.SearchInfo.MetadataLanguage = _configurationManager.Configuration.PreferredMetadataLanguage; } if (string.IsNullOrWhiteSpace(searchInfo.SearchInfo.MetadataCountryCode)) { - searchInfo.SearchInfo.MetadataCountryCode = ConfigurationManager.Configuration.MetadataCountryCode; + searchInfo.SearchInfo.MetadataCountryCode = _configurationManager.Configuration.MetadataCountryCode; } var resultList = new List(); @@ -1010,7 +1001,7 @@ namespace MediaBrowser.Providers.Manager private async Task StartProcessingRefreshQueue() { - var libraryManager = _libraryManagerFactory(); + var libraryManager = _libraryManager; if (_disposed) { @@ -1088,7 +1079,7 @@ namespace MediaBrowser.Providers.Manager private async Task RefreshArtist(MusicArtist item, MetadataRefreshOptions options, CancellationToken cancellationToken) { - var albums = _libraryManagerFactory() + var albums = _libraryManager .GetItemList(new InternalItemsQuery { IncludeItemTypes = new[] { nameof(MusicAlbum) }, From 0ce82ab33288727fcbb400d72db62df440ef104d Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 15:05:50 -0400 Subject: [PATCH 19/83] Remove unnecessary fields in ApplicationHost --- .../ApplicationHost.cs | 21 ++++++++----------- Jellyfin.Server/Program.cs | 1 - 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 8a3398e01..81736f053 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -120,9 +120,7 @@ namespace Emby.Server.Implementations { private SqliteUserRepository _userRepository; private SqliteDisplayPreferencesRepository _displayPreferencesRepository; - private IChannelManager _channelManager; private ISessionManager _sessionManager; - private ILiveTvManager _liveTvManager; private INotificationManager _notificationManager; private IHttpServer _httpServer; @@ -803,10 +801,7 @@ namespace Emby.Server.Implementations /// public void InitializeServices() { - _channelManager = Resolve(); _sessionManager = Resolve(); - _liveTvManager = Resolve(); - _notificationManager = Resolve(); _httpServer = Resolve(); ((ActivityRepository)Resolve()).Initialize(); @@ -821,6 +816,8 @@ namespace Emby.Server.Implementations ((UserDataManager)UserDataManager).Repository = userDataRepo; ItemRepository.Initialize(userDataRepo, UserManager); ((LibraryManager)LibraryManager).ItemRepository = ItemRepository; + + FindParts(); } public static void LogEnvironmentInfo(ILogger logger, IApplicationPaths appPaths) @@ -930,8 +927,8 @@ namespace Emby.Server.Implementations User.UserManager = UserManager; BaseItem.FileSystem = FileSystemManager; BaseItem.UserDataManager = UserDataManager; - BaseItem.ChannelManager = _channelManager; - Video.LiveTvManager = _liveTvManager; + BaseItem.ChannelManager = Resolve(); + Video.LiveTvManager = Resolve(); Folder.UserViewManager = Resolve(); UserView.TVSeriesManager = TVSeriesManager; UserView.CollectionManager = Resolve(); @@ -978,9 +975,9 @@ namespace Emby.Server.Implementations } /// - /// Finds the parts. + /// Finds plugin components and register them with the appropriate services. /// - public void FindParts() + private void FindParts() { InstallationManager = ServiceProvider.GetService(); InstallationManager.PluginInstalled += PluginInstalled; @@ -1013,15 +1010,15 @@ namespace Emby.Server.Implementations GetExports(), GetExports()); - _liveTvManager.AddParts(GetExports(), GetExports(), GetExports()); + Resolve().AddParts(GetExports(), GetExports(), GetExports()); SubtitleManager.AddParts(GetExports()); - _channelManager.AddParts(GetExports()); + Resolve().AddParts(GetExports()); MediaSourceManager.AddParts(GetExports()); - _notificationManager.AddParts(GetExports(), GetExports()); + Resolve().AddParts(GetExports(), GetExports()); UserManager.AddParts(GetExports(), GetExports()); IsoManager.AddParts(GetExports()); diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 4abdd59aa..6be9ba4f2 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -210,7 +210,6 @@ namespace Jellyfin.Server // Re-use the web host service provider in the app host since ASP.NET doesn't allow a custom service collection. appHost.ServiceProvider = webHost.Services; appHost.InitializeServices(); - appHost.FindParts(); Migrations.MigrationRunner.Run(appHost, _loggerFactory); try From 3d8b81039d0f735a893fde8e0bef4bdfefd2db8a Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 15:08:04 -0400 Subject: [PATCH 20/83] Log refresh progress at Debug level --- MediaBrowser.Providers/Manager/ProviderManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 337bc37eb..cfff89767 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -958,7 +958,7 @@ namespace MediaBrowser.Providers.Manager public void OnRefreshProgress(BaseItem item, double progress) { var id = item.Id; - _logger.LogInformation("OnRefreshProgress {0} {1}", id.ToString("N", CultureInfo.InvariantCulture), progress); + _logger.LogDebug("OnRefreshProgress {0} {1}", id.ToString("N", CultureInfo.InvariantCulture), progress); // TODO: Need to hunt down the conditions for this happening _activeRefreshes.AddOrUpdate( From dd5a55aeba0ad90c277d0acb243558e3a37d2506 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 15:12:02 -0400 Subject: [PATCH 21/83] Register ISubtitleManager correctly --- Emby.Server.Implementations/ApplicationHost.cs | 10 ++-------- MediaBrowser.Providers/Subtitles/SubtitleManager.cs | 8 ++++---- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 81736f053..6db832b79 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -121,7 +121,6 @@ namespace Emby.Server.Implementations private SqliteUserRepository _userRepository; private SqliteDisplayPreferencesRepository _displayPreferencesRepository; private ISessionManager _sessionManager; - private INotificationManager _notificationManager; private IHttpServer _httpServer; /// @@ -283,10 +282,6 @@ namespace Emby.Server.Implementations internal SqliteItemRepository ItemRepository { get; set; } - - - private ISubtitleManager SubtitleManager { get; set; } - private IDeviceManager DeviceManager { get; set; } private IAuthenticationRepository AuthenticationRepository { get; set; } @@ -748,8 +743,7 @@ namespace Emby.Server.Implementations MediaSourceManager = new MediaSourceManager(ItemRepository, ApplicationPaths, LocalizationManager, UserManager, LibraryManager, LoggerFactory, JsonSerializer, FileSystemManager, UserDataManager, () => MediaEncoder); serviceCollection.AddSingleton(MediaSourceManager); - SubtitleManager = new SubtitleManager(LoggerFactory, FileSystemManager, LibraryMonitor, MediaSourceManager, LocalizationManager); - serviceCollection.AddSingleton(SubtitleManager); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); @@ -1012,7 +1006,7 @@ namespace Emby.Server.Implementations Resolve().AddParts(GetExports(), GetExports(), GetExports()); - SubtitleManager.AddParts(GetExports()); + Resolve().AddParts(GetExports()); Resolve().AddParts(GetExports()); diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs index 583c7e8ea..127d29c04 100644 --- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs +++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs @@ -25,22 +25,22 @@ namespace MediaBrowser.Providers.Subtitles { public class SubtitleManager : ISubtitleManager { - private ISubtitleProvider[] _subtitleProviders; private readonly ILogger _logger; private readonly IFileSystem _fileSystem; private readonly ILibraryMonitor _monitor; private readonly IMediaSourceManager _mediaSourceManager; + private readonly ILocalizationManager _localization; - private ILocalizationManager _localization; + private ISubtitleProvider[] _subtitleProviders; public SubtitleManager( - ILoggerFactory loggerFactory, + ILogger logger, IFileSystem fileSystem, ILibraryMonitor monitor, IMediaSourceManager mediaSourceManager, ILocalizationManager localizationManager) { - _logger = loggerFactory.CreateLogger(nameof(SubtitleManager)); + _logger = logger; _fileSystem = fileSystem; _monitor = monitor; _mediaSourceManager = mediaSourceManager; From 573da63d41e47af7cdd54cb1f5017b0317a6ba64 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 15:28:21 -0400 Subject: [PATCH 22/83] Register and construct IMediaSourceManager correctly --- .../ApplicationHost.cs | 11 ++++------ .../Library/MediaSourceManager.cs | 22 +++++++++---------- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 6db832b79..0f1b24bbc 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -288,8 +288,6 @@ namespace Emby.Server.Implementations private ITVSeriesManager TVSeriesManager { get; set; } - private IMediaSourceManager MediaSourceManager { get; set; } - /// /// Gets the installation manager. /// @@ -740,14 +738,13 @@ namespace Emby.Server.Implementations DeviceManager = new DeviceManager(AuthenticationRepository, JsonSerializer, LibraryManager, LocalizationManager, UserManager, FileSystemManager, LibraryMonitor, ServerConfigurationManager); serviceCollection.AddSingleton(DeviceManager); - MediaSourceManager = new MediaSourceManager(ItemRepository, ApplicationPaths, LocalizationManager, UserManager, LibraryManager, LoggerFactory, JsonSerializer, FileSystemManager, UserDataManager, () => MediaEncoder); - serviceCollection.AddSingleton(MediaSourceManager); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); - // TODO: Refactor to eliminate circular dependency here so Lazy<> isn't required + // TODO: Refactor to eliminate the circular dependency here so that Lazy isn't required serviceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); serviceCollection.AddSingleton(); @@ -926,7 +923,7 @@ namespace Emby.Server.Implementations Folder.UserViewManager = Resolve(); UserView.TVSeriesManager = TVSeriesManager; UserView.CollectionManager = Resolve(); - BaseItem.MediaSourceManager = MediaSourceManager; + BaseItem.MediaSourceManager = Resolve(); CollectionFolder.XmlSerializer = XmlSerializer; CollectionFolder.JsonSerializer = JsonSerializer; CollectionFolder.ApplicationHost = this; @@ -1010,7 +1007,7 @@ namespace Emby.Server.Implementations Resolve().AddParts(GetExports()); - MediaSourceManager.AddParts(GetExports()); + Resolve().AddParts(GetExports()); Resolve().AddParts(GetExports(), GetExports()); UserManager.AddParts(GetExports(), GetExports()); diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index 70d5bd9f4..01fe98f3a 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -33,13 +33,13 @@ namespace Emby.Server.Implementations.Library private readonly ILibraryManager _libraryManager; private readonly IJsonSerializer _jsonSerializer; private readonly IFileSystem _fileSystem; - - private IMediaSourceProvider[] _providers; private readonly ILogger _logger; private readonly IUserDataManager _userDataManager; - private readonly Func _mediaEncoder; - private ILocalizationManager _localizationManager; - private IApplicationPaths _appPaths; + private readonly IMediaEncoder _mediaEncoder; + private readonly ILocalizationManager _localizationManager; + private readonly IApplicationPaths _appPaths; + + private IMediaSourceProvider[] _providers; public MediaSourceManager( IItemRepository itemRepo, @@ -47,16 +47,16 @@ namespace Emby.Server.Implementations.Library ILocalizationManager localizationManager, IUserManager userManager, ILibraryManager libraryManager, - ILoggerFactory loggerFactory, + ILogger logger, IJsonSerializer jsonSerializer, IFileSystem fileSystem, IUserDataManager userDataManager, - Func mediaEncoder) + IMediaEncoder mediaEncoder) { _itemRepo = itemRepo; _userManager = userManager; _libraryManager = libraryManager; - _logger = loggerFactory.CreateLogger(nameof(MediaSourceManager)); + _logger = logger; _jsonSerializer = jsonSerializer; _fileSystem = fileSystem; _userDataManager = userDataManager; @@ -496,7 +496,7 @@ namespace Emby.Server.Implementations.Library // hack - these two values were taken from LiveTVMediaSourceProvider string cacheKey = request.OpenToken; - await new LiveStreamHelper(_mediaEncoder(), _logger, _jsonSerializer, _appPaths) + await new LiveStreamHelper(_mediaEncoder, _logger, _jsonSerializer, _appPaths) .AddMediaInfoWithProbe(mediaSource, isAudio, cacheKey, true, cancellationToken) .ConfigureAwait(false); } @@ -621,7 +621,7 @@ namespace Emby.Server.Implementations.Library if (liveStreamInfo is IDirectStreamProvider) { - var info = await _mediaEncoder().GetMediaInfo(new MediaInfoRequest + var info = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest { MediaSource = mediaSource, ExtractChapters = false, @@ -674,7 +674,7 @@ namespace Emby.Server.Implementations.Library mediaSource.AnalyzeDurationMs = 3000; } - mediaInfo = await _mediaEncoder().GetMediaInfo(new MediaInfoRequest + mediaInfo = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest { MediaSource = mediaSource, MediaType = isAudio ? DlnaProfileType.Audio : DlnaProfileType.Video, From 7b31b0e322332690fa9bda7d16a5f9a0cdeffa8d Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 15:33:23 -0400 Subject: [PATCH 23/83] Inject logger correctly into ActivityManager and ActivityRepository --- Emby.Server.Implementations/Activity/ActivityManager.cs | 4 ++-- Emby.Server.Implementations/Activity/ActivityRepository.cs | 4 ++-- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Emby.Server.Implementations/Activity/ActivityManager.cs b/Emby.Server.Implementations/Activity/ActivityManager.cs index ee10845cf..34ccd4bba 100644 --- a/Emby.Server.Implementations/Activity/ActivityManager.cs +++ b/Emby.Server.Implementations/Activity/ActivityManager.cs @@ -18,11 +18,11 @@ namespace Emby.Server.Implementations.Activity private readonly IUserManager _userManager; public ActivityManager( - ILoggerFactory loggerFactory, + ILogger logger, IActivityRepository repo, IUserManager userManager) { - _logger = loggerFactory.CreateLogger(nameof(ActivityManager)); + _logger = logger; _repo = repo; _userManager = userManager; } diff --git a/Emby.Server.Implementations/Activity/ActivityRepository.cs b/Emby.Server.Implementations/Activity/ActivityRepository.cs index 7be72319e..0fd262521 100644 --- a/Emby.Server.Implementations/Activity/ActivityRepository.cs +++ b/Emby.Server.Implementations/Activity/ActivityRepository.cs @@ -20,8 +20,8 @@ namespace Emby.Server.Implementations.Activity private static readonly CultureInfo _usCulture = CultureInfo.ReadOnly(new CultureInfo("en-US")); private readonly IFileSystem _fileSystem; - public ActivityRepository(ILoggerFactory loggerFactory, IServerApplicationPaths appPaths, IFileSystem fileSystem) - : base(loggerFactory.CreateLogger(nameof(ActivityRepository))) + public ActivityRepository(ILogger logger, IServerApplicationPaths appPaths, IFileSystem fileSystem) + : base(logger) { DbFilePath = Path.Combine(appPaths.DataPath, "activitylog.db"); _fileSystem = fileSystem; diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index ce576a6c3..42379c73b 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -471,7 +471,7 @@ namespace MediaBrowser.Controller.MediaEncoding { var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, encodingOptions); var outputVideoCodec = GetVideoEncoder(state, encodingOptions); - + var hasTextSubs = state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode; if (!hasTextSubs) From 71c84905de8f1c303c991b240d22a2f9616965e8 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 15:40:06 -0400 Subject: [PATCH 24/83] Register IDeviceManager correctly --- Emby.Server.Implementations/ApplicationHost.cs | 5 +---- Emby.Server.Implementations/Devices/DeviceManager.cs | 6 +++--- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 0f1b24bbc..9d4964a9e 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -282,8 +282,6 @@ namespace Emby.Server.Implementations internal SqliteItemRepository ItemRepository { get; set; } - private IDeviceManager DeviceManager { get; set; } - private IAuthenticationRepository AuthenticationRepository { get; set; } private ITVSeriesManager TVSeriesManager { get; set; } @@ -735,8 +733,7 @@ namespace Emby.Server.Implementations TVSeriesManager = new TVSeriesManager(UserManager, UserDataManager, LibraryManager, ServerConfigurationManager); serviceCollection.AddSingleton(TVSeriesManager); - DeviceManager = new DeviceManager(AuthenticationRepository, JsonSerializer, LibraryManager, LocalizationManager, UserManager, FileSystemManager, LibraryMonitor, ServerConfigurationManager); - serviceCollection.AddSingleton(DeviceManager); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); diff --git a/Emby.Server.Implementations/Devices/DeviceManager.cs b/Emby.Server.Implementations/Devices/DeviceManager.cs index adb8e793d..579cb895e 100644 --- a/Emby.Server.Implementations/Devices/DeviceManager.cs +++ b/Emby.Server.Implementations/Devices/DeviceManager.cs @@ -38,10 +38,11 @@ namespace Emby.Server.Implementations.Devices private readonly IServerConfigurationManager _config; private readonly ILibraryManager _libraryManager; private readonly ILocalizationManager _localizationManager; - private readonly IAuthenticationRepository _authRepo; + private readonly Dictionary _capabilitiesCache; public event EventHandler>> DeviceOptionsUpdated; + public event EventHandler> CameraImageUploaded; private readonly object _cameraUploadSyncLock = new object(); @@ -65,10 +66,9 @@ namespace Emby.Server.Implementations.Devices _libraryManager = libraryManager; _localizationManager = localizationManager; _authRepo = authRepo; + _capabilitiesCache = new Dictionary(StringComparer.OrdinalIgnoreCase); } - - private Dictionary _capabilitiesCache = new Dictionary(StringComparer.OrdinalIgnoreCase); public void SaveCapabilities(string deviceId, ClientCapabilities capabilities) { var path = Path.Combine(GetDevicePath(deviceId), "capabilities.json"); From 11693d6024f4b8dafb69ac4a4fcb85ee2caad065 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 15:44:44 -0400 Subject: [PATCH 25/83] Register ITvManagerService correctly --- Emby.Server.Implementations/ApplicationHost.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 9d4964a9e..c5b8878f8 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -272,8 +272,6 @@ namespace Emby.Server.Implementations public LocalizationManager LocalizationManager { get; set; } - - /// /// Gets or sets the user data repository. /// @@ -284,8 +282,6 @@ namespace Emby.Server.Implementations private IAuthenticationRepository AuthenticationRepository { get; set; } - private ITVSeriesManager TVSeriesManager { get; set; } - /// /// Gets the installation manager. /// @@ -730,8 +726,7 @@ namespace Emby.Server.Implementations ImageProcessor = new ImageProcessor(LoggerFactory.CreateLogger(), ServerConfigurationManager.ApplicationPaths, FileSystemManager, ImageEncoder, () => LibraryManager, () => MediaEncoder); serviceCollection.AddSingleton(ImageProcessor); - TVSeriesManager = new TVSeriesManager(UserManager, UserDataManager, LibraryManager, ServerConfigurationManager); - serviceCollection.AddSingleton(TVSeriesManager); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); @@ -918,7 +913,7 @@ namespace Emby.Server.Implementations BaseItem.ChannelManager = Resolve(); Video.LiveTvManager = Resolve(); Folder.UserViewManager = Resolve(); - UserView.TVSeriesManager = TVSeriesManager; + UserView.TVSeriesManager = Resolve(); UserView.CollectionManager = Resolve(); BaseItem.MediaSourceManager = Resolve(); CollectionFolder.XmlSerializer = XmlSerializer; From efe3ebaab8fbb064652ac4923297f315e4a798e7 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 16:01:10 -0400 Subject: [PATCH 26/83] Eliminate circular dependency between LibraryManager and ImageProcessor --- Emby.Drawing/ImageProcessor.cs | 25 ------------------- Emby.Photos/PhotoProvider.cs | 2 +- .../ApplicationHost.cs | 2 +- MediaBrowser.Api/Images/ImageService.cs | 9 ++++++- .../Drawing/IImageProcessor.cs | 9 ------- 5 files changed, 10 insertions(+), 37 deletions(-) diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index eca4b56eb..a9cab147c 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -33,7 +33,6 @@ namespace Emby.Drawing private readonly IFileSystem _fileSystem; private readonly IServerApplicationPaths _appPaths; private readonly IImageEncoder _imageEncoder; - private readonly Func _libraryManager; private readonly Func _mediaEncoder; private bool _disposed = false; @@ -45,20 +44,17 @@ namespace Emby.Drawing /// The server application paths. /// The filesystem. /// The image encoder. - /// The library manager. /// The media encoder. public ImageProcessor( ILogger logger, IServerApplicationPaths appPaths, IFileSystem fileSystem, IImageEncoder imageEncoder, - Func libraryManager, Func mediaEncoder) { _logger = logger; _fileSystem = fileSystem; _imageEncoder = imageEncoder; - _libraryManager = libraryManager; _mediaEncoder = mediaEncoder; _appPaths = appPaths; } @@ -126,21 +122,9 @@ namespace Emby.Drawing throw new ArgumentNullException(nameof(options)); } - var libraryManager = _libraryManager(); - ItemImageInfo originalImage = options.Image; BaseItem item = options.Item; - if (!originalImage.IsLocalFile) - { - if (item == null) - { - item = libraryManager.GetItemById(options.ItemId); - } - - originalImage = await libraryManager.ConvertImageToLocal(item, originalImage, options.ImageIndex).ConfigureAwait(false); - } - string originalImagePath = originalImage.Path; DateTime dateModified = originalImage.DateModified; ImageDimensions? originalImageSize = null; @@ -312,10 +296,6 @@ namespace Emby.Drawing /// public ImageDimensions GetImageDimensions(BaseItem item, ItemImageInfo info) - => GetImageDimensions(item, info, true); - - /// - public ImageDimensions GetImageDimensions(BaseItem item, ItemImageInfo info, bool updateItem) { int width = info.Width; int height = info.Height; @@ -332,11 +312,6 @@ namespace Emby.Drawing info.Width = size.Width; info.Height = size.Height; - if (updateItem) - { - _libraryManager().UpdateImages(item); - } - return size; } diff --git a/Emby.Photos/PhotoProvider.cs b/Emby.Photos/PhotoProvider.cs index 63631e512..987cb7fb2 100644 --- a/Emby.Photos/PhotoProvider.cs +++ b/Emby.Photos/PhotoProvider.cs @@ -160,7 +160,7 @@ namespace Emby.Photos try { - var size = _imageProcessor.GetImageDimensions(item, img, false); + var size = _imageProcessor.GetImageDimensions(item, img); if (size.Width > 0 && size.Height > 0) { diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index c5b8878f8..a6ad005e0 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -723,7 +723,7 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); - ImageProcessor = new ImageProcessor(LoggerFactory.CreateLogger(), ServerConfigurationManager.ApplicationPaths, FileSystemManager, ImageEncoder, () => LibraryManager, () => MediaEncoder); + ImageProcessor = new ImageProcessor(LoggerFactory.CreateLogger(), ServerConfigurationManager.ApplicationPaths, FileSystemManager, ImageEncoder, () => MediaEncoder); serviceCollection.AddSingleton(ImageProcessor); serviceCollection.AddSingleton(); diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs index af455987b..c11e0c1b7 100644 --- a/MediaBrowser.Api/Images/ImageService.cs +++ b/MediaBrowser.Api/Images/ImageService.cs @@ -332,7 +332,8 @@ namespace MediaBrowser.Api.Images var fileInfo = _fileSystem.GetFileInfo(info.Path); length = fileInfo.Length; - ImageDimensions size = _imageProcessor.GetImageDimensions(item, info, true); + ImageDimensions size = _imageProcessor.GetImageDimensions(item, info); + _libraryManager.UpdateImages(item); width = size.Width; height = size.Height; @@ -606,6 +607,12 @@ namespace MediaBrowser.Api.Images IDictionary headers, bool isHeadRequest) { + if (!image.IsLocalFile) + { + item ??= _libraryManager.GetItemById(itemId); + image = await _libraryManager.ConvertImageToLocal(item, image, request.Index ?? 0).ConfigureAwait(false); + } + var options = new ImageProcessingOptions { CropWhiteSpace = cropwhitespace, diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs index 79399807f..36c746624 100644 --- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs +++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs @@ -40,15 +40,6 @@ namespace MediaBrowser.Controller.Drawing /// ImageDimensions ImageDimensions GetImageDimensions(BaseItem item, ItemImageInfo info); - /// - /// Gets the dimensions of the image. - /// - /// The base item. - /// The information. - /// Whether or not the item info should be updated. - /// ImageDimensions - ImageDimensions GetImageDimensions(BaseItem item, ItemImageInfo info, bool updateItem); - /// /// Gets the image cache tag. /// From 07cebbeae2bbbe63f0f97428e73e419220ab5804 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 17:12:24 -0400 Subject: [PATCH 27/83] Register and construct IImageProcessor, SqliteItemRepository and IImageEncoder correctly --- Emby.Drawing/ImageProcessor.cs | 8 ++--- .../ApplicationHost.cs | 33 ++++++++----------- .../Data/SqliteItemRepository.cs | 13 ++++---- .../Emby.Server.Implementations.csproj | 1 + Jellyfin.Drawing.Skia/SkiaEncoder.cs | 17 +++++++--- Jellyfin.Server/CoreAppHost.cs | 3 -- Jellyfin.Server/Program.cs | 20 ----------- 7 files changed, 38 insertions(+), 57 deletions(-) diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index a9cab147c..903b958a4 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -33,7 +33,7 @@ namespace Emby.Drawing private readonly IFileSystem _fileSystem; private readonly IServerApplicationPaths _appPaths; private readonly IImageEncoder _imageEncoder; - private readonly Func _mediaEncoder; + private readonly IMediaEncoder _mediaEncoder; private bool _disposed = false; @@ -50,7 +50,7 @@ namespace Emby.Drawing IServerApplicationPaths appPaths, IFileSystem fileSystem, IImageEncoder imageEncoder, - Func mediaEncoder) + IMediaEncoder mediaEncoder) { _logger = logger; _fileSystem = fileSystem; @@ -359,13 +359,13 @@ namespace Emby.Drawing { string filename = (originalImagePath + dateModified.Ticks.ToString(CultureInfo.InvariantCulture)).GetMD5().ToString("N", CultureInfo.InvariantCulture); - string cacheExtension = _mediaEncoder().SupportsEncoder("libwebp") ? ".webp" : ".png"; + string cacheExtension = _mediaEncoder.SupportsEncoder("libwebp") ? ".webp" : ".png"; var outputPath = Path.Combine(_appPaths.ImageCachePath, "converted-images", filename + cacheExtension); var file = _fileSystem.GetFileInfo(outputPath); if (!file.Exists) { - await _mediaEncoder().ConvertImage(originalImagePath, outputPath).ConfigureAwait(false); + await _mediaEncoder.ConvertImage(originalImagePath, outputPath).ConfigureAwait(false); dateModified = _fileSystem.GetLastWriteTimeUtc(outputPath); } else diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index a6ad005e0..ff4fb54b5 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -48,6 +48,7 @@ using Emby.Server.Implementations.Session; using Emby.Server.Implementations.SocketSharp; using Emby.Server.Implementations.TV; using Emby.Server.Implementations.Updates; +using Jellyfin.Drawing.Skia; using MediaBrowser.Api; using MediaBrowser.Common; using MediaBrowser.Common.Configuration; @@ -262,8 +263,6 @@ namespace Emby.Server.Implementations /// The directory watchers. private ILibraryMonitor LibraryMonitor { get; set; } - public IImageProcessor ImageProcessor { get; set; } - /// /// Gets or sets the media encoder. /// @@ -278,8 +277,6 @@ namespace Emby.Server.Implementations /// The user data repository. private IUserDataManager UserDataManager { get; set; } - internal SqliteItemRepository ItemRepository { get; set; } - private IAuthenticationRepository AuthenticationRepository { get; set; } /// @@ -290,8 +287,6 @@ namespace Emby.Server.Implementations public IStartupOptions StartupOptions { get; } - internal IImageEncoder ImageEncoder { get; private set; } - protected IProcessFactory ProcessFactory { get; private set; } protected readonly IXmlSerializer XmlSerializer; @@ -316,7 +311,6 @@ namespace Emby.Server.Implementations ILoggerFactory loggerFactory, IStartupOptions options, IFileSystem fileSystem, - IImageEncoder imageEncoder, INetworkManager networkManager) { XmlSerializer = new MyXmlSerializer(); @@ -334,8 +328,6 @@ namespace Emby.Server.Implementations StartupOptions = options; - ImageEncoder = imageEncoder; - fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem)); NetworkManager.NetworkChanged += OnNetworkChanged; @@ -603,6 +595,11 @@ namespace Emby.Server.Implementations /// protected async Task RegisterServices(IServiceCollection serviceCollection, IConfiguration startupConfig) { + var imageEncoderType = SkiaEncoder.IsNativeLibAvailable() + ? typeof(SkiaEncoder) + : typeof(NullImageEncoder); + serviceCollection.AddSingleton(typeof(IImageEncoder), imageEncoderType); + serviceCollection.AddMemoryCache(); serviceCollection.AddSingleton(ConfigurationManager); @@ -672,8 +669,7 @@ namespace Emby.Server.Implementations FileSystemManager); serviceCollection.AddSingleton(_displayPreferencesRepository); - ItemRepository = new SqliteItemRepository(ServerConfigurationManager, this, LoggerFactory.CreateLogger(), LocalizationManager); - serviceCollection.AddSingleton(ItemRepository); + serviceCollection.AddSingleton(); AuthenticationRepository = GetAuthenticationRepository(); serviceCollection.AddSingleton(AuthenticationRepository); @@ -685,7 +681,7 @@ namespace Emby.Server.Implementations _userRepository, XmlSerializer, NetworkManager, - () => ImageProcessor, + Resolve, Resolve, this, JsonSerializer, @@ -723,8 +719,7 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); - ImageProcessor = new ImageProcessor(LoggerFactory.CreateLogger(), ServerConfigurationManager.ApplicationPaths, FileSystemManager, ImageEncoder, () => MediaEncoder); - serviceCollection.AddSingleton(ImageProcessor); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); @@ -797,8 +792,10 @@ namespace Emby.Server.Implementations ((UserManager)UserManager).Initialize(); ((UserDataManager)UserDataManager).Repository = userDataRepo; - ItemRepository.Initialize(userDataRepo, UserManager); - ((LibraryManager)LibraryManager).ItemRepository = ItemRepository; + + var itemRepo = (SqliteItemRepository)Resolve(); + itemRepo.Initialize(userDataRepo, UserManager); + ((LibraryManager)LibraryManager).ItemRepository = itemRepo; FindParts(); } @@ -898,15 +895,13 @@ namespace Emby.Server.Implementations /// private void SetStaticProperties() { - ItemRepository.ImageProcessor = ImageProcessor; - // For now there's no real way to inject these properly BaseItem.Logger = LoggerFactory.CreateLogger("BaseItem"); BaseItem.ConfigurationManager = ServerConfigurationManager; BaseItem.LibraryManager = LibraryManager; BaseItem.ProviderManager = Resolve(); BaseItem.LocalizationManager = LocalizationManager; - BaseItem.ItemRepository = ItemRepository; + BaseItem.ItemRepository = Resolve(); User.UserManager = UserManager; BaseItem.FileSystem = FileSystemManager; BaseItem.UserDataManager = UserDataManager; diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index e3242f7b4..227f1a5e7 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -39,12 +39,11 @@ namespace Emby.Server.Implementations.Data { private const string ChaptersTableName = "Chapters2"; - /// - /// The _app paths - /// private readonly IServerConfigurationManager _config; private readonly IServerApplicationHost _appHost; private readonly ILocalizationManager _localization; + // TODO: Remove this dependency + private readonly IImageProcessor _imageProcessor; private readonly TypeMapper _typeMapper; private readonly JsonSerializerOptions _jsonOptions; @@ -71,7 +70,8 @@ namespace Emby.Server.Implementations.Data IServerConfigurationManager config, IServerApplicationHost appHost, ILogger logger, - ILocalizationManager localization) + ILocalizationManager localization, + IImageProcessor imageProcessor) : base(logger) { if (config == null) @@ -82,6 +82,7 @@ namespace Emby.Server.Implementations.Data _config = config; _appHost = appHost; _localization = localization; + _imageProcessor = imageProcessor; _typeMapper = new TypeMapper(); _jsonOptions = JsonDefaults.GetOptions(); @@ -98,8 +99,6 @@ namespace Emby.Server.Implementations.Data /// protected override TempStoreMode TempStore => TempStoreMode.Memory; - public IImageProcessor ImageProcessor { get; set; } - /// /// Opens the connection to the database /// @@ -1991,7 +1990,7 @@ namespace Emby.Server.Implementations.Data if (!string.IsNullOrEmpty(chapter.ImagePath)) { - chapter.ImageTag = ImageProcessor.GetImageCacheTag(item, chapter); + chapter.ImageTag = _imageProcessor.GetImageCacheTag(item, chapter); } } diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index d302d8984..6c20842c7 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -4,6 +4,7 @@ + diff --git a/Jellyfin.Drawing.Skia/SkiaEncoder.cs b/Jellyfin.Drawing.Skia/SkiaEncoder.cs index a67118f18..97717e626 100644 --- a/Jellyfin.Drawing.Skia/SkiaEncoder.cs +++ b/Jellyfin.Drawing.Skia/SkiaEncoder.cs @@ -78,12 +78,21 @@ namespace Jellyfin.Drawing.Skia => new HashSet() { ImageFormat.Webp, ImageFormat.Jpg, ImageFormat.Png }; /// - /// Test to determine if the native lib is available. + /// Check if the native lib is available. /// - public static void TestSkia() + /// True if the native lib is available, otherwise false. + public static bool IsNativeLibAvailable() { - // test an operation that requires the native library - SKPMColor.PreMultiply(SKColors.Black); + try + { + // test an operation that requires the native library + SKPMColor.PreMultiply(SKColors.Black); + return true; + } + catch (Exception) + { + return false; + } } private static bool IsTransparent(SKColor color) diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index 1d5313c13..b35200e75 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -20,21 +20,18 @@ namespace Jellyfin.Server /// The to be used by the . /// The to be used by the . /// The to be used by the . - /// The to be used by the . /// The to be used by the . public CoreAppHost( ServerApplicationPaths applicationPaths, ILoggerFactory loggerFactory, StartupOptions options, IFileSystem fileSystem, - IImageEncoder imageEncoder, INetworkManager networkManager) : base( applicationPaths, loggerFactory, options, fileSystem, - imageEncoder, networkManager) { } diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 6be9ba4f2..5e9c15e20 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -183,7 +183,6 @@ namespace Jellyfin.Server _loggerFactory, options, new ManagedFileSystem(_loggerFactory.CreateLogger(), appPaths), - GetImageEncoder(appPaths), new NetworkManager(_loggerFactory.CreateLogger())); try @@ -553,25 +552,6 @@ namespace Jellyfin.Server } } - private static IImageEncoder GetImageEncoder(IApplicationPaths appPaths) - { - try - { - // Test if the native lib is available - SkiaEncoder.TestSkia(); - - return new SkiaEncoder( - _loggerFactory.CreateLogger(), - appPaths); - } - catch (Exception ex) - { - _logger.LogWarning(ex, $"Skia not available. Will fallback to {nameof(NullImageEncoder)}."); - } - - return new NullImageEncoder(); - } - private static void StartNewInstance(StartupOptions options) { _logger.LogInformation("Starting new instance"); From d173358065c65710476b225168bd8a348d99cf11 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 17:19:16 -0400 Subject: [PATCH 28/83] Move ApplicationHost certificate initialization to constructor --- .../ApplicationHost.cs | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index ff4fb54b5..57ec71c9d 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -331,6 +331,13 @@ namespace Emby.Server.Implementations fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem)); NetworkManager.NetworkChanged += OnNetworkChanged; + + CertificateInfo = new CertificateInfo + { + Path = ServerConfigurationManager.Configuration.CertificatePath, + Password = ServerConfigurationManager.Configuration.CertificatePassword + }; + Certificate = GetCertificate(CertificateInfo); } public string ExpandVirtualPath(string path) @@ -712,9 +719,6 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(new SearchEngine(LoggerFactory, LibraryManager, UserManager)); - CertificateInfo = GetCertificateInfo(true); - Certificate = GetCertificate(CertificateInfo); - serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); @@ -1106,16 +1110,6 @@ namespace Emby.Server.Implementations }); } - private CertificateInfo GetCertificateInfo(bool generateCertificate) - { - // Custom cert - return new CertificateInfo - { - Path = ServerConfigurationManager.Configuration.CertificatePath, - Password = ServerConfigurationManager.Configuration.CertificatePassword - }; - } - /// /// Called when [configuration updated]. /// @@ -1148,8 +1142,7 @@ namespace Emby.Server.Implementations } var currentCertPath = CertificateInfo?.Path; - var newCertInfo = GetCertificateInfo(false); - var newCertPath = newCertInfo?.Path; + var newCertPath = ServerConfigurationManager.Configuration.CertificatePath; if (!string.Equals(currentCertPath, newCertPath, StringComparison.OrdinalIgnoreCase)) { From c2b21ce5531a2b53fd0d0cc8231b4fd7d4261abe Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 17:33:00 -0400 Subject: [PATCH 29/83] Register and construct ILibraryMonitor correctly --- .../ApplicationHost.cs | 11 +--- .../IO/LibraryMonitor.cs | 58 +++++++++---------- 2 files changed, 28 insertions(+), 41 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 57ec71c9d..51c6f1342 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -257,12 +257,6 @@ namespace Emby.Server.Implementations /// The library manager. internal ILibraryManager LibraryManager { get; set; } - /// - /// Gets or sets the directory watchers. - /// - /// The directory watchers. - private ILibraryMonitor LibraryMonitor { get; set; } - /// /// Gets or sets the media encoder. /// @@ -708,14 +702,13 @@ namespace Emby.Server.Implementations StartupOptions.FFmpegPath); serviceCollection.AddSingleton(MediaEncoder); - LibraryManager = new LibraryManager(this, LoggerFactory, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, Resolve, Resolve, MediaEncoder); + LibraryManager = new LibraryManager(this, LoggerFactory, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, Resolve, FileSystemManager, Resolve, Resolve, MediaEncoder); serviceCollection.AddSingleton(LibraryManager); var musicManager = new MusicManager(LibraryManager); serviceCollection.AddSingleton(musicManager); - LibraryMonitor = new LibraryMonitor(LoggerFactory, LibraryManager, ServerConfigurationManager, FileSystemManager); - serviceCollection.AddSingleton(LibraryMonitor); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(new SearchEngine(LoggerFactory, LibraryManager, UserManager)); diff --git a/Emby.Server.Implementations/IO/LibraryMonitor.cs b/Emby.Server.Implementations/IO/LibraryMonitor.cs index b1fb8cc63..5a1eb43bc 100644 --- a/Emby.Server.Implementations/IO/LibraryMonitor.cs +++ b/Emby.Server.Implementations/IO/LibraryMonitor.cs @@ -17,6 +17,11 @@ namespace Emby.Server.Implementations.IO { public class LibraryMonitor : ILibraryMonitor { + private readonly ILogger _logger; + private readonly ILibraryManager _libraryManager; + private readonly IServerConfigurationManager _configurationManager; + private readonly IFileSystem _fileSystem; + /// /// The file system watchers. /// @@ -113,34 +118,23 @@ namespace Emby.Server.Implementations.IO } catch (Exception ex) { - Logger.LogError(ex, "Error in ReportFileSystemChanged for {path}", path); + _logger.LogError(ex, "Error in ReportFileSystemChanged for {path}", path); } } } - /// - /// Gets or sets the logger. - /// - /// The logger. - private ILogger Logger { get; set; } - - private ILibraryManager LibraryManager { get; set; } - private IServerConfigurationManager ConfigurationManager { get; set; } - - private readonly IFileSystem _fileSystem; - /// /// Initializes a new instance of the class. /// public LibraryMonitor( - ILoggerFactory loggerFactory, + ILogger logger, ILibraryManager libraryManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem) { - LibraryManager = libraryManager; - Logger = loggerFactory.CreateLogger(GetType().Name); - ConfigurationManager = configurationManager; + _libraryManager = libraryManager; + _logger = logger; + _configurationManager = configurationManager; _fileSystem = fileSystem; } @@ -151,7 +145,7 @@ namespace Emby.Server.Implementations.IO return false; } - var options = LibraryManager.GetLibraryOptions(item); + var options = _libraryManager.GetLibraryOptions(item); if (options != null) { @@ -163,12 +157,12 @@ namespace Emby.Server.Implementations.IO public void Start() { - LibraryManager.ItemAdded += OnLibraryManagerItemAdded; - LibraryManager.ItemRemoved += OnLibraryManagerItemRemoved; + _libraryManager.ItemAdded += OnLibraryManagerItemAdded; + _libraryManager.ItemRemoved += OnLibraryManagerItemRemoved; var pathsToWatch = new List(); - var paths = LibraryManager + var paths = _libraryManager .RootFolder .Children .Where(IsLibraryMonitorEnabled) @@ -261,7 +255,7 @@ namespace Emby.Server.Implementations.IO if (!Directory.Exists(path)) { // Seeing a crash in the mono runtime due to an exception being thrown on a different thread - Logger.LogInformation("Skipping realtime monitor for {Path} because the path does not exist", path); + _logger.LogInformation("Skipping realtime monitor for {Path} because the path does not exist", path); return; } @@ -297,7 +291,7 @@ namespace Emby.Server.Implementations.IO if (_fileSystemWatchers.TryAdd(path, newWatcher)) { newWatcher.EnableRaisingEvents = true; - Logger.LogInformation("Watching directory " + path); + _logger.LogInformation("Watching directory " + path); } else { @@ -307,7 +301,7 @@ namespace Emby.Server.Implementations.IO } catch (Exception ex) { - Logger.LogError(ex, "Error watching path: {path}", path); + _logger.LogError(ex, "Error watching path: {path}", path); } }); } @@ -333,7 +327,7 @@ namespace Emby.Server.Implementations.IO { using (watcher) { - Logger.LogInformation("Stopping directory watching for path {Path}", watcher.Path); + _logger.LogInformation("Stopping directory watching for path {Path}", watcher.Path); watcher.Created -= OnWatcherChanged; watcher.Deleted -= OnWatcherChanged; @@ -372,7 +366,7 @@ namespace Emby.Server.Implementations.IO var ex = e.GetException(); var dw = (FileSystemWatcher)sender; - Logger.LogError(ex, "Error in Directory watcher for: {Path}", dw.Path); + _logger.LogError(ex, "Error in Directory watcher for: {Path}", dw.Path); DisposeWatcher(dw, true); } @@ -390,7 +384,7 @@ namespace Emby.Server.Implementations.IO } catch (Exception ex) { - Logger.LogError(ex, "Exception in ReportFileSystemChanged. Path: {FullPath}", e.FullPath); + _logger.LogError(ex, "Exception in ReportFileSystemChanged. Path: {FullPath}", e.FullPath); } } @@ -416,13 +410,13 @@ namespace Emby.Server.Implementations.IO { if (_fileSystem.AreEqual(i, path)) { - Logger.LogDebug("Ignoring change to {Path}", path); + _logger.LogDebug("Ignoring change to {Path}", path); return true; } if (_fileSystem.ContainsSubPath(i, path)) { - Logger.LogDebug("Ignoring change to {Path}", path); + _logger.LogDebug("Ignoring change to {Path}", path); return true; } @@ -430,7 +424,7 @@ namespace Emby.Server.Implementations.IO var parent = Path.GetDirectoryName(i); if (!string.IsNullOrEmpty(parent) && _fileSystem.AreEqual(parent, path)) { - Logger.LogDebug("Ignoring change to {Path}", path); + _logger.LogDebug("Ignoring change to {Path}", path); return true; } @@ -485,7 +479,7 @@ namespace Emby.Server.Implementations.IO } } - var newRefresher = new FileRefresher(path, ConfigurationManager, LibraryManager, Logger); + var newRefresher = new FileRefresher(path, _configurationManager, _libraryManager, _logger); newRefresher.Completed += NewRefresher_Completed; _activeRefreshers.Add(newRefresher); } @@ -502,8 +496,8 @@ namespace Emby.Server.Implementations.IO /// public void Stop() { - LibraryManager.ItemAdded -= OnLibraryManagerItemAdded; - LibraryManager.ItemRemoved -= OnLibraryManagerItemRemoved; + _libraryManager.ItemAdded -= OnLibraryManagerItemAdded; + _libraryManager.ItemRemoved -= OnLibraryManagerItemRemoved; foreach (var watcher in _fileSystemWatchers.Values.ToList()) { From 7fd25f94f3432f1c9319e49f4d62454f45ad7515 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 18:22:29 -0400 Subject: [PATCH 30/83] Inject and construct ISearchEngine and IMusicManager correctly --- Emby.Server.Implementations/ApplicationHost.cs | 5 ++--- Emby.Server.Implementations/Library/SearchEngine.cs | 7 +++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 51c6f1342..ba149590f 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -705,12 +705,11 @@ namespace Emby.Server.Implementations LibraryManager = new LibraryManager(this, LoggerFactory, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, Resolve, FileSystemManager, Resolve, Resolve, MediaEncoder); serviceCollection.AddSingleton(LibraryManager); - var musicManager = new MusicManager(LibraryManager); - serviceCollection.AddSingleton(musicManager); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(new SearchEngine(LoggerFactory, LibraryManager, UserManager)); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); diff --git a/Emby.Server.Implementations/Library/SearchEngine.cs b/Emby.Server.Implementations/Library/SearchEngine.cs index 11d6c737a..59a77607d 100644 --- a/Emby.Server.Implementations/Library/SearchEngine.cs +++ b/Emby.Server.Implementations/Library/SearchEngine.cs @@ -17,16 +17,15 @@ namespace Emby.Server.Implementations.Library { public class SearchEngine : ISearchEngine { + private readonly ILogger _logger; private readonly ILibraryManager _libraryManager; private readonly IUserManager _userManager; - private readonly ILogger _logger; - public SearchEngine(ILoggerFactory loggerFactory, ILibraryManager libraryManager, IUserManager userManager) + public SearchEngine(ILogger logger, ILibraryManager libraryManager, IUserManager userManager) { + _logger = logger; _libraryManager = libraryManager; _userManager = userManager; - - _logger = loggerFactory.CreateLogger("SearchEngine"); } public QueryResult GetSearchHints(SearchQuery query) From fe9f4e06d1362eb6d0e7cc5e68d8819b872cb7bc Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 18:28:46 -0400 Subject: [PATCH 31/83] Register and construct LibraryManager correctly --- .../ApplicationHost.cs | 21 +- .../Library/LibraryManager.cs | 227 ++++++++---------- 2 files changed, 107 insertions(+), 141 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index ba149590f..aca1abf9f 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -251,12 +251,6 @@ namespace Emby.Server.Implementations /// The user manager. public IUserManager UserManager { get; set; } - /// - /// Gets or sets the library manager. - /// - /// The library manager. - internal ILibraryManager LibraryManager { get; set; } - /// /// Gets or sets the media encoder. /// @@ -702,8 +696,11 @@ namespace Emby.Server.Implementations StartupOptions.FFmpegPath); serviceCollection.AddSingleton(MediaEncoder); - LibraryManager = new LibraryManager(this, LoggerFactory, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, Resolve, FileSystemManager, Resolve, Resolve, MediaEncoder); - serviceCollection.AddSingleton(LibraryManager); + // TODO: Refactor to eliminate the circular dependencies here so that Lazy isn't required + serviceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); + serviceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); + serviceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); @@ -789,9 +786,7 @@ namespace Emby.Server.Implementations ((UserDataManager)UserDataManager).Repository = userDataRepo; - var itemRepo = (SqliteItemRepository)Resolve(); - itemRepo.Initialize(userDataRepo, UserManager); - ((LibraryManager)LibraryManager).ItemRepository = itemRepo; + ((SqliteItemRepository)Resolve()).Initialize(userDataRepo, UserManager); FindParts(); } @@ -894,7 +889,7 @@ namespace Emby.Server.Implementations // For now there's no real way to inject these properly BaseItem.Logger = LoggerFactory.CreateLogger("BaseItem"); BaseItem.ConfigurationManager = ServerConfigurationManager; - BaseItem.LibraryManager = LibraryManager; + BaseItem.LibraryManager = Resolve(); BaseItem.ProviderManager = Resolve(); BaseItem.LocalizationManager = LocalizationManager; BaseItem.ItemRepository = Resolve(); @@ -970,7 +965,7 @@ namespace Emby.Server.Implementations _httpServer.Init(GetExportTypes(), GetExports(), GetUrlPrefixes()); - LibraryManager.AddParts( + Resolve().AddParts( GetExports(), GetExports(), GetExports(), diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 8ec4d08be..e2985c26c 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -54,9 +54,29 @@ namespace Emby.Server.Implementations.Library /// public class LibraryManager : ILibraryManager { + private readonly ILogger _logger; + private readonly ITaskManager _taskManager; + private readonly IUserManager _userManager; + private readonly IUserDataManager _userDataRepository; + private readonly IServerConfigurationManager _configurationManager; + private readonly Lazy _libraryMonitorFactory; + private readonly Lazy _providerManagerFactory; + private readonly Lazy _userviewManagerFactory; + private readonly IServerApplicationHost _appHost; + private readonly IMediaEncoder _mediaEncoder; + private readonly IFileSystem _fileSystem; + private readonly IItemRepository _itemRepository; + private readonly ConcurrentDictionary _libraryItemsCache; + private NamingOptions _namingOptions; private string[] _videoFileExtensions; + private ILibraryMonitor LibraryMonitor => _libraryMonitorFactory.Value; + + private IProviderManager ProviderManager => _providerManagerFactory.Value; + + private IUserViewManager UserViewManager => _userviewManagerFactory.Value; + /// /// Gets or sets the postscan tasks. /// @@ -89,12 +109,6 @@ namespace Emby.Server.Implementations.Library /// The comparers. private IBaseItemComparer[] Comparers { get; set; } - /// - /// Gets or sets the active item repository - /// - /// The item repository. - public IItemRepository ItemRepository { get; set; } - /// /// Occurs when [item added]. /// @@ -110,90 +124,47 @@ namespace Emby.Server.Implementations.Library /// public event EventHandler ItemRemoved; - /// - /// The _logger - /// - private readonly ILogger _logger; - - /// - /// The _task manager - /// - private readonly ITaskManager _taskManager; - - /// - /// The _user manager - /// - private readonly IUserManager _userManager; - - /// - /// The _user data repository - /// - private readonly IUserDataManager _userDataRepository; - - /// - /// Gets or sets the configuration manager. - /// - /// The configuration manager. - private IServerConfigurationManager ConfigurationManager { get; set; } - - private readonly Func _libraryMonitorFactory; - private readonly Func _providerManagerFactory; - private readonly Func _userviewManager; public bool IsScanRunning { get; private set; } - private IServerApplicationHost _appHost; - private readonly IMediaEncoder _mediaEncoder; - - /// - /// The _library items cache - /// - private readonly ConcurrentDictionary _libraryItemsCache; - - /// - /// Gets the library items cache. - /// - /// The library items cache. - private ConcurrentDictionary LibraryItemsCache => _libraryItemsCache; - - private readonly IFileSystem _fileSystem; - /// /// Initializes a new instance of the class. /// /// The application host - /// The logger factory. + /// The logger. /// The task manager. /// The user manager. /// The configuration manager. /// The user data repository. public LibraryManager( IServerApplicationHost appHost, - ILoggerFactory loggerFactory, + ILogger logger, ITaskManager taskManager, IUserManager userManager, IServerConfigurationManager configurationManager, IUserDataManager userDataRepository, - Func libraryMonitorFactory, + Lazy libraryMonitorFactory, IFileSystem fileSystem, - Func providerManagerFactory, - Func userviewManager, - IMediaEncoder mediaEncoder) + Lazy providerManagerFactory, + Lazy userviewManagerFactory, + IMediaEncoder mediaEncoder, + IItemRepository itemRepository) { _appHost = appHost; - _logger = loggerFactory.CreateLogger(nameof(LibraryManager)); + _logger = logger; _taskManager = taskManager; _userManager = userManager; - ConfigurationManager = configurationManager; + _configurationManager = configurationManager; _userDataRepository = userDataRepository; _libraryMonitorFactory = libraryMonitorFactory; _fileSystem = fileSystem; _providerManagerFactory = providerManagerFactory; - _userviewManager = userviewManager; + _userviewManagerFactory = userviewManagerFactory; _mediaEncoder = mediaEncoder; + _itemRepository = itemRepository; _libraryItemsCache = new ConcurrentDictionary(); - ConfigurationManager.ConfigurationUpdated += ConfigurationUpdated; + _configurationManager.ConfigurationUpdated += ConfigurationUpdated; RecordConfigurationValues(configurationManager.Configuration); } @@ -272,7 +243,7 @@ namespace Emby.Server.Implementations.Library /// The instance containing the event data. private void ConfigurationUpdated(object sender, EventArgs e) { - var config = ConfigurationManager.Configuration; + var config = _configurationManager.Configuration; var wizardChanged = config.IsStartupWizardCompleted != _wizardCompleted; @@ -306,7 +277,7 @@ namespace Emby.Server.Implementations.Library } } - LibraryItemsCache.AddOrUpdate(item.Id, item, delegate { return item; }); + _libraryItemsCache.AddOrUpdate(item.Id, item, delegate { return item; }); } public void DeleteItem(BaseItem item, DeleteOptions options) @@ -437,10 +408,10 @@ namespace Emby.Server.Implementations.Library item.SetParent(null); - ItemRepository.DeleteItem(item.Id, CancellationToken.None); + _itemRepository.DeleteItem(item.Id, CancellationToken.None); foreach (var child in children) { - ItemRepository.DeleteItem(child.Id, CancellationToken.None); + _itemRepository.DeleteItem(child.Id, CancellationToken.None); } _libraryItemsCache.TryRemove(item.Id, out BaseItem removed); @@ -509,15 +480,15 @@ namespace Emby.Server.Implementations.Library throw new ArgumentNullException(nameof(type)); } - if (key.StartsWith(ConfigurationManager.ApplicationPaths.ProgramDataPath, StringComparison.Ordinal)) + if (key.StartsWith(_configurationManager.ApplicationPaths.ProgramDataPath, StringComparison.Ordinal)) { // Try to normalize paths located underneath program-data in an attempt to make them more portable - key = key.Substring(ConfigurationManager.ApplicationPaths.ProgramDataPath.Length) + key = key.Substring(_configurationManager.ApplicationPaths.ProgramDataPath.Length) .TrimStart(new[] { '/', '\\' }) .Replace("/", "\\"); } - if (forceCaseInsensitive || !ConfigurationManager.Configuration.EnableCaseSensitiveItemIds) + if (forceCaseInsensitive || !_configurationManager.Configuration.EnableCaseSensitiveItemIds) { key = key.ToLowerInvariant(); } @@ -550,7 +521,7 @@ namespace Emby.Server.Implementations.Library collectionType = GetContentTypeOverride(fullPath, true); } - var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths, directoryService) + var args = new ItemResolveArgs(_configurationManager.ApplicationPaths, directoryService) { Parent = parent, Path = fullPath, @@ -720,7 +691,7 @@ namespace Emby.Server.Implementations.Library /// Cannot create the root folder until plugins have loaded. public AggregateFolder CreateRootFolder() { - var rootFolderPath = ConfigurationManager.ApplicationPaths.RootFolderPath; + var rootFolderPath = _configurationManager.ApplicationPaths.RootFolderPath; Directory.CreateDirectory(rootFolderPath); @@ -734,7 +705,7 @@ namespace Emby.Server.Implementations.Library } // Add in the plug-in folders - var path = Path.Combine(ConfigurationManager.ApplicationPaths.DataPath, "playlists"); + var path = Path.Combine(_configurationManager.ApplicationPaths.DataPath, "playlists"); Directory.CreateDirectory(path); @@ -786,7 +757,7 @@ namespace Emby.Server.Implementations.Library { if (_userRootFolder == null) { - var userRootPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; + var userRootPath = _configurationManager.ApplicationPaths.DefaultUserViewsPath; _logger.LogDebug("Creating userRootPath at {path}", userRootPath); Directory.CreateDirectory(userRootPath); @@ -980,7 +951,7 @@ namespace Emby.Server.Implementations.Library where T : BaseItem, new() { var path = getPathFn(name); - var forceCaseInsensitiveId = ConfigurationManager.Configuration.EnableNormalizedItemByNameIds; + var forceCaseInsensitiveId = _configurationManager.Configuration.EnableNormalizedItemByNameIds; return GetNewItemIdInternal(path, typeof(T), forceCaseInsensitiveId); } @@ -994,7 +965,7 @@ namespace Emby.Server.Implementations.Library public Task ValidatePeople(CancellationToken cancellationToken, IProgress progress) { // Ensure the location is available. - Directory.CreateDirectory(ConfigurationManager.ApplicationPaths.PeoplePath); + Directory.CreateDirectory(_configurationManager.ApplicationPaths.PeoplePath); return new PeopleValidator(this, _logger, _fileSystem).ValidatePeople(cancellationToken, progress); } @@ -1031,7 +1002,7 @@ namespace Emby.Server.Implementations.Library public async Task ValidateMediaLibraryInternal(IProgress progress, CancellationToken cancellationToken) { IsScanRunning = true; - _libraryMonitorFactory().Stop(); + LibraryMonitor.Stop(); try { @@ -1039,7 +1010,7 @@ namespace Emby.Server.Implementations.Library } finally { - _libraryMonitorFactory().Start(); + LibraryMonitor.Start(); IsScanRunning = false; } } @@ -1148,7 +1119,7 @@ namespace Emby.Server.Implementations.Library progress.Report(percent * 100); } - ItemRepository.UpdateInheritedValues(cancellationToken); + _itemRepository.UpdateInheritedValues(cancellationToken); progress.Report(100); } @@ -1168,9 +1139,9 @@ namespace Emby.Server.Implementations.Library var topLibraryFolders = GetUserRootFolder().Children.ToList(); _logger.LogDebug("Getting refreshQueue"); - var refreshQueue = includeRefreshState ? _providerManagerFactory().GetRefreshQueue() : null; + var refreshQueue = includeRefreshState ? ProviderManager.GetRefreshQueue() : null; - return _fileSystem.GetDirectoryPaths(ConfigurationManager.ApplicationPaths.DefaultUserViewsPath) + return _fileSystem.GetDirectoryPaths(_configurationManager.ApplicationPaths.DefaultUserViewsPath) .Select(dir => GetVirtualFolderInfo(dir, topLibraryFolders, refreshQueue)) .ToList(); } @@ -1245,7 +1216,7 @@ namespace Emby.Server.Implementations.Library throw new ArgumentException("Guid can't be empty", nameof(id)); } - if (LibraryItemsCache.TryGetValue(id, out BaseItem item)) + if (_libraryItemsCache.TryGetValue(id, out BaseItem item)) { return item; } @@ -1276,7 +1247,7 @@ namespace Emby.Server.Implementations.Library AddUserToQuery(query, query.User, allowExternalContent); } - return ItemRepository.GetItemList(query); + return _itemRepository.GetItemList(query); } public List GetItemList(InternalItemsQuery query) @@ -1300,7 +1271,7 @@ namespace Emby.Server.Implementations.Library AddUserToQuery(query, query.User); } - return ItemRepository.GetCount(query); + return _itemRepository.GetCount(query); } public List GetItemList(InternalItemsQuery query, List parents) @@ -1315,7 +1286,7 @@ namespace Emby.Server.Implementations.Library } } - return ItemRepository.GetItemList(query); + return _itemRepository.GetItemList(query); } public QueryResult QueryItems(InternalItemsQuery query) @@ -1327,12 +1298,12 @@ namespace Emby.Server.Implementations.Library if (query.EnableTotalRecordCount) { - return ItemRepository.GetItems(query); + return _itemRepository.GetItems(query); } return new QueryResult { - Items = ItemRepository.GetItemList(query).ToArray() + Items = _itemRepository.GetItemList(query).ToArray() }; } @@ -1343,7 +1314,7 @@ namespace Emby.Server.Implementations.Library AddUserToQuery(query, query.User); } - return ItemRepository.GetItemIdsList(query); + return _itemRepository.GetItemIdsList(query); } public QueryResult<(BaseItem, ItemCounts)> GetStudios(InternalItemsQuery query) @@ -1354,7 +1325,7 @@ namespace Emby.Server.Implementations.Library } SetTopParentOrAncestorIds(query); - return ItemRepository.GetStudios(query); + return _itemRepository.GetStudios(query); } public QueryResult<(BaseItem, ItemCounts)> GetGenres(InternalItemsQuery query) @@ -1365,7 +1336,7 @@ namespace Emby.Server.Implementations.Library } SetTopParentOrAncestorIds(query); - return ItemRepository.GetGenres(query); + return _itemRepository.GetGenres(query); } public QueryResult<(BaseItem, ItemCounts)> GetMusicGenres(InternalItemsQuery query) @@ -1376,7 +1347,7 @@ namespace Emby.Server.Implementations.Library } SetTopParentOrAncestorIds(query); - return ItemRepository.GetMusicGenres(query); + return _itemRepository.GetMusicGenres(query); } public QueryResult<(BaseItem, ItemCounts)> GetAllArtists(InternalItemsQuery query) @@ -1387,7 +1358,7 @@ namespace Emby.Server.Implementations.Library } SetTopParentOrAncestorIds(query); - return ItemRepository.GetAllArtists(query); + return _itemRepository.GetAllArtists(query); } public QueryResult<(BaseItem, ItemCounts)> GetArtists(InternalItemsQuery query) @@ -1398,7 +1369,7 @@ namespace Emby.Server.Implementations.Library } SetTopParentOrAncestorIds(query); - return ItemRepository.GetArtists(query); + return _itemRepository.GetArtists(query); } private void SetTopParentOrAncestorIds(InternalItemsQuery query) @@ -1439,7 +1410,7 @@ namespace Emby.Server.Implementations.Library } SetTopParentOrAncestorIds(query); - return ItemRepository.GetAlbumArtists(query); + return _itemRepository.GetAlbumArtists(query); } public QueryResult GetItemsResult(InternalItemsQuery query) @@ -1460,10 +1431,10 @@ namespace Emby.Server.Implementations.Library if (query.EnableTotalRecordCount) { - return ItemRepository.GetItems(query); + return _itemRepository.GetItems(query); } - var list = ItemRepository.GetItemList(query); + var list = _itemRepository.GetItemList(query); return new QueryResult { @@ -1509,7 +1480,7 @@ namespace Emby.Server.Implementations.Library string.IsNullOrEmpty(query.SeriesPresentationUniqueKey) && query.ItemIds.Length == 0) { - var userViews = _userviewManager().GetUserViews(new UserViewQuery + var userViews = UserViewManager.GetUserViews(new UserViewQuery { UserId = user.Id, IncludeHidden = true, @@ -1809,7 +1780,7 @@ namespace Emby.Server.Implementations.Library // Don't iterate multiple times var itemsList = items.ToList(); - ItemRepository.SaveItems(itemsList, cancellationToken); + _itemRepository.SaveItems(itemsList, cancellationToken); foreach (var item in itemsList) { @@ -1846,7 +1817,7 @@ namespace Emby.Server.Implementations.Library public void UpdateImages(BaseItem item) { - ItemRepository.SaveImages(item); + _itemRepository.SaveImages(item); RegisterItem(item); } @@ -1863,7 +1834,7 @@ namespace Emby.Server.Implementations.Library { if (item.IsFileProtocol) { - _providerManagerFactory().SaveMetadata(item, updateReason); + ProviderManager.SaveMetadata(item, updateReason); } item.DateLastSaved = DateTime.UtcNow; @@ -1871,7 +1842,7 @@ namespace Emby.Server.Implementations.Library RegisterItem(item); } - ItemRepository.SaveItems(itemsList, cancellationToken); + _itemRepository.SaveItems(itemsList, cancellationToken); if (ItemUpdated != null) { @@ -1947,7 +1918,7 @@ namespace Emby.Server.Implementations.Library /// BaseItem. public BaseItem RetrieveItem(Guid id) { - return ItemRepository.RetrieveItem(id); + return _itemRepository.RetrieveItem(id); } public List GetCollectionFolders(BaseItem item) @@ -2066,7 +2037,7 @@ namespace Emby.Server.Implementations.Library private string GetContentTypeOverride(string path, bool inherit) { - var nameValuePair = ConfigurationManager.Configuration.ContentTypes + var nameValuePair = _configurationManager.Configuration.ContentTypes .FirstOrDefault(i => _fileSystem.AreEqual(i.Name, path) || (inherit && !string.IsNullOrEmpty(i.Name) && _fileSystem.ContainsSubPath(i.Name, path))); @@ -2115,7 +2086,7 @@ namespace Emby.Server.Implementations.Library string sortName) { var path = Path.Combine( - ConfigurationManager.ApplicationPaths.InternalMetadataPath, + _configurationManager.ApplicationPaths.InternalMetadataPath, "views", _fileSystem.GetValidFilename(viewType)); @@ -2147,7 +2118,7 @@ namespace Emby.Server.Implementations.Library if (refresh) { item.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None); - _providerManagerFactory().QueueRefresh(item.Id, new MetadataRefreshOptions(new DirectoryService(_fileSystem)), RefreshPriority.Normal); + ProviderManager.QueueRefresh(item.Id, new MetadataRefreshOptions(new DirectoryService(_fileSystem)), RefreshPriority.Normal); } return item; @@ -2165,7 +2136,7 @@ namespace Emby.Server.Implementations.Library var id = GetNewItemId(idValues, typeof(UserView)); - var path = Path.Combine(ConfigurationManager.ApplicationPaths.InternalMetadataPath, "views", id.ToString("N", CultureInfo.InvariantCulture)); + var path = Path.Combine(_configurationManager.ApplicationPaths.InternalMetadataPath, "views", id.ToString("N", CultureInfo.InvariantCulture)); var item = GetItemById(id) as UserView; @@ -2202,7 +2173,7 @@ namespace Emby.Server.Implementations.Library if (refresh) { - _providerManagerFactory().QueueRefresh( + ProviderManager.QueueRefresh( item.Id, new MetadataRefreshOptions(new DirectoryService(_fileSystem)) { @@ -2269,7 +2240,7 @@ namespace Emby.Server.Implementations.Library if (refresh) { - _providerManagerFactory().QueueRefresh( + ProviderManager.QueueRefresh( item.Id, new MetadataRefreshOptions(new DirectoryService(_fileSystem)) { @@ -2303,7 +2274,7 @@ namespace Emby.Server.Implementations.Library var id = GetNewItemId(idValues, typeof(UserView)); - var path = Path.Combine(ConfigurationManager.ApplicationPaths.InternalMetadataPath, "views", id.ToString("N", CultureInfo.InvariantCulture)); + var path = Path.Combine(_configurationManager.ApplicationPaths.InternalMetadataPath, "views", id.ToString("N", CultureInfo.InvariantCulture)); var item = GetItemById(id) as UserView; @@ -2346,7 +2317,7 @@ namespace Emby.Server.Implementations.Library if (refresh) { - _providerManagerFactory().QueueRefresh( + ProviderManager.QueueRefresh( item.Id, new MetadataRefreshOptions(new DirectoryService(_fileSystem)) { @@ -2677,8 +2648,8 @@ namespace Emby.Server.Implementations.Library } } - var metadataPath = ConfigurationManager.Configuration.MetadataPath; - var metadataNetworkPath = ConfigurationManager.Configuration.MetadataNetworkPath; + var metadataPath = _configurationManager.Configuration.MetadataPath; + var metadataNetworkPath = _configurationManager.Configuration.MetadataNetworkPath; if (!string.IsNullOrWhiteSpace(metadataPath) && !string.IsNullOrWhiteSpace(metadataNetworkPath)) { @@ -2689,7 +2660,7 @@ namespace Emby.Server.Implementations.Library } } - foreach (var map in ConfigurationManager.Configuration.PathSubstitutions) + foreach (var map in _configurationManager.Configuration.PathSubstitutions) { if (!string.IsNullOrWhiteSpace(map.From)) { @@ -2758,7 +2729,7 @@ namespace Emby.Server.Implementations.Library public List GetPeople(InternalPeopleQuery query) { - return ItemRepository.GetPeople(query); + return _itemRepository.GetPeople(query); } public List GetPeople(BaseItem item) @@ -2781,7 +2752,7 @@ namespace Emby.Server.Implementations.Library public List GetPeopleItems(InternalPeopleQuery query) { - return ItemRepository.GetPeopleNames(query).Select(i => + return _itemRepository.GetPeopleNames(query).Select(i => { try { @@ -2798,7 +2769,7 @@ namespace Emby.Server.Implementations.Library public List GetPeopleNames(InternalPeopleQuery query) { - return ItemRepository.GetPeopleNames(query); + return _itemRepository.GetPeopleNames(query); } public void UpdatePeople(BaseItem item, List people) @@ -2808,7 +2779,7 @@ namespace Emby.Server.Implementations.Library return; } - ItemRepository.UpdatePeople(item.Id, people); + _itemRepository.UpdatePeople(item.Id, people); } public async Task ConvertImageToLocal(BaseItem item, ItemImageInfo image, int imageIndex) @@ -2819,7 +2790,7 @@ namespace Emby.Server.Implementations.Library { _logger.LogDebug("ConvertImageToLocal item {0} - image url: {1}", item.Id, url); - await _providerManagerFactory().SaveImage(item, url, image.Type, imageIndex, CancellationToken.None).ConfigureAwait(false); + await ProviderManager.SaveImage(item, url, image.Type, imageIndex, CancellationToken.None).ConfigureAwait(false); item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); @@ -2852,7 +2823,7 @@ namespace Emby.Server.Implementations.Library name = _fileSystem.GetValidFilename(name); - var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; + var rootFolderPath = _configurationManager.ApplicationPaths.DefaultUserViewsPath; var virtualFolderPath = Path.Combine(rootFolderPath, name); while (Directory.Exists(virtualFolderPath)) @@ -2871,7 +2842,7 @@ namespace Emby.Server.Implementations.Library } } - _libraryMonitorFactory().Stop(); + LibraryMonitor.Stop(); try { @@ -2906,7 +2877,7 @@ namespace Emby.Server.Implementations.Library { // Need to add a delay here or directory watchers may still pick up the changes await Task.Delay(1000).ConfigureAwait(false); - _libraryMonitorFactory().Start(); + LibraryMonitor.Start(); } } } @@ -2966,7 +2937,7 @@ namespace Emby.Server.Implementations.Library throw new FileNotFoundException("The network path does not exist."); } - var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; + var rootFolderPath = _configurationManager.ApplicationPaths.DefaultUserViewsPath; var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName); var shortcutFilename = Path.GetFileNameWithoutExtension(path); @@ -3009,7 +2980,7 @@ namespace Emby.Server.Implementations.Library throw new FileNotFoundException("The network path does not exist."); } - var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; + var rootFolderPath = _configurationManager.ApplicationPaths.DefaultUserViewsPath; var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName); var libraryOptions = CollectionFolder.GetLibraryOptions(virtualFolderPath); @@ -3062,7 +3033,7 @@ namespace Emby.Server.Implementations.Library throw new ArgumentNullException(nameof(name)); } - var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; + var rootFolderPath = _configurationManager.ApplicationPaths.DefaultUserViewsPath; var path = Path.Combine(rootFolderPath, name); @@ -3071,7 +3042,7 @@ namespace Emby.Server.Implementations.Library throw new FileNotFoundException("The media folder does not exist"); } - _libraryMonitorFactory().Stop(); + LibraryMonitor.Stop(); try { @@ -3091,7 +3062,7 @@ namespace Emby.Server.Implementations.Library { // Need to add a delay here or directory watchers may still pick up the changes await Task.Delay(1000).ConfigureAwait(false); - _libraryMonitorFactory().Start(); + LibraryMonitor.Start(); } } } @@ -3105,7 +3076,7 @@ namespace Emby.Server.Implementations.Library var removeList = new List(); - foreach (var contentType in ConfigurationManager.Configuration.ContentTypes) + foreach (var contentType in _configurationManager.Configuration.ContentTypes) { if (string.IsNullOrWhiteSpace(contentType.Name)) { @@ -3120,11 +3091,11 @@ namespace Emby.Server.Implementations.Library if (removeList.Count > 0) { - ConfigurationManager.Configuration.ContentTypes = ConfigurationManager.Configuration.ContentTypes + _configurationManager.Configuration.ContentTypes = _configurationManager.Configuration.ContentTypes .Except(removeList) .ToArray(); - ConfigurationManager.SaveConfiguration(); + _configurationManager.SaveConfiguration(); } } @@ -3135,7 +3106,7 @@ namespace Emby.Server.Implementations.Library throw new ArgumentNullException(nameof(mediaPath)); } - var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; + var rootFolderPath = _configurationManager.ApplicationPaths.DefaultUserViewsPath; var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName); if (!Directory.Exists(virtualFolderPath)) From 84b48eb69c1bd6c87dc33e359fe989cd88714f19 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 19:01:21 -0400 Subject: [PATCH 32/83] Convert MediaEncoder property to field --- Emby.Server.Implementations/ApplicationHost.cs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index aca1abf9f..d3014a2d8 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -121,6 +121,7 @@ namespace Emby.Server.Implementations { private SqliteUserRepository _userRepository; private SqliteDisplayPreferencesRepository _displayPreferencesRepository; + private IMediaEncoder _mediaEncoder; private ISessionManager _sessionManager; private IHttpServer _httpServer; @@ -251,12 +252,6 @@ namespace Emby.Server.Implementations /// The user manager. public IUserManager UserManager { get; set; } - /// - /// Gets or sets the media encoder. - /// - /// The media encoder. - private IMediaEncoder MediaEncoder { get; set; } - public LocalizationManager LocalizationManager { get; set; } /// @@ -486,7 +481,7 @@ namespace Emby.Server.Implementations ConfigurationManager.ConfigurationUpdated += OnConfigurationUpdated; - MediaEncoder.SetFFmpegPath(); + _mediaEncoder.SetFFmpegPath(); Logger.LogInformation("ServerId: {0}", SystemId); @@ -685,7 +680,8 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(UserManager); - MediaEncoder = new MediaBrowser.MediaEncoding.Encoder.MediaEncoder( + // TODO: Add StartupOptions.FFmpegPath to IConfiguration so this doesn't need to be constructed manually + serviceCollection.AddSingleton(new MediaBrowser.MediaEncoding.Encoder.MediaEncoder( LoggerFactory.CreateLogger(), ServerConfigurationManager, FileSystemManager, @@ -693,8 +689,7 @@ namespace Emby.Server.Implementations LocalizationManager, Resolve, startupConfig, - StartupOptions.FFmpegPath); - serviceCollection.AddSingleton(MediaEncoder); + StartupOptions.FFmpegPath)); // TODO: Refactor to eliminate the circular dependencies here so that Lazy isn't required serviceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); @@ -772,6 +767,7 @@ namespace Emby.Server.Implementations /// public void InitializeServices() { + _mediaEncoder = Resolve(); _sessionManager = Resolve(); _httpServer = Resolve(); @@ -1306,7 +1302,7 @@ namespace Emby.Server.Implementations ServerName = FriendlyName, LocalAddress = localAddress, SupportsLibraryMonitor = true, - EncoderLocation = MediaEncoder.EncoderLocation, + EncoderLocation = _mediaEncoder.EncoderLocation, SystemArchitecture = RuntimeInformation.OSArchitecture, SystemUpdateLevel = SystemUpdateLevel, PackageName = StartupOptions.PackageName From 4daa5436fc0d635fa8ae7b391efa7e1a8561d029 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 19:31:14 -0400 Subject: [PATCH 33/83] Register and construct IUserManager and IUserRepository correctly --- .../ApplicationHost.cs | 51 ++++--------------- .../Library/UserManager.cs | 26 ++++------ 2 files changed, 21 insertions(+), 56 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index d3014a2d8..9e570588a 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -246,12 +246,6 @@ namespace Emby.Server.Implementations /// The server configuration manager. public IServerConfigurationManager ServerConfigurationManager => (IServerConfigurationManager)ConfigurationManager; - /// - /// Gets or sets the user manager. - /// - /// The user manager. - public IUserManager UserManager { get; set; } - public LocalizationManager LocalizationManager { get; set; } /// @@ -650,7 +644,7 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(new BdInfoExaminer(FileSystemManager)); - UserDataManager = new UserDataManager(LoggerFactory, ServerConfigurationManager, () => UserManager); + UserDataManager = new UserDataManager(LoggerFactory, ServerConfigurationManager, Resolve); serviceCollection.AddSingleton(UserDataManager); _displayPreferencesRepository = new SqliteDisplayPreferencesRepository( @@ -664,21 +658,11 @@ namespace Emby.Server.Implementations AuthenticationRepository = GetAuthenticationRepository(); serviceCollection.AddSingleton(AuthenticationRepository); - _userRepository = GetUserRepository(); + serviceCollection.AddSingleton(); - UserManager = new UserManager( - LoggerFactory.CreateLogger(), - _userRepository, - XmlSerializer, - NetworkManager, - Resolve, - Resolve, - this, - JsonSerializer, - FileSystemManager, - cryptoProvider); - - serviceCollection.AddSingleton(UserManager); + // TODO: Refactor to eliminate the circular dependency here so that Lazy isn't required + serviceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); + serviceCollection.AddSingleton(); // TODO: Add StartupOptions.FFmpegPath to IConfiguration so this doesn't need to be constructed manually serviceCollection.AddSingleton(new MediaBrowser.MediaEncoding.Encoder.MediaEncoder( @@ -771,6 +755,7 @@ namespace Emby.Server.Implementations _sessionManager = Resolve(); _httpServer = Resolve(); + ((SqliteUserRepository)Resolve()).Initialize(); ((ActivityRepository)Resolve()).Initialize(); _displayPreferencesRepository.Initialize(); @@ -778,11 +763,12 @@ namespace Emby.Server.Implementations SetStaticProperties(); - ((UserManager)UserManager).Initialize(); + var userManager = (UserManager)Resolve(); + userManager.Initialize(); ((UserDataManager)UserDataManager).Repository = userDataRepo; - ((SqliteItemRepository)Resolve()).Initialize(userDataRepo, UserManager); + ((SqliteItemRepository)Resolve()).Initialize(userDataRepo, userManager); FindParts(); } @@ -853,21 +839,6 @@ namespace Emby.Server.Implementations } } - /// - /// Gets the user repository. - /// - /// . - private SqliteUserRepository GetUserRepository() - { - var repo = new SqliteUserRepository( - LoggerFactory.CreateLogger(), - ApplicationPaths); - - repo.Initialize(); - - return repo; - } - private IAuthenticationRepository GetAuthenticationRepository() { var repo = new AuthenticationRepository(LoggerFactory, ServerConfigurationManager); @@ -889,7 +860,7 @@ namespace Emby.Server.Implementations BaseItem.ProviderManager = Resolve(); BaseItem.LocalizationManager = LocalizationManager; BaseItem.ItemRepository = Resolve(); - User.UserManager = UserManager; + User.UserManager = Resolve(); BaseItem.FileSystem = FileSystemManager; BaseItem.UserDataManager = UserDataManager; BaseItem.ChannelManager = Resolve(); @@ -984,7 +955,7 @@ namespace Emby.Server.Implementations Resolve().AddParts(GetExports()); Resolve().AddParts(GetExports(), GetExports()); - UserManager.AddParts(GetExports(), GetExports()); + Resolve().AddParts(GetExports(), GetExports()); IsoManager.AddParts(GetExports()); } diff --git a/Emby.Server.Implementations/Library/UserManager.cs b/Emby.Server.Implementations/Library/UserManager.cs index 7b17cc913..64193a8ec 100644 --- a/Emby.Server.Implementations/Library/UserManager.cs +++ b/Emby.Server.Implementations/Library/UserManager.cs @@ -44,22 +44,14 @@ namespace Emby.Server.Implementations.Library { private readonly object _policySyncLock = new object(); private readonly object _configSyncLock = new object(); - /// - /// The logger. - /// - private readonly ILogger _logger; - /// - /// Gets the active user repository. - /// - /// The user repository. + private readonly ILogger _logger; private readonly IUserRepository _userRepository; private readonly IXmlSerializer _xmlSerializer; private readonly IJsonSerializer _jsonSerializer; private readonly INetworkManager _networkManager; - - private readonly Func _imageProcessorFactory; - private readonly Func _dtoServiceFactory; + private readonly IImageProcessor _imageProcessor; + private readonly Lazy _dtoServiceFactory; private readonly IServerApplicationHost _appHost; private readonly IFileSystem _fileSystem; private readonly ICryptoProvider _cryptoProvider; @@ -74,13 +66,15 @@ namespace Emby.Server.Implementations.Library private IPasswordResetProvider[] _passwordResetProviders; private DefaultPasswordResetProvider _defaultPasswordResetProvider; + private IDtoService DtoService => _dtoServiceFactory.Value; + public UserManager( ILogger logger, IUserRepository userRepository, IXmlSerializer xmlSerializer, INetworkManager networkManager, - Func imageProcessorFactory, - Func dtoServiceFactory, + IImageProcessor imageProcessor, + Lazy dtoServiceFactory, IServerApplicationHost appHost, IJsonSerializer jsonSerializer, IFileSystem fileSystem, @@ -90,7 +84,7 @@ namespace Emby.Server.Implementations.Library _userRepository = userRepository; _xmlSerializer = xmlSerializer; _networkManager = networkManager; - _imageProcessorFactory = imageProcessorFactory; + _imageProcessor = imageProcessor; _dtoServiceFactory = dtoServiceFactory; _appHost = appHost; _jsonSerializer = jsonSerializer; @@ -600,7 +594,7 @@ namespace Emby.Server.Implementations.Library try { - _dtoServiceFactory().AttachPrimaryImageAspectRatio(dto, user); + DtoService.AttachPrimaryImageAspectRatio(dto, user); } catch (Exception ex) { @@ -625,7 +619,7 @@ namespace Emby.Server.Implementations.Library { try { - return _imageProcessorFactory().GetImageCacheTag(item, image); + return _imageProcessor.GetImageCacheTag(item, image); } catch (Exception ex) { From a5234dfd886e9938ede838dcee79ff81d2139f57 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 19:36:27 -0400 Subject: [PATCH 34/83] Register and construct IAuthenticationRepository correctly --- Emby.Server.Implementations/ApplicationHost.cs | 15 ++------------- .../Security/AuthenticationRepository.cs | 4 ++-- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 9e570588a..86b267303 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -254,8 +254,6 @@ namespace Emby.Server.Implementations /// The user data repository. private IUserDataManager UserDataManager { get; set; } - private IAuthenticationRepository AuthenticationRepository { get; set; } - /// /// Gets the installation manager. /// @@ -655,8 +653,7 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(); - AuthenticationRepository = GetAuthenticationRepository(); - serviceCollection.AddSingleton(AuthenticationRepository); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); @@ -755,6 +752,7 @@ namespace Emby.Server.Implementations _sessionManager = Resolve(); _httpServer = Resolve(); + ((AuthenticationRepository)Resolve()).Initialize(); ((SqliteUserRepository)Resolve()).Initialize(); ((ActivityRepository)Resolve()).Initialize(); _displayPreferencesRepository.Initialize(); @@ -839,15 +837,6 @@ namespace Emby.Server.Implementations } } - private IAuthenticationRepository GetAuthenticationRepository() - { - var repo = new AuthenticationRepository(LoggerFactory, ServerConfigurationManager); - - repo.Initialize(); - - return repo; - } - /// /// Dirty hacks. /// diff --git a/Emby.Server.Implementations/Security/AuthenticationRepository.cs b/Emby.Server.Implementations/Security/AuthenticationRepository.cs index 1ef5c4b99..4e4029f06 100644 --- a/Emby.Server.Implementations/Security/AuthenticationRepository.cs +++ b/Emby.Server.Implementations/Security/AuthenticationRepository.cs @@ -15,8 +15,8 @@ namespace Emby.Server.Implementations.Security { public class AuthenticationRepository : BaseSqliteRepository, IAuthenticationRepository { - public AuthenticationRepository(ILoggerFactory loggerFactory, IServerConfigurationManager config) - : base(loggerFactory.CreateLogger(nameof(AuthenticationRepository))) + public AuthenticationRepository(ILogger logger, IServerConfigurationManager config) + : base(logger) { DbFilePath = Path.Combine(config.ApplicationPaths.DataPath, "authentication.db"); } From 5827f0f5a96574f1c87904a866890b998cab48a7 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 19:40:53 -0400 Subject: [PATCH 35/83] Register IDisplayPreferencesRepository correctly --- Emby.Server.Implementations/ApplicationHost.cs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 86b267303..875ed62fe 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -120,7 +120,6 @@ namespace Emby.Server.Implementations public abstract class ApplicationHost : IServerApplicationHost, IDisposable { private SqliteUserRepository _userRepository; - private SqliteDisplayPreferencesRepository _displayPreferencesRepository; private IMediaEncoder _mediaEncoder; private ISessionManager _sessionManager; private IHttpServer _httpServer; @@ -645,11 +644,7 @@ namespace Emby.Server.Implementations UserDataManager = new UserDataManager(LoggerFactory, ServerConfigurationManager, Resolve); serviceCollection.AddSingleton(UserDataManager); - _displayPreferencesRepository = new SqliteDisplayPreferencesRepository( - LoggerFactory.CreateLogger(), - ApplicationPaths, - FileSystemManager); - serviceCollection.AddSingleton(_displayPreferencesRepository); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); @@ -752,10 +747,10 @@ namespace Emby.Server.Implementations _sessionManager = Resolve(); _httpServer = Resolve(); + ((SqliteDisplayPreferencesRepository)Resolve()).Initialize(); ((AuthenticationRepository)Resolve()).Initialize(); ((SqliteUserRepository)Resolve()).Initialize(); ((ActivityRepository)Resolve()).Initialize(); - _displayPreferencesRepository.Initialize(); var userDataRepo = new SqliteUserDataRepository(LoggerFactory.CreateLogger(), ApplicationPaths); @@ -1628,11 +1623,9 @@ namespace Emby.Server.Implementations } _userRepository?.Dispose(); - _displayPreferencesRepository?.Dispose(); } _userRepository = null; - _displayPreferencesRepository = null; _disposed = true; } From 615717e562f98c5cbd4e9ad648380a555d44d774 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 19:57:26 -0400 Subject: [PATCH 36/83] Register and construct IUserDataManager and IUserDataRepository correctly --- .../ApplicationHost.cs | 17 +++------ .../Library/UserDataManager.cs | 35 +++++++++---------- 2 files changed, 21 insertions(+), 31 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 875ed62fe..ea580bad8 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -247,12 +247,6 @@ namespace Emby.Server.Implementations public LocalizationManager LocalizationManager { get; set; } - /// - /// Gets or sets the user data repository. - /// - /// The user data repository. - private IUserDataManager UserDataManager { get; set; } - /// /// Gets the installation manager. /// @@ -641,8 +635,8 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(new BdInfoExaminer(FileSystemManager)); - UserDataManager = new UserDataManager(LoggerFactory, ServerConfigurationManager, Resolve); - serviceCollection.AddSingleton(UserDataManager); + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); @@ -752,15 +746,12 @@ namespace Emby.Server.Implementations ((SqliteUserRepository)Resolve()).Initialize(); ((ActivityRepository)Resolve()).Initialize(); - var userDataRepo = new SqliteUserDataRepository(LoggerFactory.CreateLogger(), ApplicationPaths); - SetStaticProperties(); var userManager = (UserManager)Resolve(); userManager.Initialize(); - ((UserDataManager)UserDataManager).Repository = userDataRepo; - + var userDataRepo = (SqliteUserDataRepository)Resolve(); ((SqliteItemRepository)Resolve()).Initialize(userDataRepo, userManager); FindParts(); @@ -846,7 +837,7 @@ namespace Emby.Server.Implementations BaseItem.ItemRepository = Resolve(); User.UserManager = Resolve(); BaseItem.FileSystem = FileSystemManager; - BaseItem.UserDataManager = UserDataManager; + BaseItem.UserDataManager = Resolve(); BaseItem.ChannelManager = Resolve(); Video.LiveTvManager = Resolve(); Folder.UserViewManager = Resolve(); diff --git a/Emby.Server.Implementations/Library/UserDataManager.cs b/Emby.Server.Implementations/Library/UserDataManager.cs index 071681b08..a9772a078 100644 --- a/Emby.Server.Implementations/Library/UserDataManager.cs +++ b/Emby.Server.Implementations/Library/UserDataManager.cs @@ -28,25 +28,24 @@ namespace Emby.Server.Implementations.Library private readonly ILogger _logger; private readonly IServerConfigurationManager _config; + private readonly IUserManager _userManager; + private readonly IUserDataRepository _repository; - private Func _userManager; - - public UserDataManager(ILoggerFactory loggerFactory, IServerConfigurationManager config, Func userManager) + public UserDataManager( + ILogger logger, + IServerConfigurationManager config, + IUserManager userManager, + IUserDataRepository repository) { + _logger = logger; _config = config; - _logger = loggerFactory.CreateLogger(GetType().Name); _userManager = userManager; + _repository = repository; } - /// - /// Gets or sets the repository. - /// - /// The repository. - public IUserDataRepository Repository { get; set; } - public void SaveUserData(Guid userId, BaseItem item, UserItemData userData, UserDataSaveReason reason, CancellationToken cancellationToken) { - var user = _userManager().GetUserById(userId); + var user = _userManager.GetUserById(userId); SaveUserData(user, item, userData, reason, cancellationToken); } @@ -71,7 +70,7 @@ namespace Emby.Server.Implementations.Library foreach (var key in keys) { - Repository.SaveUserData(userId, key, userData, cancellationToken); + _repository.SaveUserData(userId, key, userData, cancellationToken); } var cacheKey = GetCacheKey(userId, item.Id); @@ -96,9 +95,9 @@ namespace Emby.Server.Implementations.Library /// public void SaveAllUserData(Guid userId, UserItemData[] userData, CancellationToken cancellationToken) { - var user = _userManager().GetUserById(userId); + var user = _userManager.GetUserById(userId); - Repository.SaveAllUserData(user.InternalId, userData, cancellationToken); + _repository.SaveAllUserData(user.InternalId, userData, cancellationToken); } /// @@ -108,14 +107,14 @@ namespace Emby.Server.Implementations.Library /// public List GetAllUserData(Guid userId) { - var user = _userManager().GetUserById(userId); + var user = _userManager.GetUserById(userId); - return Repository.GetAllUserData(user.InternalId); + return _repository.GetAllUserData(user.InternalId); } public UserItemData GetUserData(Guid userId, Guid itemId, List keys) { - var user = _userManager().GetUserById(userId); + var user = _userManager.GetUserById(userId); return GetUserData(user, itemId, keys); } @@ -131,7 +130,7 @@ namespace Emby.Server.Implementations.Library private UserItemData GetUserDataInternal(long internalUserId, List keys) { - var userData = Repository.GetUserData(internalUserId, keys); + var userData = _repository.GetUserData(internalUserId, keys); if (userData != null) { From cbc0224aafa1e0a4c9d52f55e03ab944ff3b7132 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 20:00:55 -0400 Subject: [PATCH 37/83] Register IStreamHelper, IInstallationManager, IZipClient, IHttpResultFactory and IBlurayExaminer correctly --- Emby.Server.Implementations/ApplicationHost.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index ea580bad8..e951ab114 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -610,7 +610,7 @@ namespace Emby.Server.Implementations ProcessFactory = new ProcessFactory(); serviceCollection.AddSingleton(ProcessFactory); - serviceCollection.AddSingleton(typeof(IStreamHelper), typeof(StreamHelper)); + serviceCollection.AddSingleton(); var cryptoProvider = new CryptographyProvider(); serviceCollection.AddSingleton(cryptoProvider); @@ -618,11 +618,11 @@ namespace Emby.Server.Implementations SocketFactory = new SocketFactory(); serviceCollection.AddSingleton(SocketFactory); - serviceCollection.AddSingleton(typeof(IInstallationManager), typeof(InstallationManager)); + serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(typeof(IZipClient), typeof(ZipClient)); + serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(typeof(IHttpResultFactory), typeof(HttpResultFactory)); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(this); serviceCollection.AddSingleton(ApplicationPaths); @@ -633,7 +633,7 @@ namespace Emby.Server.Implementations await LocalizationManager.LoadAll().ConfigureAwait(false); serviceCollection.AddSingleton(LocalizationManager); - serviceCollection.AddSingleton(new BdInfoExaminer(FileSystemManager)); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); From 5d648bf54f3c0fe503f8fdebb58a72b8c5e64673 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 20:21:48 -0400 Subject: [PATCH 38/83] Register and construct ILocalizationManager correctly --- .../ApplicationHost.cs | 33 ++++++++++--------- .../Localization/LocalizationManager.cs | 3 -- Jellyfin.Server/Program.cs | 2 +- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index e951ab114..75a2b194a 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -245,8 +245,6 @@ namespace Emby.Server.Implementations /// The server configuration manager. public IServerConfigurationManager ServerConfigurationManager => (IServerConfigurationManager)ConfigurationManager; - public LocalizationManager LocalizationManager { get; set; } - /// /// Gets the installation manager. /// @@ -629,9 +627,7 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(ServerConfigurationManager); - LocalizationManager = new LocalizationManager(ServerConfigurationManager, JsonSerializer, LoggerFactory.CreateLogger()); - await LocalizationManager.LoadAll().ConfigureAwait(false); - serviceCollection.AddSingleton(LocalizationManager); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); @@ -651,15 +647,16 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(); // TODO: Add StartupOptions.FFmpegPath to IConfiguration so this doesn't need to be constructed manually - serviceCollection.AddSingleton(new MediaBrowser.MediaEncoding.Encoder.MediaEncoder( - LoggerFactory.CreateLogger(), - ServerConfigurationManager, - FileSystemManager, - ProcessFactory, - LocalizationManager, - Resolve, - startupConfig, - StartupOptions.FFmpegPath)); + serviceCollection.AddSingleton(provider => + new MediaBrowser.MediaEncoding.Encoder.MediaEncoder( + provider.GetRequiredService>(), + provider.GetRequiredService(), + provider.GetRequiredService(), + provider.GetRequiredService(), + provider.GetRequiredService(), + provider.GetRequiredService, + provider.GetRequiredService(), + StartupOptions.FFmpegPath)); // TODO: Refactor to eliminate the circular dependencies here so that Lazy isn't required serviceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); @@ -735,8 +732,12 @@ namespace Emby.Server.Implementations /// /// Create services registered with the service container that need to be initialized at application startup. /// - public void InitializeServices() + /// A task representing the service initialization operation. + public async Task InitializeServices() { + var localizationManager = (LocalizationManager)Resolve(); + await localizationManager.LoadAll().ConfigureAwait(false); + _mediaEncoder = Resolve(); _sessionManager = Resolve(); _httpServer = Resolve(); @@ -833,7 +834,7 @@ namespace Emby.Server.Implementations BaseItem.ConfigurationManager = ServerConfigurationManager; BaseItem.LibraryManager = Resolve(); BaseItem.ProviderManager = Resolve(); - BaseItem.LocalizationManager = LocalizationManager; + BaseItem.LocalizationManager = Resolve(); BaseItem.ItemRepository = Resolve(); User.UserManager = Resolve(); BaseItem.FileSystem = FileSystemManager; diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index bda43e832..e2a634e1a 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -23,9 +23,6 @@ namespace Emby.Server.Implementations.Localization private static readonly Assembly _assembly = typeof(LocalizationManager).Assembly; private static readonly string[] _unratedValues = { "n/a", "unrated", "not rated" }; - /// - /// The _configuration manager. - /// private readonly IServerConfigurationManager _configurationManager; private readonly IJsonSerializer _jsonSerializer; private readonly ILogger _logger; diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 5e9c15e20..83170c6ae 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -208,7 +208,7 @@ namespace Jellyfin.Server // Re-use the web host service provider in the app host since ASP.NET doesn't allow a custom service collection. appHost.ServiceProvider = webHost.Services; - appHost.InitializeServices(); + await appHost.InitializeServices().ConfigureAwait(false); Migrations.MigrationRunner.Run(appHost, _loggerFactory); try From aee6a1b4764869143edab160eef4d6fb111032a2 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 20:40:50 -0400 Subject: [PATCH 39/83] Remove unnecessary async and parameter from ApplicationHost initialization method --- Emby.Server.Implementations/ApplicationHost.cs | 6 +++--- Jellyfin.Server/Program.cs | 2 +- MediaBrowser.Common/IApplicationHost.cs | 4 +--- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 75a2b194a..4597b65f3 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -500,7 +500,7 @@ namespace Emby.Server.Implementations } /// - public async Task InitAsync(IServiceCollection serviceCollection, IConfiguration startupConfig) + public void Init(IServiceCollection serviceCollection) { HttpPort = ServerConfigurationManager.Configuration.HttpServerPortNumber; HttpsPort = ServerConfigurationManager.Configuration.HttpsPortNumber; @@ -533,7 +533,7 @@ namespace Emby.Server.Implementations DiscoverTypes(); - await RegisterServices(serviceCollection, startupConfig).ConfigureAwait(false); + RegisterServices(serviceCollection); } public async Task ExecuteWebsocketHandlerAsync(HttpContext context, Func next) @@ -566,7 +566,7 @@ namespace Emby.Server.Implementations /// /// Registers services/resources with the service collection that will be available via DI. /// - protected async Task RegisterServices(IServiceCollection serviceCollection, IConfiguration startupConfig) + protected void RegisterServices(IServiceCollection serviceCollection) { var imageEncoderType = SkiaEncoder.IsNativeLibAvailable() ? typeof(SkiaEncoder) diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 83170c6ae..56017cf89 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -202,7 +202,7 @@ namespace Jellyfin.Server } ServiceCollection serviceCollection = new ServiceCollection(); - await appHost.InitAsync(serviceCollection, startupConfig).ConfigureAwait(false); + appHost.Init(serviceCollection); var webHost = CreateWebHostBuilder(appHost, serviceCollection, options, startupConfig, appPaths).Build(); diff --git a/MediaBrowser.Common/IApplicationHost.cs b/MediaBrowser.Common/IApplicationHost.cs index 0e282cf53..904138381 100644 --- a/MediaBrowser.Common/IApplicationHost.cs +++ b/MediaBrowser.Common/IApplicationHost.cs @@ -125,9 +125,7 @@ namespace MediaBrowser.Common /// Initializes this instance. /// /// The service collection. - /// The configuration to use for initialization. - /// A task. - Task InitAsync(IServiceCollection serviceCollection, IConfiguration startupConfig); + void Init(IServiceCollection serviceCollection); /// /// Creates the instance. From 3f2f95d8774df3dc27e9a24d89e7f7d6f57e2886 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 20:42:11 -0400 Subject: [PATCH 40/83] Register IProcessFactory, ICryptoProvider and ISocketFactory correctly --- Emby.Server.Implementations/ApplicationHost.cs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 4597b65f3..6c1719ac1 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -253,12 +253,8 @@ namespace Emby.Server.Implementations public IStartupOptions StartupOptions { get; } - protected IProcessFactory ProcessFactory { get; private set; } - protected readonly IXmlSerializer XmlSerializer; - protected ISocketFactory SocketFactory { get; private set; } - protected ITaskManager TaskManager { get; private set; } public IHttpClient HttpClient { get; private set; } @@ -605,16 +601,13 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(XmlSerializer); - ProcessFactory = new ProcessFactory(); - serviceCollection.AddSingleton(ProcessFactory); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); - var cryptoProvider = new CryptographyProvider(); - serviceCollection.AddSingleton(cryptoProvider); + serviceCollection.AddSingleton(); - SocketFactory = new SocketFactory(); - serviceCollection.AddSingleton(SocketFactory); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); @@ -1539,7 +1532,7 @@ namespace Emby.Server.Implementations throw new NotSupportedException(); } - var process = ProcessFactory.Create(new ProcessOptions + var process = Resolve().Create(new ProcessOptions { FileName = url, EnableRaisingEvents = true, From adf0e8d3fd8724a78e97fc0f4874beef67e5b891 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 21:00:11 -0400 Subject: [PATCH 41/83] Register and construct ITaskManager and IIsoManager correctly --- .../ApplicationHost.cs | 12 +++-------- .../ScheduledTasks/TaskManager.cs | 20 +++---------------- 2 files changed, 6 insertions(+), 26 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 6c1719ac1..0fde273c5 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -255,16 +255,12 @@ namespace Emby.Server.Implementations protected readonly IXmlSerializer XmlSerializer; - protected ITaskManager TaskManager { get; private set; } - public IHttpClient HttpClient { get; private set; } protected INetworkManager NetworkManager { get; set; } public IJsonSerializer JsonSerializer { get; private set; } - protected IIsoManager IsoManager { get; private set; } - /// /// Initializes a new instance of the class. /// @@ -593,11 +589,9 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(NetworkManager); - IsoManager = new IsoManager(); - serviceCollection.AddSingleton(IsoManager); + serviceCollection.AddSingleton(); - TaskManager = new TaskManager(ApplicationPaths, JsonSerializer, LoggerFactory, FileSystemManager); - serviceCollection.AddSingleton(TaskManager); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(XmlSerializer); @@ -926,7 +920,7 @@ namespace Emby.Server.Implementations Resolve().AddParts(GetExports(), GetExports()); Resolve().AddParts(GetExports(), GetExports()); - IsoManager.AddParts(GetExports()); + Resolve().AddParts(GetExports()); } private IPlugin LoadPlugin(IPlugin plugin) diff --git a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs index ecf58dbc0..6ffa581a9 100644 --- a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs +++ b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs @@ -32,22 +32,8 @@ namespace Emby.Server.Implementations.ScheduledTasks private readonly ConcurrentQueue> _taskQueue = new ConcurrentQueue>(); - /// - /// Gets or sets the json serializer. - /// - /// The json serializer. private readonly IJsonSerializer _jsonSerializer; - - /// - /// Gets or sets the application paths. - /// - /// The application paths. private readonly IApplicationPaths _applicationPaths; - - /// - /// Gets the logger. - /// - /// The logger. private readonly ILogger _logger; private readonly IFileSystem _fileSystem; @@ -56,17 +42,17 @@ namespace Emby.Server.Implementations.ScheduledTasks /// /// The application paths. /// The json serializer. - /// The logger factory. + /// The logger. /// The filesystem manager. public TaskManager( IApplicationPaths applicationPaths, IJsonSerializer jsonSerializer, - ILoggerFactory loggerFactory, + ILogger logger, IFileSystem fileSystem) { _applicationPaths = applicationPaths; _jsonSerializer = jsonSerializer; - _logger = loggerFactory.CreateLogger(nameof(TaskManager)); + _logger = logger; _fileSystem = fileSystem; ScheduledTasks = Array.Empty(); From e16c16dd51c62b1ad004979d729e4ef022359505 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 21:18:09 -0400 Subject: [PATCH 42/83] Register and construct IHttpClient correctly --- Emby.Server.Implementations/ApplicationHost.cs | 18 +++++------------- .../HttpClientManager/HttpClientManager.cs | 9 +++++---- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 0fde273c5..5592d3919 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -123,6 +123,7 @@ namespace Emby.Server.Implementations private IMediaEncoder _mediaEncoder; private ISessionManager _sessionManager; private IHttpServer _httpServer; + private IHttpClient _httpClient; /// /// Gets a value indicating whether this instance can self restart. @@ -255,8 +256,6 @@ namespace Emby.Server.Implementations protected readonly IXmlSerializer XmlSerializer; - public IHttpClient HttpClient { get; private set; } - protected INetworkManager NetworkManager { get; set; } public IJsonSerializer JsonSerializer { get; private set; } @@ -363,10 +362,7 @@ namespace Emby.Server.Implementations } } - /// - /// Gets the name. - /// - /// The name. + /// public string Name => ApplicationProductName; /// @@ -580,12 +576,7 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(FileSystemManager); serviceCollection.AddSingleton(); - HttpClient = new HttpClientManager.HttpClientManager( - ApplicationPaths, - LoggerFactory.CreateLogger(), - FileSystemManager, - () => ApplicationUserAgent); - serviceCollection.AddSingleton(HttpClient); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(NetworkManager); @@ -728,6 +719,7 @@ namespace Emby.Server.Implementations _mediaEncoder = Resolve(); _sessionManager = Resolve(); _httpServer = Resolve(); + _httpClient = Resolve(); ((SqliteDisplayPreferencesRepository)Resolve()).Initialize(); ((AuthenticationRepository)Resolve()).Initialize(); @@ -1423,7 +1415,7 @@ namespace Emby.Server.Implementations try { - using (var response = await HttpClient.SendAsync( + using (var response = await _httpClient.SendAsync( new HttpRequestOptions { Url = apiUrl, diff --git a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs index 882bfe2f6..d66bb7638 100644 --- a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs +++ b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Net; using System.Net.Http; using System.Threading.Tasks; +using MediaBrowser.Common; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; @@ -24,7 +25,7 @@ namespace Emby.Server.Implementations.HttpClientManager private readonly ILogger _logger; private readonly IApplicationPaths _appPaths; private readonly IFileSystem _fileSystem; - private readonly Func _defaultUserAgentFn; + private readonly IApplicationHost _appHost; /// /// Holds a dictionary of http clients by host. Use GetHttpClient(host) to retrieve or create a client for web requests. @@ -40,12 +41,12 @@ namespace Emby.Server.Implementations.HttpClientManager IApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem, - Func defaultUserAgentFn) + IApplicationHost appHost) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _fileSystem = fileSystem; _appPaths = appPaths ?? throw new ArgumentNullException(nameof(appPaths)); - _defaultUserAgentFn = defaultUserAgentFn; + _appHost = appHost; } /// @@ -91,7 +92,7 @@ namespace Emby.Server.Implementations.HttpClientManager if (options.EnableDefaultUserAgent && !request.Headers.TryGetValues(HeaderNames.UserAgent, out _)) { - request.Headers.Add(HeaderNames.UserAgent, _defaultUserAgentFn()); + request.Headers.Add(HeaderNames.UserAgent, _appHost.ApplicationUserAgent); } switch (options.DecompressionMethod) From 710767fbf2c80491448e3c978eec6b2745c9e4db Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 21:27:48 -0400 Subject: [PATCH 43/83] Add deprecation warning message for injecting ILogger --- Emby.Server.Implementations/ApplicationHost.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 5592d3919..b724dc320 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -570,8 +570,12 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(JsonSerializer); - // TODO: Support for injecting ILogger should be deprecated in favour of ILogger and this removed - serviceCollection.AddSingleton(Logger); + // TODO: Remove support for injecting ILogger completely + serviceCollection.AddSingleton((provider) => + { + Logger.LogWarning("Injecting ILogger directly is deprecated and should be replaced with ILogger"); + return Logger; + }); serviceCollection.AddSingleton(FileSystemManager); serviceCollection.AddSingleton(); From 809cf3a0c288713fd0ed0cc0ace6f7bb90a90ca2 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 21:33:57 -0400 Subject: [PATCH 44/83] Register IJsonSerializer correctly --- Emby.Server.Implementations/ApplicationHost.cs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index b724dc320..bae97c17e 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -258,8 +258,6 @@ namespace Emby.Server.Implementations protected INetworkManager NetworkManager { get; set; } - public IJsonSerializer JsonSerializer { get; private set; } - /// /// Initializes a new instance of the class. /// @@ -500,8 +498,6 @@ namespace Emby.Server.Implementations HttpsPort = ServerConfiguration.DefaultHttpsPort; } - JsonSerializer = new JsonSerializer(); - if (Plugins != null) { var pluginBuilder = new StringBuilder(); @@ -568,7 +564,7 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(ApplicationPaths); - serviceCollection.AddSingleton(JsonSerializer); + serviceCollection.AddSingleton(); // TODO: Remove support for injecting ILogger completely serviceCollection.AddSingleton((provider) => @@ -813,7 +809,7 @@ namespace Emby.Server.Implementations private void SetStaticProperties() { // For now there's no real way to inject these properly - BaseItem.Logger = LoggerFactory.CreateLogger("BaseItem"); + BaseItem.Logger = Resolve>(); BaseItem.ConfigurationManager = ServerConfigurationManager; BaseItem.LibraryManager = Resolve(); BaseItem.ProviderManager = Resolve(); @@ -829,7 +825,7 @@ namespace Emby.Server.Implementations UserView.CollectionManager = Resolve(); BaseItem.MediaSourceManager = Resolve(); CollectionFolder.XmlSerializer = XmlSerializer; - CollectionFolder.JsonSerializer = JsonSerializer; + CollectionFolder.JsonSerializer = Resolve(); CollectionFolder.ApplicationHost = this; AuthenticatedAttribute.AuthService = Resolve(); } From 241d0ae65cca0ffdd92b7c366d692acaa71cd211 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 23:14:35 -0400 Subject: [PATCH 45/83] Inject IStartupOptions into StartupWizard --- Emby.Server.Implementations/ApplicationHost.cs | 2 ++ .../EntryPoints/StartupWizard.cs | 14 ++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index bae97c17e..0620469c0 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -557,6 +557,8 @@ namespace Emby.Server.Implementations : typeof(NullImageEncoder); serviceCollection.AddSingleton(typeof(IImageEncoder), imageEncoderType); + serviceCollection.AddSingleton(_startupOptions); + serviceCollection.AddMemoryCache(); serviceCollection.AddSingleton(ConfigurationManager); diff --git a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs index 8e9771931..af1604aa6 100644 --- a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs +++ b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs @@ -16,17 +16,25 @@ namespace Emby.Server.Implementations.EntryPoints private readonly IServerApplicationHost _appHost; private readonly IConfiguration _appConfig; private readonly IServerConfigurationManager _config; + private readonly IStartupOptions _startupOptions; /// /// Initializes a new instance of the class. /// /// The application host. + /// The application configuration. /// The configuration manager. - public StartupWizard(IServerApplicationHost appHost, IConfiguration appConfig, IServerConfigurationManager config) + /// The application startup options. + public StartupWizard( + IServerApplicationHost appHost, + IConfiguration appConfig, + IServerConfigurationManager config, + IStartupOptions startupOptions) { _appHost = appHost; _appConfig = appConfig; _config = config; + _startupOptions = startupOptions; } /// @@ -47,9 +55,7 @@ namespace Emby.Server.Implementations.EntryPoints } else if (_config.Configuration.AutoRunWebApp) { - var options = ((ApplicationHost)_appHost).StartupOptions; - - if (!options.NoAutoRunWebApp) + if (!_startupOptions.NoAutoRunWebApp) { BrowserLauncher.OpenWebApp(_appHost); } From 735d6c8ad531904c24650d88dd07ef3e57ded46a Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 23:18:11 -0400 Subject: [PATCH 46/83] Convert properties in ApplicationHost to private readonly fields, where possible --- .../ApplicationHost.cs | 67 +++++++------------ .../Data/SqliteItemRepository.cs | 2 +- Jellyfin.Server/CoreAppHost.cs | 3 - 3 files changed, 27 insertions(+), 45 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 0620469c0..06b6fec55 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -119,17 +119,21 @@ namespace Emby.Server.Implementations /// public abstract class ApplicationHost : IServerApplicationHost, IDisposable { - private SqliteUserRepository _userRepository; + private readonly IFileSystem _fileSystemManager; + private readonly INetworkManager _networkManager; + private readonly IXmlSerializer _xmlSerializer; + private readonly IStartupOptions _startupOptions; + private IMediaEncoder _mediaEncoder; private ISessionManager _sessionManager; private IHttpServer _httpServer; private IHttpClient _httpClient; + private IInstallationManager _installationManager; /// /// Gets a value indicating whether this instance can self restart. /// - /// true if this instance can self restart; otherwise, false. - public abstract bool CanSelfRestart { get; } + public bool CanSelfRestart => _startupOptions.RestartPath != null; public virtual bool CanLaunchWebBrowser { @@ -140,7 +144,7 @@ namespace Emby.Server.Implementations return false; } - if (StartupOptions.IsService) + if (_startupOptions.IsService) { return false; } @@ -210,8 +214,6 @@ namespace Emby.Server.Implementations /// The configuration manager. protected IConfigurationManager ConfigurationManager { get; set; } - public IFileSystem FileSystemManager { get; set; } - /// public PackageVersionClass SystemUpdateLevel { @@ -246,18 +248,6 @@ namespace Emby.Server.Implementations /// The server configuration manager. public IServerConfigurationManager ServerConfigurationManager => (IServerConfigurationManager)ConfigurationManager; - /// - /// Gets the installation manager. - /// - /// The installation manager. - protected IInstallationManager InstallationManager { get; private set; } - - public IStartupOptions StartupOptions { get; } - - protected readonly IXmlSerializer XmlSerializer; - - protected INetworkManager NetworkManager { get; set; } - /// /// Initializes a new instance of the class. /// @@ -268,24 +258,24 @@ namespace Emby.Server.Implementations IFileSystem fileSystem, INetworkManager networkManager) { - XmlSerializer = new MyXmlSerializer(); + _xmlSerializer = new MyXmlSerializer(); - NetworkManager = networkManager; + _networkManager = networkManager; networkManager.LocalSubnetsFn = GetConfiguredLocalSubnets; ApplicationPaths = applicationPaths; LoggerFactory = loggerFactory; - FileSystemManager = fileSystem; + _fileSystemManager = fileSystem; - ConfigurationManager = new ServerConfigurationManager(ApplicationPaths, LoggerFactory, XmlSerializer, FileSystemManager); + ConfigurationManager = new ServerConfigurationManager(ApplicationPaths, LoggerFactory, _xmlSerializer, _fileSystemManager); Logger = LoggerFactory.CreateLogger("App"); - StartupOptions = options; + _startupOptions = options; fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem)); - NetworkManager.NetworkChanged += OnNetworkChanged; + _networkManager.NetworkChanged += OnNetworkChanged; CertificateInfo = new CertificateInfo { @@ -575,18 +565,18 @@ namespace Emby.Server.Implementations return Logger; }); - serviceCollection.AddSingleton(FileSystemManager); + serviceCollection.AddSingleton(_fileSystemManager); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(NetworkManager); + serviceCollection.AddSingleton(_networkManager); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(XmlSerializer); + serviceCollection.AddSingleton(_xmlSerializer); serviceCollection.AddSingleton(); @@ -636,7 +626,7 @@ namespace Emby.Server.Implementations provider.GetRequiredService(), provider.GetRequiredService, provider.GetRequiredService(), - StartupOptions.FFmpegPath)); + _startupOptions.FFmpegPath)); // TODO: Refactor to eliminate the circular dependencies here so that Lazy isn't required serviceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); @@ -736,6 +726,8 @@ namespace Emby.Server.Implementations var userDataRepo = (SqliteUserDataRepository)Resolve(); ((SqliteItemRepository)Resolve()).Initialize(userDataRepo, userManager); + Resolve().PluginInstalled += PluginInstalled; + FindParts(); } @@ -818,7 +810,7 @@ namespace Emby.Server.Implementations BaseItem.LocalizationManager = Resolve(); BaseItem.ItemRepository = Resolve(); User.UserManager = Resolve(); - BaseItem.FileSystem = FileSystemManager; + BaseItem.FileSystem = _fileSystemManager; BaseItem.UserDataManager = Resolve(); BaseItem.ChannelManager = Resolve(); Video.LiveTvManager = Resolve(); @@ -826,7 +818,7 @@ namespace Emby.Server.Implementations UserView.TVSeriesManager = Resolve(); UserView.CollectionManager = Resolve(); BaseItem.MediaSourceManager = Resolve(); - CollectionFolder.XmlSerializer = XmlSerializer; + CollectionFolder.XmlSerializer = _xmlSerializer; CollectionFolder.JsonSerializer = Resolve(); CollectionFolder.ApplicationHost = this; AuthenticatedAttribute.AuthService = Resolve(); @@ -872,9 +864,6 @@ namespace Emby.Server.Implementations /// private void FindParts() { - InstallationManager = ServiceProvider.GetService(); - InstallationManager.PluginInstalled += PluginInstalled; - if (!ServerConfigurationManager.Configuration.IsPortAuthorized) { ServerConfigurationManager.Configuration.IsPortAuthorized = true; @@ -1210,7 +1199,7 @@ namespace Emby.Server.Implementations IsShuttingDown = IsShuttingDown, Version = ApplicationVersionString, WebSocketPortNumber = HttpPort, - CompletedInstallations = InstallationManager.CompletedInstallations.ToArray(), + CompletedInstallations = _installationManager.CompletedInstallations.ToArray(), Id = SystemId, ProgramDataPath = ApplicationPaths.ProgramDataPath, WebPath = ApplicationPaths.WebPath, @@ -1233,12 +1222,12 @@ namespace Emby.Server.Implementations EncoderLocation = _mediaEncoder.EncoderLocation, SystemArchitecture = RuntimeInformation.OSArchitecture, SystemUpdateLevel = SystemUpdateLevel, - PackageName = StartupOptions.PackageName + PackageName = _startupOptions.PackageName }; } public IEnumerable GetWakeOnLanInfo() - => NetworkManager.GetMacAddresses() + => _networkManager.GetMacAddresses() .Select(i => new WakeOnLanInfo(i)) .ToList(); @@ -1350,7 +1339,7 @@ namespace Emby.Server.Implementations if (addresses.Count == 0) { - addresses.AddRange(NetworkManager.GetLocalIpAddresses(ServerConfigurationManager.Configuration.IgnoreVirtualInterfaces)); + addresses.AddRange(_networkManager.GetLocalIpAddresses(ServerConfigurationManager.Configuration.IgnoreVirtualInterfaces)); } var resultList = new List(); @@ -1594,12 +1583,8 @@ namespace Emby.Server.Implementations Logger.LogError(ex, "Error disposing {Type}", part.GetType().Name); } } - - _userRepository?.Dispose(); } - _userRepository = null; - _disposed = true; } } diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 227f1a5e7..8db4146cd 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -42,7 +42,7 @@ namespace Emby.Server.Implementations.Data private readonly IServerConfigurationManager _config; private readonly IServerApplicationHost _appHost; private readonly ILocalizationManager _localization; - // TODO: Remove this dependency + // TODO: Remove this dependency. GetImageCacheTag() is the only method used and it can be converted to a static helper method private readonly IImageProcessor _imageProcessor; private readonly TypeMapper _typeMapper; diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index b35200e75..c3ac2ab41 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -36,9 +36,6 @@ namespace Jellyfin.Server { } - /// - public override bool CanSelfRestart => StartupOptions.RestartPath != null; - /// protected override void RestartInternal() => Program.Restart(); From f2760cb055ae6ee5971ca4a3ff342ecd7d829d99 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sun, 5 Apr 2020 10:03:53 -0400 Subject: [PATCH 47/83] Register IImageEncoder in Jellyfin.Server instead of Emby.Server.Implementations --- Emby.Server.Implementations/ApplicationHost.cs | 8 +------- .../Emby.Server.Implementations.csproj | 1 - Jellyfin.Server/CoreAppHost.cs | 14 ++++++++++++++ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 06b6fec55..0bc47627a 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -48,7 +48,6 @@ using Emby.Server.Implementations.Session; using Emby.Server.Implementations.SocketSharp; using Emby.Server.Implementations.TV; using Emby.Server.Implementations.Updates; -using Jellyfin.Drawing.Skia; using MediaBrowser.Api; using MediaBrowser.Common; using MediaBrowser.Common.Configuration; @@ -540,13 +539,8 @@ namespace Emby.Server.Implementations /// /// Registers services/resources with the service collection that will be available via DI. /// - protected void RegisterServices(IServiceCollection serviceCollection) + protected virtual void RegisterServices(IServiceCollection serviceCollection) { - var imageEncoderType = SkiaEncoder.IsNativeLibAvailable() - ? typeof(SkiaEncoder) - : typeof(NullImageEncoder); - serviceCollection.AddSingleton(typeof(IImageEncoder), imageEncoderType); - serviceCollection.AddSingleton(_startupOptions); serviceCollection.AddMemoryCache(); diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 6c20842c7..d302d8984 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -4,7 +4,6 @@ - diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index c3ac2ab41..0769bf844 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -1,9 +1,12 @@ using System.Collections.Generic; using System.Reflection; +using Emby.Drawing; using Emby.Server.Implementations; +using Jellyfin.Drawing.Skia; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Drawing; using MediaBrowser.Model.IO; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; namespace Jellyfin.Server @@ -36,6 +39,17 @@ namespace Jellyfin.Server { } + /// + protected override void RegisterServices(IServiceCollection serviceCollection) + { + var imageEncoderType = SkiaEncoder.IsNativeLibAvailable() + ? typeof(SkiaEncoder) + : typeof(NullImageEncoder); + serviceCollection.AddSingleton(typeof(IImageEncoder), imageEncoderType); + + base.RegisterServices(serviceCollection); + } + /// protected override void RestartInternal() => Program.Restart(); From 2fcbc2a5b804e8d426dfd014560291d2399ab799 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 5 Apr 2020 21:19:04 +0200 Subject: [PATCH 48/83] Enable nullabe reference types for Emby.Drawing and Jellyfin.Drawing.Skia --- Emby.Dlna/ConfigurationExtension.cs | 1 + Emby.Drawing/Emby.Drawing.csproj | 1 + Emby.Drawing/ImageProcessor.cs | 22 +++---------- .../Data/SqliteItemRepository.cs | 9 +++++- .../Jellyfin.Drawing.Skia.csproj | 1 + .../PlayedIndicatorDrawer.cs | 13 +++----- Jellyfin.Drawing.Skia/SkiaEncoder.cs | 32 +++++++++---------- Jellyfin.Drawing.Skia/StripCollageBuilder.cs | 10 +++--- .../UnplayedCountIndicator.cs | 4 +-- .../Extensions/ShuffleExtensions.cs | 2 ++ 10 files changed, 45 insertions(+), 50 deletions(-) diff --git a/Emby.Dlna/ConfigurationExtension.cs b/Emby.Dlna/ConfigurationExtension.cs index e224d10bd..dba901967 100644 --- a/Emby.Dlna/ConfigurationExtension.cs +++ b/Emby.Dlna/ConfigurationExtension.cs @@ -1,3 +1,4 @@ +#nullable enable #pragma warning disable CS1591 using System.Collections.Generic; diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj index b7090b262..b17fff751 100644 --- a/Emby.Drawing/Emby.Drawing.csproj +++ b/Emby.Drawing/Emby.Drawing.csproj @@ -5,6 +5,7 @@ false true true + enable diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index eca4b56eb..3d6bcc045 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -121,11 +121,6 @@ namespace Emby.Drawing /// public async Task<(string path, string mimeType, DateTime dateModified)> ProcessImage(ImageProcessingOptions options) { - if (options == null) - { - throw new ArgumentNullException(nameof(options)); - } - var libraryManager = _libraryManager(); ItemImageInfo originalImage = options.Image; @@ -351,19 +346,12 @@ namespace Emby.Drawing /// public string GetImageCacheTag(BaseItem item, ChapterInfo chapter) { - try + return GetImageCacheTag(item, new ItemImageInfo { - return GetImageCacheTag(item, new ItemImageInfo - { - Path = chapter.ImagePath, - Type = ImageType.Chapter, - DateModified = chapter.ImageDateModified - }); - } - catch - { - return null; - } + Path = chapter.ImagePath, + Type = ImageType.Chapter, + DateModified = chapter.ImageDateModified + }); } private async Task<(string path, DateTime dateModified)> GetSupportedImage(string originalImagePath, DateTime dateModified) diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 46c6d5520..d3b3f7b7a 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -1991,7 +1991,14 @@ namespace Emby.Server.Implementations.Data if (!string.IsNullOrEmpty(chapter.ImagePath)) { - chapter.ImageTag = ImageProcessor.GetImageCacheTag(item, chapter); + try + { + chapter.ImageTag = ImageProcessor.GetImageCacheTag(item, chapter); + } + catch + { + + } } } diff --git a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj index d0a99e1e2..e4b4c058e 100644 --- a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj +++ b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj @@ -5,6 +5,7 @@ false true true + enable diff --git a/Jellyfin.Drawing.Skia/PlayedIndicatorDrawer.cs b/Jellyfin.Drawing.Skia/PlayedIndicatorDrawer.cs index 5084fd211..7eed5f4f7 100644 --- a/Jellyfin.Drawing.Skia/PlayedIndicatorDrawer.cs +++ b/Jellyfin.Drawing.Skia/PlayedIndicatorDrawer.cs @@ -26,7 +26,7 @@ namespace Jellyfin.Drawing.Skia { paint.Color = SKColor.Parse("#CC00A4DC"); paint.Style = SKPaintStyle.Fill; - canvas.DrawCircle((float)x, OffsetFromTopRightCorner, 20, paint); + canvas.DrawCircle(x, OffsetFromTopRightCorner, 20, paint); } using (var paint = new SKPaint()) @@ -39,16 +39,13 @@ namespace Jellyfin.Drawing.Skia // or: // var emojiChar = 0x1F680; - var text = "✔️"; - var emojiChar = StringUtilities.GetUnicodeCharacterCode(text, SKTextEncoding.Utf32); + const string Text = "✔️"; + var emojiChar = StringUtilities.GetUnicodeCharacterCode(Text, SKTextEncoding.Utf32); // ask the font manager for a font with that character - var fontManager = SKFontManager.Default; - var emojiTypeface = fontManager.MatchCharacter(emojiChar); + paint.Typeface = SKFontManager.Default.MatchCharacter(emojiChar); - paint.Typeface = emojiTypeface; - - canvas.DrawText(text, (float)x - 20, OffsetFromTopRightCorner + 12, paint); + canvas.DrawText(Text, (float)x - 20, OffsetFromTopRightCorner + 12, paint); } } } diff --git a/Jellyfin.Drawing.Skia/SkiaEncoder.cs b/Jellyfin.Drawing.Skia/SkiaEncoder.cs index a67118f18..723c52340 100644 --- a/Jellyfin.Drawing.Skia/SkiaEncoder.cs +++ b/Jellyfin.Drawing.Skia/SkiaEncoder.cs @@ -205,11 +205,6 @@ namespace Jellyfin.Drawing.Skia /// The file at the specified path could not be used to generate a codec. public ImageDimensions GetImageSize(string path) { - if (path == null) - { - throw new ArgumentNullException(nameof(path)); - } - if (!File.Exists(path)) { throw new FileNotFoundException("File not found", path); @@ -297,7 +292,7 @@ namespace Jellyfin.Drawing.Skia /// The orientation of the image. /// The detected origin of the image. /// The resulting bitmap of the image. - internal SKBitmap Decode(string path, bool forceCleanBitmap, ImageOrientation? orientation, out SKEncodedOrigin origin) + internal SKBitmap? Decode(string path, bool forceCleanBitmap, ImageOrientation? orientation, out SKEncodedOrigin origin) { if (!File.Exists(path)) { @@ -348,12 +343,17 @@ namespace Jellyfin.Drawing.Skia return resultBitmap; } - private SKBitmap GetBitmap(string path, bool cropWhitespace, bool forceAnalyzeBitmap, ImageOrientation? orientation, out SKEncodedOrigin origin) + private SKBitmap? GetBitmap(string path, bool cropWhitespace, bool forceAnalyzeBitmap, ImageOrientation? orientation, out SKEncodedOrigin origin) { if (cropWhitespace) { using (var bitmap = Decode(path, forceAnalyzeBitmap, orientation, out origin)) { + if (bitmap == null) + { + return null; + } + return CropWhiteSpace(bitmap); } } @@ -361,13 +361,11 @@ namespace Jellyfin.Drawing.Skia return Decode(path, forceAnalyzeBitmap, orientation, out origin); } - private SKBitmap GetBitmap(string path, bool cropWhitespace, bool autoOrient, ImageOrientation? orientation) + private SKBitmap? GetBitmap(string path, bool cropWhitespace, bool autoOrient, ImageOrientation? orientation) { - SKEncodedOrigin origin; - if (autoOrient) { - var bitmap = GetBitmap(path, cropWhitespace, true, orientation, out origin); + var bitmap = GetBitmap(path, cropWhitespace, true, orientation, out var origin); if (bitmap != null && origin != SKEncodedOrigin.TopLeft) { @@ -380,7 +378,7 @@ namespace Jellyfin.Drawing.Skia return bitmap; } - return GetBitmap(path, cropWhitespace, false, orientation, out origin); + return GetBitmap(path, cropWhitespace, false, orientation, out _); } private SKBitmap OrientImage(SKBitmap bitmap, SKEncodedOrigin origin) @@ -517,14 +515,14 @@ namespace Jellyfin.Drawing.Skia /// public string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation? orientation, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) { - if (string.IsNullOrWhiteSpace(inputPath)) + if (inputPath.Length == 0) { - throw new ArgumentNullException(nameof(inputPath)); + throw new ArgumentException("String can't be empty.", nameof(inputPath)); } - if (string.IsNullOrWhiteSpace(inputPath)) + if (outputPath.Length == 0) { - throw new ArgumentNullException(nameof(outputPath)); + throw new ArgumentException("String can't be empty.", nameof(outputPath)); } var skiaOutputFormat = GetImageFormat(selectedOutputFormat); @@ -538,7 +536,7 @@ namespace Jellyfin.Drawing.Skia { if (bitmap == null) { - throw new ArgumentOutOfRangeException($"Skia unable to read image {inputPath}"); + throw new InvalidDataException($"Skia unable to read image {inputPath}"); } var originalImageSize = new ImageDimensions(bitmap.Width, bitmap.Height); diff --git a/Jellyfin.Drawing.Skia/StripCollageBuilder.cs b/Jellyfin.Drawing.Skia/StripCollageBuilder.cs index 0735ef194..61bef90ec 100644 --- a/Jellyfin.Drawing.Skia/StripCollageBuilder.cs +++ b/Jellyfin.Drawing.Skia/StripCollageBuilder.cs @@ -120,13 +120,13 @@ namespace Jellyfin.Drawing.Skia } // resize to the same aspect as the original - int iWidth = (int)Math.Abs(iHeight * currentBitmap.Width / currentBitmap.Height); + int iWidth = Math.Abs(iHeight * currentBitmap.Width / currentBitmap.Height); using (var resizeBitmap = new SKBitmap(iWidth, iHeight, currentBitmap.ColorType, currentBitmap.AlphaType)) { currentBitmap.ScalePixels(resizeBitmap, SKFilterQuality.High); // crop image - int ix = (int)Math.Abs((iWidth - iSlice) / 2); + int ix = Math.Abs((iWidth - iSlice) / 2); using (var image = SKImage.FromBitmap(resizeBitmap)) using (var subset = image.Subset(SKRectI.Create(ix, 0, iSlice, iHeight))) { @@ -141,10 +141,10 @@ namespace Jellyfin.Drawing.Skia return bitmap; } - private SKBitmap GetNextValidImage(string[] paths, int currentIndex, out int newIndex) + private SKBitmap? GetNextValidImage(string[] paths, int currentIndex, out int newIndex) { var imagesTested = new Dictionary(); - SKBitmap bitmap = null; + SKBitmap? bitmap = null; while (imagesTested.Count < paths.Length) { @@ -153,7 +153,7 @@ namespace Jellyfin.Drawing.Skia currentIndex = 0; } - bitmap = _skiaEncoder.Decode(paths[currentIndex], false, null, out var origin); + bitmap = _skiaEncoder.Decode(paths[currentIndex], false, null, out _); imagesTested[currentIndex] = 0; diff --git a/Jellyfin.Drawing.Skia/UnplayedCountIndicator.cs b/Jellyfin.Drawing.Skia/UnplayedCountIndicator.cs index a10fff9df..cf3dbde2c 100644 --- a/Jellyfin.Drawing.Skia/UnplayedCountIndicator.cs +++ b/Jellyfin.Drawing.Skia/UnplayedCountIndicator.cs @@ -32,7 +32,7 @@ namespace Jellyfin.Drawing.Skia { paint.Color = SKColor.Parse("#CC00A4DC"); paint.Style = SKPaintStyle.Fill; - canvas.DrawCircle((float)x, OffsetFromTopRightCorner, 20, paint); + canvas.DrawCircle(x, OffsetFromTopRightCorner, 20, paint); } using (var paint = new SKPaint()) @@ -61,7 +61,7 @@ namespace Jellyfin.Drawing.Skia paint.TextSize = 18; } - canvas.DrawText(text, (float)x, y, paint); + canvas.DrawText(text, x, y, paint); } } } diff --git a/MediaBrowser.Common/Extensions/ShuffleExtensions.cs b/MediaBrowser.Common/Extensions/ShuffleExtensions.cs index 0432f36b5..459bec110 100644 --- a/MediaBrowser.Common/Extensions/ShuffleExtensions.cs +++ b/MediaBrowser.Common/Extensions/ShuffleExtensions.cs @@ -1,3 +1,5 @@ +#nullable enable + using System; using System.Collections.Generic; From 8e9aeb84b18f43b6fe8dd89ab84f1627bf2e8dbd Mon Sep 17 00:00:00 2001 From: dkanada Date: Sat, 11 Apr 2020 19:33:36 +0900 Subject: [PATCH 49/83] remove release channel from plugin classes --- .../ApplicationHost.cs | 14 ------------- .../Updates/InstallationManager.cs | 21 +++++++------------ MediaBrowser.Api/PackageService.cs | 10 +-------- MediaBrowser.Common/IApplicationHost.cs | 6 ------ .../Updates/IInstallationManager.cs | 8 ++----- .../Services/IHasRequestFilter.cs | 10 ++++----- MediaBrowser.Model/System/SystemInfo.cs | 2 -- .../Updates/InstallationInfo.cs | 6 ------ MediaBrowser.Model/Updates/ReleaseChannel.cs | 18 ---------------- MediaBrowser.Model/Updates/VersionInfo.cs | 6 ------ 10 files changed, 15 insertions(+), 86 deletions(-) delete mode 100644 MediaBrowser.Model/Updates/ReleaseChannel.cs diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index ad77ab8b4..3cf4d6c6d 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -211,19 +211,6 @@ namespace Emby.Server.Implementations public IFileSystem FileSystemManager { get; set; } - /// - public ReleaseChannel SystemUpdateLevel - { - get - { -#if NIGHTLY - return PackageChannel.Nightly; -#else - return ReleaseChannel.Stable; -#endif - } - } - /// /// Gets or sets the service provider. /// @@ -1416,7 +1403,6 @@ namespace Emby.Server.Implementations SupportsLibraryMonitor = true, EncoderLocation = MediaEncoder.EncoderLocation, SystemArchitecture = RuntimeInformation.OSArchitecture, - SystemUpdateLevel = SystemUpdateLevel, PackageName = StartupOptions.PackageName }; } diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 1450c74d2..a00dec4c3 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -150,13 +150,11 @@ namespace Emby.Server.Implementations.Updates /// public IEnumerable GetCompatibleVersions( IEnumerable availableVersions, - Version minVersion = null, - ReleaseChannel releaseChannel = ReleaseChannel.Stable) + Version minVersion = null) { var appVer = _applicationHost.ApplicationVersion; availableVersions = availableVersions - .Where(x => x.channel == releaseChannel - && Version.Parse(x.minimumServerVersion) <= appVer); + .Where(x => Version.Parse(x.minimumServerVersion) <= appVer); if (minVersion != null) { @@ -171,8 +169,7 @@ namespace Emby.Server.Implementations.Updates IEnumerable availablePackages, string name = null, Guid guid = default, - Version minVersion = null, - ReleaseChannel releaseChannel = ReleaseChannel.Stable) + Version minVersion = null) { var package = FilterPackages(availablePackages, name, guid).FirstOrDefault(); @@ -184,8 +181,7 @@ namespace Emby.Server.Implementations.Updates return GetCompatibleVersions( package.versions, - minVersion, - releaseChannel); + minVersion); } /// @@ -193,12 +189,10 @@ namespace Emby.Server.Implementations.Updates { var catalog = await GetAvailablePackages(cancellationToken).ConfigureAwait(false); - var systemUpdateLevel = _applicationHost.SystemUpdateLevel; - // Figure out what needs to be installed foreach (var plugin in _applicationHost.Plugins) { - var compatibleVersions = GetCompatibleVersions(catalog, plugin.Name, plugin.Id, plugin.Version, systemUpdateLevel); + var compatibleVersions = GetCompatibleVersions(catalog, plugin.Name, plugin.Id, plugin.Version); var version = compatibleVersions.FirstOrDefault(y => y.versionCode > plugin.Version); if (version != null && !CompletedInstallations.Any(x => string.Equals(x.AssemblyGuid, version.guid, StringComparison.OrdinalIgnoreCase))) @@ -221,7 +215,6 @@ namespace Emby.Server.Implementations.Updates Id = Guid.NewGuid(), Name = package.name, AssemblyGuid = package.guid, - UpdateClass = package.channel, Version = package.versionString }; @@ -313,13 +306,13 @@ namespace Emby.Server.Implementations.Updates // Do plugin-specific processing if (plugin == null) { - _logger.LogInformation("New plugin installed: {0} {1} {2}", package.name, package.versionString ?? string.Empty, package.channel); + _logger.LogInformation("New plugin installed: {0} {1} {2}", package.name, package.versionString ?? string.Empty); PluginInstalled?.Invoke(this, new GenericEventArgs(package)); } else { - _logger.LogInformation("Plugin updated: {0} {1} {2}", package.name, package.versionString ?? string.Empty, package.channel); + _logger.LogInformation("Plugin updated: {0} {1} {2}", package.name, package.versionString ?? string.Empty); PluginUpdated?.Invoke(this, new GenericEventArgs<(IPlugin, VersionInfo)>((plugin, package))); } diff --git a/MediaBrowser.Api/PackageService.cs b/MediaBrowser.Api/PackageService.cs index ccc978295..444354a99 100644 --- a/MediaBrowser.Api/PackageService.cs +++ b/MediaBrowser.Api/PackageService.cs @@ -71,13 +71,6 @@ namespace MediaBrowser.Api /// The version. [ApiMember(Name = "Version", Description = "Optional version. Defaults to latest version.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] public string Version { get; set; } - - /// - /// Gets or sets the update class. - /// - /// The update class. - [ApiMember(Name = "UpdateClass", Description = "Optional update class (Dev, Beta, Release). Defaults to Release.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] - public ReleaseChannel UpdateClass { get; set; } } /// @@ -152,8 +145,7 @@ namespace MediaBrowser.Api packages, request.Name, string.IsNullOrEmpty(request.AssemblyGuid) ? Guid.Empty : Guid.Parse(request.AssemblyGuid), - string.IsNullOrEmpty(request.Version) ? null : Version.Parse(request.Version), - request.UpdateClass).FirstOrDefault(); + string.IsNullOrEmpty(request.Version) ? null : Version.Parse(request.Version)).FirstOrDefault(); if (package == null) { diff --git a/MediaBrowser.Common/IApplicationHost.cs b/MediaBrowser.Common/IApplicationHost.cs index c88eac27a..695e6f875 100644 --- a/MediaBrowser.Common/IApplicationHost.cs +++ b/MediaBrowser.Common/IApplicationHost.cs @@ -47,12 +47,6 @@ namespace MediaBrowser.Common /// true if this instance can self restart; otherwise, false. bool CanSelfRestart { get; } - /// - /// Gets the version class of the system. - /// - /// or . - ReleaseChannel SystemUpdateLevel { get; } - /// /// Gets the application version. /// diff --git a/MediaBrowser.Common/Updates/IInstallationManager.cs b/MediaBrowser.Common/Updates/IInstallationManager.cs index 284e418d9..4d512220b 100644 --- a/MediaBrowser.Common/Updates/IInstallationManager.cs +++ b/MediaBrowser.Common/Updates/IInstallationManager.cs @@ -65,12 +65,10 @@ namespace MediaBrowser.Common.Updates /// /// The available version of the plugin. /// The minimum required version of the plugin. - /// The classification of updates. /// All compatible versions ordered from newest to oldest. IEnumerable GetCompatibleVersions( IEnumerable availableVersions, - Version minVersion = null, - ReleaseChannel releaseChannel = ReleaseChannel.Stable); + Version minVersion = null); /// /// Returns all compatible versions ordered from newest to oldest. @@ -79,14 +77,12 @@ namespace MediaBrowser.Common.Updates /// The name. /// The guid of the plugin. /// The minimum required version of the plugin. - /// The classification. /// All compatible versions ordered from newest to oldest. IEnumerable GetCompatibleVersions( IEnumerable availablePackages, string name = null, Guid guid = default, - Version minVersion = null, - ReleaseChannel releaseChannel = ReleaseChannel.Stable); + Version minVersion = null); /// /// Returns the available plugin updates. diff --git a/MediaBrowser.Model/Services/IHasRequestFilter.cs b/MediaBrowser.Model/Services/IHasRequestFilter.cs index c81e49e4e..418d5c501 100644 --- a/MediaBrowser.Model/Services/IHasRequestFilter.cs +++ b/MediaBrowser.Model/Services/IHasRequestFilter.cs @@ -9,17 +9,17 @@ namespace MediaBrowser.Model.Services { /// /// Order in which Request Filters are executed. - /// <0 Executed before global request filters - /// >0 Executed after global request filters + /// <0 Executed before global request filters. + /// >0 Executed after global request filters. /// int Priority { get; } /// /// The request filter is executed before the service. /// - /// The http request wrapper - /// The http response wrapper - /// The request DTO + /// The http request wrapper. + /// The http response wrapper. + /// The request DTO. void RequestFilter(IRequest req, HttpResponse res, object requestDto); } } diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs index da39ee208..bda43e1af 100644 --- a/MediaBrowser.Model/System/SystemInfo.cs +++ b/MediaBrowser.Model/System/SystemInfo.cs @@ -27,8 +27,6 @@ namespace MediaBrowser.Model.System /// public class SystemInfo : PublicSystemInfo { - public ReleaseChannel SystemUpdateLevel { get; set; } - /// /// Gets or sets the display name of the operating system. /// diff --git a/MediaBrowser.Model/Updates/InstallationInfo.cs b/MediaBrowser.Model/Updates/InstallationInfo.cs index 870bf8c0b..95357262a 100644 --- a/MediaBrowser.Model/Updates/InstallationInfo.cs +++ b/MediaBrowser.Model/Updates/InstallationInfo.cs @@ -30,11 +30,5 @@ namespace MediaBrowser.Model.Updates /// /// The version. public string Version { get; set; } - - /// - /// Gets or sets the update class. - /// - /// The update class. - public ReleaseChannel UpdateClass { get; set; } } } diff --git a/MediaBrowser.Model/Updates/ReleaseChannel.cs b/MediaBrowser.Model/Updates/ReleaseChannel.cs deleted file mode 100644 index ed4a774a7..000000000 --- a/MediaBrowser.Model/Updates/ReleaseChannel.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace MediaBrowser.Model.Updates -{ - /// - /// Enum PackageVersionClass. - /// - public enum ReleaseChannel - { - /// - /// The stable. - /// - Stable = 0, - - /// - /// The nightly. - /// - Nightly = 1 - } -} diff --git a/MediaBrowser.Model/Updates/VersionInfo.cs b/MediaBrowser.Model/Updates/VersionInfo.cs index ad893db2e..177b8dbc3 100644 --- a/MediaBrowser.Model/Updates/VersionInfo.cs +++ b/MediaBrowser.Model/Updates/VersionInfo.cs @@ -34,12 +34,6 @@ namespace MediaBrowser.Model.Updates /// The version. public Version versionCode { get; set; } - /// - /// Gets or sets the release channel. - /// - /// The release channel for a given package version. - public ReleaseChannel channel { get; set; } - /// /// Gets or sets the description. /// From 78abbcc25117a20511f70f65c89f2f1063d0e547 Mon Sep 17 00:00:00 2001 From: dkanada Date: Sat, 11 Apr 2020 19:52:40 +0900 Subject: [PATCH 50/83] standardize plugin version and guid properties --- .../Activity/ActivityLogEntryPoint.cs | 4 +-- .../Updates/InstallationManager.cs | 21 +++++++------- .../Updates/CheckForUpdateResult.cs | 29 ------------------- .../Updates/InstallationInfo.cs | 12 ++------ MediaBrowser.Model/Updates/PackageInfo.cs | 12 -------- MediaBrowser.Model/Updates/VersionInfo.cs | 8 +---- 6 files changed, 16 insertions(+), 70 deletions(-) delete mode 100644 MediaBrowser.Model/Updates/CheckForUpdateResult.cs diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index 0f0b8b97b..f60fdea84 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -433,7 +433,7 @@ namespace Emby.Server.Implementations.Activity ShortOverview = string.Format( CultureInfo.InvariantCulture, _localization.GetLocalizedString("VersionNumber"), - e.Argument.Item2.versionString), + e.Argument.Item2.version), Overview = e.Argument.Item2.description }); } @@ -462,7 +462,7 @@ namespace Emby.Server.Implementations.Activity ShortOverview = string.Format( CultureInfo.InvariantCulture, _localization.GetLocalizedString("VersionNumber"), - e.Argument.versionString) + e.Argument.version) }); } diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index a00dec4c3..ffb6b5cbc 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -158,10 +158,10 @@ namespace Emby.Server.Implementations.Updates if (minVersion != null) { - availableVersions = availableVersions.Where(x => x.versionCode >= minVersion); + availableVersions = availableVersions.Where(x => x.version >= minVersion); } - return availableVersions.OrderByDescending(x => x.versionCode); + return availableVersions.OrderByDescending(x => x.version); } /// @@ -193,9 +193,9 @@ namespace Emby.Server.Implementations.Updates foreach (var plugin in _applicationHost.Plugins) { var compatibleVersions = GetCompatibleVersions(catalog, plugin.Name, plugin.Id, plugin.Version); - var version = compatibleVersions.FirstOrDefault(y => y.versionCode > plugin.Version); + var version = compatibleVersions.FirstOrDefault(y => y.version > plugin.Version); if (version != null - && !CompletedInstallations.Any(x => string.Equals(x.AssemblyGuid, version.guid, StringComparison.OrdinalIgnoreCase))) + && !CompletedInstallations.Any(x => string.Equals(x.Guid, version.guid, StringComparison.OrdinalIgnoreCase))) { yield return version; } @@ -212,10 +212,9 @@ namespace Emby.Server.Implementations.Updates var installationInfo = new InstallationInfo { - Id = Guid.NewGuid(), + Guid = package.guid, Name = package.name, - AssemblyGuid = package.guid, - Version = package.versionString + Version = package.version.ToString() }; var innerCancellationTokenSource = new CancellationTokenSource(); @@ -258,7 +257,7 @@ namespace Emby.Server.Implementations.Updates _currentInstallations.Remove(tuple); } - _logger.LogInformation("Package installation cancelled: {0} {1}", package.name, package.versionString); + _logger.LogInformation("Package installation cancelled: {0} {1}", package.name, package.version); PackageInstallationCancelled?.Invoke(this, installationEventArgs); @@ -306,13 +305,13 @@ namespace Emby.Server.Implementations.Updates // Do plugin-specific processing if (plugin == null) { - _logger.LogInformation("New plugin installed: {0} {1} {2}", package.name, package.versionString ?? string.Empty); + _logger.LogInformation("New plugin installed: {0} {1} {2}", package.name, package.version); PluginInstalled?.Invoke(this, new GenericEventArgs(package)); } else { - _logger.LogInformation("Plugin updated: {0} {1} {2}", package.name, package.versionString ?? string.Empty); + _logger.LogInformation("Plugin updated: {0} {1} {2}", package.name, package.version); PluginUpdated?.Invoke(this, new GenericEventArgs<(IPlugin, VersionInfo)>((plugin, package))); } @@ -430,7 +429,7 @@ namespace Emby.Server.Implementations.Updates { lock (_currentInstallationsLock) { - var install = _currentInstallations.Find(x => x.info.Id == id); + var install = _currentInstallations.Find(x => x.info.Guid == id.ToString()); if (install == default((InstallationInfo, CancellationTokenSource))) { return false; diff --git a/MediaBrowser.Model/Updates/CheckForUpdateResult.cs b/MediaBrowser.Model/Updates/CheckForUpdateResult.cs deleted file mode 100644 index 883fc636b..000000000 --- a/MediaBrowser.Model/Updates/CheckForUpdateResult.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace MediaBrowser.Model.Updates -{ - /// - /// Class CheckForUpdateResult. - /// - public class CheckForUpdateResult - { - /// - /// Gets or sets a value indicating whether this instance is update available. - /// - /// true if this instance is update available; otherwise, false. - public bool IsUpdateAvailable { get; set; } - - /// - /// Gets or sets the available version. - /// - /// The available version. - public string AvailableVersion - { - get => Package != null ? Package.versionString : "0.0.0.1"; - set { } // need this for the serializer - } - - /// - /// Get or sets package information for an available update - /// - public VersionInfo Package { get; set; } - } -} diff --git a/MediaBrowser.Model/Updates/InstallationInfo.cs b/MediaBrowser.Model/Updates/InstallationInfo.cs index 95357262a..e0d450d06 100644 --- a/MediaBrowser.Model/Updates/InstallationInfo.cs +++ b/MediaBrowser.Model/Updates/InstallationInfo.cs @@ -8,10 +8,10 @@ namespace MediaBrowser.Model.Updates public class InstallationInfo { /// - /// Gets or sets the id. + /// Gets or sets the guid. /// - /// The id. - public Guid Id { get; set; } + /// The guid. + public string Guid { get; set; } /// /// Gets or sets the name. @@ -19,12 +19,6 @@ namespace MediaBrowser.Model.Updates /// The name. public string Name { get; set; } - /// - /// Gets or sets the assembly guid. - /// - /// The guid of the assembly. - public string AssemblyGuid { get; set; } - /// /// Gets or sets the version. /// diff --git a/MediaBrowser.Model/Updates/PackageInfo.cs b/MediaBrowser.Model/Updates/PackageInfo.cs index d06ffe1e6..b19c311e4 100644 --- a/MediaBrowser.Model/Updates/PackageInfo.cs +++ b/MediaBrowser.Model/Updates/PackageInfo.cs @@ -26,18 +26,6 @@ namespace MediaBrowser.Model.Updates /// The overview. public string overview { get; set; } - /// - /// Gets or sets the thumb image. - /// - /// The thumb image. - public string thumbImage { get; set; } - - /// - /// Gets or sets the preview image. - /// - /// The preview image. - public string previewImage { get; set; } - /// /// Gets or sets the target filename for the downloaded binary. /// diff --git a/MediaBrowser.Model/Updates/VersionInfo.cs b/MediaBrowser.Model/Updates/VersionInfo.cs index 177b8dbc3..6756e7454 100644 --- a/MediaBrowser.Model/Updates/VersionInfo.cs +++ b/MediaBrowser.Model/Updates/VersionInfo.cs @@ -22,17 +22,11 @@ namespace MediaBrowser.Model.Updates /// The guid. public string guid { get; set; } - /// - /// Gets or sets the version string. - /// - /// The version string. - public string versionString { get; set; } - /// /// Gets or sets the version. /// /// The version. - public Version versionCode { get; set; } + public Version version { get; set; } /// /// Gets or sets the description. From abb7ed9c35cc7727e81357c3b55555ee4c714d10 Mon Sep 17 00:00:00 2001 From: dkanada Date: Sat, 11 Apr 2020 19:54:33 +0900 Subject: [PATCH 51/83] rename target abi property --- Emby.Server.Implementations/Updates/InstallationManager.cs | 2 +- MediaBrowser.Model/Updates/VersionInfo.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index ffb6b5cbc..6a34ca74b 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -154,7 +154,7 @@ namespace Emby.Server.Implementations.Updates { var appVer = _applicationHost.ApplicationVersion; availableVersions = availableVersions - .Where(x => Version.Parse(x.minimumServerVersion) <= appVer); + .Where(x => Version.Parse(x.targetAbi) <= appVer); if (minVersion != null) { diff --git a/MediaBrowser.Model/Updates/VersionInfo.cs b/MediaBrowser.Model/Updates/VersionInfo.cs index 6756e7454..ac47e97da 100644 --- a/MediaBrowser.Model/Updates/VersionInfo.cs +++ b/MediaBrowser.Model/Updates/VersionInfo.cs @@ -35,10 +35,10 @@ namespace MediaBrowser.Model.Updates public string description { get; set; } /// - /// Gets or sets the minimum required version for the server. + /// Gets or sets the ABI that this version was built against. /// - /// The minimum required version. - public string minimumServerVersion { get; set; } + /// The target ABI version. + public string targetAbi { get; set; } /// /// Gets or sets the source URL. From 2da5df6c25b96e2a2d6790df7df8066a666dbe0e Mon Sep 17 00:00:00 2001 From: dkanada Date: Sat, 11 Apr 2020 19:56:42 +0900 Subject: [PATCH 52/83] add new property for version changelogs --- .../Activity/ActivityLogEntryPoint.cs | 2 +- MediaBrowser.Model/Updates/VersionInfo.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index f60fdea84..c91506b85 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -434,7 +434,7 @@ namespace Emby.Server.Implementations.Activity CultureInfo.InvariantCulture, _localization.GetLocalizedString("VersionNumber"), e.Argument.Item2.version), - Overview = e.Argument.Item2.description + Overview = e.Argument.Item2.changelog }); } diff --git a/MediaBrowser.Model/Updates/VersionInfo.cs b/MediaBrowser.Model/Updates/VersionInfo.cs index ac47e97da..e67e60d74 100644 --- a/MediaBrowser.Model/Updates/VersionInfo.cs +++ b/MediaBrowser.Model/Updates/VersionInfo.cs @@ -29,10 +29,10 @@ namespace MediaBrowser.Model.Updates public Version version { get; set; } /// - /// Gets or sets the description. + /// Gets or sets the changelog for this version. /// - /// The description. - public string description { get; set; } + /// The changelog. + public string changelog { get; set; } /// /// Gets or sets the ABI that this version was built against. From cbe1fe2c8f82af2233201203367ba8a532dbec8b Mon Sep 17 00:00:00 2001 From: dkanada Date: Sat, 11 Apr 2020 20:00:32 +0900 Subject: [PATCH 53/83] update description and overview for plugins --- MediaBrowser.Model/Updates/PackageInfo.cs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/MediaBrowser.Model/Updates/PackageInfo.cs b/MediaBrowser.Model/Updates/PackageInfo.cs index b19c311e4..f5aa8b6fa 100644 --- a/MediaBrowser.Model/Updates/PackageInfo.cs +++ b/MediaBrowser.Model/Updates/PackageInfo.cs @@ -15,23 +15,17 @@ namespace MediaBrowser.Model.Updates public string name { get; set; } /// - /// Gets or sets the short description. + /// Gets or sets a long description of the plugin containing features or helpful explanations. /// - /// The short description. - public string shortDescription { get; set; } + /// The description. + public string description { get; set; } /// - /// Gets or sets the overview. + /// Gets or sets a short overview of what the plugin does. /// /// The overview. public string overview { get; set; } - /// - /// Gets or sets the target filename for the downloaded binary. - /// - /// The target filename. - public string filename { get; set; } - /// /// Gets or sets the owner. /// From ff065df9863f30a4eec52a95d260cdadcced7b1e Mon Sep 17 00:00:00 2001 From: dkanada Date: Sat, 11 Apr 2020 20:11:41 +0900 Subject: [PATCH 54/83] update plugin manifest url --- Emby.Server.Implementations/ConfigurationOptions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/ConfigurationOptions.cs b/Emby.Server.Implementations/ConfigurationOptions.cs index 20bdd18e7..db7c35a7c 100644 --- a/Emby.Server.Implementations/ConfigurationOptions.cs +++ b/Emby.Server.Implementations/ConfigurationOptions.cs @@ -18,7 +18,7 @@ namespace Emby.Server.Implementations { { HostWebClientKey, bool.TrueString }, { HttpListenerHost.DefaultRedirectKey, "web/index.html" }, - { InstallationManager.PluginManifestUrlKey, "https://repo.jellyfin.org/releases/plugin/manifest.json" }, + { InstallationManager.PluginManifestUrlKey, "https://repo.jellyfin.org/releases/plugin/manifest-stable.json" }, { FfmpegProbeSizeKey, "1G" }, { FfmpegAnalyzeDurationKey, "200M" }, { PlaylistsAllowDuplicatesKey, bool.TrueString } From 17e8813378c2fe1a83d1eddb829dae68f8c71bfe Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 11 Apr 2020 10:53:13 -0400 Subject: [PATCH 55/83] Use ActivatorUtilities to construct MediaEncoder and update constructor to inject EncodingHelper correctly --- Emby.Server.Implementations/ApplicationHost.cs | 16 ++++------------ .../Encoder/MediaEncoder.cs | 16 ++++------------ 2 files changed, 8 insertions(+), 24 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 5b93981f0..ad0a69b19 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -88,7 +88,6 @@ using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Cryptography; using MediaBrowser.Model.Diagnostics; using MediaBrowser.Model.Dlna; -using MediaBrowser.Model.Events; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; @@ -106,7 +105,6 @@ using MediaBrowser.WebDashboard.Api; using MediaBrowser.XbmcMetadata.Providers; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Extensions; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using OperatingSystem = MediaBrowser.Common.System.OperatingSystem; @@ -614,17 +612,11 @@ namespace Emby.Server.Implementations serviceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); serviceCollection.AddSingleton(); - // TODO: Add StartupOptions.FFmpegPath to IConfiguration so this doesn't need to be constructed manually + // TODO: Refactor to eliminate the circular dependency here so that Lazy isn't required + // TODO: Add StartupOptions.FFmpegPath to IConfiguration and remove this custom activation + serviceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); serviceCollection.AddSingleton(provider => - new MediaBrowser.MediaEncoding.Encoder.MediaEncoder( - provider.GetRequiredService>(), - provider.GetRequiredService(), - provider.GetRequiredService(), - provider.GetRequiredService(), - provider.GetRequiredService(), - provider.GetRequiredService, - provider.GetRequiredService(), - _startupOptions.FFmpegPath)); + ActivatorUtilities.CreateInstance(provider, _startupOptions.FFmpegPath ?? string.Empty)); // TODO: Refactor to eliminate the circular dependencies here so that Lazy isn't required serviceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index f3f2b86ee..c5bba8780 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -40,8 +40,7 @@ namespace MediaBrowser.MediaEncoding.Encoder private readonly IFileSystem _fileSystem; private readonly IProcessFactory _processFactory; private readonly ILocalizationManager _localization; - private readonly Func _subtitleEncoder; - private readonly IConfiguration _configuration; + private readonly Lazy _encodingHelperFactory; private readonly string _startupOptionFFmpegPath; private readonly SemaphoreSlim _thumbnailResourcePool = new SemaphoreSlim(2, 2); @@ -49,8 +48,6 @@ namespace MediaBrowser.MediaEncoding.Encoder private readonly object _runningProcessesLock = new object(); private readonly List _runningProcesses = new List(); - private EncodingHelper _encodingHelper; - private string _ffmpegPath; private string _ffprobePath; @@ -60,8 +57,7 @@ namespace MediaBrowser.MediaEncoding.Encoder IFileSystem fileSystem, IProcessFactory processFactory, ILocalizationManager localization, - Func subtitleEncoder, - IConfiguration configuration, + Lazy encodingHelperFactory, string startupOptionsFFmpegPath) { _logger = logger; @@ -69,15 +65,11 @@ namespace MediaBrowser.MediaEncoding.Encoder _fileSystem = fileSystem; _processFactory = processFactory; _localization = localization; + _encodingHelperFactory = encodingHelperFactory; _startupOptionFFmpegPath = startupOptionsFFmpegPath; - _subtitleEncoder = subtitleEncoder; - _configuration = configuration; } - private EncodingHelper EncodingHelper - => LazyInitializer.EnsureInitialized( - ref _encodingHelper, - () => new EncodingHelper(this, _fileSystem, _subtitleEncoder(), _configuration)); + private EncodingHelper EncodingHelper => _encodingHelperFactory.Value; /// public string EncoderPath => _ffmpegPath; From 129e844252bae9becd3515a6dbf3bdff35180696 Mon Sep 17 00:00:00 2001 From: dkanada Date: Mon, 13 Apr 2020 02:20:37 +0900 Subject: [PATCH 56/83] use web artifacts for build step on ci --- .ci/azure-pipelines-compat.yml | 18 ++++++------ .ci/azure-pipelines-main.yml | 52 ++++++++++++++-------------------- .ci/azure-pipelines-test.yml | 35 +++++++++++------------ .ci/azure-pipelines.yml | 12 ++++---- 4 files changed, 54 insertions(+), 63 deletions(-) diff --git a/.ci/azure-pipelines-compat.yml b/.ci/azure-pipelines-compat.yml index de60d2ccb..1ffaaf2b9 100644 --- a/.ci/azure-pipelines-compat.yml +++ b/.ci/azure-pipelines-compat.yml @@ -1,13 +1,13 @@ parameters: - - name: Packages - type: object - default: {} - - name: LinuxImage - type: string - default: "ubuntu-latest" - - name: DotNetSdkVersion - type: string - default: 3.1.100 +- name: Packages + type: object + default: {} +- name: LinuxImage + type: string + default: "ubuntu-latest" +- name: DotNetSdkVersion + type: string + default: 3.1.100 jobs: - job: CompatibilityCheck diff --git a/.ci/azure-pipelines-main.yml b/.ci/azure-pipelines-main.yml index d155624ab..59acd51ec 100644 --- a/.ci/azure-pipelines-main.yml +++ b/.ci/azure-pipelines-main.yml @@ -20,41 +20,33 @@ jobs: submodules: true persistCredentials: true - - task: CmdLine@2 - displayName: "Clone Web Branch" - condition: and(succeeded(), or(contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')), eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI', 'BuildCompletion')) + - task: DownloadPipelineArtifact@2 + displayName: "Download Web Branch" + condition: in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI', 'BuildCompletion') inputs: - script: "git clone --single-branch --branch $(Build.SourceBranchName) --depth=1 https://github.com/jellyfin/jellyfin-web.git $(Agent.TempDirectory)/jellyfin-web" + path: '$(Agent.TempDirectory)' + artifact: 'jellyfin-web-production' + source: 'specific' + project: 'Jellyfin Web' + pipeline: 'Build' + runBranch: variables['Build.SourceBranch'] - - task: CmdLine@2 - displayName: "Clone Web Target" - condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master')), eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest')) + - task: DownloadPipelineArtifact@2 + displayName: "Download Web Target" + condition: in(variables['Build.Reason'], 'PullRequest') inputs: - script: "git clone --single-branch --branch $(System.PullRequest.TargetBranch) --depth 1 https://github.com/jellyfin/jellyfin-web.git $(Agent.TempDirectory)/jellyfin-web" + path: '$(Agent.TempDirectory)' + artifact: 'jellyfin-web-production' + source: 'specific' + project: 'Jellyfin Web' + pipeline: 'Build' + runBranch: variables['System.PullRequest.TargetBranch'] - - task: NodeTool@0 - displayName: "Install Node" - condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master'), contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')), eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest', 'IndividualCI', 'BatchedCI', 'BuildCompletion')) + - task: ExtractFiles@1 + displayName: "Extract Web Client" inputs: - versionSpec: "12.x" - - - task: CmdLine@2 - displayName: "Build Web Client" - condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master'), contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')), eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest', 'IndividualCI', 'BatchedCI', 'BuildCompletion')) - inputs: - script: yarn install - workingDirectory: $(Agent.TempDirectory)/jellyfin-web - - - task: CopyFiles@2 - displayName: "Copy Web Client" - condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master'), contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')), eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest', 'IndividualCI', 'BatchedCI', 'BuildCompletion')) - inputs: - sourceFolder: $(Agent.TempDirectory)/jellyfin-web/dist - contents: "**" - targetFolder: $(Build.SourcesDirectory)/MediaBrowser.WebDashboard/jellyfin-web - cleanTargetFolder: true - overWrite: true - flattenFolders: false + archiveFilePatterns: '$(Agent.TempDirectory)/*.zip' + destinationFolder: '$(Build.SourcesDirectory)/MediaBrowser.WebDashboard' - task: UseDotNet@2 displayName: "Update DotNet" diff --git a/.ci/azure-pipelines-test.yml b/.ci/azure-pipelines-test.yml index 4455632e1..a5d29fb61 100644 --- a/.ci/azure-pipelines-test.yml +++ b/.ci/azure-pipelines-test.yml @@ -1,26 +1,25 @@ parameters: - - name: ImageNames - type: object - default: - Linux: "ubuntu-latest" - Windows: "windows-latest" - macOS: "macos-latest" - - name: TestProjects - type: string - default: "tests/**/*Tests.csproj" - - name: DotNetSdkVersion - type: string - default: 3.1.100 +- name: ImageNames + type: object + default: + Linux: "ubuntu-latest" + Windows: "windows-latest" + macOS: "macos-latest" +- name: TestProjects + type: string + default: "tests/**/*Tests.csproj" +- name: DotNetSdkVersion + type: string + default: 3.1.100 jobs: - - job: MainTest - displayName: Main Test + - job: Test + displayName: Test strategy: matrix: ${{ each imageName in parameters.ImageNames }}: ${{ imageName.key }}: ImageName: ${{ imageName.value }} - maxParallel: 3 pool: vmImage: "$(ImageName)" steps: @@ -36,7 +35,7 @@ jobs: version: ${{ parameters.DotNetSdkVersion }} - task: DotNetCoreCLI@2 - displayName: Run .NET Core CLI tests + displayName: 'Run CLI Tests' inputs: command: "test" projects: ${{ parameters.TestProjects }} @@ -47,7 +46,7 @@ jobs: - task: Palmmedia.reportgenerator.reportgenerator-build-release-task.reportgenerator@4 condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux')) # !! THIS is for V1 only V2 will/should support merging - displayName: ReportGenerator (merge) + displayName: 'Run ReportGenerator' inputs: reports: "$(Agent.TempDirectory)/**/coverage.cobertura.xml" targetdir: "$(Agent.TempDirectory)/merged/" @@ -56,7 +55,7 @@ jobs: ## V2 is already in the repository but it does not work "wrong number of segments" YAML error. - task: PublishCodeCoverageResults@1 condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux')) # !! THIS is for V1 only V2 will/should support merging - displayName: Publish Code Coverage + displayName: 'Publish Code Coverage' inputs: codeCoverageTool: "cobertura" #summaryFileLocation: '$(Agent.TempDirectory)/**/coverage.cobertura.xml' # !!THIS IS FOR V2 diff --git a/.ci/azure-pipelines.yml b/.ci/azure-pipelines.yml index 3522cbf00..1a439c718 100644 --- a/.ci/azure-pipelines.yml +++ b/.ci/azure-pipelines.yml @@ -1,12 +1,12 @@ name: $(Date:yyyyMMdd)$(Rev:.r) variables: - - name: TestProjects - value: "tests/**/*Tests.csproj" - - name: RestoreBuildProjects - value: "Jellyfin.Server/Jellyfin.Server.csproj" - - name: DotNetSdkVersion - value: 3.1.100 +- name: TestProjects + value: "tests/**/*Tests.csproj" +- name: RestoreBuildProjects + value: "Jellyfin.Server/Jellyfin.Server.csproj" +- name: DotNetSdkVersion + value: 3.1.100 pr: autoCancel: true From 8c6e1ef27e79ad38f8cd5fdc42feb2e8ee313d41 Mon Sep 17 00:00:00 2001 From: dkanada Date: Mon, 13 Apr 2020 02:27:42 +0900 Subject: [PATCH 57/83] fix pipeline references --- .ci/azure-pipelines-main.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.ci/azure-pipelines-main.yml b/.ci/azure-pipelines-main.yml index 59acd51ec..de20412ab 100644 --- a/.ci/azure-pipelines-main.yml +++ b/.ci/azure-pipelines-main.yml @@ -27,8 +27,8 @@ jobs: path: '$(Agent.TempDirectory)' artifact: 'jellyfin-web-production' source: 'specific' - project: 'Jellyfin Web' - pipeline: 'Build' + project: 'jellyfin' + pipeline: 'Jellyfin Web' runBranch: variables['Build.SourceBranch'] - task: DownloadPipelineArtifact@2 @@ -38,8 +38,8 @@ jobs: path: '$(Agent.TempDirectory)' artifact: 'jellyfin-web-production' source: 'specific' - project: 'Jellyfin Web' - pipeline: 'Build' + project: 'jellyfin' + pipeline: 'Jellyfin Web' runBranch: variables['System.PullRequest.TargetBranch'] - task: ExtractFiles@1 From 4758e750907f28df3b324b8fb3243baf716c5a30 Mon Sep 17 00:00:00 2001 From: dkanada Date: Mon, 13 Apr 2020 02:34:52 +0900 Subject: [PATCH 58/83] leave files in destination folder during extraction --- .ci/azure-pipelines-main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.ci/azure-pipelines-main.yml b/.ci/azure-pipelines-main.yml index de20412ab..40568a3ae 100644 --- a/.ci/azure-pipelines-main.yml +++ b/.ci/azure-pipelines-main.yml @@ -47,6 +47,7 @@ jobs: inputs: archiveFilePatterns: '$(Agent.TempDirectory)/*.zip' destinationFolder: '$(Build.SourcesDirectory)/MediaBrowser.WebDashboard' + cleanDestinationFolder: false - task: UseDotNet@2 displayName: "Update DotNet" From b937eb0c1150a650492e666016e268d2b3f463c9 Mon Sep 17 00:00:00 2001 From: dkanada Date: Mon, 13 Apr 2020 14:34:31 +0900 Subject: [PATCH 59/83] change conditional for download task on ci Co-Authored-By: Mark Monteiro --- .ci/azure-pipelines-main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/azure-pipelines-main.yml b/.ci/azure-pipelines-main.yml index 40568a3ae..456be7108 100644 --- a/.ci/azure-pipelines-main.yml +++ b/.ci/azure-pipelines-main.yml @@ -33,7 +33,7 @@ jobs: - task: DownloadPipelineArtifact@2 displayName: "Download Web Target" - condition: in(variables['Build.Reason'], 'PullRequest') + condition: eq(variables['Build.Reason'], 'PullRequest') inputs: path: '$(Agent.TempDirectory)' artifact: 'jellyfin-web-production' From 6d35dd6b326b98995e363c64083a2ca46b2582fd Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Mon, 13 Apr 2020 13:13:48 -0400 Subject: [PATCH 60/83] Clean up SecurityException - Remove unused SecurityExceptionType - Add missing constructor for InnerException - Add missing documentation --- .../HttpServer/Security/AuthService.cs | 30 ++++------------- MediaBrowser.Api/UserService.cs | 2 +- .../Net/SecurityException.cs | 32 ++++++++++++++----- 3 files changed, 31 insertions(+), 33 deletions(-) diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs index 58421aaf1..1360a5e0c 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs @@ -108,18 +108,12 @@ namespace Emby.Server.Implementations.HttpServer.Security { if (user.Policy.IsDisabled) { - throw new SecurityException("User account has been disabled.") - { - SecurityExceptionType = SecurityExceptionType.Unauthenticated - }; + throw new SecurityException("User account has been disabled."); } if (!user.Policy.EnableRemoteAccess && !_networkManager.IsInLocalNetwork(request.RemoteIp)) { - throw new SecurityException("User account has been disabled.") - { - SecurityExceptionType = SecurityExceptionType.Unauthenticated - }; + throw new SecurityException("User account has been disabled."); } if (!user.Policy.IsAdministrator @@ -128,10 +122,7 @@ namespace Emby.Server.Implementations.HttpServer.Security { request.Response.Headers.Add("X-Application-Error-Code", "ParentalControl"); - throw new SecurityException("This user account is not allowed access at this time.") - { - SecurityExceptionType = SecurityExceptionType.ParentalControl - }; + throw new SecurityException("This user account is not allowed access at this time."); } } @@ -190,10 +181,7 @@ namespace Emby.Server.Implementations.HttpServer.Security { if (user == null || !user.Policy.IsAdministrator) { - throw new SecurityException("User does not have admin access.") - { - SecurityExceptionType = SecurityExceptionType.Unauthenticated - }; + throw new SecurityException("User does not have admin access."); } } @@ -201,10 +189,7 @@ namespace Emby.Server.Implementations.HttpServer.Security { if (user == null || !user.Policy.EnableContentDeletion) { - throw new SecurityException("User does not have delete access.") - { - SecurityExceptionType = SecurityExceptionType.Unauthenticated - }; + throw new SecurityException("User does not have delete access."); } } @@ -212,10 +197,7 @@ namespace Emby.Server.Implementations.HttpServer.Security { if (user == null || !user.Policy.EnableContentDownloading) { - throw new SecurityException("User does not have download access.") - { - SecurityExceptionType = SecurityExceptionType.Unauthenticated - }; + throw new SecurityException("User does not have download access."); } } } diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs index 401514349..78fc6c694 100644 --- a/MediaBrowser.Api/UserService.cs +++ b/MediaBrowser.Api/UserService.cs @@ -426,7 +426,7 @@ namespace MediaBrowser.Api catch (SecurityException e) { // rethrow adding IP address to message - throw new SecurityException($"[{Request.RemoteIp}] {e.Message}"); + throw new SecurityException($"[{Request.RemoteIp}] {e.Message}", e); } } diff --git a/MediaBrowser.Controller/Net/SecurityException.cs b/MediaBrowser.Controller/Net/SecurityException.cs index 3ccecf0eb..a5b94ea5e 100644 --- a/MediaBrowser.Controller/Net/SecurityException.cs +++ b/MediaBrowser.Controller/Net/SecurityException.cs @@ -2,20 +2,36 @@ using System; namespace MediaBrowser.Controller.Net { + /// + /// The exception that is thrown when a user is authenticated, but not authorized to access a requested resource. + /// public class SecurityException : Exception { + /// + /// Initializes a new instance of the class. + /// + public SecurityException() + : base() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. public SecurityException(string message) : base(message) { - } - public SecurityExceptionType SecurityExceptionType { get; set; } - } - - public enum SecurityExceptionType - { - Unauthenticated = 0, - ParentalControl = 1 + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error + /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. + public SecurityException(string message, Exception innerException) + : base(message, innerException) + { + } } } From 53380689ad00f00efc0c1790f1d25d08c95d7f2d Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Mon, 13 Apr 2020 13:17:46 -0400 Subject: [PATCH 61/83] Return correct status codes for authentication and authorization errors - Use AuthenticatonException to return 401 - Use SecurityException to return 403 - Update existing throws to throw the correct exception for the circumstance --- .../HttpServer/HttpListenerHost.cs | 5 ++++- .../HttpServer/Security/AuthService.cs | 7 ++++--- Emby.Server.Implementations/Library/UserManager.cs | 11 ++++------- Emby.Server.Implementations/Session/SessionManager.cs | 2 +- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs index 5ae65a4e3..f496ff1ba 100644 --- a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -14,6 +14,7 @@ using Emby.Server.Implementations.Services; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller; +using MediaBrowser.Controller.Authentication; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Net; using MediaBrowser.Model.Events; @@ -230,7 +231,8 @@ namespace Emby.Server.Implementations.HttpServer switch (ex) { case ArgumentException _: return 400; - case SecurityException _: return 401; + case AuthenticationException _: return 401; + case SecurityException _: return 403; case DirectoryNotFoundException _: case FileNotFoundException _: case ResourceNotFoundException _: return 404; @@ -550,6 +552,7 @@ namespace Emby.Server.Implementations.HttpServer || ex is IOException || ex is OperationCanceledException || ex is SecurityException + || ex is AuthenticationException || ex is FileNotFoundException; await ErrorHandler(ex, httpReq, !ignoreStackTrace, urlToLog).ConfigureAwait(false); } diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs index 1360a5e0c..256b24924 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs @@ -2,6 +2,7 @@ using System; using System.Linq; +using System.Security.Authentication; using Emby.Server.Implementations.SocketSharp; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; @@ -68,7 +69,7 @@ namespace Emby.Server.Implementations.HttpServer.Security if (user == null && auth.UserId != Guid.Empty) { - throw new SecurityException("User with Id " + auth.UserId + " not found"); + throw new AuthenticationException("User with Id " + auth.UserId + " not found"); } if (user != null) @@ -212,14 +213,14 @@ namespace Emby.Server.Implementations.HttpServer.Security { if (string.IsNullOrEmpty(token)) { - throw new SecurityException("Access token is required."); + throw new AuthenticationException("Access token is required."); } var info = GetTokenInfo(request); if (info == null) { - throw new SecurityException("Access token is invalid or expired."); + throw new AuthenticationException("Access token is invalid or expired."); } //if (!string.IsNullOrEmpty(info.UserId)) diff --git a/Emby.Server.Implementations/Library/UserManager.cs b/Emby.Server.Implementations/Library/UserManager.cs index 7b17cc913..f92cb6ae6 100644 --- a/Emby.Server.Implementations/Library/UserManager.cs +++ b/Emby.Server.Implementations/Library/UserManager.cs @@ -20,6 +20,7 @@ using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Providers; @@ -324,21 +325,17 @@ namespace Emby.Server.Implementations.Library if (user.Policy.IsDisabled) { - throw new AuthenticationException( - string.Format( - CultureInfo.InvariantCulture, - "The {0} account is currently disabled. Please consult with your administrator.", - user.Name)); + throw new SecurityException($"The {user.Name} account is currently disabled. Please consult with your administrator."); } if (!user.Policy.EnableRemoteAccess && !_networkManager.IsInLocalNetwork(remoteEndPoint)) { - throw new AuthenticationException("Forbidden."); + throw new SecurityException("Forbidden."); } if (!user.IsParentalScheduleAllowed()) { - throw new AuthenticationException("User is not allowed access at this time."); + throw new SecurityException("User is not allowed access at this time."); } // Update LastActivityDate and LastLoginDate, then save diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index de768333d..c93c02c48 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -1414,7 +1414,7 @@ namespace Emby.Server.Implementations.Session if (user == null) { AuthenticationFailed?.Invoke(this, new GenericEventArgs(request)); - throw new SecurityException("Invalid username or password entered."); + throw new AuthenticationException("Invalid username or password entered."); } if (!string.IsNullOrEmpty(request.DeviceId) From 98044e77935afdd4ff00a65d43b17d285fea82c7 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Mon, 13 Apr 2020 13:18:12 -0400 Subject: [PATCH 62/83] Document AuthenticationException correctly --- .../Authentication/AuthenticationException.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/MediaBrowser.Controller/Authentication/AuthenticationException.cs b/MediaBrowser.Controller/Authentication/AuthenticationException.cs index 62eca3ea9..28209f639 100644 --- a/MediaBrowser.Controller/Authentication/AuthenticationException.cs +++ b/MediaBrowser.Controller/Authentication/AuthenticationException.cs @@ -7,23 +7,29 @@ namespace MediaBrowser.Controller.Authentication /// public class AuthenticationException : Exception { - /// + /// + /// Initializes a new instance of the class. + /// public AuthenticationException() : base() { - } - /// + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. public AuthenticationException(string message) : base(message) { - } - /// + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error + /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. public AuthenticationException(string message, Exception innerException) : base(message, innerException) { - } } } From 9c7b3850f98633570cfb426e020153363921ce40 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Mon, 13 Apr 2020 14:55:24 -0400 Subject: [PATCH 63/83] Throw AuthenticationException instead of ArgumentNullException when a user does not exist --- .../Library/DefaultAuthenticationProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs b/Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs index ab036eca7..52c8facc3 100644 --- a/Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs +++ b/Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs @@ -47,7 +47,7 @@ namespace Emby.Server.Implementations.Library { if (resolvedUser == null) { - throw new ArgumentNullException(nameof(resolvedUser)); + throw new AuthenticationException($"Specified user does not exist."); } bool success = false; From a8c3951c1798ced5c10631da7d9ca64731a12f26 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Mon, 13 Apr 2020 15:26:49 -0400 Subject: [PATCH 64/83] Only show developer exception page for 500 server exceptions Other response codes should be returned as normal --- .../HttpServer/HttpListenerHost.cs | 93 ++++++++++--------- 1 file changed, 50 insertions(+), 43 deletions(-) diff --git a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs index f496ff1ba..4c69b35e2 100644 --- a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -241,40 +241,38 @@ namespace Emby.Server.Implementations.HttpServer } } - private async Task ErrorHandler(Exception ex, IRequest httpReq, bool logExceptionStackTrace, string urlToLog) + private async Task ErrorHandler(Exception ex, IRequest httpReq, int statusCode, string urlToLog) { - try + bool ignoreStackTrace = + ex is SocketException + || ex is IOException + || ex is OperationCanceledException + || ex is SecurityException + || ex is AuthenticationException + || ex is FileNotFoundException; + + if (ignoreStackTrace) { - ex = GetActualException(ex); - - if (logExceptionStackTrace) - { - _logger.LogError(ex, "Error processing request. URL: {Url}", urlToLog); - } - else - { - _logger.LogError("Error processing request: {Message}. URL: {Url}", ex.Message.TrimEnd('.'), urlToLog); - } - - var httpRes = httpReq.Response; - - if (httpRes.HasStarted) - { - return; - } - - var statusCode = GetStatusCode(ex); - httpRes.StatusCode = statusCode; - - var errContent = NormalizeExceptionMessage(ex.Message); - httpRes.ContentType = "text/plain"; - httpRes.ContentLength = errContent.Length; - await httpRes.WriteAsync(errContent).ConfigureAwait(false); + _logger.LogError("Error processing request: {Message}. URL: {Url}", ex.Message.TrimEnd('.'), urlToLog); } - catch (Exception errorEx) + else { - _logger.LogError(errorEx, "Error this.ProcessRequest(context)(Exception while writing error to the response). URL: {Url}", urlToLog); + _logger.LogError(ex, "Error processing request. URL: {Url}", urlToLog); } + + var httpRes = httpReq.Response; + + if (httpRes.HasStarted) + { + return; + } + + httpRes.StatusCode = statusCode; + + var errContent = NormalizeExceptionMessage(ex.Message); + httpRes.ContentType = "text/plain"; + httpRes.ContentLength = errContent.Length; + await httpRes.WriteAsync(errContent).ConfigureAwait(false); } private string NormalizeExceptionMessage(string msg) @@ -538,23 +536,32 @@ namespace Emby.Server.Implementations.HttpServer throw new FileNotFoundException(); } } - catch (Exception ex) + catch (Exception requestEx) { - // Do not handle exceptions manually when in development mode - // The framework-defined development exception page will be returned instead - if (_hostEnvironment.IsDevelopment()) + try { - throw; - } + var requestInnerEx = GetActualException(requestEx); + var statusCode = GetStatusCode(requestInnerEx); - bool ignoreStackTrace = - ex is SocketException - || ex is IOException - || ex is OperationCanceledException - || ex is SecurityException - || ex is AuthenticationException - || ex is FileNotFoundException; - await ErrorHandler(ex, httpReq, !ignoreStackTrace, urlToLog).ConfigureAwait(false); + // Do not handle 500 server exceptions manually when in development mode + // The framework-defined development exception page will be returned instead + if (statusCode == 500 && _hostEnvironment.IsDevelopment()) + { + throw; + } + + await ErrorHandler(requestInnerEx, httpReq, statusCode, urlToLog).ConfigureAwait(false); + } + catch (Exception handlerException) + { + var aggregateEx = new AggregateException("Error while handling request exception", requestEx, handlerException); + _logger.LogError(aggregateEx, "Error while handling exception in response to {Url}", urlToLog); + + if (_hostEnvironment.IsDevelopment()) + { + throw aggregateEx; + } + } } finally { From 8b4b4b4127945354731036e13ca0b5366134958d Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Mon, 13 Apr 2020 16:10:55 -0400 Subject: [PATCH 65/83] Do not return the exception message to the client for AuthenticationExceptions --- .../HttpServer/HttpListenerHost.cs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs index 4c69b35e2..211a0c1d9 100644 --- a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -269,25 +269,24 @@ namespace Emby.Server.Implementations.HttpServer httpRes.StatusCode = statusCode; - var errContent = NormalizeExceptionMessage(ex.Message); + var errContent = NormalizeExceptionMessage(ex) ?? string.Empty; httpRes.ContentType = "text/plain"; httpRes.ContentLength = errContent.Length; await httpRes.WriteAsync(errContent).ConfigureAwait(false); } - private string NormalizeExceptionMessage(string msg) + private string NormalizeExceptionMessage(Exception ex) { - if (msg == null) + // Do not expose the exception message for AuthenticationException + if (ex is AuthenticationException) { - return string.Empty; + return null; } // Strip any information we don't want to reveal - - msg = msg.Replace(_config.ApplicationPaths.ProgramSystemPath, string.Empty, StringComparison.OrdinalIgnoreCase); - msg = msg.Replace(_config.ApplicationPaths.ProgramDataPath, string.Empty, StringComparison.OrdinalIgnoreCase); - - return msg; + return ex.Message + ?.Replace(_config.ApplicationPaths.ProgramSystemPath, string.Empty, StringComparison.OrdinalIgnoreCase) + .Replace(_config.ApplicationPaths.ProgramDataPath, string.Empty, StringComparison.OrdinalIgnoreCase); } /// From 10afa4509db6fc7e3c2e7dd6ccc8997dfe3b10f9 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Wed, 15 Apr 2020 11:14:54 +0200 Subject: [PATCH 66/83] Log exception --- Emby.Server.Implementations/Data/SqliteItemRepository.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index d3b3f7b7a..aac0d8d38 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -1995,9 +1995,9 @@ namespace Emby.Server.Implementations.Data { chapter.ImageTag = ImageProcessor.GetImageCacheTag(item, chapter); } - catch + catch (Exception ex) { - + Logger.LogError(ex, "Failed to create image cache tag."); } } } From daed41815f23795aad7f54965a8ef7eae44a1e08 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Wed, 15 Apr 2020 08:56:00 -0400 Subject: [PATCH 67/83] Add missing punctuation in xml comment Co-Authored-By: Bond-009 --- .../Authentication/AuthenticationException.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Controller/Authentication/AuthenticationException.cs b/MediaBrowser.Controller/Authentication/AuthenticationException.cs index 28209f639..081f877f7 100644 --- a/MediaBrowser.Controller/Authentication/AuthenticationException.cs +++ b/MediaBrowser.Controller/Authentication/AuthenticationException.cs @@ -25,7 +25,7 @@ namespace MediaBrowser.Controller.Authentication /// /// Initializes a new instance of the class. /// - /// The message that describes the error + /// The message that describes the error. /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. public AuthenticationException(string message, Exception innerException) : base(message, innerException) From ecf49caf0d1392b0f2aa83bce1d08a006463566d Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Fri, 17 Apr 2020 10:24:46 -0400 Subject: [PATCH 68/83] Add back warning message when Skia encoder cannot be used --- Jellyfin.Server/CoreAppHost.cs | 11 ++++++++++- .../MediaEncoding/EncodingHelper.cs | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index 0769bf844..f678e714c 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Reflection; using Emby.Drawing; @@ -42,11 +43,19 @@ namespace Jellyfin.Server /// protected override void RegisterServices(IServiceCollection serviceCollection) { - var imageEncoderType = SkiaEncoder.IsNativeLibAvailable() + // Register an image encoder + bool useSkiaEncoder = SkiaEncoder.IsNativeLibAvailable(); + Type imageEncoderType = useSkiaEncoder ? typeof(SkiaEncoder) : typeof(NullImageEncoder); serviceCollection.AddSingleton(typeof(IImageEncoder), imageEncoderType); + // Log a warning if the Skia encoder could not be used + if (!useSkiaEncoder) + { + Logger.LogWarning($"Skia not available. Will fallback to {nameof(NullImageEncoder)}."); + } + base.RegisterServices(serviceCollection); } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 3552a45a2..5efb10d3a 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -459,7 +459,7 @@ namespace MediaBrowser.Controller.MediaEncoding { var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, encodingOptions); var outputVideoCodec = GetVideoEncoder(state, encodingOptions); - + var hasTextSubs = state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode; if (!hasTextSubs) From e6ef680775be122c3fcfbe64d4b8d868197b6f5e Mon Sep 17 00:00:00 2001 From: dkanada Date: Mon, 20 Apr 2020 14:27:46 +0900 Subject: [PATCH 69/83] add code suggestions --- MediaBrowser.Common/Extensions/BaseExtensions.cs | 1 + MediaBrowser.Model/Updates/VersionInfo.cs | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/MediaBrowser.Common/Extensions/BaseExtensions.cs b/MediaBrowser.Common/Extensions/BaseExtensions.cs index bc002e523..08964420e 100644 --- a/MediaBrowser.Common/Extensions/BaseExtensions.cs +++ b/MediaBrowser.Common/Extensions/BaseExtensions.cs @@ -35,6 +35,7 @@ namespace MediaBrowser.Common.Extensions { return new Guid(provider.ComputeHash(Encoding.Unicode.GetBytes(str))); } + #pragma warning restore CA5351 } } diff --git a/MediaBrowser.Model/Updates/VersionInfo.cs b/MediaBrowser.Model/Updates/VersionInfo.cs index e67e60d74..fe5826ad2 100644 --- a/MediaBrowser.Model/Updates/VersionInfo.cs +++ b/MediaBrowser.Model/Updates/VersionInfo.cs @@ -1,6 +1,3 @@ -#pragma warning disable CS1591 -#pragma warning disable SA1600 - using System; namespace MediaBrowser.Model.Updates From bd81825d2d2abba551d97d5c75890358d961fd27 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Mon, 20 Apr 2020 14:48:12 -0400 Subject: [PATCH 70/83] Respect AutoRunWebApp and NoAutoRunWebApp settings when HostWebClient is false --- .../EntryPoints/StartupWizard.cs | 36 ++++++++++++------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs index 8e9771931..a0a653d75 100644 --- a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs +++ b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs @@ -31,31 +31,41 @@ namespace Emby.Server.Implementations.EntryPoints /// public Task RunAsync() + { + Run(); + return Task.CompletedTask; + } + + private void Run() { if (!_appHost.CanLaunchWebBrowser) { - return Task.CompletedTask; + return; } - if (!_appConfig.HostWebClient()) + // Always launch the startup wizard if possible when it has not been completed + if (!_config.Configuration.IsStartupWizardCompleted && _appConfig.HostWebClient()) { - BrowserLauncher.OpenSwaggerPage(_appHost); + BrowserLauncher.OpenWebApp(_appHost); + return; } - else if (!_config.Configuration.IsStartupWizardCompleted) + + // Do nothing if the web app is configured to not run automatically + var options = ((ApplicationHost)_appHost).StartupOptions; + if (!_config.Configuration.AutoRunWebApp || options.NoAutoRunWebApp) + { + return; + } + + // Launch the swagger page if the web client is not hosted, otherwise open the web client + if (_appConfig.HostWebClient()) { BrowserLauncher.OpenWebApp(_appHost); } - else if (_config.Configuration.AutoRunWebApp) + else { - var options = ((ApplicationHost)_appHost).StartupOptions; - - if (!options.NoAutoRunWebApp) - { - BrowserLauncher.OpenWebApp(_appHost); - } + BrowserLauncher.OpenSwaggerPage(_appHost); } - - return Task.CompletedTask; } /// From bc4e72b29b7e43242028549df1d2471e65b045bc Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Mon, 20 Apr 2020 20:20:39 -0400 Subject: [PATCH 71/83] Create ApplicationHost logger correctly --- Emby.Server.Implementations/ApplicationHost.cs | 2 +- Emby.Server.Implementations/Library/LibraryManager.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 28aecf55b..33aec1a06 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -255,7 +255,7 @@ namespace Emby.Server.Implementations ConfigurationManager = new ServerConfigurationManager(ApplicationPaths, LoggerFactory, _xmlSerializer, _fileSystemManager); - Logger = LoggerFactory.CreateLogger("App"); + Logger = LoggerFactory.CreateLogger(); _startupOptions = options; diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 7b606c9f4..0b86b2db7 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -3091,7 +3091,7 @@ namespace Emby.Server.Implementations.Library { _configurationManager.Configuration.ContentTypes = _configurationManager.Configuration.ContentTypes .Except(removeList) - .ToArray(); + .ToArray(); _configurationManager.SaveConfiguration(); } From 166a4e8129d51f508e0e8a7566381c22fa6cf239 Mon Sep 17 00:00:00 2001 From: Mehdi Khosravi Date: Tue, 21 Apr 2020 09:21:56 +0000 Subject: [PATCH 72/83] Translated using Weblate (Persian) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/fa/ --- Emby.Server.Implementations/Localization/Core/fa.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/fa.json b/Emby.Server.Implementations/Localization/Core/fa.json index be6f87ee3..500c29217 100644 --- a/Emby.Server.Implementations/Localization/Core/fa.json +++ b/Emby.Server.Implementations/Localization/Core/fa.json @@ -23,7 +23,7 @@ "HeaderFavoriteEpisodes": "قسمت‌های مورد علاقه", "HeaderFavoriteShows": "سریال‌های مورد علاقه", "HeaderFavoriteSongs": "آهنگ‌های مورد علاقه", - "HeaderLiveTV": "تلویزیون زنده", + "HeaderLiveTV": "پخش زنده", "HeaderNextUp": "قسمت بعدی", "HeaderRecordingGroups": "گروه‌های ضبط", "HomeVideos": "ویدیوهای خانگی", From b88a94116bb7ac0857bffb38a3eb8bfe88a40d7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Silva?= Date: Tue, 21 Apr 2020 09:20:22 +0000 Subject: [PATCH 73/83] Translated using Weblate (Portuguese (Portugal)) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/pt_PT/ --- .../Localization/Core/pt-PT.json | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/pt-PT.json b/Emby.Server.Implementations/Localization/Core/pt-PT.json index ebf35c492..c1fb65743 100644 --- a/Emby.Server.Implementations/Localization/Core/pt-PT.json +++ b/Emby.Server.Implementations/Localization/Core/pt-PT.json @@ -26,7 +26,7 @@ "HeaderLiveTV": "TV em Direto", "HeaderNextUp": "A Seguir", "HeaderRecordingGroups": "Grupos de Gravação", - "HomeVideos": "Home videos", + "HomeVideos": "Videos caseiros", "Inherit": "Herdar", "ItemAddedWithName": "{0} foi adicionado à biblioteca", "ItemRemovedWithName": "{0} foi removido da biblioteca", @@ -92,5 +92,27 @@ "UserStoppedPlayingItemWithValues": "{0} terminou a reprodução de {1} em {2}", "ValueHasBeenAddedToLibrary": "{0} foi adicionado à sua biblioteca multimédia", "ValueSpecialEpisodeName": "Especial - {0}", - "VersionNumber": "Versão {0}" + "VersionNumber": "Versão {0}", + "TaskDownloadMissingSubtitlesDescription": "Procurar na internet por legendas em falta baseado na configuração de metadados.", + "TaskDownloadMissingSubtitles": "Fazer download de legendas em falta", + "TaskRefreshChannelsDescription": "Atualizar informação sobre canais da Internet.", + "TaskRefreshChannels": "Atualizar Canais", + "TaskCleanTranscodeDescription": "Apagar ficheiros de transcode com mais de um dia.", + "TaskCleanTranscode": "Limpar a Diretoria de Transcode", + "TaskUpdatePluginsDescription": "Faz o download e instala updates para os plugins que estão configurados para atualizar automaticamente.", + "TaskUpdatePlugins": "Atualizar Plugins", + "TaskRefreshPeopleDescription": "Atualizar metadados para atores e diretores na biblioteca.", + "TaskRefreshPeople": "Atualizar Pessoas", + "TaskCleanLogsDescription": "Apagar ficheiros de log que têm mais de {0} dias.", + "TaskCleanLogs": "Limpar a Diretoria de Logs", + "TaskRefreshLibraryDescription": "Scannear a biblioteca de música para novos ficheiros e atualizar os metadados.", + "TaskRefreshLibrary": "Scannear Biblioteca de Música", + "TaskRefreshChapterImagesDescription": "Criar thumbnails para os vídeos que têm capítulos.", + "TaskRefreshChapterImages": "Extrair Imagens dos Capítulos", + "TaskCleanCacheDescription": "Apagar ficheiros em cache que já não são necessários.", + "TaskCleanCache": "Limpar Cache", + "TasksChannelsCategory": "Canais da Internet", + "TasksApplicationCategory": "Aplicação", + "TasksLibraryCategory": "Biblioteca", + "TasksMaintenanceCategory": "Manutenção" } From a2f19eadf739297cbbc99c9082b0175e8b881054 Mon Sep 17 00:00:00 2001 From: "Chen-Tai,Peng" Date: Tue, 21 Apr 2020 17:18:29 +0000 Subject: [PATCH 74/83] Translated using Weblate (Chinese (Traditional)) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/zh_Hant/ --- .../Localization/Core/zh-TW.json | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/zh-TW.json b/Emby.Server.Implementations/Localization/Core/zh-TW.json index c423c7ea7..766e338da 100644 --- a/Emby.Server.Implementations/Localization/Core/zh-TW.json +++ b/Emby.Server.Implementations/Localization/Core/zh-TW.json @@ -91,5 +91,18 @@ "VersionNumber": "版本 {0}", "HeaderRecordingGroups": "錄製組", "Inherit": "繼承", - "SubtitleDownloadFailureFromForItem": "無法為 {1} 從 {0} 下載字幕" + "SubtitleDownloadFailureFromForItem": "無法為 {1} 從 {0} 下載字幕", + "TaskDownloadMissingSubtitlesDescription": "在網路上透過描述資料搜尋遺失的字幕。", + "TaskDownloadMissingSubtitles": "下載遺失的字幕", + "TaskRefreshChannels": "重新整理頻道", + "TaskUpdatePlugins": "更新插件", + "TaskRefreshPeople": "重新整理人員", + "TaskCleanLogsDescription": "刪除超過{0}天的紀錄檔案。", + "TaskCleanLogs": "清空紀錄資料夾", + "TaskRefreshLibraryDescription": "掃描媒體庫內新的檔案並重新整理描述資料。", + "TaskRefreshLibrary": "掃描媒體庫", + "TaskRefreshChapterImages": "擷取章節圖片", + "TaskCleanCacheDescription": "刪除系統長時間不需要的快取。", + "TaskCleanCache": "清除快取資料夾", + "TasksLibraryCategory": "媒體庫" } From 66364eba922bd3e9c14fd5dde276928c1750f880 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sun, 12 Apr 2020 19:36:42 -0400 Subject: [PATCH 75/83] Add tasks required for SonarCloud integration --- .ci/azure-pipelines-test.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/.ci/azure-pipelines-test.yml b/.ci/azure-pipelines-test.yml index a5d29fb61..bdc1838fb 100644 --- a/.ci/azure-pipelines-test.yml +++ b/.ci/azure-pipelines-test.yml @@ -28,12 +28,26 @@ jobs: submodules: true persistCredentials: false + # This is required for the SonarCloud analyzer + - task: UseDotNet@2 + displayName: "Install .NET Core SDK 2.1" + inputs: + packageType: sdk + version: '2.1.805' + - task: UseDotNet@2 displayName: "Update DotNet" inputs: packageType: sdk version: ${{ parameters.DotNetSdkVersion }} + - task: SonarCloudPrepare@1 + displayName: 'Prepare analysis on SonarCloud' + inputs: + SonarCloud: 'Sonarcloud for Jellyfin' + organization: 'jellyfin' + projectKey: 'jellyfin_jellyfin' + - task: DotNetCoreCLI@2 displayName: 'Run CLI Tests' inputs: @@ -44,6 +58,12 @@ jobs: testRunTitle: $(Agent.JobName) workingDirectory: "$(Build.SourcesDirectory)" + - task: SonarCloudAnalyze@1 + displayName: 'Run Code Analysis' + + - task: SonarCloudPublish@1 + displayName: 'Publish Quality Gate Result' + - task: Palmmedia.reportgenerator.reportgenerator-build-release-task.reportgenerator@4 condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux')) # !! THIS is for V1 only V2 will/should support merging displayName: 'Run ReportGenerator' @@ -62,3 +82,4 @@ jobs: summaryFileLocation: "$(Agent.TempDirectory)/merged/**.xml" pathToSources: $(Build.SourcesDirectory) failIfCoverageEmpty: true + From c5f163293fb29145245393b976f02aae53217944 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Tue, 21 Apr 2020 16:21:09 -0400 Subject: [PATCH 76/83] Add properties to all project files This is required for SonarCloud analysis to run --- DvdLib/DvdLib.csproj | 5 +++++ Emby.Dlna/Emby.Dlna.csproj | 5 +++++ Emby.Drawing/Emby.Drawing.csproj | 5 +++++ Emby.Naming/Emby.Naming.csproj | 5 +++++ Emby.Notifications/Emby.Notifications.csproj | 5 +++++ Emby.Photos/Emby.Photos.csproj | 6 ++++++ .../Emby.Server.Implementations.csproj | 5 +++++ Jellyfin.Api/Jellyfin.Api.csproj | 5 +++++ Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj | 5 +++++ Jellyfin.Server/Jellyfin.Server.csproj | 5 +++++ MediaBrowser.Api/MediaBrowser.Api.csproj | 5 +++++ MediaBrowser.Common/MediaBrowser.Common.csproj | 5 +++++ MediaBrowser.Controller/MediaBrowser.Controller.csproj | 5 +++++ .../MediaBrowser.LocalMetadata.csproj | 5 +++++ .../MediaBrowser.MediaEncoding.csproj | 5 +++++ MediaBrowser.Model/MediaBrowser.Model.csproj | 5 +++++ MediaBrowser.Providers/MediaBrowser.Providers.csproj | 5 +++++ MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj | 5 +++++ MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj | 5 +++++ RSSDP/RSSDP.csproj | 5 +++++ tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj | 5 +++++ tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj | 5 +++++ .../Jellyfin.Controller.Tests.csproj | 5 +++++ .../Jellyfin.MediaEncoding.Tests.csproj | 5 +++++ tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj | 5 +++++ .../Jellyfin.Server.Implementations.Tests.csproj | 5 +++++ 26 files changed, 131 insertions(+) diff --git a/DvdLib/DvdLib.csproj b/DvdLib/DvdLib.csproj index f4df6a9f5..72a50124b 100644 --- a/DvdLib/DvdLib.csproj +++ b/DvdLib/DvdLib.csproj @@ -1,5 +1,10 @@ + + + {713F42B5-878E-499D-A878-E4C652B1D5E8} + + diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj index 0cabe43d5..42a5f95c1 100644 --- a/Emby.Dlna/Emby.Dlna.csproj +++ b/Emby.Dlna/Emby.Dlna.csproj @@ -1,5 +1,10 @@ + + + {805844AB-E92F-45E6-9D99-4F6D48D129A5} + + diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj index b7090b262..f48507b34 100644 --- a/Emby.Drawing/Emby.Drawing.csproj +++ b/Emby.Drawing/Emby.Drawing.csproj @@ -1,5 +1,10 @@ + + + {08FFF49B-F175-4807-A2B5-73B0EBD9F716} + + netstandard2.1 false diff --git a/Emby.Naming/Emby.Naming.csproj b/Emby.Naming/Emby.Naming.csproj index 4e08170a4..c017e76c7 100644 --- a/Emby.Naming/Emby.Naming.csproj +++ b/Emby.Naming/Emby.Naming.csproj @@ -1,5 +1,10 @@  + + + {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2} + + netstandard2.1 false diff --git a/Emby.Notifications/Emby.Notifications.csproj b/Emby.Notifications/Emby.Notifications.csproj index e6bf785bf..1d430a5e5 100644 --- a/Emby.Notifications/Emby.Notifications.csproj +++ b/Emby.Notifications/Emby.Notifications.csproj @@ -1,5 +1,10 @@ + + + {2E030C33-6923-4530-9E54-FA29FA6AD1A9} + + netstandard2.1 false diff --git a/Emby.Photos/Emby.Photos.csproj b/Emby.Photos/Emby.Photos.csproj index cc3fbb43f..dbe01257f 100644 --- a/Emby.Photos/Emby.Photos.csproj +++ b/Emby.Photos/Emby.Photos.csproj @@ -1,4 +1,10 @@ + + + + {89AB4548-770D-41FD-A891-8DAFF44F452C} + + diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index d46b9507b..765aa1759 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -1,5 +1,10 @@  + + + {E383961B-9356-4D5D-8233-9A1079D03055} + + diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index 8f23ef9d0..a582a209c 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -1,5 +1,10 @@ + + + {DFBEFB4C-DA19-4143-98B7-27320C7F7163} + + netstandard2.1 true diff --git a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj index d0a99e1e2..6326278f5 100644 --- a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj +++ b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj @@ -1,5 +1,10 @@ + + + {154872D9-6C12-4007-96E3-8F70A58386CE} + + netstandard2.1 false diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 02ae202b4..270cdeaaf 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -1,5 +1,10 @@ + + + {07E39F42-A2C6-4B32-AF8C-725F957A73FF} + + jellyfin Exe diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index 0d62cf8c5..d703bdb05 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -1,5 +1,10 @@ + + + {4FD51AC5-2C16-4308-A993-C3A84F3B4582} + + diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 3b0347802..69864106c 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -1,5 +1,10 @@  + + + {9142EEFA-7570-41E1-BFCC-468BB571AF2F} + + Jellyfin Contributors Jellyfin.Common diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 662ab2535..4e7d02737 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -1,5 +1,10 @@ + + + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2} + + Jellyfin Contributors Jellyfin.Controller diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj index 71eb62693..24104d779 100644 --- a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj +++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj @@ -1,5 +1,10 @@ + + + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392} + + diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index a312dcd70..af8bee301 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -1,5 +1,10 @@  + + + {960295EE-4AF4-4440-A525-B4C295B01A61} + + netstandard2.1 false diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 27486c68f..b41d0af1d 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -1,5 +1,10 @@ + + + {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B} + + Jellyfin Contributors Jellyfin.Model diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 330a4d1e5..1b3df63b6 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -1,5 +1,10 @@  + + + {442B5058-DCAF-4263-BB6A-F21E31120A1B} + + diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index da52b852a..bcaee50f2 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -1,5 +1,10 @@ + + + {5624B7B5-B5A7-41D8-9F10-CC5611109619} + + diff --git a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj index e26282095..45fd9add9 100644 --- a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj +++ b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj @@ -1,5 +1,10 @@ + + + {23499896-B135-4527-8574-C26E926EA99E} + + diff --git a/RSSDP/RSSDP.csproj b/RSSDP/RSSDP.csproj index 9753ae9b1..e3f3127b6 100644 --- a/RSSDP/RSSDP.csproj +++ b/RSSDP/RSSDP.csproj @@ -1,5 +1,10 @@ + + + {21002819-C39A-4D3E-BE83-2A276A77FB1F} + + diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index b159db2bd..fb76f34d0 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -1,5 +1,10 @@ + + + {A2FD0A10-8F62-4F9D-B171-FFDF9F0AFA9D} + + netcoreapp3.1 false diff --git a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj index 81a2242e7..cd41c5604 100644 --- a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj +++ b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj @@ -1,5 +1,10 @@ + + + {DF194677-DFD3-42AF-9F75-D44D5A416478} + + netcoreapp3.1 false diff --git a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj index 30994dee6..407fe2eda 100644 --- a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj +++ b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj @@ -1,5 +1,10 @@ + + + {462584F7-5023-4019-9EAC-B98CA458C0A0} + + netcoreapp3.1 false diff --git a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj index 78a020ad5..276c50ca3 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj +++ b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj @@ -1,5 +1,10 @@ + + + {28464062-0939-4AA7-9F7B-24DDDA61A7C0} + + netcoreapp3.1 false diff --git a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj index f404b3e46..ac0c970c1 100644 --- a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj +++ b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj @@ -1,5 +1,10 @@ + + + {3998657B-1CCC-49DD-A19F-275DC8495F57} + + netcoreapp3.1 false diff --git a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj index b7865439c..ba7ecb3d1 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj +++ b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj @@ -1,5 +1,10 @@  + + + {2E3A1B4B-4225-4AAA-8B29-0181A84E7AEE} + + netcoreapp3.1 false From 9a401c3728c2ac45ea98f9de5ffc75c037a8c12f Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Tue, 21 Apr 2020 17:55:19 -0400 Subject: [PATCH 77/83] Only run SonarCloud analysis for ubuntu tests --- .ci/azure-pipelines-test.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.ci/azure-pipelines-test.yml b/.ci/azure-pipelines-test.yml index bdc1838fb..cb5338ac8 100644 --- a/.ci/azure-pipelines-test.yml +++ b/.ci/azure-pipelines-test.yml @@ -31,6 +31,7 @@ jobs: # This is required for the SonarCloud analyzer - task: UseDotNet@2 displayName: "Install .NET Core SDK 2.1" + condition: eq(variables['ImageName'], 'ubuntu-latest') inputs: packageType: sdk version: '2.1.805' @@ -43,6 +44,7 @@ jobs: - task: SonarCloudPrepare@1 displayName: 'Prepare analysis on SonarCloud' + condition: eq(variables['ImageName'], 'ubuntu-latest') inputs: SonarCloud: 'Sonarcloud for Jellyfin' organization: 'jellyfin' @@ -60,9 +62,11 @@ jobs: - task: SonarCloudAnalyze@1 displayName: 'Run Code Analysis' + condition: eq(variables['ImageName'], 'ubuntu-latest') - task: SonarCloudPublish@1 displayName: 'Publish Quality Gate Result' + condition: eq(variables['ImageName'], 'ubuntu-latest') - task: Palmmedia.reportgenerator.reportgenerator-build-release-task.reportgenerator@4 condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux')) # !! THIS is for V1 only V2 will/should support merging From e943facebb12791cf01e9c64000c79f32aefc1f1 Mon Sep 17 00:00:00 2001 From: Wouter Kayser Date: Wed, 22 Apr 2020 07:37:10 +0000 Subject: [PATCH 78/83] Translated using Weblate (Dutch) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/nl/ --- Emby.Server.Implementations/Localization/Core/nl.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/nl.json b/Emby.Server.Implementations/Localization/Core/nl.json index 3bc9c2a77..22dcf1d2e 100644 --- a/Emby.Server.Implementations/Localization/Core/nl.json +++ b/Emby.Server.Implementations/Localization/Core/nl.json @@ -1,11 +1,11 @@ { "Albums": "Albums", "AppDeviceValues": "App: {0}, Apparaat: {1}", - "Application": "Applicatie", + "Application": "Programma", "Artists": "Artiesten", - "AuthenticationSucceededWithUserName": "{0} succesvol geauthenticeerd", + "AuthenticationSucceededWithUserName": "{0} is succesvol geverifiëerd", "Books": "Boeken", - "CameraImageUploadedFrom": "Er is een nieuwe foto toegevoegd van {0}", + "CameraImageUploadedFrom": "Er is een nieuwe afbeelding toegevoegd via {0}", "Channels": "Kanalen", "ChapterNameValue": "Hoofdstuk {0}", "Collections": "Verzamelingen", From de328a46cdba2182c478761659e3b6fd3a8dc0c0 Mon Sep 17 00:00:00 2001 From: Michael Ong Date: Wed, 22 Apr 2020 07:17:06 +0000 Subject: [PATCH 79/83] Translated using Weblate (Chinese (Traditional)) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/zh_Hant/ --- .../Localization/Core/zh-TW.json | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/zh-TW.json b/Emby.Server.Implementations/Localization/Core/zh-TW.json index 766e338da..a22f66df9 100644 --- a/Emby.Server.Implementations/Localization/Core/zh-TW.json +++ b/Emby.Server.Implementations/Localization/Core/zh-TW.json @@ -50,10 +50,10 @@ "NotificationOptionCameraImageUploaded": "相機相片已上傳", "NotificationOptionInstallationFailed": "安裝失敗", "NotificationOptionNewLibraryContent": "已新增新內容", - "NotificationOptionPluginError": "擴充元件錯誤", - "NotificationOptionPluginInstalled": "擴充元件已安裝", - "NotificationOptionPluginUninstalled": "擴充元件已移除", - "NotificationOptionPluginUpdateInstalled": "已更新擴充元件", + "NotificationOptionPluginError": "插件安裝錯誤", + "NotificationOptionPluginInstalled": "插件已安裝", + "NotificationOptionPluginUninstalled": "插件已移除", + "NotificationOptionPluginUpdateInstalled": "插件已更新", "NotificationOptionServerRestartRequired": "伺服器需要重新啟動", "NotificationOptionTaskFailed": "排程任務失敗", "NotificationOptionUserLockedOut": "使用者已鎖定", @@ -61,7 +61,7 @@ "NotificationOptionVideoPlaybackStopped": "影片停止播放", "Photos": "相片", "Playlists": "播放清單", - "Plugin": "外掛", + "Plugin": "插件", "PluginInstalledWithName": "{0} 已安裝", "PluginUninstalledWithName": "{0} 已移除", "PluginUpdatedWithName": "{0} 已更新", @@ -104,5 +104,14 @@ "TaskRefreshChapterImages": "擷取章節圖片", "TaskCleanCacheDescription": "刪除系統長時間不需要的快取。", "TaskCleanCache": "清除快取資料夾", - "TasksLibraryCategory": "媒體庫" + "TasksLibraryCategory": "媒體庫", + "TaskRefreshChannelsDescription": "重新整理網絡頻道資料。", + "TaskCleanTranscodeDescription": "刪除超過一天的轉碼檔案。", + "TaskCleanTranscode": "清除轉碼資料夾", + "TaskUpdatePluginsDescription": "下載並安裝配置為自動更新的插件的更新。", + "TaskRefreshPeopleDescription": "更新媒體庫中演員和導演的中繼資料。", + "TaskRefreshChapterImagesDescription": "為有章節的視頻創建縮圖。", + "TasksChannelsCategory": "網絡頻道", + "TasksApplicationCategory": "應用程式", + "TasksMaintenanceCategory": "維修" } From 8f02fb9a4f062e2b6d980b6645a85e2681298dfa Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Wed, 22 Apr 2020 13:09:59 -0400 Subject: [PATCH 80/83] Remove unused usings This addresses the new issues identified in SonarCloud analysis --- Emby.Drawing/ImageProcessor.cs | 1 - MediaBrowser.Common/IApplicationHost.cs | 2 -- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 1 - 3 files changed, 4 deletions(-) diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index 903b958a4..ba14b4dca 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -8,7 +8,6 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Controller; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Entities; diff --git a/MediaBrowser.Common/IApplicationHost.cs b/MediaBrowser.Common/IApplicationHost.cs index eabf8f3d7..e8d9282e4 100644 --- a/MediaBrowser.Common/IApplicationHost.cs +++ b/MediaBrowser.Common/IApplicationHost.cs @@ -2,8 +2,6 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; using MediaBrowser.Common.Plugins; -using MediaBrowser.Model.Updates; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; namespace MediaBrowser.Common diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 2cc89b0dc..992ad146d 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -19,7 +19,6 @@ using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.System; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using System.Diagnostics; From 7d22a3c394fa418699265da0aa289829df4f1e6d Mon Sep 17 00:00:00 2001 From: Unlimitediq Date: Wed, 22 Apr 2020 13:22:29 +0000 Subject: [PATCH 81/83] Translated using Weblate (Dutch) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/nl/ --- Emby.Server.Implementations/Localization/Core/nl.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/nl.json b/Emby.Server.Implementations/Localization/Core/nl.json index 22dcf1d2e..baa12e98e 100644 --- a/Emby.Server.Implementations/Localization/Core/nl.json +++ b/Emby.Server.Implementations/Localization/Core/nl.json @@ -3,7 +3,7 @@ "AppDeviceValues": "App: {0}, Apparaat: {1}", "Application": "Programma", "Artists": "Artiesten", - "AuthenticationSucceededWithUserName": "{0} is succesvol geverifiëerd", + "AuthenticationSucceededWithUserName": "{0} is succesvol geverifieerd", "Books": "Boeken", "CameraImageUploadedFrom": "Er is een nieuwe afbeelding toegevoegd via {0}", "Channels": "Kanalen", From 964e27793253717bf2fde79f253bcb4050339bba Mon Sep 17 00:00:00 2001 From: tyaprak Date: Wed, 22 Apr 2020 22:59:20 +0000 Subject: [PATCH 82/83] Translated using Weblate (Turkish) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/tr/ --- .../Localization/Core/tr.json | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/tr.json b/Emby.Server.Implementations/Localization/Core/tr.json index 62d205516..3cf3482eb 100644 --- a/Emby.Server.Implementations/Localization/Core/tr.json +++ b/Emby.Server.Implementations/Localization/Core/tr.json @@ -50,7 +50,7 @@ "NotificationOptionAudioPlayback": "Ses çalma başladı", "NotificationOptionAudioPlaybackStopped": "Ses çalma durduruldu", "NotificationOptionCameraImageUploaded": "Kamera fotoğrafı yüklendi", - "NotificationOptionInstallationFailed": "Yükleme başarısız oldu", + "NotificationOptionInstallationFailed": "Kurulum hatası", "NotificationOptionNewLibraryContent": "Yeni içerik eklendi", "NotificationOptionPluginError": "Eklenti hatası", "NotificationOptionPluginInstalled": "Eklenti yüklendi", @@ -95,7 +95,24 @@ "VersionNumber": "Versiyon {0}", "TaskCleanCache": "Geçici dosya klasörünü temizle", "TasksChannelsCategory": "İnternet kanalları", - "TasksApplicationCategory": "Yazılım", + "TasksApplicationCategory": "Uygulama", "TasksLibraryCategory": "Kütüphane", - "TasksMaintenanceCategory": "Onarım" + "TasksMaintenanceCategory": "Onarım", + "TaskRefreshPeopleDescription": "Medya kütüphanenizdeki videoların oyuncu ve yönetmen bilgilerini günceller.", + "TaskDownloadMissingSubtitlesDescription": "Metadata ayarlarını baz alarak eksik altyazıları internette arar.", + "TaskDownloadMissingSubtitles": "Eksik altyazıları indir", + "TaskRefreshChannelsDescription": "Internet kanal bilgilerini yenile.", + "TaskRefreshChannels": "Kanalları Yenile", + "TaskCleanTranscodeDescription": "Bir günü dolmuş dönüştürme bilgisi içeren dosyaları siler.", + "TaskCleanTranscode": "Dönüşüm Dizinini Temizle", + "TaskUpdatePluginsDescription": "Otomatik güncellenmeye ayarlanmış eklentilerin güncellemelerini indirir ve kurar.", + "TaskUpdatePlugins": "Eklentileri Güncelle", + "TaskRefreshPeople": "Kullanıcıları Yenile", + "TaskCleanLogsDescription": "{0} günden eski log dosyalarını siler.", + "TaskCleanLogs": "Log Dizinini Temizle", + "TaskRefreshLibraryDescription": "Medya kütüphanenize eklenen yeni dosyaları arar ve bilgileri yeniler.", + "TaskRefreshLibrary": "Medya Kütüphanesini Tara", + "TaskRefreshChapterImagesDescription": "Sahnelere ayrılmış videolar için küçük resimler oluştur.", + "TaskRefreshChapterImages": "Bölüm Resimlerini Çıkar", + "TaskCleanCacheDescription": "Sistem tarafından artık ihtiyaç duyulmayan önbellek dosyalarını siler." } From 97e383d108a4adb7e57c13d67f1d36bd1b5ce7b5 Mon Sep 17 00:00:00 2001 From: Miko Dela Cruz Date: Wed, 22 Apr 2020 17:57:29 +0000 Subject: [PATCH 83/83] Translated using Weblate (Japanese) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ja/ --- Emby.Server.Implementations/Localization/Core/ja.json | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/ja.json b/Emby.Server.Implementations/Localization/Core/ja.json index 5e017d4c4..a4d9f9ef6 100644 --- a/Emby.Server.Implementations/Localization/Core/ja.json +++ b/Emby.Server.Implementations/Localization/Core/ja.json @@ -104,13 +104,14 @@ "TasksMaintenanceCategory": "メンテナンス", "TaskRefreshChannelsDescription": "ネットチャンネルの情報をリフレッシュします。", "TaskRefreshChannels": "チャンネルのリフレッシュ", - "TaskCleanTranscodeDescription": "一日以上前のトランスコードを消去します。", - "TaskCleanTranscode": "トランスコード用のディレクトリの掃除", + "TaskCleanTranscodeDescription": "1日以上経過したトランスコードファイルを削除します。", + "TaskCleanTranscode": "トランスコードディレクトリの削除", "TaskUpdatePluginsDescription": "自動更新可能なプラグインのアップデートをダウンロードしてインストールします。", "TaskUpdatePlugins": "プラグインの更新", - "TaskRefreshPeopleDescription": "メディアライブラリで俳優や監督のメタデータをリフレッシュします。", - "TaskRefreshPeople": "俳優や監督のデータのリフレッシュ", + "TaskRefreshPeopleDescription": "メディアライブラリで俳優や監督のメタデータを更新します。", + "TaskRefreshPeople": "俳優や監督のデータの更新", "TaskDownloadMissingSubtitlesDescription": "メタデータ構成に基づいて、欠落している字幕をインターネットで検索します。", "TaskRefreshChapterImagesDescription": "チャプターのあるビデオのサムネイルを作成します。", - "TaskRefreshChapterImages": "チャプター画像を抽出する" + "TaskRefreshChapterImages": "チャプター画像を抽出する", + "TaskDownloadMissingSubtitles": "不足している字幕をダウンロードする" }