diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index 3983824a3e..6917efefa9 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -377,50 +377,50 @@ namespace Emby.Server.Implementations.Activity }).ConfigureAwait(false); } - private async void OnPluginUpdated(object sender, GenericEventArgs<(IPlugin, VersionInfo)> e) + private async void OnPluginUpdated(object sender, InstallationInfo e) { await CreateLogEntry(new ActivityLog( string.Format( CultureInfo.InvariantCulture, _localization.GetLocalizedString("PluginUpdatedWithName"), - e.Argument.Item1.Name), + e.Name), NotificationType.PluginUpdateInstalled.ToString(), Guid.Empty) { ShortOverview = string.Format( CultureInfo.InvariantCulture, _localization.GetLocalizedString("VersionNumber"), - e.Argument.Item2.version), - Overview = e.Argument.Item2.changelog + e.Version), + Overview = e.Changelog }).ConfigureAwait(false); } - private async void OnPluginUninstalled(object sender, GenericEventArgs e) + private async void OnPluginUninstalled(object sender, IPlugin e) { await CreateLogEntry(new ActivityLog( string.Format( CultureInfo.InvariantCulture, _localization.GetLocalizedString("PluginUninstalledWithName"), - e.Argument.Name), + e.Name), NotificationType.PluginUninstalled.ToString(), Guid.Empty)) .ConfigureAwait(false); } - private async void OnPluginInstalled(object sender, GenericEventArgs e) + private async void OnPluginInstalled(object sender, InstallationInfo e) { await CreateLogEntry(new ActivityLog( string.Format( CultureInfo.InvariantCulture, _localization.GetLocalizedString("PluginInstalledWithName"), - e.Argument.name), + e.Name), NotificationType.PluginInstalled.ToString(), Guid.Empty) { ShortOverview = string.Format( CultureInfo.InvariantCulture, _localization.GetLocalizedString("VersionNumber"), - e.Argument.version) + e.Version) }).ConfigureAwait(false); } diff --git a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs index dea85d299a..11ba6f7489 100644 --- a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs @@ -12,6 +12,7 @@ using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Events; using MediaBrowser.Model.Tasks; +using MediaBrowser.Model.Updates; namespace Emby.Server.Implementations.EntryPoints { @@ -85,19 +86,19 @@ namespace Emby.Server.Implementations.EntryPoints return Task.CompletedTask; } - private async void OnPackageInstalling(object sender, InstallationEventArgs e) + private async void OnPackageInstalling(object sender, InstallationInfo e) { - await SendMessageToAdminSessions("PackageInstalling", e.InstallationInfo).ConfigureAwait(false); + await SendMessageToAdminSessions("PackageInstalling", e).ConfigureAwait(false); } - private async void OnPackageInstallationCancelled(object sender, InstallationEventArgs e) + private async void OnPackageInstallationCancelled(object sender, InstallationInfo e) { - await SendMessageToAdminSessions("PackageInstallationCancelled", e.InstallationInfo).ConfigureAwait(false); + await SendMessageToAdminSessions("PackageInstallationCancelled", e).ConfigureAwait(false); } - private async void OnPackageInstallationCompleted(object sender, InstallationEventArgs e) + private async void OnPackageInstallationCompleted(object sender, InstallationInfo e) { - await SendMessageToAdminSessions("PackageInstallationCompleted", e.InstallationInfo).ConfigureAwait(false); + await SendMessageToAdminSessions("PackageInstallationCompleted", e).ConfigureAwait(false); } private async void OnPackageInstallationFailed(object sender, InstallationFailedEventArgs e) @@ -115,9 +116,9 @@ namespace Emby.Server.Implementations.EntryPoints /// /// The sender. /// The e. - private async void OnPluginUninstalled(object sender, GenericEventArgs e) + private async void OnPluginUninstalled(object sender, IPlugin e) { - await SendMessageToAdminSessions("PluginUninstalled", e.Argument.GetPluginInfo()).ConfigureAwait(false); + await SendMessageToAdminSessions("PluginUninstalled", e).ConfigureAwait(false); } /// diff --git a/Emby.Server.Implementations/Images/ArtistImageProvider.cs b/Emby.Server.Implementations/Images/ArtistImageProvider.cs new file mode 100644 index 0000000000..7fa13a49fd --- /dev/null +++ b/Emby.Server.Implementations/Images/ArtistImageProvider.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Emby.Server.Implementations.Images; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.Drawing; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Playlists; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Querying; + +namespace Emby.Server.Implementations.Images +{ + public class ArtistImageProvider : BaseDynamicImageProvider + { + private readonly ILibraryManager _libraryManager; + + public ArtistImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, ILibraryManager libraryManager) : base(fileSystem, providerManager, applicationPaths, imageProcessor) + { + _libraryManager = libraryManager; + } + + protected override IReadOnlyList GetItemsWithImages(BaseItem item) + { + return Array.Empty(); + + // TODO enable this when BaseDynamicImageProvider objects are configurable + // return _libraryManager.GetItemList(new InternalItemsQuery + // { + // ArtistIds = new[] { item.Id }, + // IncludeItemTypes = new[] { typeof(MusicAlbum).Name }, + // OrderBy = new[] { (ItemSortBy.Random, SortOrder.Ascending) }, + // Limit = 4, + // Recursive = true, + // ImageTypes = new[] { ImageType.Primary }, + // DtoOptions = new DtoOptions(false) + // }); + } + } +} diff --git a/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs b/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs index fd50f156af..57302b5067 100644 --- a/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs +++ b/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs @@ -194,7 +194,8 @@ namespace Emby.Server.Implementations.Images return outputPath; } - protected virtual string CreateImage(BaseItem item, + protected virtual string CreateImage( + BaseItem item, IReadOnlyCollection itemsWithImages, string outputPathWithoutExtension, ImageType imageType, @@ -214,7 +215,12 @@ namespace Emby.Server.Implementations.Images if (imageType == ImageType.Primary) { - if (item is UserView || item is Playlist || item is MusicGenre || item is Genre || item is PhotoAlbum) + if (item is UserView + || item is Playlist + || item is MusicGenre + || item is Genre + || item is PhotoAlbum + || item is MusicArtist) { return CreateSquareCollage(item, itemsWithImages, outputPath); } @@ -225,7 +231,7 @@ namespace Emby.Server.Implementations.Images throw new ArgumentException("Unexpected image type", nameof(imageType)); } - public bool HasChanged(BaseItem item, IDirectoryService directoryServicee) + public bool HasChanged(BaseItem item, IDirectoryService directoryService) { if (!Supports(item)) { @@ -236,6 +242,7 @@ namespace Emby.Server.Implementations.Images { return true; } + if (SupportedImages.Contains(ImageType.Thumb) && HasChanged(item, ImageType.Thumb)) { return true; diff --git a/Emby.Server.Implementations/UserViews/CollectionFolderImageProvider.cs b/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs similarity index 98% rename from Emby.Server.Implementations/UserViews/CollectionFolderImageProvider.cs rename to Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs index 7b7d66ca6c..dc8062b457 100644 --- a/Emby.Server.Implementations/UserViews/CollectionFolderImageProvider.cs +++ b/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs @@ -13,7 +13,7 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.Querying; -namespace Emby.Server.Implementations.UserViews +namespace Emby.Server.Implementations.Images { public class CollectionFolderImageProvider : BaseDynamicImageProvider { diff --git a/Emby.Server.Implementations/UserViews/DynamicImageProvider.cs b/Emby.Server.Implementations/Images/DynamicImageProvider.cs similarity index 98% rename from Emby.Server.Implementations/UserViews/DynamicImageProvider.cs rename to Emby.Server.Implementations/Images/DynamicImageProvider.cs index e7888595fc..ca0aa4a9f5 100644 --- a/Emby.Server.Implementations/UserViews/DynamicImageProvider.cs +++ b/Emby.Server.Implementations/Images/DynamicImageProvider.cs @@ -16,7 +16,7 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; -namespace Emby.Server.Implementations.UserViews +namespace Emby.Server.Implementations.Images { public class DynamicImageProvider : BaseDynamicImageProvider { diff --git a/Emby.Server.Implementations/UserViews/FolderImageProvider.cs b/Emby.Server.Implementations/Images/FolderImageProvider.cs similarity index 93% rename from Emby.Server.Implementations/UserViews/FolderImageProvider.cs rename to Emby.Server.Implementations/Images/FolderImageProvider.cs index 58a023638f..e9523386ea 100644 --- a/Emby.Server.Implementations/UserViews/FolderImageProvider.cs +++ b/Emby.Server.Implementations/Images/FolderImageProvider.cs @@ -13,7 +13,7 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.Querying; -namespace Emby.Server.Implementations.UserViews +namespace Emby.Server.Implementations.Images { public abstract class BaseFolderImageProvider : BaseDynamicImageProvider where T : Folder, new() @@ -77,16 +77,12 @@ namespace Emby.Server.Implementations.UserViews return false; } - if (item is Folder folder) + if (item is Folder && item.IsTopParent) { - if (folder.IsTopParent) - { - return false; - } + return false; } return true; - //return item.SourceType == SourceType.Library; } } diff --git a/Emby.Server.Implementations/Playlists/PlaylistImageProvider.cs b/Emby.Server.Implementations/Images/GenreImageProvider.cs similarity index 61% rename from Emby.Server.Implementations/Playlists/PlaylistImageProvider.cs rename to Emby.Server.Implementations/Images/GenreImageProvider.cs index f8a2d97417..a184ed4f52 100644 --- a/Emby.Server.Implementations/Playlists/PlaylistImageProvider.cs +++ b/Emby.Server.Implementations/Images/GenreImageProvider.cs @@ -1,5 +1,4 @@ -#pragma warning disable CS1591 - +using System; using System.Collections.Generic; using System.Linq; using Emby.Server.Implementations.Images; @@ -17,56 +16,8 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.Querying; -namespace Emby.Server.Implementations.Playlists +namespace Emby.Server.Implementations.Images { - public class PlaylistImageProvider : BaseDynamicImageProvider - { - public PlaylistImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor) : base(fileSystem, providerManager, applicationPaths, imageProcessor) - { - } - - protected override IReadOnlyList GetItemsWithImages(BaseItem item) - { - var playlist = (Playlist)item; - - return playlist.GetManageableItems() - .Select(i => - { - var subItem = i.Item2; - - if (subItem is Episode episode) - { - var series = episode.Series; - if (series != null && series.HasImage(ImageType.Primary)) - { - return series; - } - } - - if (subItem.HasImage(ImageType.Primary)) - { - return subItem; - } - - var parent = subItem.GetOwner() ?? subItem.GetParent(); - - if (parent != null && parent.HasImage(ImageType.Primary)) - { - if (parent is MusicAlbum) - { - return parent; - } - } - - return null; - }) - .Where(i => i != null) - .GroupBy(x => x.Id) - .Select(x => x.First()) - .ToList(); - } - } - public class MusicGenreImageProvider : BaseDynamicImageProvider { private readonly ILibraryManager _libraryManager; diff --git a/Emby.Server.Implementations/Images/PlaylistImageProvider.cs b/Emby.Server.Implementations/Images/PlaylistImageProvider.cs new file mode 100644 index 0000000000..0ce1b91e88 --- /dev/null +++ b/Emby.Server.Implementations/Images/PlaylistImageProvider.cs @@ -0,0 +1,66 @@ +#pragma warning disable CS1591 + +using System.Collections.Generic; +using System.Linq; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.Drawing; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Playlists; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.IO; + +namespace Emby.Server.Implementations.Images +{ + public class PlaylistImageProvider : BaseDynamicImageProvider + { + public PlaylistImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor) : base(fileSystem, providerManager, applicationPaths, imageProcessor) + { + } + + protected override IReadOnlyList GetItemsWithImages(BaseItem item) + { + var playlist = (Playlist)item; + + return playlist.GetManageableItems() + .Select(i => + { + var subItem = i.Item2; + + var episode = subItem as Episode; + + if (episode != null) + { + var series = episode.Series; + if (series != null && series.HasImage(ImageType.Primary)) + { + return series; + } + } + + if (subItem.HasImage(ImageType.Primary)) + { + return subItem; + } + + var parent = subItem.GetOwner() ?? subItem.GetParent(); + + if (parent != null && parent.HasImage(ImageType.Primary)) + { + if (parent is MusicAlbum) + { + return parent; + } + } + + return null; + }) + .Where(i => i != null) + .GroupBy(x => x.Id) + .Select(x => x.First()) + .ToList(); + } + } +} diff --git a/Emby.Server.Implementations/Localization/Core/nb.json b/Emby.Server.Implementations/Localization/Core/nb.json index 5637ce3462..1b55c2e383 100644 --- a/Emby.Server.Implementations/Localization/Core/nb.json +++ b/Emby.Server.Implementations/Localization/Core/nb.json @@ -101,5 +101,18 @@ "TaskRefreshLibrary": "Skann mediebibliotek", "TaskRefreshChapterImagesDescription": "Lager forhåndsvisningsbilder for videoer som har kapitler.", "TaskRefreshChapterImages": "Trekk ut Kapittelbilder", - "TaskCleanCacheDescription": "Sletter mellomlagrede filer som ikke lengre trengs av systemet." + "TaskCleanCacheDescription": "Sletter mellomlagrede filer som ikke lengre trengs av systemet.", + "TaskDownloadMissingSubtitlesDescription": "Søker etter manglende underteksting på nett basert på metadatakonfigurasjon.", + "TaskDownloadMissingSubtitles": "Last ned manglende underteksting", + "TaskRefreshChannelsDescription": "Frisker opp internettkanalinformasjon.", + "TaskRefreshChannels": "Oppfrisk kanaler", + "TaskCleanTranscodeDescription": "Sletter omkodede filer som er mer enn én dag gamle.", + "TaskCleanTranscode": "Tøm transkodingmappe", + "TaskUpdatePluginsDescription": "Laster ned og installerer oppdateringer for utvidelser som er stilt inn til å oppdatere automatisk.", + "TaskUpdatePlugins": "Oppdater utvidelser", + "TaskRefreshPeopleDescription": "Oppdaterer metadata for skuespillere og regissører i mediebiblioteket ditt.", + "TaskRefreshPeople": "Oppfrisk personer", + "TaskCleanLogsDescription": "Sletter loggfiler som er eldre enn {0} dager gamle.", + "TaskCleanLogs": "Tøm loggmappe", + "TaskRefreshLibraryDescription": "Skanner mediebibliotekene dine for nye filer og oppdaterer metadata." } diff --git a/Emby.Server.Implementations/Localization/Core/sl-SI.json b/Emby.Server.Implementations/Localization/Core/sl-SI.json index 60c58d472d..329c562e73 100644 --- a/Emby.Server.Implementations/Localization/Core/sl-SI.json +++ b/Emby.Server.Implementations/Localization/Core/sl-SI.json @@ -113,5 +113,6 @@ "TasksChannelsCategory": "Spletni kanali", "TasksApplicationCategory": "Aplikacija", "TasksLibraryCategory": "Knjižnica", - "TasksMaintenanceCategory": "Vzdrževanje" + "TasksMaintenanceCategory": "Vzdrževanje", + "TaskDownloadMissingSubtitlesDescription": "Na podlagi nastavitev metapodatkov poišče manjkajoče podnapise na internetu." } diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs index 9d9d77538e..acab3aeea9 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs @@ -82,11 +82,11 @@ namespace Emby.Server.Implementations.ScheduledTasks } catch (HttpException ex) { - _logger.LogError(ex, "Error downloading {0}", package.name); + _logger.LogError(ex, "Error downloading {0}", package.Name); } catch (IOException ex) { - _logger.LogError(ex, "Error updating {0}", package.name); + _logger.LogError(ex, "Error updating {0}", package.Name); } // Update progress diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 8a47226a14..178f32c313 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -1,6 +1,7 @@ #pragma warning disable CS1591 using System; +using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; @@ -97,25 +98,25 @@ namespace Emby.Server.Implementations.Updates } /// - public event EventHandler PackageInstalling; + public event EventHandler PackageInstalling; /// - public event EventHandler PackageInstallationCompleted; + public event EventHandler PackageInstallationCompleted; /// public event EventHandler PackageInstallationFailed; /// - public event EventHandler PackageInstallationCancelled; + public event EventHandler PackageInstallationCancelled; /// - public event EventHandler> PluginUninstalled; + public event EventHandler PluginUninstalled; /// - public event EventHandler> PluginUpdated; + public event EventHandler PluginUpdated; /// - public event EventHandler> PluginInstalled; + public event EventHandler PluginInstalled; /// public IEnumerable CompletedInstallations => _completedInstallationsInternal; @@ -183,24 +184,7 @@ namespace Emby.Server.Implementations.Updates } /// - public IEnumerable GetCompatibleVersions( - IEnumerable availableVersions, - Version minVersion = null) - { - var appVer = _applicationHost.ApplicationVersion; - availableVersions = availableVersions - .Where(x => Version.Parse(x.targetAbi) <= appVer); - - if (minVersion != null) - { - availableVersions = availableVersions.Where(x => x.version >= minVersion); - } - - return availableVersions.OrderByDescending(x => x.version); - } - - /// - public IEnumerable GetCompatibleVersions( + public IEnumerable GetCompatibleVersions( IEnumerable availablePackages, string name = null, Guid guid = default, @@ -211,28 +195,46 @@ namespace Emby.Server.Implementations.Updates // Package not found in repository if (package == null) { - return Enumerable.Empty(); + yield break; } - return GetCompatibleVersions( - package.versions, - minVersion); + var appVer = _applicationHost.ApplicationVersion; + var availableVersions = package.versions + .Where(x => Version.Parse(x.targetAbi) <= appVer); + + if (minVersion != null) + { + availableVersions = availableVersions.Where(x => new Version(x.version) >= minVersion); + } + + foreach (var v in availableVersions.OrderByDescending(x => x.version)) + { + yield return new InstallationInfo + { + Changelog = v.changelog, + Guid = new Guid(package.guid), + Name = package.name, + Version = new Version(v.version), + SourceUrl = v.sourceUrl, + Checksum = v.checksum + }; + } } /// - public async Task> GetAvailablePluginUpdates(CancellationToken cancellationToken = default) + public async Task> GetAvailablePluginUpdates(CancellationToken cancellationToken = default) { var catalog = await GetAvailablePackages(cancellationToken).ConfigureAwait(false); return GetAvailablePluginUpdates(catalog); } - private IEnumerable GetAvailablePluginUpdates(IReadOnlyList pluginCatalog) + private IEnumerable GetAvailablePluginUpdates(IReadOnlyList pluginCatalog) { foreach (var plugin in _applicationHost.Plugins) { var compatibleversions = GetCompatibleVersions(pluginCatalog, plugin.Name, plugin.Id, plugin.Version); - var version = compatibleversions.FirstOrDefault(y => y.version > plugin.Version); - if (version != null && !CompletedInstallations.Any(x => string.Equals(x.Guid, version.guid, StringComparison.OrdinalIgnoreCase))) + var version = compatibleversions.FirstOrDefault(y => y.Version > plugin.Version); + if (version != null && CompletedInstallations.All(x => x.Guid != version.Guid)) { yield return version; } @@ -240,23 +242,16 @@ namespace Emby.Server.Implementations.Updates } /// - public async Task InstallPackage(VersionInfo package, CancellationToken cancellationToken) + public async Task InstallPackage(InstallationInfo package, CancellationToken cancellationToken) { if (package == null) { throw new ArgumentNullException(nameof(package)); } - var installationInfo = new InstallationInfo - { - Guid = package.guid, - Name = package.name, - Version = package.version.ToString() - }; - var innerCancellationTokenSource = new CancellationTokenSource(); - var tuple = (installationInfo, innerCancellationTokenSource); + var tuple = (package, innerCancellationTokenSource); // Add it to the in-progress list lock (_currentInstallationsLock) @@ -266,13 +261,7 @@ namespace Emby.Server.Implementations.Updates var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, innerCancellationTokenSource.Token).Token; - var installationEventArgs = new InstallationEventArgs - { - InstallationInfo = installationInfo, - VersionInfo = package - }; - - PackageInstalling?.Invoke(this, installationEventArgs); + PackageInstalling?.Invoke(this, package); try { @@ -283,9 +272,9 @@ namespace Emby.Server.Implementations.Updates _currentInstallations.Remove(tuple); } - _completedInstallationsInternal.Add(installationInfo); + _completedInstallationsInternal.Add(package); - PackageInstallationCompleted?.Invoke(this, installationEventArgs); + PackageInstallationCompleted?.Invoke(this, package); } catch (OperationCanceledException) { @@ -294,9 +283,9 @@ namespace Emby.Server.Implementations.Updates _currentInstallations.Remove(tuple); } - _logger.LogInformation("Package installation cancelled: {0} {1}", package.name, package.version); + _logger.LogInformation("Package installation cancelled: {0} {1}", package.Name, package.Version); - PackageInstallationCancelled?.Invoke(this, installationEventArgs); + PackageInstallationCancelled?.Invoke(this, package); throw; } @@ -311,7 +300,7 @@ namespace Emby.Server.Implementations.Updates PackageInstallationFailed?.Invoke(this, new InstallationFailedEventArgs { - InstallationInfo = installationInfo, + InstallationInfo = package, Exception = ex }); @@ -330,11 +319,11 @@ namespace Emby.Server.Implementations.Updates /// The package. /// The cancellation token. /// . - private async Task InstallPackageInternal(VersionInfo package, CancellationToken cancellationToken) + private async Task InstallPackageInternal(InstallationInfo 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)) - ?? _applicationHost.Plugins.FirstOrDefault(p => p.Name.Equals(package.name, StringComparison.OrdinalIgnoreCase)); + IPlugin plugin = _applicationHost.Plugins.FirstOrDefault(p => p.Id == package.Guid) + ?? _applicationHost.Plugins.FirstOrDefault(p => p.Name.Equals(package.Name, StringComparison.OrdinalIgnoreCase)); // Do the install await PerformPackageInstallation(package, cancellationToken).ConfigureAwait(false); @@ -342,38 +331,38 @@ namespace Emby.Server.Implementations.Updates // Do plugin-specific processing if (plugin == null) { - _logger.LogInformation("New plugin installed: {0} {1} {2}", package.name, package.version); + _logger.LogInformation("New plugin installed: {0} {1}", package.Name, package.Version); - PluginInstalled?.Invoke(this, new GenericEventArgs(package)); + PluginInstalled?.Invoke(this, package); } else { - _logger.LogInformation("Plugin updated: {0} {1} {2}", package.name, package.version); + _logger.LogInformation("Plugin updated: {0} {1}", package.Name, package.Version); - PluginUpdated?.Invoke(this, new GenericEventArgs<(IPlugin, VersionInfo)>((plugin, package))); + PluginUpdated?.Invoke(this, package); } _applicationHost.NotifyPendingRestart(); } - private async Task PerformPackageInstallation(VersionInfo package, CancellationToken cancellationToken) + private async Task PerformPackageInstallation(InstallationInfo package, CancellationToken cancellationToken) { - var extension = Path.GetExtension(package.filename); + var extension = Path.GetExtension(package.SourceUrl); if (!string.Equals(extension, ".zip", StringComparison.OrdinalIgnoreCase)) { - _logger.LogError("Only zip packages are supported. {Filename} is not a zip archive.", package.filename); + _logger.LogError("Only zip packages are supported. {SourceUrl} is not a zip archive.", package.SourceUrl); return; } // Always override the passed-in target (which is a file) and figure it out again - string targetDir = Path.Combine(_appPaths.PluginsPath, package.name); + string targetDir = Path.Combine(_appPaths.PluginsPath, package.Name); // CA5351: Do Not Use Broken Cryptographic Algorithms #pragma warning disable CA5351 using (var res = await _httpClient.SendAsync( new HttpRequestOptions { - Url = package.sourceUrl, + Url = package.SourceUrl, CancellationToken = cancellationToken, // We need it to be buffered for setting the position BufferContent = true @@ -385,12 +374,12 @@ namespace Emby.Server.Implementations.Updates cancellationToken.ThrowIfCancellationRequested(); var hash = Hex.Encode(md5.ComputeHash(stream)); - if (!string.Equals(package.checksum, hash, StringComparison.OrdinalIgnoreCase)) + if (!string.Equals(package.Checksum, hash, StringComparison.OrdinalIgnoreCase)) { _logger.LogError( "The checksums didn't match while installing {Package}, expected: {Expected}, got: {Received}", - package.name, - package.checksum, + package.Name, + package.Checksum, hash); throw new InvalidDataException("The checksum of the received data doesn't match."); } @@ -456,7 +445,7 @@ namespace Emby.Server.Implementations.Updates _config.SaveConfiguration(); } - PluginUninstalled?.Invoke(this, new GenericEventArgs(plugin)); + PluginUninstalled?.Invoke(this, plugin); _applicationHost.NotifyPendingRestart(); } @@ -466,7 +455,7 @@ namespace Emby.Server.Implementations.Updates { lock (_currentInstallationsLock) { - var install = _currentInstallations.Find(x => x.info.Guid == id.ToString()); + var install = _currentInstallations.Find(x => x.info.Guid == id); if (install == default((InstallationInfo, CancellationTokenSource))) { return false; @@ -486,9 +475,9 @@ namespace Emby.Server.Implementations.Updates } /// - /// Releases unmanaged and - optionally - managed resources. + /// Releases unmanaged and optionally managed resources. /// - /// true to release both managed and unmanaged resources; false to release only unmanaged resources. + /// true to release both managed and unmanaged resources or false to release only unmanaged resources. protected virtual void Dispose(bool dispose) { if (dispose) diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index 25d5d0c893..a8de171ccc 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -9,6 +9,7 @@ netstandard2.1 true true + enable diff --git a/Jellyfin.Api/Models/StartupDtos/StartupConfigurationDto.cs b/Jellyfin.Api/Models/StartupDtos/StartupConfigurationDto.cs index d048dad0a1..5a83a030d2 100644 --- a/Jellyfin.Api/Models/StartupDtos/StartupConfigurationDto.cs +++ b/Jellyfin.Api/Models/StartupDtos/StartupConfigurationDto.cs @@ -1,3 +1,5 @@ +#nullable disable + namespace Jellyfin.Api.Models.StartupDtos { /// diff --git a/Jellyfin.Api/Models/StartupDtos/StartupUserDto.cs b/Jellyfin.Api/Models/StartupDtos/StartupUserDto.cs index 3a9348037a..0dbb245ec6 100644 --- a/Jellyfin.Api/Models/StartupDtos/StartupUserDto.cs +++ b/Jellyfin.Api/Models/StartupDtos/StartupUserDto.cs @@ -1,3 +1,5 @@ +#nullable disable + namespace Jellyfin.Api.Models.StartupDtos { /// diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj index 9157c3ead9..c2c105917d 100644 --- a/Jellyfin.Data/Jellyfin.Data.csproj +++ b/Jellyfin.Data/Jellyfin.Data.csproj @@ -4,6 +4,7 @@ netstandard2.0;netstandard2.1 false true + true diff --git a/Jellyfin.Drawing.Skia/SkiaEncoder.cs b/Jellyfin.Drawing.Skia/SkiaEncoder.cs index dae0e94d45..ccee5c5b91 100644 --- a/Jellyfin.Drawing.Skia/SkiaEncoder.cs +++ b/Jellyfin.Drawing.Skia/SkiaEncoder.cs @@ -53,9 +53,7 @@ namespace Jellyfin.Drawing.Skia "jpeg", "jpg", "png", - "dng", - "webp", "gif", "bmp", @@ -64,10 +62,8 @@ namespace Jellyfin.Drawing.Skia "ktx", "pkm", "wbmp", - - // TODO - // Are all of these supported? https://github.com/google/skia/blob/master/infra/bots/recipes/test.py#L454 - + // TODO: check if these are supported on multiple platforms + // https://github.com/google/skia/blob/master/infra/bots/recipes/test.py#L454 // working on windows at least "cr2", "nef", @@ -272,7 +268,7 @@ namespace Jellyfin.Drawing.Skia return path; } - var tempPath = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + Path.GetExtension(path) ?? string.Empty); + var tempPath = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + Path.GetExtension(path)); Directory.CreateDirectory(Path.GetDirectoryName(tempPath)); File.Copy(path, tempPath, true); diff --git a/MediaBrowser.Common/Configuration/ConfigurationStore.cs b/MediaBrowser.Common/Configuration/ConfigurationStore.cs new file mode 100644 index 0000000000..d31d45e4c3 --- /dev/null +++ b/MediaBrowser.Common/Configuration/ConfigurationStore.cs @@ -0,0 +1,20 @@ +using System; + +namespace MediaBrowser.Common.Configuration +{ + /// + /// Describes a single entry in the application configuration. + /// + public class ConfigurationStore + { + /// + /// Gets or sets the unique identifier for the configuration. + /// + public string Key { get; set; } + + /// + /// Gets or sets the type used to store the data for this configuration entry. + /// + public Type ConfigurationType { get; set; } + } +} diff --git a/MediaBrowser.Common/Configuration/IApplicationPaths.cs b/MediaBrowser.Common/Configuration/IApplicationPaths.cs index 870b90796c..4cea616826 100644 --- a/MediaBrowser.Common/Configuration/IApplicationPaths.cs +++ b/MediaBrowser.Common/Configuration/IApplicationPaths.cs @@ -3,12 +3,12 @@ using MediaBrowser.Model.Configuration; namespace MediaBrowser.Common.Configuration { /// - /// Interface IApplicationPaths + /// Interface IApplicationPaths. /// public interface IApplicationPaths { /// - /// Gets the path to the program data folder + /// Gets the path to the program data folder. /// /// The program data path. string ProgramDataPath { get; } @@ -23,13 +23,13 @@ namespace MediaBrowser.Common.Configuration string WebPath { get; } /// - /// Gets the path to the program system folder + /// Gets the path to the program system folder. /// /// The program data path. string ProgramSystemPath { get; } /// - /// Gets the folder path to the data directory + /// Gets the folder path to the data directory. /// /// The data directory. string DataPath { get; } @@ -41,43 +41,43 @@ namespace MediaBrowser.Common.Configuration string ImageCachePath { get; } /// - /// Gets the path to the plugin directory + /// Gets the path to the plugin directory. /// /// The plugins path. string PluginsPath { get; } /// - /// Gets the path to the plugin configurations directory + /// Gets the path to the plugin configurations directory. /// /// The plugin configurations path. string PluginConfigurationsPath { get; } /// - /// Gets the path to the log directory + /// Gets the path to the log directory. /// /// The log directory path. string LogDirectoryPath { get; } /// - /// Gets the path to the application configuration root directory + /// Gets the path to the application configuration root directory. /// /// The configuration directory path. string ConfigurationDirectoryPath { get; } /// - /// Gets the path to the system configuration file + /// Gets the path to the system configuration file. /// /// The system configuration file path. string SystemConfigurationFilePath { get; } /// - /// Gets the folder path to the cache directory + /// Gets the folder path to the cache directory. /// /// The cache directory. string CachePath { get; } /// - /// Gets the folder path to the temp directory within the cache folder + /// Gets the folder path to the temp directory within the cache folder. /// /// The temp directory. string TempDirectory { get; } diff --git a/MediaBrowser.Common/Configuration/IConfigurationFactory.cs b/MediaBrowser.Common/Configuration/IConfigurationFactory.cs index 07ca2b58ba..6db1f1364b 100644 --- a/MediaBrowser.Common/Configuration/IConfigurationFactory.cs +++ b/MediaBrowser.Common/Configuration/IConfigurationFactory.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace MediaBrowser.Common.Configuration @@ -15,33 +14,4 @@ namespace MediaBrowser.Common.Configuration /// The configuration store. IEnumerable GetConfigurations(); } - - /// - /// Describes a single entry in the application configuration. - /// - public class ConfigurationStore - { - /// - /// Gets or sets the unique identifier for the configuration. - /// - public string Key { get; set; } - - /// - /// Gets or sets the type used to store the data for this configuration entry. - /// - public Type ConfigurationType { get; set; } - } - - /// - /// A configuration store that can be validated. - /// - public interface IValidatingConfiguration - { - /// - /// Validation method to be invoked before saving the configuration. - /// - /// The old configuration. - /// The new configuration. - void Validate(object oldConfig, object newConfig); - } } diff --git a/MediaBrowser.Common/Configuration/IConfigurationManager.cs b/MediaBrowser.Common/Configuration/IConfigurationManager.cs index caf2edd836..fe726090d6 100644 --- a/MediaBrowser.Common/Configuration/IConfigurationManager.cs +++ b/MediaBrowser.Common/Configuration/IConfigurationManager.cs @@ -24,7 +24,7 @@ namespace MediaBrowser.Common.Configuration event EventHandler NamedConfigurationUpdated; /// - /// Gets or sets the application paths. + /// Gets the application paths. /// /// The application paths. IApplicationPaths CommonApplicationPaths { get; } diff --git a/MediaBrowser.Common/Configuration/IValidatingConfiguration.cs b/MediaBrowser.Common/Configuration/IValidatingConfiguration.cs new file mode 100644 index 0000000000..3b1d84f3c2 --- /dev/null +++ b/MediaBrowser.Common/Configuration/IValidatingConfiguration.cs @@ -0,0 +1,15 @@ +namespace MediaBrowser.Common.Configuration +{ + /// + /// A configuration store that can be validated. + /// + public interface IValidatingConfiguration + { + /// + /// Validation method to be invoked before saving the configuration. + /// + /// The old configuration. + /// The new configuration. + void Validate(object oldConfig, object newConfig); + } +} diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index a597b90524..0713b83b75 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -37,7 +37,7 @@ - + diff --git a/MediaBrowser.Common/Net/CacheMode.cs b/MediaBrowser.Common/Net/CacheMode.cs new file mode 100644 index 0000000000..78fa3bf9bb --- /dev/null +++ b/MediaBrowser.Common/Net/CacheMode.cs @@ -0,0 +1,11 @@ +#pragma warning disable CS1591 +#pragma warning disable SA1602 + +namespace MediaBrowser.Common.Net +{ + public enum CacheMode + { + None = 0, + Unconditional = 1 + } +} diff --git a/MediaBrowser.Common/Net/CompressionMethods.cs b/MediaBrowser.Common/Net/CompressionMethods.cs new file mode 100644 index 0000000000..39b72609fe --- /dev/null +++ b/MediaBrowser.Common/Net/CompressionMethods.cs @@ -0,0 +1,15 @@ +#pragma warning disable CS1591 +#pragma warning disable SA1602 + +using System; + +namespace MediaBrowser.Common.Net +{ + [Flags] + public enum CompressionMethods + { + None = 0b00000001, + Deflate = 0b00000010, + Gzip = 0b00000100 + } +} diff --git a/MediaBrowser.Common/Net/HttpRequestOptions.cs b/MediaBrowser.Common/Net/HttpRequestOptions.cs index 38274a80e4..347fc98332 100644 --- a/MediaBrowser.Common/Net/HttpRequestOptions.cs +++ b/MediaBrowser.Common/Net/HttpRequestOptions.cs @@ -102,18 +102,4 @@ namespace MediaBrowser.Common.Net return value; } } - - public enum CacheMode - { - None = 0, - Unconditional = 1 - } - - [Flags] - public enum CompressionMethods - { - None = 0b00000001, - Deflate = 0b00000010, - Gzip = 0b00000100 - } } diff --git a/MediaBrowser.Common/Progress/ActionableProgress.cs b/MediaBrowser.Common/Progress/ActionableProgress.cs index af69055aa9..d5bcd5be96 100644 --- a/MediaBrowser.Common/Progress/ActionableProgress.cs +++ b/MediaBrowser.Common/Progress/ActionableProgress.cs @@ -5,15 +5,16 @@ using System; namespace MediaBrowser.Common.Progress { /// - /// Class ActionableProgress + /// Class ActionableProgress. /// - /// + /// The type for the action parameter. public class ActionableProgress : IProgress { /// - /// The _actions + /// The _actions. /// private Action _action; + public event EventHandler ProgressChanged; /// @@ -32,14 +33,4 @@ namespace MediaBrowser.Common.Progress _action?.Invoke(value); } } - - public class SimpleProgress : IProgress - { - public event EventHandler ProgressChanged; - - public void Report(T value) - { - ProgressChanged?.Invoke(this, value); - } - } } diff --git a/MediaBrowser.Common/Progress/SimpleProgress.cs b/MediaBrowser.Common/Progress/SimpleProgress.cs new file mode 100644 index 0000000000..d75675bf17 --- /dev/null +++ b/MediaBrowser.Common/Progress/SimpleProgress.cs @@ -0,0 +1,16 @@ +#pragma warning disable CS1591 + +using System; + +namespace MediaBrowser.Common.Progress +{ + public class SimpleProgress : IProgress + { + public event EventHandler ProgressChanged; + + public void Report(T value) + { + ProgressChanged?.Invoke(this, value); + } + } +} diff --git a/MediaBrowser.Common/Updates/IInstallationManager.cs b/MediaBrowser.Common/Updates/IInstallationManager.cs index 950604432d..965ffe0ec2 100644 --- a/MediaBrowser.Common/Updates/IInstallationManager.cs +++ b/MediaBrowser.Common/Updates/IInstallationManager.cs @@ -12,28 +12,28 @@ namespace MediaBrowser.Common.Updates { public interface IInstallationManager : IDisposable { - event EventHandler PackageInstalling; + event EventHandler PackageInstalling; - event EventHandler PackageInstallationCompleted; + event EventHandler PackageInstallationCompleted; event EventHandler PackageInstallationFailed; - event EventHandler PackageInstallationCancelled; + event EventHandler PackageInstallationCancelled; /// /// Occurs when a plugin is uninstalled. /// - event EventHandler> PluginUninstalled; + event EventHandler PluginUninstalled; /// /// 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. @@ -59,16 +59,6 @@ namespace MediaBrowser.Common.Updates string name = null, Guid guid = default); - /// - /// Returns all compatible versions ordered from newest to oldest. - /// - /// The available version of the plugin. - /// The minimum required version of the plugin. - /// All compatible versions ordered from newest to oldest. - IEnumerable GetCompatibleVersions( - IEnumerable availableVersions, - Version minVersion = null); - /// /// Returns all compatible versions ordered from newest to oldest. /// @@ -77,7 +67,7 @@ namespace MediaBrowser.Common.Updates /// The guid of the plugin. /// The minimum required version of the plugin. /// All compatible versions ordered from newest to oldest. - IEnumerable GetCompatibleVersions( + IEnumerable GetCompatibleVersions( IEnumerable availablePackages, string name = null, Guid guid = default, @@ -88,7 +78,7 @@ namespace MediaBrowser.Common.Updates /// /// The cancellation token. /// The available plugin updates. - Task> GetAvailablePluginUpdates(CancellationToken cancellationToken = default); + Task> GetAvailablePluginUpdates(CancellationToken cancellationToken = default); /// /// Installs the package. @@ -96,7 +86,7 @@ namespace MediaBrowser.Common.Updates /// The package. /// The cancellation token. /// . - Task InstallPackage(VersionInfo package, CancellationToken cancellationToken = default); + Task InstallPackage(InstallationInfo package, CancellationToken cancellationToken = default); /// /// Uninstalls a plugin. diff --git a/MediaBrowser.Model/Updates/InstallationInfo.cs b/MediaBrowser.Model/Updates/InstallationInfo.cs index 57dc746aca..a6d80dba62 100644 --- a/MediaBrowser.Model/Updates/InstallationInfo.cs +++ b/MediaBrowser.Model/Updates/InstallationInfo.cs @@ -12,7 +12,7 @@ namespace MediaBrowser.Model.Updates /// Gets or sets the guid. /// /// The guid. - public string Guid { get; set; } + public Guid Guid { get; set; } /// /// Gets or sets the name. @@ -24,6 +24,24 @@ namespace MediaBrowser.Model.Updates /// Gets or sets the version. /// /// The version. - public string Version { get; set; } + public Version Version { get; set; } + + /// + /// Gets or sets the changelog for this version. + /// + /// The changelog. + public string Changelog { 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; } } } diff --git a/MediaBrowser.Model/Updates/VersionInfo.cs b/MediaBrowser.Model/Updates/VersionInfo.cs index 5ab276b898..a4aa0e75f3 100644 --- a/MediaBrowser.Model/Updates/VersionInfo.cs +++ b/MediaBrowser.Model/Updates/VersionInfo.cs @@ -9,23 +9,11 @@ namespace MediaBrowser.Model.Updates /// 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. /// /// The version. - public Version version { get; set; } + public string version { get; set; } /// /// Gets or sets the changelog for this version. @@ -52,9 +40,9 @@ namespace MediaBrowser.Model.Updates public string checksum { get; set; } /// - /// Gets or sets the target filename for the downloaded binary. + /// Gets or sets a timestamp of when the binary was built. /// - /// The target filename. - public string filename { get; set; } + /// The timestamp. + public string timestamp { get; set; } } } diff --git a/RSSDP/RSSDP.csproj b/RSSDP/RSSDP.csproj index e3f3127b64..5536931717 100644 --- a/RSSDP/RSSDP.csproj +++ b/RSSDP/RSSDP.csproj @@ -14,6 +14,7 @@ netstandard2.1 false + true