From 88bfd1bcf45bdfa6c64e3439d7f406799645163c Mon Sep 17 00:00:00 2001 From: David Ullmer Date: Mon, 10 May 2021 17:58:21 +0200 Subject: [PATCH 001/120] Add tests for LocalizationManager --- .../Localization/LocalizationManagerTests.cs | 167 ++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs diff --git a/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs new file mode 100644 index 0000000000..acdf74c4f7 --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs @@ -0,0 +1,167 @@ +using System.Linq; +using System.Threading.Tasks; +using Emby.Server.Implementations.Localization; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Model.Configuration; +using Microsoft.Extensions.Logging.Abstractions; +using Moq; +using Xunit; + +namespace Jellyfin.Server.Implementations.Tests.Localization +{ + public class LocalizationManagerTests + { + private LocalizationManager _localizationManager = null!; + + public LocalizationManagerTests() + { + var config = new ServerConfiguration() { UICulture = "de-DE" }; + Setup(config); + } + + [Fact] + public void GetCountries_All_Success() + { + var countries = _localizationManager.GetCountries(); + var countryInfos = countries.ToList(); + + Assert.Equal(139, countryInfos.Count); + + var germany = countryInfos.FirstOrDefault(x => x.Name == "DE"); + Assert.NotNull(germany); + Assert.Equal("Germany", germany!.DisplayName); + Assert.Equal("DEU", germany!.ThreeLetterISORegionName); + Assert.Equal("DE", germany!.TwoLetterISORegionName); + } + + [Fact] + public async Task GetCultures_All_Success() + { + await _localizationManager.LoadAll(); + var cultures = _localizationManager.GetCultures().ToList(); + + Assert.Equal(189, cultures.Count); + + var germany = cultures.FirstOrDefault(x => x.TwoLetterISOLanguageName == "de"); + Assert.NotNull(germany); + Assert.Equal("ger", germany!.ThreeLetterISOLanguageName); + Assert.Equal("German", germany!.DisplayName); + Assert.Equal("German", germany!.Name); + Assert.Contains("deu", germany!.ThreeLetterISOLanguageNames); + Assert.Contains("ger", germany!.ThreeLetterISOLanguageNames); + } + + [Theory] + [InlineData("de")] + [InlineData("ger")] + [InlineData("german")] + public async Task FindLanguage_Valid_Success(string identifier) + { + await _localizationManager.LoadAll(); + + var germany = _localizationManager.FindLanguageInfo(identifier); + Assert.NotNull(germany); + + Assert.Equal("ger", germany!.ThreeLetterISOLanguageName); + Assert.Equal("German", germany!.DisplayName); + Assert.Equal("German", germany!.Name); + Assert.Contains("deu", germany!.ThreeLetterISOLanguageNames); + Assert.Contains("ger", germany!.ThreeLetterISOLanguageNames); + } + + [Fact] + public async Task ParentalRatings_Default_Success() + { + await _localizationManager.LoadAll(); + var ratings = _localizationManager.GetParentalRatings().ToList(); + + Assert.Equal(23, ratings.Count); + + var tvma = ratings.FirstOrDefault(x => x.Name == "TV-MA"); + Assert.NotNull(tvma); + Assert.Equal(9, tvma!.Value); + } + + [Fact] + public async Task ParentalRatings_ConfiguredCountryCode_Success() + { + Setup(new ServerConfiguration() + { + MetadataCountryCode = "DE" + }); + await _localizationManager.LoadAll(); + var ratings = _localizationManager.GetParentalRatings().ToList(); + + Assert.Equal(10, ratings.Count); + + var fsk = ratings.FirstOrDefault(x => x.Name == "FSK-12"); + Assert.NotNull(fsk); + Assert.Equal(7, fsk!.Value); + } + + [Theory] + [InlineData("CA-R", "CA", 10)] + [InlineData("FSK-16", "DE", 8)] + [InlineData("FSK-18", "DE", 9)] + [InlineData("FSK-18", "US", 9)] + [InlineData("TV-MA", "US", 9)] + [InlineData("XXX", "asdf", 100)] + [InlineData("Germany: FSK-18", "DE", 9)] + public async Task GetRatingLevelFromString_Valid_Success(string value, string countryCode, int expectedLevel) + { + Setup(new ServerConfiguration() + { + MetadataCountryCode = countryCode + }); + await _localizationManager.LoadAll(); + var level = _localizationManager.GetRatingLevel(value); + Assert.NotNull(level); + Assert.Equal(expectedLevel, level!); + } + + [Fact] + public async Task GetRatingLevelFromString_Unrated_Success() + { + await _localizationManager.LoadAll(); + Assert.Null(_localizationManager.GetRatingLevel("n/a")); + } + + [Theory] + [InlineData("Default", "Default")] + [InlineData("HeaderLiveTV", "Live TV")] + public void GetLocalizedString_Valid_Success(string key, string expected) + { + Setup(new ServerConfiguration() + { + UICulture = "en-US" + }); + + var translated = _localizationManager.GetLocalizedString(key); + Assert.NotNull(translated); + Assert.Equal(expected, translated); + } + + [Fact] + public void GetLocalizedString_Invalid_Success() + { + Setup(new ServerConfiguration() + { + UICulture = "en-US" + }); + + var key = "SuperInvalidTranslationKeyThatWillNeverBeAdded"; + + var translated = _localizationManager.GetLocalizedString(key); + Assert.NotNull(translated); + Assert.Equal(key, translated); + } + + private void Setup(ServerConfiguration config) + { + var mockConfiguration = new Mock(); + mockConfiguration.SetupGet(x => x.Configuration).Returns(config); + + _localizationManager = new LocalizationManager(mockConfiguration.Object, new NullLogger()); + } + } +} From db2b53a4b52d0c1e9797bfc70030b04421ba46a6 Mon Sep 17 00:00:00 2001 From: David Ullmer Date: Mon, 10 May 2021 18:05:35 +0200 Subject: [PATCH 002/120] Refactor LocalizationManager and remove dead method --- .../Localization/LocalizationManager.cs | 400 +++++++++--------- .../Globalization/ILocalizationManager.cs | 8 - 2 files changed, 190 insertions(+), 218 deletions(-) diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index 220e423bf5..efbccaa5b9 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -25,18 +25,18 @@ namespace Emby.Server.Implementations.Localization private static readonly Assembly _assembly = typeof(LocalizationManager).Assembly; private static readonly string[] _unratedValues = { "n/a", "unrated", "not rated" }; - private readonly IServerConfigurationManager _configurationManager; - private readonly ILogger _logger; - private readonly Dictionary> _allParentalRatings = new Dictionary>(StringComparer.OrdinalIgnoreCase); + private readonly IServerConfigurationManager _configurationManager; + private readonly ConcurrentDictionary> _dictionaries = new ConcurrentDictionary>(StringComparer.OrdinalIgnoreCase); - private List _cultures; - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; + private readonly ILogger _logger; + + private List _cultures; /// /// Initializes a new instance of the class. @@ -51,57 +51,6 @@ namespace Emby.Server.Implementations.Localization _logger = logger; } - /// - /// Loads all resources into memory. - /// - /// . - public async Task LoadAll() - { - const string RatingsResource = "Emby.Server.Implementations.Localization.Ratings."; - - // Extract from the assembly - foreach (var resource in _assembly.GetManifestResourceNames()) - { - if (!resource.StartsWith(RatingsResource, StringComparison.Ordinal)) - { - continue; - } - - string countryCode = resource.Substring(RatingsResource.Length, 2); - var dict = new Dictionary(StringComparer.OrdinalIgnoreCase); - - using (var str = _assembly.GetManifestResourceStream(resource)) - using (var reader = new StreamReader(str)) - { - await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false)) - { - if (string.IsNullOrWhiteSpace(line)) - { - continue; - } - - string[] parts = line.Split(','); - if (parts.Length == 2 - && int.TryParse(parts[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var value)) - { - var name = parts[0]; - dict.Add(name, new ParentalRating(name, value)); - } -#if DEBUG - else - { - _logger.LogWarning("Malformed line in ratings file for country {CountryCode}", countryCode); - } -#endif - } - } - - _allParentalRatings[countryCode] = dict; - } - - await LoadCultures().ConfigureAwait(false); - } - /// /// Gets the cultures. /// @@ -109,62 +58,6 @@ namespace Emby.Server.Implementations.Localization public IEnumerable GetCultures() => _cultures; - private async Task LoadCultures() - { - List list = new List(); - - const string ResourcePath = "Emby.Server.Implementations.Localization.iso6392.txt"; - - using (var stream = _assembly.GetManifestResourceStream(ResourcePath)) - using (var reader = new StreamReader(stream)) - { - await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false)) - { - if (string.IsNullOrWhiteSpace(line)) - { - continue; - } - - var parts = line.Split('|'); - - if (parts.Length == 5) - { - string name = parts[3]; - if (string.IsNullOrWhiteSpace(name)) - { - continue; - } - - string twoCharName = parts[2]; - if (string.IsNullOrWhiteSpace(twoCharName)) - { - continue; - } - - string[] threeletterNames; - if (string.IsNullOrWhiteSpace(parts[1])) - { - threeletterNames = new[] { parts[0] }; - } - else - { - threeletterNames = new[] { parts[0], parts[1] }; - } - - list.Add(new CultureDto - { - DisplayName = name, - Name = name, - ThreeLetterISOLanguageNames = threeletterNames, - TwoLetterISOLanguageName = twoCharName - }); - } - } - } - - _cultures = list; - } - /// public CultureDto FindLanguageInfo(string language) => GetCultures() @@ -186,34 +79,6 @@ namespace Emby.Server.Implementations.Localization public IEnumerable GetParentalRatings() => GetParentalRatingsDictionary().Values; - /// - /// Gets the parental ratings dictionary. - /// - /// . - private Dictionary GetParentalRatingsDictionary() - { - var countryCode = _configurationManager.Configuration.MetadataCountryCode; - - if (string.IsNullOrEmpty(countryCode)) - { - countryCode = "us"; - } - - return GetRatings(countryCode) ?? GetRatings("us"); - } - - /// - /// Gets the ratings. - /// - /// The country code. - /// The ratings. - private Dictionary GetRatings(string countryCode) - { - _allParentalRatings.TryGetValue(countryCode, out var value); - - return value; - } - /// public int? GetRatingLevel(string rating) { @@ -250,7 +115,7 @@ namespace Emby.Server.Implementations.Localization var index = rating.IndexOf(':', StringComparison.Ordinal); if (index != -1) { - rating = rating.Substring(index).TrimStart(':').Trim(); + rating = rating.Substring(index + 1).Trim(); if (!string.IsNullOrWhiteSpace(rating)) { @@ -262,20 +127,6 @@ namespace Emby.Server.Implementations.Localization return null; } - /// - public bool HasUnicodeCategory(string value, UnicodeCategory category) - { - foreach (var chr in value) - { - if (char.GetUnicodeCategory(chr) == category) - { - return true; - } - } - - return false; - } - /// public string GetLocalizedString(string phrase) { @@ -305,6 +156,179 @@ namespace Emby.Server.Implementations.Localization return phrase; } + /// + public IEnumerable GetLocalizationOptions() + { + yield return new LocalizationOption("Arabic", "ar"); + yield return new LocalizationOption("Bulgarian (Bulgaria)", "bg-BG"); + yield return new LocalizationOption("Catalan", "ca"); + yield return new LocalizationOption("Chinese Simplified", "zh-CN"); + yield return new LocalizationOption("Chinese Traditional", "zh-TW"); + yield return new LocalizationOption("Croatian", "hr"); + yield return new LocalizationOption("Czech", "cs"); + yield return new LocalizationOption("Danish", "da"); + yield return new LocalizationOption("Dutch", "nl"); + yield return new LocalizationOption("English (United Kingdom)", "en-GB"); + yield return new LocalizationOption("English (United States)", "en-US"); + yield return new LocalizationOption("French", "fr"); + yield return new LocalizationOption("French (Canada)", "fr-CA"); + yield return new LocalizationOption("German", "de"); + yield return new LocalizationOption("Greek", "el"); + yield return new LocalizationOption("Hebrew", "he"); + yield return new LocalizationOption("Hungarian", "hu"); + yield return new LocalizationOption("Italian", "it"); + yield return new LocalizationOption("Kazakh", "kk"); + yield return new LocalizationOption("Korean", "ko"); + yield return new LocalizationOption("Lithuanian", "lt-LT"); + yield return new LocalizationOption("Malay", "ms"); + yield return new LocalizationOption("Norwegian Bokmål", "nb"); + yield return new LocalizationOption("Persian", "fa"); + yield return new LocalizationOption("Polish", "pl"); + yield return new LocalizationOption("Portuguese (Brazil)", "pt-BR"); + yield return new LocalizationOption("Portuguese (Portugal)", "pt-PT"); + yield return new LocalizationOption("Russian", "ru"); + yield return new LocalizationOption("Slovak", "sk"); + yield return new LocalizationOption("Slovenian (Slovenia)", "sl-SI"); + yield return new LocalizationOption("Spanish", "es"); + yield return new LocalizationOption("Spanish (Argentina)", "es-AR"); + yield return new LocalizationOption("Spanish (Mexico)", "es-MX"); + yield return new LocalizationOption("Swedish", "sv"); + yield return new LocalizationOption("Swiss German", "gsw"); + yield return new LocalizationOption("Turkish", "tr"); + yield return new LocalizationOption("Tiếng Việt", "vi"); + } + + /// + /// Loads all resources into memory. + /// + /// . + public async Task LoadAll() + { + const string RatingsResource = "Emby.Server.Implementations.Localization.Ratings."; + + // Extract from the assembly + foreach (var resource in _assembly.GetManifestResourceNames()) + { + if (!resource.StartsWith(RatingsResource, StringComparison.Ordinal)) + { + continue; + } + + string countryCode = resource.Substring(RatingsResource.Length, 2); + var dict = new Dictionary(StringComparer.OrdinalIgnoreCase); + + await using var str = _assembly.GetManifestResourceStream(resource); + using var reader = new StreamReader(str); + await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false)) + { + if (string.IsNullOrWhiteSpace(line)) + { + continue; + } + + string[] parts = line.Split(','); + if (parts.Length == 2 + && int.TryParse(parts[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var value)) + { + var name = parts[0]; + dict.Add(name, new ParentalRating(name, value)); + } +#if DEBUG + else + { + _logger.LogWarning("Malformed line in ratings file for country {CountryCode}", countryCode); + } +#endif + } + + _allParentalRatings[countryCode] = dict; + } + + await LoadCultures().ConfigureAwait(false); + } + + private async Task LoadCultures() + { + List list = new List(); + + const string ResourcePath = "Emby.Server.Implementations.Localization.iso6392.txt"; + + await using var stream = _assembly.GetManifestResourceStream(ResourcePath); + using var reader = new StreamReader(stream); + await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false)) + { + if (string.IsNullOrWhiteSpace(line)) + { + continue; + } + + var parts = line.Split('|'); + + if (parts.Length == 5) + { + string name = parts[3]; + if (string.IsNullOrWhiteSpace(name)) + { + continue; + } + + string twoCharName = parts[2]; + if (string.IsNullOrWhiteSpace(twoCharName)) + { + continue; + } + + string[] threeletterNames; + if (string.IsNullOrWhiteSpace(parts[1])) + { + threeletterNames = new[] { parts[0] }; + } + else + { + threeletterNames = new[] { parts[0], parts[1] }; + } + + list.Add(new CultureDto + { + DisplayName = name, + Name = name, + ThreeLetterISOLanguageNames = threeletterNames, + TwoLetterISOLanguageName = twoCharName + }); + } + } + + _cultures = list; + } + + /// + /// Gets the parental ratings dictionary. + /// + /// . + private Dictionary GetParentalRatingsDictionary() + { + var countryCode = _configurationManager.Configuration.MetadataCountryCode; + + if (string.IsNullOrEmpty(countryCode)) + { + countryCode = "us"; + } + + return GetRatings(countryCode) ?? GetRatings("us"); + } + + /// + /// Gets the ratings. + /// + /// The country code. + /// The ratings. + private Dictionary GetRatings(string countryCode) + { + _allParentalRatings.TryGetValue(countryCode, out var value); + + return value; + } + private Dictionary GetLocalizationDictionary(string culture) { if (string.IsNullOrEmpty(culture)) @@ -316,7 +340,7 @@ namespace Emby.Server.Implementations.Localization return _dictionaries.GetOrAdd( culture, - f => GetDictionary(Prefix, culture, DefaultCulture + ".json").GetAwaiter().GetResult()); + _ => GetDictionary(Prefix, culture, DefaultCulture + ".json").GetAwaiter().GetResult()); } private async Task> GetDictionary(string prefix, string culture, string baseFilename) @@ -338,23 +362,21 @@ namespace Emby.Server.Implementations.Localization private async Task CopyInto(IDictionary dictionary, string resourcePath) { - using (var stream = _assembly.GetManifestResourceStream(resourcePath)) + await using var stream = _assembly.GetManifestResourceStream(resourcePath); + // If a Culture doesn't have a translation the stream will be null and it defaults to en-us further up the chain + if (stream != null) { - // If a Culture doesn't have a translation the stream will be null and it defaults to en-us further up the chain - if (stream != null) - { - var dict = await JsonSerializer.DeserializeAsync>(stream, _jsonOptions).ConfigureAwait(false); + var dict = await JsonSerializer.DeserializeAsync>(stream, _jsonOptions).ConfigureAwait(false); - foreach (var key in dict.Keys) - { - dictionary[key] = dict[key]; - } - } - else + foreach (var key in dict.Keys) { - _logger.LogError("Missing translation/culture resource: {ResourcePath}", resourcePath); + dictionary[key] = dict[key]; } } + else + { + _logger.LogError("Missing translation/culture resource: {ResourcePath}", resourcePath); + } } private static string GetResourceFilename(string culture) @@ -372,47 +394,5 @@ namespace Emby.Server.Implementations.Localization return culture + ".json"; } - - /// - public IEnumerable GetLocalizationOptions() - { - yield return new LocalizationOption("Arabic", "ar"); - yield return new LocalizationOption("Bulgarian (Bulgaria)", "bg-BG"); - yield return new LocalizationOption("Catalan", "ca"); - yield return new LocalizationOption("Chinese Simplified", "zh-CN"); - yield return new LocalizationOption("Chinese Traditional", "zh-TW"); - yield return new LocalizationOption("Croatian", "hr"); - yield return new LocalizationOption("Czech", "cs"); - yield return new LocalizationOption("Danish", "da"); - yield return new LocalizationOption("Dutch", "nl"); - yield return new LocalizationOption("English (United Kingdom)", "en-GB"); - yield return new LocalizationOption("English (United States)", "en-US"); - yield return new LocalizationOption("French", "fr"); - yield return new LocalizationOption("French (Canada)", "fr-CA"); - yield return new LocalizationOption("German", "de"); - yield return new LocalizationOption("Greek", "el"); - yield return new LocalizationOption("Hebrew", "he"); - yield return new LocalizationOption("Hungarian", "hu"); - yield return new LocalizationOption("Italian", "it"); - yield return new LocalizationOption("Kazakh", "kk"); - yield return new LocalizationOption("Korean", "ko"); - yield return new LocalizationOption("Lithuanian", "lt-LT"); - yield return new LocalizationOption("Malay", "ms"); - yield return new LocalizationOption("Norwegian Bokmål", "nb"); - yield return new LocalizationOption("Persian", "fa"); - yield return new LocalizationOption("Polish", "pl"); - yield return new LocalizationOption("Portuguese (Brazil)", "pt-BR"); - yield return new LocalizationOption("Portuguese (Portugal)", "pt-PT"); - yield return new LocalizationOption("Russian", "ru"); - yield return new LocalizationOption("Slovak", "sk"); - yield return new LocalizationOption("Slovenian (Slovenia)", "sl-SI"); - yield return new LocalizationOption("Spanish", "es"); - yield return new LocalizationOption("Spanish (Argentina)", "es-AR"); - yield return new LocalizationOption("Spanish (Mexico)", "es-MX"); - yield return new LocalizationOption("Swedish", "sv"); - yield return new LocalizationOption("Swiss German", "gsw"); - yield return new LocalizationOption("Turkish", "tr"); - yield return new LocalizationOption("Tiếng Việt", "vi"); - } } } diff --git a/MediaBrowser.Model/Globalization/ILocalizationManager.cs b/MediaBrowser.Model/Globalization/ILocalizationManager.cs index baefeb39cf..e0e7317efd 100644 --- a/MediaBrowser.Model/Globalization/ILocalizationManager.cs +++ b/MediaBrowser.Model/Globalization/ILocalizationManager.cs @@ -56,14 +56,6 @@ namespace MediaBrowser.Model.Globalization /// . IEnumerable GetLocalizationOptions(); - /// - /// Checks if the string contains a character with the specified unicode category. - /// - /// The string. - /// The unicode category. - /// Wether or not the string contains a character with the specified unicode category. - bool HasUnicodeCategory(string value, UnicodeCategory category); - /// /// Returns the correct for the given language. /// From e33e3ba61037b594fd9035550e3ca646bb7f2c8f Mon Sep 17 00:00:00 2001 From: David Ullmer Date: Tue, 25 May 2021 12:33:55 +0200 Subject: [PATCH 003/120] Make localizationManager local instead of field --- .../Localization/LocalizationManagerTests.cs | 70 +++++++++++-------- 1 file changed, 41 insertions(+), 29 deletions(-) diff --git a/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs index acdf74c4f7..651957ae39 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs @@ -11,18 +11,14 @@ namespace Jellyfin.Server.Implementations.Tests.Localization { public class LocalizationManagerTests { - private LocalizationManager _localizationManager = null!; - - public LocalizationManagerTests() - { - var config = new ServerConfiguration() { UICulture = "de-DE" }; - Setup(config); - } - [Fact] public void GetCountries_All_Success() { - var countries = _localizationManager.GetCountries(); + var localizationManager = Setup(new ServerConfiguration + { + UICulture = "de-DE" + }); + var countries = localizationManager.GetCountries(); var countryInfos = countries.ToList(); Assert.Equal(139, countryInfos.Count); @@ -37,8 +33,12 @@ namespace Jellyfin.Server.Implementations.Tests.Localization [Fact] public async Task GetCultures_All_Success() { - await _localizationManager.LoadAll(); - var cultures = _localizationManager.GetCultures().ToList(); + var localizationManager = Setup(new ServerConfiguration + { + UICulture = "de-DE" + }); + await localizationManager.LoadAll(); + var cultures = localizationManager.GetCultures().ToList(); Assert.Equal(189, cultures.Count); @@ -57,9 +57,13 @@ namespace Jellyfin.Server.Implementations.Tests.Localization [InlineData("german")] public async Task FindLanguage_Valid_Success(string identifier) { - await _localizationManager.LoadAll(); + var localizationManager = Setup(new ServerConfiguration + { + UICulture = "de-DE" + }); + await localizationManager.LoadAll(); - var germany = _localizationManager.FindLanguageInfo(identifier); + var germany = localizationManager.FindLanguageInfo(identifier); Assert.NotNull(germany); Assert.Equal("ger", germany!.ThreeLetterISOLanguageName); @@ -72,8 +76,12 @@ namespace Jellyfin.Server.Implementations.Tests.Localization [Fact] public async Task ParentalRatings_Default_Success() { - await _localizationManager.LoadAll(); - var ratings = _localizationManager.GetParentalRatings().ToList(); + var localizationManager = Setup(new ServerConfiguration + { + UICulture = "de-DE" + }); + await localizationManager.LoadAll(); + var ratings = localizationManager.GetParentalRatings().ToList(); Assert.Equal(23, ratings.Count); @@ -85,12 +93,12 @@ namespace Jellyfin.Server.Implementations.Tests.Localization [Fact] public async Task ParentalRatings_ConfiguredCountryCode_Success() { - Setup(new ServerConfiguration() + var localizationManager = Setup(new ServerConfiguration() { MetadataCountryCode = "DE" }); - await _localizationManager.LoadAll(); - var ratings = _localizationManager.GetParentalRatings().ToList(); + await localizationManager.LoadAll(); + var ratings = localizationManager.GetParentalRatings().ToList(); Assert.Equal(10, ratings.Count); @@ -109,12 +117,12 @@ namespace Jellyfin.Server.Implementations.Tests.Localization [InlineData("Germany: FSK-18", "DE", 9)] public async Task GetRatingLevelFromString_Valid_Success(string value, string countryCode, int expectedLevel) { - Setup(new ServerConfiguration() + var localizationManager = Setup(new ServerConfiguration() { MetadataCountryCode = countryCode }); - await _localizationManager.LoadAll(); - var level = _localizationManager.GetRatingLevel(value); + await localizationManager.LoadAll(); + var level = localizationManager.GetRatingLevel(value); Assert.NotNull(level); Assert.Equal(expectedLevel, level!); } @@ -122,8 +130,12 @@ namespace Jellyfin.Server.Implementations.Tests.Localization [Fact] public async Task GetRatingLevelFromString_Unrated_Success() { - await _localizationManager.LoadAll(); - Assert.Null(_localizationManager.GetRatingLevel("n/a")); + var localizationManager = Setup(new ServerConfiguration() + { + UICulture = "de-DE" + }); + await localizationManager.LoadAll(); + Assert.Null(localizationManager.GetRatingLevel("n/a")); } [Theory] @@ -131,12 +143,12 @@ namespace Jellyfin.Server.Implementations.Tests.Localization [InlineData("HeaderLiveTV", "Live TV")] public void GetLocalizedString_Valid_Success(string key, string expected) { - Setup(new ServerConfiguration() + var localizationManager = Setup(new ServerConfiguration() { UICulture = "en-US" }); - var translated = _localizationManager.GetLocalizedString(key); + var translated = localizationManager.GetLocalizedString(key); Assert.NotNull(translated); Assert.Equal(expected, translated); } @@ -144,24 +156,24 @@ namespace Jellyfin.Server.Implementations.Tests.Localization [Fact] public void GetLocalizedString_Invalid_Success() { - Setup(new ServerConfiguration() + var localizationManager = Setup(new ServerConfiguration() { UICulture = "en-US" }); var key = "SuperInvalidTranslationKeyThatWillNeverBeAdded"; - var translated = _localizationManager.GetLocalizedString(key); + var translated = localizationManager.GetLocalizedString(key); Assert.NotNull(translated); Assert.Equal(key, translated); } - private void Setup(ServerConfiguration config) + private LocalizationManager Setup(ServerConfiguration config) { var mockConfiguration = new Mock(); mockConfiguration.SetupGet(x => x.Configuration).Returns(config); - _localizationManager = new LocalizationManager(mockConfiguration.Object, new NullLogger()); + return new LocalizationManager(mockConfiguration.Object, new NullLogger()); } } } From bcae195cc3dc0b4c39acb00b7c4590c871daf61c Mon Sep 17 00:00:00 2001 From: MrTimscampi Date: Sat, 3 Jul 2021 01:32:57 +0200 Subject: [PATCH 004/120] Refactor GetResolutionText This improves GetResolutionText a little by making it easier to read and better parsing resolutions (Also adding a few new ones like PAL resolutions and 8K) Co-authored-by: Maxr1998 --- MediaBrowser.Model/Entities/MediaStream.cs | 75 +++++++--------------- 1 file changed, 22 insertions(+), 53 deletions(-) diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index c67f30d045..bc3586ff21 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -471,62 +471,31 @@ namespace MediaBrowser.Model.Entities private string GetResolutionText() { - var i = this; - - if (i.Width.HasValue && i.Height.HasValue) + if (!this.Width.HasValue || !this.Height.HasValue) { - var width = i.Width.Value; - var height = i.Height.Value; - - if (width >= 3800 || height >= 2000) - { - return "4K"; - } - - if (width >= 2500) - { - if (i.IsInterlaced) - { - return "1440i"; - } - - return "1440p"; - } - - if (width >= 1900 || height >= 1000) - { - if (i.IsInterlaced) - { - return "1080i"; - } - - return "1080p"; - } - - if (width >= 1260 || height >= 700) - { - if (i.IsInterlaced) - { - return "720i"; - } - - return "720p"; - } - - if (width >= 700 || height >= 440) - { - if (i.IsInterlaced) - { - return "480i"; - } - - return "480p"; - } - - return "SD"; + return null; } - return null; + var width = this.Width.Value; + var height = this.Height.Value; + + return width switch + { + <= 720 when height <= 480 => this.IsInterlaced ? "480i" : "480p", + // 720x576 (PAL) (768 when rescaled for square pixels) + <= 768 when height <= 576 => this.IsInterlaced ? "576i" : "576p", + // 960x540 (sometimes 544 which is multiple of 16) + <= 960 when height <= 544 => this.IsInterlaced ? "540i" : "540p", + // 1280x720 + <= 1280 when height <= 962 => this.IsInterlaced ? "720i" : "720p", + // 1920x1080 + <= 1920 when height <= 1440 => this.IsInterlaced ? "1080i" : "1080p", + // 4K + <= 4096 when height <= 3072 => "4K", + // 8K + <= 8192 when height <= 6144 => "8K", + _ => null + }; } public static bool IsTextFormat(string format) From 7e3c94d094732c3c174375b0025604f1faa28f9e Mon Sep 17 00:00:00 2001 From: Brandon Nguyen Date: Sat, 3 Jul 2021 01:12:09 -0700 Subject: [PATCH 005/120] Add hardware encoding status to playback data Resolves #6087 --- CONTRIBUTORS.md | 1 + Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 1 + MediaBrowser.Model/Session/TranscodingInfo.cs | 2 ++ 3 files changed, 4 insertions(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index b44961bf8d..c2d2aff341 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -212,3 +212,4 @@ - [Tim Hobbs](https://github.com/timhobbs) - [SvenVandenbrande](https://github.com/SvenVandenbrande) - [olsh](https://github.com/olsh) + - [gnuyent](https://github.com/gnuyent) diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index c295af7eb3..9e63638902 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -458,6 +458,7 @@ namespace Jellyfin.Api.Helpers AudioChannels = state.OutputAudioChannels, IsAudioDirect = EncodingHelper.IsCopyCodec(state.OutputAudioCodec), IsVideoDirect = EncodingHelper.IsCopyCodec(state.OutputVideoCodec), + IsHardwareEncode = !string.IsNullOrEmpty(_serverConfigurationManager.GetEncodingOptions().HardwareAccelerationType), TranscodeReasons = state.TranscodeReasons }); } diff --git a/MediaBrowser.Model/Session/TranscodingInfo.cs b/MediaBrowser.Model/Session/TranscodingInfo.cs index 064a087d5d..98f3268b9b 100644 --- a/MediaBrowser.Model/Session/TranscodingInfo.cs +++ b/MediaBrowser.Model/Session/TranscodingInfo.cs @@ -34,6 +34,8 @@ namespace MediaBrowser.Model.Session public int? AudioChannels { get; set; } + public bool IsHardwareEncode { get; set; } + public TranscodeReason[] TranscodeReasons { get; set; } } } From df17c67f11468a645a2630401178bbd35b489c80 Mon Sep 17 00:00:00 2001 From: Brandon Nguyen Date: Sat, 3 Jul 2021 15:29:07 -0700 Subject: [PATCH 006/120] Use hardware encoding string over boolean --- Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 4 +++- MediaBrowser.Model/Session/TranscodingInfo.cs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 9e63638902..b8a8491adc 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -444,6 +444,8 @@ namespace Jellyfin.Api.Helpers { var audioCodec = state.ActualOutputAudioCodec; var videoCodec = state.ActualOutputVideoCodec; + var hardwareAccelerationType = _serverConfigurationManager.GetEncodingOptions().HardwareAccelerationType; + hardwareAccelerationType = string.IsNullOrEmpty(hardwareAccelerationType) ? "none" : hardwareAccelerationType; _sessionManager.ReportTranscodingInfo(deviceId, new TranscodingInfo { @@ -458,7 +460,7 @@ namespace Jellyfin.Api.Helpers AudioChannels = state.OutputAudioChannels, IsAudioDirect = EncodingHelper.IsCopyCodec(state.OutputAudioCodec), IsVideoDirect = EncodingHelper.IsCopyCodec(state.OutputVideoCodec), - IsHardwareEncode = !string.IsNullOrEmpty(_serverConfigurationManager.GetEncodingOptions().HardwareAccelerationType), + HardwareAccelerationType = hardwareAccelerationType, TranscodeReasons = state.TranscodeReasons }); } diff --git a/MediaBrowser.Model/Session/TranscodingInfo.cs b/MediaBrowser.Model/Session/TranscodingInfo.cs index 98f3268b9b..57f0a322e6 100644 --- a/MediaBrowser.Model/Session/TranscodingInfo.cs +++ b/MediaBrowser.Model/Session/TranscodingInfo.cs @@ -34,7 +34,7 @@ namespace MediaBrowser.Model.Session public int? AudioChannels { get; set; } - public bool IsHardwareEncode { get; set; } + public string HardwareAccelerationType { get; set; } public TranscodeReason[] TranscodeReasons { get; set; } } From a25c3d1cdaf185c40f36f9271dc8805ff3c5a374 Mon Sep 17 00:00:00 2001 From: MrTimscampi Date: Sun, 4 Jul 2021 10:22:17 +0200 Subject: [PATCH 007/120] Remove usage of this in GetResolutionText --- MediaBrowser.Model/Entities/MediaStream.cs | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index bc3586ff21..275b438f52 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -471,29 +471,26 @@ namespace MediaBrowser.Model.Entities private string GetResolutionText() { - if (!this.Width.HasValue || !this.Height.HasValue) + if (!Width.HasValue || !Height.HasValue) { return null; } - var width = this.Width.Value; - var height = this.Height.Value; - - return width switch + return Width switch { - <= 720 when height <= 480 => this.IsInterlaced ? "480i" : "480p", + <= 720 when Height <= 480 => IsInterlaced ? "480i" : "480p", // 720x576 (PAL) (768 when rescaled for square pixels) - <= 768 when height <= 576 => this.IsInterlaced ? "576i" : "576p", + <= 768 when Height <= 576 => IsInterlaced ? "576i" : "576p", // 960x540 (sometimes 544 which is multiple of 16) - <= 960 when height <= 544 => this.IsInterlaced ? "540i" : "540p", + <= 960 when Height <= 544 => IsInterlaced ? "540i" : "540p", // 1280x720 - <= 1280 when height <= 962 => this.IsInterlaced ? "720i" : "720p", + <= 1280 when Height <= 962 => IsInterlaced ? "720i" : "720p", // 1920x1080 - <= 1920 when height <= 1440 => this.IsInterlaced ? "1080i" : "1080p", + <= 1920 when Height <= 1440 => IsInterlaced ? "1080i" : "1080p", // 4K - <= 4096 when height <= 3072 => "4K", + <= 4096 when Height <= 3072 => "4K", // 8K - <= 8192 when height <= 6144 => "8K", + <= 8192 when Height <= 6144 => "8K", _ => null }; } From 5bd8ba886ae0855b9b976c497c2db6a4edc59359 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Mon, 28 Jun 2021 12:03:46 +0200 Subject: [PATCH 008/120] Add tests for QuickConnectManager --- .../QuickConnect/QuickConnectManagerTests.cs | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 tests/Jellyfin.Server.Implementations.Tests/QuickConnect/QuickConnectManagerTests.cs diff --git a/tests/Jellyfin.Server.Implementations.Tests/QuickConnect/QuickConnectManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/QuickConnect/QuickConnectManagerTests.cs new file mode 100644 index 0000000000..365acfa341 --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/QuickConnect/QuickConnectManagerTests.cs @@ -0,0 +1,73 @@ +using System; +using AutoFixture; +using AutoFixture.AutoMoq; +using Emby.Server.Implementations.QuickConnect; +using MediaBrowser.Controller.Authentication; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Model.Configuration; +using Moq; +using Xunit; + +namespace Jellyfin.Server.Implementations.Tests.LiveTv +{ + public class QuickConnectManagerTests + { + private readonly Fixture _fixture; + private readonly ServerConfiguration _config; + private readonly QuickConnectManager _quickConnectManager; + + public QuickConnectManagerTests() + { + _config = new ServerConfiguration(); + var configManager = new Mock(); + configManager.Setup(x => x.Configuration).Returns(_config); + + _fixture = new Fixture(); + _fixture.Customize(new AutoMoqCustomization + { + ConfigureMembers = true + }).Inject(configManager.Object); + _quickConnectManager = _fixture.Create(); + } + + [Fact] + public void IsEnabled_QuickConnectUnavailable_False() + => Assert.False(_quickConnectManager.IsEnabled); + + [Fact] + public void TryConnect_QuickConnectUnavailable_ThrowsAuthenticationException() + => Assert.Throws(_quickConnectManager.TryConnect); + + [Fact] + public void CheckRequestStatus_QuickConnectUnavailable_ThrowsAuthenticationException() + => Assert.Throws(() => _quickConnectManager.CheckRequestStatus(string.Empty)); + + [Fact] + public void AuthorizeRequest_QuickConnectUnavailable_ThrowsAuthenticationException() + => Assert.Throws(() => _quickConnectManager.AuthorizeRequest(Guid.Empty, string.Empty)); + + [Fact] + public void IsEnabled_QuickConnectAvailable_True() + { + _config.QuickConnectAvailable = true; + Assert.True(_quickConnectManager.IsEnabled); + } + + [Fact] + public void CheckRequestStatus_QuickConnectAvailable_Success() + { + _config.QuickConnectAvailable = true; + var res1 = _quickConnectManager.TryConnect(); + var res2 = _quickConnectManager.CheckRequestStatus(res1.Secret); + Assert.Equal(res1, res2); + } + + [Fact] + public void AuthorizeRequest_QuickConnectAvailable_Success() + { + _config.QuickConnectAvailable = true; + var res = _quickConnectManager.TryConnect(); + Assert.True(_quickConnectManager.AuthorizeRequest(Guid.Empty, res.Code)); + } + } +} From e19dce3c536dfb55f7430f080893f3c09f9350d0 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 6 Jul 2021 01:07:10 +0200 Subject: [PATCH 009/120] Add test for RobotsRedirectionMiddleware --- .../JellyfinApplicationFactory.cs | 5 +-- .../RobotsRedirectionMiddlewareTests.cs | 32 +++++++++++++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 tests/Jellyfin.Server.Integration.Tests/Middleware/RobotsRedirectionMiddlewareTests.cs diff --git a/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs b/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs index d9ec81a271..976e19d468 100644 --- a/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs +++ b/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs @@ -44,10 +44,7 @@ namespace Jellyfin.Server.Integration.Tests protected override void ConfigureWebHost(IWebHostBuilder builder) { // Specify the startup command line options - var commandLineOpts = new StartupOptions - { - NoWebClient = true - }; + var commandLineOpts = new StartupOptions(); // Use a temporary directory for the application paths var webHostPathRoot = Path.Combine(_testPathRoot, "test-host-" + Path.GetFileNameWithoutExtension(Path.GetRandomFileName())); diff --git a/tests/Jellyfin.Server.Integration.Tests/Middleware/RobotsRedirectionMiddlewareTests.cs b/tests/Jellyfin.Server.Integration.Tests/Middleware/RobotsRedirectionMiddlewareTests.cs new file mode 100644 index 0000000000..8c49a2e2b5 --- /dev/null +++ b/tests/Jellyfin.Server.Integration.Tests/Middleware/RobotsRedirectionMiddlewareTests.cs @@ -0,0 +1,32 @@ +using System.Net; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc.Testing; +using Xunit; + +namespace Jellyfin.Server.Integration.Tests.Middleware +{ + public sealed class RobotsRedirectionMiddlewareTests : IClassFixture + { + private readonly JellyfinApplicationFactory _factory; + + public RobotsRedirectionMiddlewareTests(JellyfinApplicationFactory factory) + { + _factory = factory; + } + + [Fact] + public async Task RobotsDotTxtRedirects() + { + var client = _factory.CreateClient( + new WebApplicationFactoryClientOptions() + { + AllowAutoRedirect = false + }); + + var response = await client.GetAsync("robots.txt").ConfigureAwait(false); + + Assert.Equal(HttpStatusCode.Redirect, response.StatusCode); + Assert.Equal("web/robots.txt", response.Headers.Location?.ToString()); + } + } +} From d0c5e25ec05c8d2bb77cfe067db0a5ac2e338f15 Mon Sep 17 00:00:00 2001 From: Brandon Nguyen Date: Mon, 5 Jul 2021 16:52:52 -0700 Subject: [PATCH 010/120] Use nullable enum type instead of strings --- Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 12 +++-- .../Session/HardwareEncodingType.cs | 48 +++++++++++++++++++ MediaBrowser.Model/Session/TranscodingInfo.cs | 2 +- 3 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 MediaBrowser.Model/Session/HardwareEncodingType.cs diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index b8a8491adc..05fa5b1350 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -380,7 +380,7 @@ namespace Jellyfin.Api.Helpers private void DeleteHlsPartialStreamFiles(string outputFilePath) { var directory = Path.GetDirectoryName(outputFilePath) - ?? throw new ArgumentException("Path can't be a root directory.", nameof(outputFilePath)); + ?? throw new ArgumentException("Path can't be a root directory.", nameof(outputFilePath)); var name = Path.GetFileNameWithoutExtension(outputFilePath); @@ -444,8 +444,10 @@ namespace Jellyfin.Api.Helpers { var audioCodec = state.ActualOutputAudioCodec; var videoCodec = state.ActualOutputVideoCodec; - var hardwareAccelerationType = _serverConfigurationManager.GetEncodingOptions().HardwareAccelerationType; - hardwareAccelerationType = string.IsNullOrEmpty(hardwareAccelerationType) ? "none" : hardwareAccelerationType; + var hardwareAccelerationTypeString = _serverConfigurationManager.GetEncodingOptions().HardwareAccelerationType; + HardwareEncodingType? hardwareAccelerationType = string.IsNullOrEmpty(hardwareAccelerationTypeString) + ? null + : (HardwareEncodingType)Enum.Parse(typeof(HardwareEncodingType), hardwareAccelerationTypeString, true); _sessionManager.ReportTranscodingInfo(deviceId, new TranscodingInfo { @@ -762,8 +764,8 @@ namespace Jellyfin.Api.Helpers if (state.MediaSource.RequiresOpening && string.IsNullOrWhiteSpace(state.Request.LiveStreamId)) { var liveStreamResponse = await _mediaSourceManager.OpenLiveStream( - new LiveStreamRequest { OpenToken = state.MediaSource.OpenToken }, - cancellationTokenSource.Token) + new LiveStreamRequest { OpenToken = state.MediaSource.OpenToken }, + cancellationTokenSource.Token) .ConfigureAwait(false); var encodingOptions = _serverConfigurationManager.GetEncodingOptions(); diff --git a/MediaBrowser.Model/Session/HardwareEncodingType.cs b/MediaBrowser.Model/Session/HardwareEncodingType.cs new file mode 100644 index 0000000000..11721f0907 --- /dev/null +++ b/MediaBrowser.Model/Session/HardwareEncodingType.cs @@ -0,0 +1,48 @@ +namespace MediaBrowser.Model.Session +{ + /// + /// Enum HardwareEncodingType. + /// + public enum HardwareEncodingType + { + /// + /// AMD AMF + /// + AMF, + + /// + /// Intel Quick Sync Video + /// + QSV, + + /// + /// NVIDIA NVENC + /// + NVENC, + + /// + /// OpenMax OMX + /// + OMX, + + /// + /// Exynos V4L2 MFC + /// + V4L2M2M, + + /// + /// MediaCodec Android + /// + MediaCodec, + + /// + /// Video Acceleration API (VAAPI) + /// + VAAPI, + + /// + /// Video ToolBox + /// + VideoToolBox + } +} diff --git a/MediaBrowser.Model/Session/TranscodingInfo.cs b/MediaBrowser.Model/Session/TranscodingInfo.cs index 57f0a322e6..68ab691f88 100644 --- a/MediaBrowser.Model/Session/TranscodingInfo.cs +++ b/MediaBrowser.Model/Session/TranscodingInfo.cs @@ -34,7 +34,7 @@ namespace MediaBrowser.Model.Session public int? AudioChannels { get; set; } - public string HardwareAccelerationType { get; set; } + public HardwareEncodingType? HardwareAccelerationType { get; set; } public TranscodeReason[] TranscodeReasons { get; set; } } From 3090971feb3784419189889e4b78ba387f8d0f53 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Thu, 8 Jul 2021 14:53:56 -0400 Subject: [PATCH 011/120] Restore max width and height params --- Jellyfin.Api/Controllers/VideosController.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs index dc64a0f1bc..29a25fa6aa 100644 --- a/Jellyfin.Api/Controllers/VideosController.cs +++ b/Jellyfin.Api/Controllers/VideosController.cs @@ -296,6 +296,8 @@ namespace Jellyfin.Api.Controllers /// Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms. /// Optional. The fixed horizontal resolution of the encoded video. /// Optional. The fixed vertical resolution of the encoded video. + /// Optional. The maximum horizontal resolution of the encoded video. + /// Optional. The maximum vertical resolution of the encoded video. /// Optional. Specify a video bitrate to encode to, e.g. 500000. If omitted this will be left to encoder defaults. /// Optional. The index of the subtitle stream to use. If omitted no subtitles will be used. /// Optional. Specify the subtitle delivery method. @@ -352,6 +354,8 @@ namespace Jellyfin.Api.Controllers [FromQuery] long? startTimeTicks, [FromQuery] int? width, [FromQuery] int? height, + [FromQuery] int? maxWidth, + [FromQuery] int? maxHeight, [FromQuery] int? videoBitRate, [FromQuery] int? subtitleStreamIndex, [FromQuery] SubtitleDeliveryMethod? subtitleMethod, @@ -407,6 +411,8 @@ namespace Jellyfin.Api.Controllers StartTimeTicks = startTimeTicks, Width = width, Height = height, + MaxWidth = maxWidth, + MaxHeight = maxHeight, VideoBitRate = videoBitRate, SubtitleStreamIndex = subtitleStreamIndex, SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.Encode, @@ -550,6 +556,8 @@ namespace Jellyfin.Api.Controllers /// Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms. /// Optional. The fixed horizontal resolution of the encoded video. /// Optional. The fixed vertical resolution of the encoded video. + /// Optional. The maximum horizontal resolution of the encoded video. + /// Optional. The maximum vertical resolution of the encoded video. /// Optional. Specify a video bitrate to encode to, e.g. 500000. If omitted this will be left to encoder defaults. /// Optional. The index of the subtitle stream to use. If omitted no subtitles will be used. /// Optional. Specify the subtitle delivery method. @@ -606,6 +614,8 @@ namespace Jellyfin.Api.Controllers [FromQuery] long? startTimeTicks, [FromQuery] int? width, [FromQuery] int? height, + [FromQuery] int? maxWidth, + [FromQuery] int? maxHeight, [FromQuery] int? videoBitRate, [FromQuery] int? subtitleStreamIndex, [FromQuery] SubtitleDeliveryMethod? subtitleMethod, @@ -657,6 +667,8 @@ namespace Jellyfin.Api.Controllers startTimeTicks, width, height, + maxWidth, + maxHeight, videoBitRate, subtitleStreamIndex, subtitleMethod, From 11a5551218cbfcd21c4dd1f33e8e8a6eea252f47 Mon Sep 17 00:00:00 2001 From: Maxr1998 Date: Fri, 9 Jul 2021 02:06:38 +0200 Subject: [PATCH 012/120] Refactor ProbeResultNormalizer Improve code structure and readability --- .../Probing/FFProbeHelpers.cs | 46 +- .../Probing/ProbeResultNormalizer.cs | 574 ++++++++---------- .../DictionaryExtensions.cs | 65 ++ 3 files changed, 317 insertions(+), 368 deletions(-) create mode 100644 src/Jellyfin.Extensions/DictionaryExtensions.cs diff --git a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs index 1fa90bb213..d0a76c4caf 100644 --- a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs +++ b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using System.Collections.Generic; using System.Globalization; @@ -22,7 +20,7 @@ namespace MediaBrowser.MediaEncoding.Probing throw new ArgumentNullException(nameof(result)); } - if (result.Format != null && result.Format.Tags != null) + if (result.Format?.Tags != null) { result.Format.Tags = ConvertDictionaryToCaseInsensitive(result.Format.Tags); } @@ -40,39 +38,17 @@ namespace MediaBrowser.MediaEncoding.Probing } } - /// - /// Gets a string from an FFProbeResult tags dictionary. - /// - /// The tags. - /// The key. - /// System.String. - public static string GetDictionaryValue(IReadOnlyDictionary tags, string key) - { - if (tags == null) - { - return null; - } - - tags.TryGetValue(key, out var val); - return val; - } - /// /// Gets an int from an FFProbeResult tags dictionary. /// /// The tags. /// The key. /// System.Nullable{System.Int32}. - public static int? GetDictionaryNumericValue(Dictionary tags, string key) + public static int? GetDictionaryNumericValue(IReadOnlyDictionary tags, string key) { - var val = GetDictionaryValue(tags, key); - - if (!string.IsNullOrEmpty(val)) + if (tags.TryGetValue(key, out var val) && int.TryParse(val, out var i)) { - if (int.TryParse(val, out var i)) - { - return i; - } + return i; } return null; @@ -84,18 +60,12 @@ namespace MediaBrowser.MediaEncoding.Probing /// The tags. /// The key. /// System.Nullable{DateTime}. - public static DateTime? GetDictionaryDateTime(Dictionary tags, string key) + public static DateTime? GetDictionaryDateTime(IReadOnlyDictionary tags, string key) { - var val = GetDictionaryValue(tags, key); - - if (string.IsNullOrEmpty(val)) - { - return null; - } - - if (DateTime.TryParse(val, DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AssumeUniversal, out var i)) + if (tags.TryGetValue(key, out var val) + && DateTime.TryParse(val, DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AssumeUniversal, out var dateTime)) { - return i.ToUniversalTime(); + return dateTime.ToUniversalTime(); } return null; diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index bbff5dacac..c50a577be6 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -8,6 +8,7 @@ using System.IO; using System.Linq; using System.Text; using System.Xml; +using Jellyfin.Extensions; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -80,68 +81,33 @@ namespace MediaBrowser.MediaEncoding.Probing var tags = new Dictionary(StringComparer.OrdinalIgnoreCase); var tagStreamType = isAudio ? "audio" : "video"; - if (data.Streams != null) - { - var tagStream = data.Streams.FirstOrDefault(i => string.Equals(i.CodecType, tagStreamType, StringComparison.OrdinalIgnoreCase)); + var tagStream = data.Streams?.FirstOrDefault(i => string.Equals(i.CodecType, tagStreamType, StringComparison.OrdinalIgnoreCase)); - if (tagStream != null && tagStream.Tags != null) + if (tagStream?.Tags != null) + { + foreach (var (key, value) in tagStream.Tags) { - foreach (var pair in tagStream.Tags) - { - tags[pair.Key] = pair.Value; - } + tags[key] = value; } } - if (data.Format != null && data.Format.Tags != null) + if (data.Format?.Tags != null) { - foreach (var pair in data.Format.Tags) + foreach (var (key, value) in data.Format.Tags) { - tags[pair.Key] = pair.Value; + tags[key] = value; } } FetchGenres(info, tags); - var overview = FFProbeHelpers.GetDictionaryValue(tags, "synopsis"); - - if (string.IsNullOrWhiteSpace(overview)) - { - overview = FFProbeHelpers.GetDictionaryValue(tags, "description"); - } - - if (string.IsNullOrWhiteSpace(overview)) - { - overview = FFProbeHelpers.GetDictionaryValue(tags, "desc"); - } - - if (!string.IsNullOrWhiteSpace(overview)) - { - info.Overview = overview; - } - var title = FFProbeHelpers.GetDictionaryValue(tags, "title"); - if (!string.IsNullOrWhiteSpace(title)) - { - info.Name = title; - } - else - { - title = FFProbeHelpers.GetDictionaryValue(tags, "title-eng"); - if (!string.IsNullOrWhiteSpace(title)) - { - info.Name = title; - } - } - - var titleSort = FFProbeHelpers.GetDictionaryValue(tags, "titlesort"); - if (!string.IsNullOrWhiteSpace(titleSort)) - { - info.ForcedSortName = titleSort; - } + info.Name = tags.GetFirstNotNullNorWhiteSpaceValue("title", "title-eng"); + info.ForcedSortName = tags.GetFirstNotNullNorWhiteSpaceValue("sort_name", "title-sort", "titlesort"); + info.Overview = tags.GetFirstNotNullNorWhiteSpaceValue("synopsis", "description", "desc"); info.IndexNumber = FFProbeHelpers.GetDictionaryNumericValue(tags, "episode_sort"); info.ParentIndexNumber = FFProbeHelpers.GetDictionaryNumericValue(tags, "season_number"); - info.ShowName = FFProbeHelpers.GetDictionaryValue(tags, "show_name"); + info.ShowName = tags.GetValueOrDefault("show_name"); info.ProductionYear = FFProbeHelpers.GetDictionaryNumericValue(tags, "date"); // Several different forms of retail/premiere date @@ -153,32 +119,21 @@ namespace MediaBrowser.MediaEncoding.Probing FFProbeHelpers.GetDictionaryDateTime(tags, "date"); // Set common metadata for music (audio) and music videos (video) - info.Album = FFProbeHelpers.GetDictionaryValue(tags, "album"); - - var artists = FFProbeHelpers.GetDictionaryValue(tags, "artists"); + info.Album = tags.GetValueOrDefault("album"); - if (!string.IsNullOrWhiteSpace(artists)) + if (tags.TryGetValue("artists", out var artists) && !string.IsNullOrWhiteSpace(artists)) { - info.Artists = SplitArtists(artists, new[] { '/', ';' }, false) - .DistinctNames() - .ToArray(); + info.Artists = SplitDistinctArtists(artists, new[] { '/', ';' }, false).ToArray(); } else { - var artist = FFProbeHelpers.GetDictionaryValue(tags, "artist"); - if (string.IsNullOrWhiteSpace(artist)) - { - info.Artists = Array.Empty(); - } - else - { - info.Artists = SplitArtists(artist, _nameDelimiters, true) - .DistinctNames() - .ToArray(); - } + var artist = tags.GetFirstNotNullNorWhiteSpaceValue("artist"); + info.Artists = artist == null + ? Array.Empty() + : SplitDistinctArtists(artist, _nameDelimiters, true).ToArray(); } - // If we don't have a ProductionYear try and get it from PremiereDate + // Guess ProductionYear from PremiereDate if missing if (!info.ProductionYear.HasValue && info.PremiereDate.HasValue) { info.ProductionYear = info.PremiereDate.Value.Year; @@ -198,10 +153,10 @@ namespace MediaBrowser.MediaEncoding.Probing { FetchStudios(info, tags, "copyright"); - var iTunEXTC = FFProbeHelpers.GetDictionaryValue(tags, "iTunEXTC"); - if (!string.IsNullOrWhiteSpace(iTunEXTC)) + var iTunExtc = tags.GetFirstNotNullNorWhiteSpaceValue("iTunEXTC"); + if (iTunExtc != null) { - var parts = iTunEXTC.Split('|', StringSplitOptions.RemoveEmptyEntries); + var parts = iTunExtc.Split('|', StringSplitOptions.RemoveEmptyEntries); // Example // mpaa|G|100|For crude humor if (parts.Length > 1) @@ -215,10 +170,10 @@ namespace MediaBrowser.MediaEncoding.Probing } } - var itunesXml = FFProbeHelpers.GetDictionaryValue(tags, "iTunMOVI"); - if (!string.IsNullOrWhiteSpace(itunesXml)) + var iTunXml = tags.GetFirstNotNullNorWhiteSpaceValue("iTunMOVI"); + if (iTunXml != null) { - FetchFromItunesInfo(itunesXml, info); + FetchFromItunesInfo(iTunXml, info); } if (data.Format != null && !string.IsNullOrEmpty(data.Format.Duration)) @@ -235,8 +190,7 @@ namespace MediaBrowser.MediaEncoding.Probing ExtractTimestamp(info); - var stereoMode = GetDictionaryValue(tags, "stereo_mode"); - if (string.Equals(stereoMode, "left_right", StringComparison.OrdinalIgnoreCase)) + if (tags.TryGetValue("stereo_mode", out var stereoMode) && string.Equals(stereoMode, "left_right", StringComparison.OrdinalIgnoreCase)) { info.Video3DFormat = Video3DFormat.FullSideBySide; } @@ -289,42 +243,36 @@ namespace MediaBrowser.MediaEncoding.Probing if (string.Equals(codec, "aac", StringComparison.OrdinalIgnoreCase) || string.Equals(codec, "mp3", StringComparison.OrdinalIgnoreCase)) { - if (channelsValue <= 2) - { - return 192000; - } - - if (channelsValue >= 5) + switch (channelsValue) { - return 320000; + case <= 2: + return 192000; + case >= 5: + return 320000; } } if (string.Equals(codec, "ac3", StringComparison.OrdinalIgnoreCase) || string.Equals(codec, "eac3", StringComparison.OrdinalIgnoreCase)) { - if (channelsValue <= 2) + switch (channelsValue) { - return 192000; - } - - if (channelsValue >= 5) - { - return 640000; + case <= 2: + return 192000; + case >= 5: + return 640000; } } if (string.Equals(codec, "flac", StringComparison.OrdinalIgnoreCase) || string.Equals(codec, "alac", StringComparison.OrdinalIgnoreCase)) { - if (channelsValue <= 2) - { - return 960000; - } - - if (channelsValue >= 5) + switch (channelsValue) { - return 2880000; + case <= 2: + return 960000; + case >= 5: + return 2880000; } } @@ -854,7 +802,7 @@ namespace MediaBrowser.MediaEncoding.Probing || string.Equals(streamInfo.CodecType, "video", StringComparison.OrdinalIgnoreCase))) { var bps = GetBPSFromTags(streamInfo); - if (bps != null && bps > 0) + if (bps > 0) { stream.BitRate = bps; } @@ -923,6 +871,7 @@ namespace MediaBrowser.MediaEncoding.Probing } tags.TryGetValue(key, out var val); + return val; } @@ -930,7 +879,7 @@ namespace MediaBrowser.MediaEncoding.Probing { if (string.IsNullOrEmpty(input)) { - return input; + return null; } return input.Split('(').FirstOrDefault(); @@ -1018,64 +967,64 @@ namespace MediaBrowser.MediaEncoding.Probing /// System.Nullable{System.Single}. private float? GetFrameRate(string value) { - if (!string.IsNullOrEmpty(value)) + if (string.IsNullOrEmpty(value)) { - var parts = value.Split('/'); + return null; + } - float result; + var parts = value.Split('/'); - if (parts.Length == 2) - { - result = float.Parse(parts[0], _usCulture) / float.Parse(parts[1], _usCulture); - } - else - { - result = float.Parse(parts[0], _usCulture); - } + float result; - return float.IsNaN(result) ? (float?)null : result; + if (parts.Length == 2) + { + result = float.Parse(parts[0], _usCulture) / float.Parse(parts[1], _usCulture); + } + else + { + result = float.Parse(parts[0], _usCulture); } - return null; + return float.IsNaN(result) ? null : result; } private void SetAudioRuntimeTicks(InternalMediaInfoResult result, MediaInfo data) { - if (result.Streams != null) + // Get the first info stream + var stream = result.Streams?.FirstOrDefault(s => string.Equals(s.CodecType, "audio", StringComparison.OrdinalIgnoreCase)); + if (stream == null) { - // Get the first info stream - var stream = result.Streams.FirstOrDefault(s => string.Equals(s.CodecType, "audio", StringComparison.OrdinalIgnoreCase)); + return; + } - if (stream != null) - { - // Get duration from stream properties - var duration = stream.Duration; + // Get duration from stream properties + var duration = stream.Duration; - // If it's not there go into format properties - if (string.IsNullOrEmpty(duration)) - { - duration = result.Format.Duration; - } + // If it's not there go into format properties + if (string.IsNullOrEmpty(duration)) + { + duration = result.Format.Duration; + } - // If we got something, parse it - if (!string.IsNullOrEmpty(duration)) - { - data.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(duration, _usCulture)).Ticks; - } - } + // If we got something, parse it + if (!string.IsNullOrEmpty(duration)) + { + data.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(duration, _usCulture)).Ticks; } } private int? GetBPSFromTags(MediaStreamInfo streamInfo) { - if (streamInfo != null && streamInfo.Tags != null) + if (streamInfo?.Tags == null) { - var bps = GetDictionaryValue(streamInfo.Tags, "BPS-eng") ?? GetDictionaryValue(streamInfo.Tags, "BPS"); - if (!string.IsNullOrEmpty(bps) - && int.TryParse(bps, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedBps)) - { - return parsedBps; - } + return null; + } + + var bps = GetDictionaryValue(streamInfo.Tags, "BPS-eng") ?? GetDictionaryValue(streamInfo.Tags, "BPS"); + if (!string.IsNullOrEmpty(bps) + && int.TryParse(bps, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedBps)) + { + return parsedBps; } return null; @@ -1083,13 +1032,15 @@ namespace MediaBrowser.MediaEncoding.Probing private double? GetRuntimeSecondsFromTags(MediaStreamInfo streamInfo) { - if (streamInfo != null && streamInfo.Tags != null) + if (streamInfo?.Tags == null) { - var duration = GetDictionaryValue(streamInfo.Tags, "DURATION-eng") ?? GetDictionaryValue(streamInfo.Tags, "DURATION"); - if (!string.IsNullOrEmpty(duration) && TimeSpan.TryParse(duration, out var parsedDuration)) - { - return parsedDuration.TotalSeconds; - } + return null; + } + + var duration = GetDictionaryValue(streamInfo.Tags, "DURATION-eng") ?? GetDictionaryValue(streamInfo.Tags, "DURATION"); + if (!string.IsNullOrEmpty(duration) && TimeSpan.TryParse(duration, out var parsedDuration)) + { + return parsedDuration.TotalSeconds; } return null; @@ -1097,14 +1048,17 @@ namespace MediaBrowser.MediaEncoding.Probing private long? GetNumberOfBytesFromTags(MediaStreamInfo streamInfo) { - if (streamInfo != null && streamInfo.Tags != null) + if (streamInfo?.Tags == null) { - var numberOfBytes = GetDictionaryValue(streamInfo.Tags, "NUMBER_OF_BYTES-eng") ?? GetDictionaryValue(streamInfo.Tags, "NUMBER_OF_BYTES"); - if (!string.IsNullOrEmpty(numberOfBytes) - && long.TryParse(numberOfBytes, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedBytes)) - { - return parsedBytes; - } + return null; + } + + var numberOfBytes = GetDictionaryValue(streamInfo.Tags, "NUMBER_OF_BYTES-eng") + ?? GetDictionaryValue(streamInfo.Tags, "NUMBER_OF_BYTES"); + if (!string.IsNullOrEmpty(numberOfBytes) + && long.TryParse(numberOfBytes, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedBytes)) + { + return parsedBytes; } return null; @@ -1112,24 +1066,18 @@ namespace MediaBrowser.MediaEncoding.Probing private void SetSize(InternalMediaInfoResult data, MediaInfo info) { - if (data.Format != null) + if (data.Format == null) { - if (!string.IsNullOrEmpty(data.Format.Size)) - { - info.Size = long.Parse(data.Format.Size, _usCulture); - } - else - { - info.Size = null; - } + return; } + + info.Size = string.IsNullOrEmpty(data.Format.Size) ? null : long.Parse(data.Format.Size, _usCulture); } - private void SetAudioInfoFromTags(MediaInfo audio, Dictionary tags) + private void SetAudioInfoFromTags(MediaInfo audio, IReadOnlyDictionary tags) { var people = new List(); - var composer = FFProbeHelpers.GetDictionaryValue(tags, "composer"); - if (!string.IsNullOrWhiteSpace(composer)) + if (tags.TryGetValue("composer", out var composer) && !string.IsNullOrWhiteSpace(composer)) { foreach (var person in Split(composer, false)) { @@ -1137,8 +1085,7 @@ namespace MediaBrowser.MediaEncoding.Probing } } - var conductor = FFProbeHelpers.GetDictionaryValue(tags, "conductor"); - if (!string.IsNullOrWhiteSpace(conductor)) + if (tags.TryGetValue("conductor", out var conductor) && !string.IsNullOrWhiteSpace(conductor)) { foreach (var person in Split(conductor, false)) { @@ -1146,8 +1093,7 @@ namespace MediaBrowser.MediaEncoding.Probing } } - var lyricist = FFProbeHelpers.GetDictionaryValue(tags, "lyricist"); - if (!string.IsNullOrWhiteSpace(lyricist)) + if (tags.TryGetValue("lyricist", out var lyricist) && !string.IsNullOrWhiteSpace(lyricist)) { foreach (var person in Split(lyricist, false)) { @@ -1156,8 +1102,7 @@ namespace MediaBrowser.MediaEncoding.Probing } // Check for writer some music is tagged that way as alternative to composer/lyricist - var writer = FFProbeHelpers.GetDictionaryValue(tags, "writer"); - if (!string.IsNullOrWhiteSpace(writer)) + if (tags.TryGetValue("writer", out var writer) && !string.IsNullOrWhiteSpace(writer)) { foreach (var person in Split(writer, false)) { @@ -1167,38 +1112,23 @@ namespace MediaBrowser.MediaEncoding.Probing audio.People = people.ToArray(); - var albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "albumartist"); - if (string.IsNullOrWhiteSpace(albumArtist)) - { - albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "album artist"); - } - - if (string.IsNullOrWhiteSpace(albumArtist)) - { - albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "album_artist"); - } - - if (string.IsNullOrWhiteSpace(albumArtist)) - { - audio.AlbumArtists = Array.Empty(); - } - else - { - audio.AlbumArtists = SplitArtists(albumArtist, _nameDelimiters, true) - .DistinctNames() - .ToArray(); - } + // Set album artist + var albumArtist = tags.GetFirstNotNullNorWhiteSpaceValue("albumartist", "album artist", "album_artist"); + audio.AlbumArtists = albumArtist != null + ? SplitDistinctArtists(albumArtist, _nameDelimiters, true).ToArray() + : Array.Empty(); + // Set album artist to artist if empty if (audio.AlbumArtists.Length == 0) { audio.AlbumArtists = audio.Artists; } // Track number - audio.IndexNumber = GetDictionaryDiscValue(tags, "track"); + audio.IndexNumber = GetDictionaryTrackOrDiscNumber(tags, "track"); // Disc number - audio.ParentIndexNumber = GetDictionaryDiscValue(tags, "disc"); + audio.ParentIndexNumber = GetDictionaryTrackOrDiscNumber(tags, "disc"); // There's several values in tags may or may not be present FetchStudios(audio, tags, "organization"); @@ -1206,30 +1136,25 @@ namespace MediaBrowser.MediaEncoding.Probing FetchStudios(audio, tags, "publisher"); FetchStudios(audio, tags, "label"); - // These support mulitple values, but for now we only store the first. - var mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Artist Id")) - ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ALBUMARTISTID")); - + // These support multiple values, but for now we only store the first. + var mb = GetMultipleMusicBrainzId(tags.GetValueOrDefault("MusicBrainz Album Artist Id")) + ?? GetMultipleMusicBrainzId(tags.GetValueOrDefault("MUSICBRAINZ_ALBUMARTISTID")); audio.SetProviderId(MetadataProvider.MusicBrainzAlbumArtist, mb); - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Artist Id")) - ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ARTISTID")); - + mb = GetMultipleMusicBrainzId(tags.GetValueOrDefault("MusicBrainz Artist Id")) + ?? GetMultipleMusicBrainzId(tags.GetValueOrDefault("MUSICBRAINZ_ARTISTID")); audio.SetProviderId(MetadataProvider.MusicBrainzArtist, mb); - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Id")) - ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ALBUMID")); - + mb = GetMultipleMusicBrainzId(tags.GetValueOrDefault("MusicBrainz Album Id")) + ?? GetMultipleMusicBrainzId(tags.GetValueOrDefault("MUSICBRAINZ_ALBUMID")); audio.SetProviderId(MetadataProvider.MusicBrainzAlbum, mb); - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Group Id")) - ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_RELEASEGROUPID")); - + mb = GetMultipleMusicBrainzId(tags.GetValueOrDefault("MusicBrainz Release Group Id")) + ?? GetMultipleMusicBrainzId(tags.GetValueOrDefault("MUSICBRAINZ_RELEASEGROUPID")); audio.SetProviderId(MetadataProvider.MusicBrainzReleaseGroup, mb); - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Track Id")) - ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_RELEASETRACKID")); - + mb = GetMultipleMusicBrainzId(tags.GetValueOrDefault("MusicBrainz Release Track Id")) + ?? GetMultipleMusicBrainzId(tags.GetValueOrDefault("MUSICBRAINZ_RELEASETRACKID")); audio.SetProviderId(MetadataProvider.MusicBrainzTrack, mb); } @@ -1253,18 +1178,18 @@ namespace MediaBrowser.MediaEncoding.Probing /// System.String[][]. private IEnumerable Split(string val, bool allowCommaDelimiter) { - // Only use the comma as a delimeter if there are no slashes or pipes. + // Only use the comma as a delimiter if there are no slashes or pipes. // We want to be careful not to split names that have commas in them - var delimeter = !allowCommaDelimiter || _nameDelimiters.Any(i => val.IndexOf(i, StringComparison.Ordinal) != -1) ? + var delimiter = !allowCommaDelimiter || _nameDelimiters.Any(i => val.IndexOf(i, StringComparison.Ordinal) != -1) ? _nameDelimiters : new[] { ',' }; - return val.Split(delimeter, StringSplitOptions.RemoveEmptyEntries) + return val.Split(delimiter, StringSplitOptions.RemoveEmptyEntries) .Where(i => !string.IsNullOrWhiteSpace(i)) .Select(i => i.Trim()); } - private IEnumerable SplitArtists(string val, char[] delimiters, bool splitFeaturing) + private IEnumerable SplitDistinctArtists(string val, char[] delimiters, bool splitFeaturing) { if (splitFeaturing) { @@ -1290,7 +1215,7 @@ namespace MediaBrowser.MediaEncoding.Probing .Select(i => i.Trim()); artistsFound.AddRange(artists); - return artistsFound; + return artistsFound.DistinctNames(); } /// @@ -1299,36 +1224,38 @@ namespace MediaBrowser.MediaEncoding.Probing /// The info. /// The tags. /// Name of the tag. - private void FetchStudios(MediaInfo info, Dictionary tags, string tagName) + private void FetchStudios(MediaInfo info, IReadOnlyDictionary tags, string tagName) { - var val = FFProbeHelpers.GetDictionaryValue(tags, tagName); + var val = tags.GetValueOrDefault(tagName); - if (!string.IsNullOrEmpty(val)) + if (string.IsNullOrEmpty(val)) { - var studios = Split(val, true); - var studioList = new List(); + return; + } - foreach (var studio in studios) - { - // Sometimes the artist name is listed here, account for that - if (info.Artists.Contains(studio, StringComparer.OrdinalIgnoreCase)) - { - continue; - } + var studios = Split(val, true); + var studioList = new List(); - if (info.AlbumArtists.Contains(studio, StringComparer.OrdinalIgnoreCase)) - { - continue; - } + foreach (var studio in studios) + { + if (string.IsNullOrWhiteSpace(studio)) + { + continue; + } - studioList.Add(studio); + // Don't add artist/album artist name to studios, even if it's listed there + if (info.Artists.Contains(studio, StringComparer.OrdinalIgnoreCase) + || info.AlbumArtists.Contains(studio, StringComparer.OrdinalIgnoreCase)) + { + continue; } - info.Studios = studioList - .Where(i => !string.IsNullOrWhiteSpace(i)) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToArray(); + studioList.Add(studio); } + + info.Studios = studioList + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToArray(); } /// @@ -1336,58 +1263,55 @@ namespace MediaBrowser.MediaEncoding.Probing /// /// The information. /// The tags. - private void FetchGenres(MediaInfo info, Dictionary tags) + private void FetchGenres(MediaInfo info, IReadOnlyDictionary tags) { - var val = FFProbeHelpers.GetDictionaryValue(tags, "genre"); + var genreVal = tags.GetValueOrDefault("genre"); + if (string.IsNullOrEmpty(genreVal)) + { + return; + } - if (!string.IsNullOrEmpty(val)) + var genres = new List(info.Genres); + foreach (var genre in Split(genreVal, true)) { - var genres = new List(info.Genres); - foreach (var genre in Split(val, true)) + if (string.IsNullOrWhiteSpace(genre)) { - genres.Add(genre); + continue; } - info.Genres = genres - .Where(i => !string.IsNullOrWhiteSpace(i)) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToArray(); + genres.Add(genre); } + + info.Genres = genres + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToArray(); } /// - /// Gets the disc number, which is sometimes can be in the form of '1', or '1/3'. + /// Gets the track or disc number, which can be in the form of '1', or '1/3'. /// /// The tags. /// Name of the tag. - /// System.Nullable{System.Int32}. - private int? GetDictionaryDiscValue(Dictionary tags, string tagName) + /// The track or disc number, or null, if missing or not parseable. + private static int? GetDictionaryTrackOrDiscNumber(IReadOnlyDictionary tags, string tagName) { - var disc = FFProbeHelpers.GetDictionaryValue(tags, tagName); + var disc = tags.GetValueOrDefault(tagName); - if (!string.IsNullOrEmpty(disc)) + if (!string.IsNullOrEmpty(disc) && int.TryParse(disc.Split('/')[0], out var discNum)) { - disc = disc.Split('/')[0]; - - if (int.TryParse(disc, out var num)) - { - return num; - } + return discNum; } return null; } - private ChapterInfo GetChapterInfo(MediaChapter chapter) + private static ChapterInfo GetChapterInfo(MediaChapter chapter) { var info = new ChapterInfo(); - if (chapter.Tags != null) + if (chapter.Tags != null && chapter.Tags.TryGetValue("title", out string name)) { - if (chapter.Tags.TryGetValue("title", out string name)) - { - info.Name = name; - } + info.Name = name; } // Limit accuracy to milliseconds to match xml saving @@ -1404,14 +1328,14 @@ namespace MediaBrowser.MediaEncoding.Probing private void FetchWtvInfo(MediaInfo video, InternalMediaInfoResult data) { - if (data.Format == null || data.Format.Tags == null) + var tags = data.Format?.Tags; + + if (tags == null) { return; } - var genres = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/Genre"); - - if (!string.IsNullOrWhiteSpace(genres)) + if (tags.TryGetValue("WM/Genre", out var genres) && !string.IsNullOrWhiteSpace(genres)) { var genreList = genres.Split(new[] { ';', '/', ',' }, StringSplitOptions.RemoveEmptyEntries) .Where(i => !string.IsNullOrWhiteSpace(i)) @@ -1425,16 +1349,12 @@ namespace MediaBrowser.MediaEncoding.Probing } } - var officialRating = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/ParentalRating"); - - if (!string.IsNullOrWhiteSpace(officialRating)) + if (tags.TryGetValue("WM/ParentalRating", out var officialRating) && !string.IsNullOrWhiteSpace(officialRating)) { video.OfficialRating = officialRating; } - var people = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/MediaCredits"); - - if (!string.IsNullOrEmpty(people)) + if (tags.TryGetValue("WM/MediaCredits", out var people) && !string.IsNullOrEmpty(people)) { video.People = people.Split(new[] { ';', '/' }, StringSplitOptions.RemoveEmptyEntries) .Where(i => !string.IsNullOrWhiteSpace(i)) @@ -1442,29 +1362,21 @@ namespace MediaBrowser.MediaEncoding.Probing .ToArray(); } - var year = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/OriginalReleaseTime"); - if (!string.IsNullOrWhiteSpace(year)) + if (tags.TryGetValue("WM/OriginalReleaseTime", out var year) && int.TryParse(year, NumberStyles.Integer, _usCulture, out var parsedYear)) { - if (int.TryParse(year, NumberStyles.Integer, _usCulture, out var val)) - { - video.ProductionYear = val; - } + video.ProductionYear = parsedYear; } - var premiereDateString = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/MediaOriginalBroadcastDateTime"); - if (!string.IsNullOrWhiteSpace(premiereDateString)) + // Credit to MCEBuddy: https://mcebuddy2x.codeplex.com/ + // DateTime is reported along with timezone info (typically Z i.e. UTC hence assume None) + if (tags.TryGetValue("WM/MediaOriginalBroadcastDateTime", out var premiereDateString) && DateTime.TryParse(year, null, DateTimeStyles.None, out var parsedDate)) { - // Credit to MCEBuddy: https://mcebuddy2x.codeplex.com/ - // DateTime is reported along with timezone info (typically Z i.e. UTC hence assume None) - if (DateTime.TryParse(year, null, DateTimeStyles.None, out var val)) - { - video.PremiereDate = val.ToUniversalTime(); - } + video.PremiereDate = parsedDate.ToUniversalTime(); } - var description = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/SubTitleDescription"); + var description = tags.GetValueOrDefault("WM/SubTitleDescription"); - var subTitle = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/SubTitle"); + var subTitle = tags.GetValueOrDefault("WM/SubTitle"); // For below code, credit to MCEBuddy: https://mcebuddy2x.codeplex.com/ @@ -1475,49 +1387,48 @@ namespace MediaBrowser.MediaEncoding.Probing // e.g. -> CBeebies Bedtime Hour. The Mystery: Animated adventures of two friends who live on an island in the middle of the big city. Some of Abney and Teal's favourite objects are missing. [S] if (string.IsNullOrWhiteSpace(subTitle) && !string.IsNullOrWhiteSpace(description) - && description.AsSpan().Slice(0, Math.Min(description.Length, MaxSubtitleDescriptionExtractionLength)).IndexOf(':') != -1) // Check within the Subtitle size limit, otherwise from description it can get too long creating an invalid filename + && description.AsSpan()[0..Math.Min(description.Length, MaxSubtitleDescriptionExtractionLength)].IndexOf(':') != -1) // Check within the Subtitle size limit, otherwise from description it can get too long creating an invalid filename { - string[] parts = description.Split(':'); - if (parts.Length > 0) + string[] descriptionParts = description.Split(':'); + if (descriptionParts.Length > 0) { - string subtitle = parts[0]; + string subtitle = descriptionParts[0]; try { - if (subtitle.Contains('/', StringComparison.Ordinal)) // It contains a episode number and season number + // Check if it contains a episode number and season number + if (subtitle.Contains('/', StringComparison.Ordinal)) { - string[] numbers = subtitle.Split(' '); - video.IndexNumber = int.Parse(numbers[0].Replace(".", string.Empty, StringComparison.Ordinal).Split('/')[0], CultureInfo.InvariantCulture); - int totalEpisodesInSeason = int.Parse(numbers[0].Replace(".", string.Empty, StringComparison.Ordinal).Split('/')[1], CultureInfo.InvariantCulture); + string[] subtitleParts = subtitle.Split(' '); + string[] numbers = subtitleParts[0].Replace(".", string.Empty, StringComparison.Ordinal).Split('/'); + video.IndexNumber = int.Parse(numbers[0], CultureInfo.InvariantCulture); + // int totalEpisodesInSeason = int.Parse(numbers[1], CultureInfo.InvariantCulture); - description = string.Join(' ', numbers, 1, numbers.Length - 1).Trim(); // Skip the first, concatenate the rest, clean up spaces and save it + // Skip the numbers, concatenate the rest, trim and set as new description + description = string.Join(' ', subtitleParts, 1, subtitleParts.Length - 1).Trim(); + } + else if (subtitle.Contains('.', StringComparison.Ordinal)) + { + var subtitleParts = subtitle.Split('.'); + description = string.Join('.', subtitleParts, 1, subtitleParts.Length - 1).Trim(); } else { - // Switch to default parsing - if (subtitle.Contains('.', StringComparison.Ordinal)) - { - // skip the comment, keep the subtitle - description = string.Join('.', subtitle.Split('.'), 1, subtitle.Split('.').Length - 1).Trim(); // skip the first - } - else - { - description = subtitle.Trim(); // Clean up whitespaces and save it - } + description = subtitle.Trim(); } } catch (Exception ex) { _logger.LogError(ex, "Error while parsing subtitle field"); - // Default parsing + // Fallback to default parsing if (subtitle.Contains('.', StringComparison.Ordinal)) { - // skip the comment, keep the subtitle - description = string.Join('.', subtitle.Split('.'), 1, subtitle.Split('.').Length - 1).Trim(); // skip the first + var subtitleParts = subtitle.Split('.'); + description = string.Join('.', subtitleParts, 1, subtitleParts.Length - 1).Trim(); } else { - description = subtitle.Trim(); // Clean up whitespaces and save it + description = subtitle.Trim(); } } } @@ -1531,24 +1442,27 @@ namespace MediaBrowser.MediaEncoding.Probing private void ExtractTimestamp(MediaInfo video) { - if (video.VideoType == VideoType.VideoFile) + if (video.VideoType != VideoType.VideoFile) { - if (string.Equals(video.Container, "mpeg2ts", StringComparison.OrdinalIgnoreCase) || - string.Equals(video.Container, "m2ts", StringComparison.OrdinalIgnoreCase) || - string.Equals(video.Container, "ts", StringComparison.OrdinalIgnoreCase)) - { - try - { - video.Timestamp = GetMpegTimestamp(video.Path); + return; + } - _logger.LogDebug("Video has {Timestamp} timestamp", video.Timestamp); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error extracting timestamp info from {Path}", video.Path); - video.Timestamp = null; - } - } + if (!string.Equals(video.Container, "mpeg2ts", StringComparison.OrdinalIgnoreCase) + && !string.Equals(video.Container, "m2ts", StringComparison.OrdinalIgnoreCase) + && !string.Equals(video.Container, "ts", StringComparison.OrdinalIgnoreCase)) + { + return; + } + + try + { + video.Timestamp = GetMpegTimestamp(video.Path); + _logger.LogDebug("Video has {Timestamp} timestamp", video.Timestamp); + } + catch (Exception ex) + { + video.Timestamp = null; + _logger.LogError(ex, "Error extracting timestamp info from {Path}", video.Path); } } @@ -1567,17 +1481,17 @@ namespace MediaBrowser.MediaEncoding.Probing return TransportStreamTimestamp.None; } - if ((packetBuffer[4] == 71) && (packetBuffer[196] == 71)) + if ((packetBuffer[4] != 71) || (packetBuffer[196] != 71)) { - if ((packetBuffer[0] == 0) && (packetBuffer[1] == 0) && (packetBuffer[2] == 0) && (packetBuffer[3] == 0)) - { - return TransportStreamTimestamp.Zero; - } + return TransportStreamTimestamp.None; + } - return TransportStreamTimestamp.Valid; + if ((packetBuffer[0] == 0) && (packetBuffer[1] == 0) && (packetBuffer[2] == 0) && (packetBuffer[3] == 0)) + { + return TransportStreamTimestamp.Zero; } - return TransportStreamTimestamp.None; + return TransportStreamTimestamp.Valid; } } } diff --git a/src/Jellyfin.Extensions/DictionaryExtensions.cs b/src/Jellyfin.Extensions/DictionaryExtensions.cs new file mode 100644 index 0000000000..43ed41ab18 --- /dev/null +++ b/src/Jellyfin.Extensions/DictionaryExtensions.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; + +namespace Jellyfin.Extensions +{ + /// + /// Static extensions for the interface. + /// + public static class DictionaryExtensions + { + /// + /// Gets a string from a string dictionary, checking all keys sequentially, + /// stopping at the first key that returns a result that's neither null nor blank. + /// + /// The dictionary. + /// The first checked key. + /// System.String. + public static string? GetFirstNotNullNorWhiteSpaceValue(this IReadOnlyDictionary dictionary, string key1) + { + return dictionary.GetFirstNotNullNorWhiteSpaceValue(key1, string.Empty, string.Empty); + } + + /// + /// Gets a string from a string dictionary, checking all keys sequentially, + /// stopping at the first key that returns a result that's neither null nor blank. + /// + /// The dictionary. + /// The first checked key. + /// The second checked key. + /// System.String. + public static string? GetFirstNotNullNorWhiteSpaceValue(this IReadOnlyDictionary dictionary, string key1, string key2) + { + return dictionary.GetFirstNotNullNorWhiteSpaceValue(key1, key2, string.Empty); + } + + /// + /// Gets a string from a string dictionary, checking all keys sequentially, + /// stopping at the first key that returns a result that's neither null nor blank. + /// + /// The dictionary. + /// The first checked key. + /// The second checked key. + /// The third checked key. + /// System.String. + public static string? GetFirstNotNullNorWhiteSpaceValue(this IReadOnlyDictionary dictionary, string key1, string key2, string key3) + { + if (dictionary.TryGetValue(key1, out var val) && !string.IsNullOrWhiteSpace(val)) + { + return val; + } + + if (!string.IsNullOrEmpty(key2) && dictionary.TryGetValue(key2, out val) && !string.IsNullOrWhiteSpace(val)) + { + return val; + } + + if (!string.IsNullOrEmpty(key3) && dictionary.TryGetValue(key3, out val) && !string.IsNullOrWhiteSpace(val)) + { + return val; + } + + return null; + } + } +} From e7022cc3fc7f6973262ed5f5a2a33fbf8c659c58 Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Fri, 9 Jul 2021 09:07:22 -0600 Subject: [PATCH 013/120] Use asp validation and increase max size --- Jellyfin.Api/Controllers/MediaInfoController.cs | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/Jellyfin.Api/Controllers/MediaInfoController.cs b/Jellyfin.Api/Controllers/MediaInfoController.cs index e330f02b61..ad11d09238 100644 --- a/Jellyfin.Api/Controllers/MediaInfoController.cs +++ b/Jellyfin.Api/Controllers/MediaInfoController.cs @@ -302,27 +302,12 @@ namespace Jellyfin.Api.Controllers /// /// The bitrate. Defaults to 102400. /// Test buffer returned. - /// Size has to be a numer between 0 and 10,000,000. /// A with specified bitrate. [HttpGet("Playback/BitrateTest")] [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status400BadRequest)] - [Produces(MediaTypeNames.Application.Octet)] [ProducesFile(MediaTypeNames.Application.Octet)] - public ActionResult GetBitrateTestBytes([FromQuery] int size = 102400) + public ActionResult GetBitrateTestBytes([FromQuery][Range(1, 100_000_000, ErrorMessage = "The requested size must be greater than 0 and less than 100,000,000")] int size = 102400) { - const int MaxSize = 10_000_000; - - if (size <= 0) - { - return BadRequest($"The requested size ({size}) is equal to or smaller than 0."); - } - - if (size > MaxSize) - { - return BadRequest($"The requested size ({size}) is larger than the max allowed value ({MaxSize})."); - } - byte[] buffer = ArrayPool.Shared.Rent(size); try { From 7a2791e904269baf4976be36a5abefad101f0a6c Mon Sep 17 00:00:00 2001 From: Hannes Date: Fri, 4 Jun 2021 09:07:33 +0000 Subject: [PATCH 014/120] 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 2973c8c6ea..8b67b50612 100644 --- a/Emby.Server.Implementations/Localization/Core/nl.json +++ b/Emby.Server.Implementations/Localization/Core/nl.json @@ -1,7 +1,7 @@ { "Albums": "Albums", "AppDeviceValues": "App: {0}, Apparaat: {1}", - "Application": "Applicatie", + "Application": "Toepassing", "Artists": "Artiesten", "AuthenticationSucceededWithUserName": "{0} is succesvol geauthenticeerd", "Books": "Boeken", From f282f6f924efd7931eecc861c76516a0effe90ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabr=C3=ADcio=20J=C3=A1come?= Date: Wed, 16 Jun 2021 16:45:57 +0000 Subject: [PATCH 015/120] Translated using Weblate (Portuguese) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/pt/ --- Emby.Server.Implementations/Localization/Core/pt.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/pt.json b/Emby.Server.Implementations/Localization/Core/pt.json index f1a78b2d32..b435672adf 100644 --- a/Emby.Server.Implementations/Localization/Core/pt.json +++ b/Emby.Server.Implementations/Localization/Core/pt.json @@ -61,7 +61,7 @@ "NameSeasonUnknown": "Temporada Desconhecida", "NameSeasonNumber": "Temporada {0}", "NameInstallFailed": "Falha na instalação de {0}", - "MusicVideos": "Videoclips", + "MusicVideos": "Videoclipes", "Music": "Música", "MixedContent": "Conteúdo Misto", "MessageServerConfigurationUpdated": "A configuração do servidor foi actualizada", From ff1a78a82f6048bf187444078c339c59b486e2ea Mon Sep 17 00:00:00 2001 From: Rajmond Burgaj Date: Fri, 11 Jun 2021 17:34:05 +0000 Subject: [PATCH 016/120] Translated using Weblate (Albanian) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/sq/ --- Emby.Server.Implementations/Localization/Core/sq.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/sq.json b/Emby.Server.Implementations/Localization/Core/sq.json index 0d909b06e9..f611cbafaa 100644 --- a/Emby.Server.Implementations/Localization/Core/sq.json +++ b/Emby.Server.Implementations/Localization/Core/sq.json @@ -112,5 +112,10 @@ "Artists": "Artistë", "Application": "Aplikacioni", "AppDeviceValues": "Aplikacioni: {0}, Pajisja: {1}", - "Albums": "Albume" + "Albums": "Albume", + "TaskCleanActivityLogDescription": "Pastro të dhënat mbi aktivitetin më të vjetra sesa koha e përcaktuar.", + "TaskCleanActivityLog": "Pastro të dhënat mbi aktivitetin", + "Undefined": "I papërcaktuar", + "Forced": "I detyruar", + "Default": "Parazgjedhur" } From faa3ec14e96ee1a2498e372546688dab953d6cc0 Mon Sep 17 00:00:00 2001 From: Benito Sebe Date: Mon, 5 Jul 2021 11:34:01 +0000 Subject: [PATCH 017/120] Translated using Weblate (Galician) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/gl/ --- .../Localization/Core/gl.json | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/gl.json b/Emby.Server.Implementations/Localization/Core/gl.json index 0398e1c9e5..afb22ab472 100644 --- a/Emby.Server.Implementations/Localization/Core/gl.json +++ b/Emby.Server.Implementations/Localization/Core/gl.json @@ -88,5 +88,34 @@ "NotificationOptionVideoPlaybackStopped": "Reproducción de vídeo parada", "NotificationOptionVideoPlayback": "Reproducción de vídeo iniciada", "NotificationOptionUserLockedOut": "Usuario bloqueado", - "NotificationOptionTaskFailed": "Falla na tarefa axendada" + "NotificationOptionTaskFailed": "Falla na tarefa axendada", + "TaskCleanTranscodeDescription": "Borra os arquivos de transcode anteriores a un día.", + "TaskCleanTranscode": "Limpar Directorio de Transcode", + "UserStoppedPlayingItemWithValues": "{0} rematou de reproducir {1} en {2}", + "UserStartedPlayingItemWithValues": "{0} está reproducindo {1} en {2}", + "TaskDownloadMissingSubtitlesDescription": "Busca en internet por subtítulos que faltan baseado na configuración de metadatos.", + "TaskDownloadMissingSubtitles": "Descargar subtítulos que faltan", + "TaskRefreshChannelsDescription": "Refresca a información do canle de internet.", + "TaskRefreshChannels": "Refrescar Canles", + "TaskUpdatePluginsDescription": "Descarga e instala actualizacións para plugins que están configurados para actualizarse automáticamente.", + "TaskRefreshPeopleDescription": "Actualiza os metadatos dos actores e directores na túa libraría multimedia.", + "TaskRefreshPeople": "Refrescar Persoas", + "TaskCleanLogsDescription": "Borra arquivos de rexistro que son mais antigos que {0} días.", + "TaskRefreshLibraryDescription": "Escanea a tua libraría multimedia buscando novos arquivos e refrescando os metadatos.", + "TaskRefreshLibrary": "Escanear Libraría Multimedia", + "TaskRefreshChapterImagesDescription": "Crea previsualizacións para videos que teñen capítulos.", + "TaskRefreshChapterImages": "Extraer Imaxes dos Capítulos", + "TaskCleanCacheDescription": "Borra ficheiros da caché que xa non son necesarios para o sistema.", + "TaskCleanCache": "Limpa Directorio de Caché", + "TaskCleanActivityLogDescription": "Borra as entradas no rexistro de actividade anteriores á data configurada.", + "TasksApplicationCategory": "Aplicación", + "ValueSpecialEpisodeName": "Especial - {0}", + "ValueHasBeenAddedToLibrary": "{0} foi engadido a túa libraría multimedia", + "TasksLibraryCategory": "Libraría", + "TasksMaintenanceCategory": "Mantemento", + "VersionNumber": "Versión {0}", + "UserPolicyUpdatedWithName": "A política de usuario foi actualizada para {0}", + "UserPasswordChangedWithName": "Cambiouse o contrasinal para o usuario {0}", + "UserOnlineFromDevice": "{0} está en liña desde {1}", + "UserOfflineFromDevice": "{0} desconectouse desde {1}" } From 7bf9cc6887875513ac3cbbda785729d4a7e897b2 Mon Sep 17 00:00:00 2001 From: Kachelkaiser Date: Thu, 8 Jul 2021 12:36:58 +0000 Subject: [PATCH 018/120] Translated using Weblate (German) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/de/ --- Emby.Server.Implementations/Localization/Core/de.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/de.json b/Emby.Server.Implementations/Localization/Core/de.json index 9d82b58784..f775ec1188 100644 --- a/Emby.Server.Implementations/Localization/Core/de.json +++ b/Emby.Server.Implementations/Localization/Core/de.json @@ -3,7 +3,7 @@ "AppDeviceValues": "App: {0}, Gerät: {1}", "Application": "Anwendung", "Artists": "Interpreten", - "AuthenticationSucceededWithUserName": "{0} wurde angemeldet", + "AuthenticationSucceededWithUserName": "{0} erfolgreich authentifiziert", "Books": "Bücher", "CameraImageUploadedFrom": "Ein neues Kamerafoto wurde von {0} hochgeladen", "Channels": "Kanäle", @@ -16,7 +16,7 @@ "Folders": "Verzeichnisse", "Genres": "Genres", "HeaderAlbumArtists": "Album-Interpreten", - "HeaderContinueWatching": "Fortsetzen", + "HeaderContinueWatching": "Weiterschauen", "HeaderFavoriteAlbums": "Lieblingsalben", "HeaderFavoriteArtists": "Lieblings-Interpreten", "HeaderFavoriteEpisodes": "Lieblingsepisoden", From 0f57959c55c7881d6190ce598b3fe75175e1a822 Mon Sep 17 00:00:00 2001 From: aqilisk <2019707275@isiswa.uitm.edu.my> Date: Thu, 8 Jul 2021 13:51:37 +0000 Subject: [PATCH 019/120] Translated using Weblate (Malay) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ms/ --- .../Localization/Core/ms.json | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/ms.json b/Emby.Server.Implementations/Localization/Core/ms.json index 5b4c8ae107..b2dcf270c1 100644 --- a/Emby.Server.Implementations/Localization/Core/ms.json +++ b/Emby.Server.Implementations/Localization/Core/ms.json @@ -5,7 +5,7 @@ "Artists": "Artis", "AuthenticationSucceededWithUserName": "{0} berjaya disahkan", "Books": "Buku-buku", - "CameraImageUploadedFrom": "Ada gambar dari kamera yang baru dimuat naik melalui {0}", + "CameraImageUploadedFrom": "Gambar baharu telah dimuat naik melalui {0}", "Channels": "Saluran", "ChapterNameValue": "Bab {0}", "Collections": "Koleksi", @@ -101,5 +101,13 @@ "Forced": "Paksa", "Default": "Asal", "TaskCleanCache": "Bersihkan Direktori Cache", - "TaskCleanActivityLogDescription": "Padamkan entri log aktiviti yang lebih tua daripada usia yang dikonfigurasi." + "TaskCleanActivityLogDescription": "Padamkan entri log aktiviti yang lebih tua daripada usia yang dikonfigurasi.", + "TaskRefreshPeople": "Segarkan Orang", + "TaskCleanLogsDescription": "Padamkan fail log yang berumur lebih dari {0} hari.", + "TaskCleanLogs": "Bersihkan Direktotri Log", + "TaskRefreshLibraryDescription": "Imbas perpustakaan media untuk mencari fail-fail baru dan menyegarkan metadata.", + "TaskRefreshLibrary": "Imbas Perpustakaan Media", + "TaskRefreshChapterImagesDescription": "Membuat gambaran kecil untuk video yang mempunyai bab.", + "TaskRefreshChapterImages": "Ekstrak Gambar-gambar Bab", + "TaskCleanCacheDescription": "Menghapuskan fail cache yang tidak lagi diperlukan oleh sistem." } From ff010c16aaeaf34c454cc9f515ca552edfe3f3ef Mon Sep 17 00:00:00 2001 From: Tim040 Date: Fri, 2 Jul 2021 21:29:53 +0000 Subject: [PATCH 020/120] Translated using Weblate (Dutch) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/nl/ --- .../Localization/Core/nl.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/nl.json b/Emby.Server.Implementations/Localization/Core/nl.json index 8b67b50612..85b8416fd9 100644 --- a/Emby.Server.Implementations/Localization/Core/nl.json +++ b/Emby.Server.Implementations/Localization/Core/nl.json @@ -25,7 +25,7 @@ "HeaderLiveTV": "Live TV", "HeaderNextUp": "Volgende", "HeaderRecordingGroups": "Opnamegroepen", - "HomeVideos": "Home video's", + "HomeVideos": "Thuis video's", "Inherit": "Erven", "ItemAddedWithName": "{0} is toegevoegd aan de bibliotheek", "ItemRemovedWithName": "{0} is verwijderd uit de bibliotheek", @@ -92,11 +92,11 @@ "ValueHasBeenAddedToLibrary": "{0} is toegevoegd aan je mediabibliotheek", "ValueSpecialEpisodeName": "Speciaal - {0}", "VersionNumber": "Versie {0}", - "TaskDownloadMissingSubtitlesDescription": "Zoekt op het internet naar missende ondertitels gebaseerd op metadata configuratie.", - "TaskDownloadMissingSubtitles": "Download missende ondertitels", + "TaskDownloadMissingSubtitlesDescription": "Zoekt op het internet naar missende ondertiteling gebaseerd op metadata configuratie.", + "TaskDownloadMissingSubtitles": "Download missende ondertiteling", "TaskRefreshChannelsDescription": "Vernieuwt informatie van internet kanalen.", "TaskRefreshChannels": "Vernieuw Kanalen", - "TaskCleanTranscodeDescription": "Verwijder transcode bestanden ouder dan 1 dag.", + "TaskCleanTranscodeDescription": "Verwijdert transcode bestanden ouder dan 1 dag.", "TaskCleanLogs": "Log Folder Opschonen", "TaskCleanTranscode": "Transcode Folder Opschonen", "TaskUpdatePluginsDescription": "Download en installeert updates voor plugins waar automatisch updaten aan staat.", @@ -108,13 +108,13 @@ "TaskRefreshLibrary": "Scan Media Bibliotheek", "TaskRefreshChapterImagesDescription": "Maakt thumbnails aan voor videos met hoofdstukken.", "TaskRefreshChapterImages": "Hoofdstukafbeeldingen Uitpakken", - "TaskCleanCacheDescription": "Verwijder gecachte bestanden die het systeem niet langer nodig heeft.", + "TaskCleanCacheDescription": "Verwijdert gecachte bestanden die het systeem niet langer nodig heeft.", "TaskCleanCache": "Cache Folder Opschonen", "TasksChannelsCategory": "Internet Kanalen", "TasksApplicationCategory": "Applicatie", "TasksLibraryCategory": "Bibliotheek", "TasksMaintenanceCategory": "Onderhoud", - "TaskCleanActivityLogDescription": "Verwijder activiteiten logs ouder dan de ingestelde tijd.", + "TaskCleanActivityLogDescription": "Verwijdert activiteiten logs ouder dan de ingestelde tijd.", "TaskCleanActivityLog": "Leeg activiteiten logboek", "Undefined": "Niet gedefinieerd", "Forced": "Geforceerd", From 43b0d0fa9528e3fbad1af647ee61772e319f4eaa Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Sat, 10 Jul 2021 05:34:15 -0600 Subject: [PATCH 021/120] Fix error message, use range parameters --- Jellyfin.Api/Controllers/MediaInfoController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jellyfin.Api/Controllers/MediaInfoController.cs b/Jellyfin.Api/Controllers/MediaInfoController.cs index ad11d09238..e7a7a6addb 100644 --- a/Jellyfin.Api/Controllers/MediaInfoController.cs +++ b/Jellyfin.Api/Controllers/MediaInfoController.cs @@ -306,7 +306,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Playback/BitrateTest")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesFile(MediaTypeNames.Application.Octet)] - public ActionResult GetBitrateTestBytes([FromQuery][Range(1, 100_000_000, ErrorMessage = "The requested size must be greater than 0 and less than 100,000,000")] int size = 102400) + public ActionResult GetBitrateTestBytes([FromQuery][Range(1, 100_000_000, ErrorMessage = "The requested size must be greater than or equal to {1} and less than or equal to {2}")] int size = 102400) { byte[] buffer = ArrayPool.Shared.Rent(size); try From abbcf5e4f7f4dff2ce75a8f767b7b316a42a4a84 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 10 Jul 2021 15:07:40 +0200 Subject: [PATCH 022/120] Add tests for Playback/BitrateTest endpoint --- .../Controllers/MediaInfoControllerTests.cs | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 tests/Jellyfin.Server.Integration.Tests/Controllers/MediaInfoControllerTests.cs diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaInfoControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaInfoControllerTests.cs new file mode 100644 index 0000000000..abf03d6584 --- /dev/null +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaInfoControllerTests.cs @@ -0,0 +1,58 @@ +using System.Globalization; +using System.Net; +using System.Net.Mime; +using System.Threading.Tasks; +using Xunit; + +namespace Jellyfin.Server.Integration.Tests.Controllers +{ + public sealed class MediaInfoControllerTests : IClassFixture + { + private readonly JellyfinApplicationFactory _factory; + private static string? _accessToken; + + public MediaInfoControllerTests(JellyfinApplicationFactory factory) + { + _factory = factory; + } + + [Fact] + public async Task BitrateTest_Default_Ok() + { + var client = _factory.CreateClient(); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + + var response = await client.GetAsync("Playback/BitrateTest").ConfigureAwait(false); + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal(MediaTypeNames.Application.Octet, response.Content.Headers.ContentType?.MediaType); + } + + [Theory] + [InlineData(102400)] + public async Task BitrateTest_WithValidParam_Ok(int size) + { + var client = _factory.CreateClient(); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + + var response = await client.GetAsync("Playback/BitrateTest?size=" + size.ToString(CultureInfo.InvariantCulture)).ConfigureAwait(false); + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal(MediaTypeNames.Application.Octet, response.Content.Headers.ContentType?.MediaType); + } + + [Theory] + [InlineData(0)] // Zero + [InlineData(-102400)] // Negative value + [InlineData(1000000000)] // Too large + public async Task BitrateTest_InvalidValue_BadRequest(int size) + { + var client = _factory.CreateClient(); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + + var response = await client.GetAsync("Playback/BitrateTest?size=" + size.ToString(CultureInfo.InvariantCulture)).ConfigureAwait(false); + + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + } + } +} From 020c0fc4cba9657b3cddf6ea237bb00a59fdf118 Mon Sep 17 00:00:00 2001 From: MrTimscampi Date: Sat, 10 Jul 2021 17:04:00 +0200 Subject: [PATCH 023/120] Add more artist names to the splitting whitelist --- .../Probing/ProbeResultNormalizer.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index c50a577be6..feefd5348a 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -39,7 +39,16 @@ namespace MediaBrowser.MediaEncoding.Probing _localization = localization; } - private IReadOnlyList SplitWhitelist => _splitWhiteList ??= new string[] { "AC/DC" }; + private IReadOnlyList SplitWhitelist => _splitWhiteList ??= new string[] + { + "AC/DC", + "Au/Ra", + "이달의 소녀 1/3", + "LOONA 1/3", + "LOONA / yyxy", + "LOONA / ODD EYE CIRCLE", + "KD/A" + }; public MediaInfo GetMediaInfo(InternalMediaInfoResult data, VideoType? videoType, bool isAudio, string path, MediaProtocol protocol) { From 4281722d5a50347c26ee92dcd47b3bbad5cedbbf Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Sat, 10 Jul 2021 10:05:41 -0600 Subject: [PATCH 024/120] Fix [SA1629] Documentation text should end with a period --- MediaBrowser.Controller/Providers/ItemLookupInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Controller/Providers/ItemLookupInfo.cs b/MediaBrowser.Controller/Providers/ItemLookupInfo.cs index 2fd89e3bb4..2219b62b81 100644 --- a/MediaBrowser.Controller/Providers/ItemLookupInfo.cs +++ b/MediaBrowser.Controller/Providers/ItemLookupInfo.cs @@ -23,7 +23,7 @@ namespace MediaBrowser.Controller.Providers public string Name { get; set; } /// - /// Gets or sets the original title + /// Gets or sets the original title. /// /// The original title of the item. public string OriginalTitle { get; set; } From 65f8d8c0cd6cf64cebcbc0cc9279d9857ebf343c Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Sat, 10 Jul 2021 10:09:02 -0600 Subject: [PATCH 025/120] [CA1801] Parameter is never used. Remove the parameter or use it in the method body. --- .../Collections/CollectionManager.cs | 2 +- .../Playlists/PlaylistManager.cs | 2 +- .../Controllers/DynamicHlsController.cs | 2 +- .../Controllers/VideoHlsController.cs | 2 +- MediaBrowser.Controller/Entities/Folder.cs | 15 +--------- .../Entities/UserViewBuilder.cs | 29 +++++++++---------- .../LiveTv/LiveTvChannel.cs | 2 +- .../MediaEncoding/EncodingHelper.cs | 4 +-- .../TV/SeriesMetadataService.cs | 2 +- 9 files changed, 22 insertions(+), 38 deletions(-) diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs index 82d80fc83c..4fc33e2ea4 100644 --- a/Emby.Server.Implementations/Collections/CollectionManager.cs +++ b/Emby.Server.Implementations/Collections/CollectionManager.cs @@ -164,7 +164,7 @@ namespace Emby.Server.Implementations.Collections DateCreated = DateTime.UtcNow }; - parentFolder.AddChild(collection, CancellationToken.None); + parentFolder.AddChild(collection); if (options.ItemIdList.Count > 0) { diff --git a/Emby.Server.Implementations/Playlists/PlaylistManager.cs b/Emby.Server.Implementations/Playlists/PlaylistManager.cs index 9a1ca99467..8cafde38ee 100644 --- a/Emby.Server.Implementations/Playlists/PlaylistManager.cs +++ b/Emby.Server.Implementations/Playlists/PlaylistManager.cs @@ -147,7 +147,7 @@ namespace Emby.Server.Implementations.Playlists playlist.SetMediaType(options.MediaType); - parentFolder.AddChild(playlist, CancellationToken.None); + parentFolder.AddChild(playlist); await playlist.RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(_fileSystem)) { ForceSave = true }, CancellationToken.None) .ConfigureAwait(false); diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index 62283d038d..fc1e4dced6 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -1496,7 +1496,7 @@ namespace Jellyfin.Api.Controllers args += " -ar " + state.OutputAudioSampleRate.Value.ToString(CultureInfo.InvariantCulture); } - args += _encodingHelper.GetAudioFilterParam(state, _encodingOptions, true); + args += _encodingHelper.GetAudioFilterParam(state, _encodingOptions); return args; } diff --git a/Jellyfin.Api/Controllers/VideoHlsController.cs b/Jellyfin.Api/Controllers/VideoHlsController.cs index 6a720b1a45..4e7bb695af 100644 --- a/Jellyfin.Api/Controllers/VideoHlsController.cs +++ b/Jellyfin.Api/Controllers/VideoHlsController.cs @@ -485,7 +485,7 @@ namespace Jellyfin.Api.Controllers args += " -ar " + state.OutputAudioSampleRate.Value.ToString(CultureInfo.InvariantCulture); } - args += _encodingHelper.GetAudioFilterParam(state, _encodingOptions, true); + args += _encodingHelper.GetAudioFilterParam(state, _encodingOptions); return args; } diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 5417474221..6587eefab7 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -206,9 +206,8 @@ namespace MediaBrowser.Controller.Entities /// Adds the child. /// /// The item. - /// The cancellation token. /// Unable to add + item.Name. - public void AddChild(BaseItem item, CancellationToken cancellationToken) + public void AddChild(BaseItem item) { item.SetParent(this); @@ -1385,18 +1384,6 @@ namespace MediaBrowser.Controller.Entities } } - /// - /// Gets allowed recursive children of an item. - /// - /// The user. - /// if set to true [include linked children]. - /// IEnumerable{BaseItem}. - /// - public IEnumerable GetRecursiveChildren(User user, bool includeLinkedChildren = true) - { - return GetRecursiveChildren(user, null); - } - public virtual IEnumerable GetRecursiveChildren(User user, InternalItemsQuery query) { if (user == null) diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index add734f626..266fda767d 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -65,7 +65,7 @@ namespace MediaBrowser.Controller.Entities switch (viewType) { case CollectionType.Folders: - return GetResult(_libraryManager.GetUserRootFolder().GetChildren(user, true), queryParent, query); + return GetResult(_libraryManager.GetUserRootFolder().GetChildren(user, true), query); case CollectionType.TvShows: return GetTvView(queryParent, user, query); @@ -110,7 +110,7 @@ namespace MediaBrowser.Controller.Entities return GetMovieMovies(queryParent, user, query); case SpecialFolder.MovieCollections: - return GetMovieCollections(queryParent, user, query); + return GetMovieCollections(user, query); case SpecialFolder.TvFavoriteEpisodes: return GetFavoriteEpisodes(queryParent, user, query); @@ -122,7 +122,7 @@ namespace MediaBrowser.Controller.Entities { if (queryParent is UserView) { - return GetResult(GetMediaFolders(user).OfType().SelectMany(i => i.GetChildren(user, true)), queryParent, query); + return GetResult(GetMediaFolders(user).OfType().SelectMany(i => i.GetChildren(user, true)), query); } return queryParent.GetItems(query); @@ -160,7 +160,7 @@ namespace MediaBrowser.Controller.Entities GetUserView(SpecialFolder.MovieGenres, "Genres", "5", parent) }; - return GetResult(list, parent, query); + return GetResult(list, query); } private QueryResult GetFavoriteMovies(Folder parent, User user, InternalItemsQuery query) @@ -207,7 +207,7 @@ namespace MediaBrowser.Controller.Entities return _libraryManager.GetItemsResult(query); } - private QueryResult GetMovieCollections(Folder parent, User user, InternalItemsQuery query) + private QueryResult GetMovieCollections(User user, InternalItemsQuery query) { query.Parent = null; query.IncludeItemTypes = new[] { nameof(BoxSet) }; @@ -275,9 +275,9 @@ namespace MediaBrowser.Controller.Entities } }) .Where(i => i != null) - .Select(i => GetUserViewWithName(i.Name, SpecialFolder.MovieGenre, i.SortName, parent)); + .Select(i => GetUserViewWithName(SpecialFolder.MovieGenre, i.SortName, parent)); - return GetResult(genres, parent, query); + return GetResult(genres, query); } private QueryResult GetMovieGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query) @@ -323,7 +323,7 @@ namespace MediaBrowser.Controller.Entities GetUserView(SpecialFolder.TvGenres, "Genres", "6", parent) }; - return GetResult(list, parent, query); + return GetResult(list, query); } private QueryResult GetTvLatest(Folder parent, User user, InternalItemsQuery query) @@ -403,9 +403,9 @@ namespace MediaBrowser.Controller.Entities } }) .Where(i => i != null) - .Select(i => GetUserViewWithName(i.Name, SpecialFolder.TvGenre, i.SortName, parent)); + .Select(i => GetUserViewWithName(SpecialFolder.TvGenre, i.SortName, parent)); - return GetResult(genres, parent, query); + return GetResult(genres, query); } private QueryResult GetTvGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query) @@ -432,13 +432,12 @@ namespace MediaBrowser.Controller.Entities private QueryResult GetResult( IEnumerable items, - BaseItem queryParent, InternalItemsQuery query) where T : BaseItem { items = items.Where(i => Filter(i, query.User, query, _userDataManager, _libraryManager)); - return PostFilterAndSort(items, queryParent, null, query, _libraryManager, _config); + return PostFilterAndSort(items, null, query, _libraryManager); } public static bool FilterItem(BaseItem item, InternalItemsQuery query) @@ -448,11 +447,9 @@ namespace MediaBrowser.Controller.Entities public static QueryResult PostFilterAndSort( IEnumerable items, - BaseItem queryParent, int? totalRecordLimit, InternalItemsQuery query, - ILibraryManager libraryManager, - IServerConfigurationManager configurationManager) + ILibraryManager libraryManager) { var user = query.User; @@ -1001,7 +998,7 @@ namespace MediaBrowser.Controller.Entities return new BaseItem[] { parent }; } - private UserView GetUserViewWithName(string name, string type, string sortName, BaseItem parent) + private UserView GetUserViewWithName(string type, string sortName, BaseItem parent) { return _userViewManager.GetUserSubView(parent.Id, parent.Id.ToString("N", CultureInfo.InvariantCulture), type, sortName); } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs index 1a893fc2d0..ecd3d10d98 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs @@ -82,7 +82,7 @@ namespace MediaBrowser.Controller.LiveTv return "TvChannel"; } - public IEnumerable GetTaggedItems(IEnumerable inputItems) + public IEnumerable GetTaggedItems() { return new List(); } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 26b0bc3def..cb15fae5cb 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -1692,7 +1692,7 @@ namespace MediaBrowser.Controller.MediaEncoding return 128000; } - public string GetAudioFilterParam(EncodingJobInfo state, EncodingOptions encodingOptions, bool isHls) + public string GetAudioFilterParam(EncodingJobInfo state, EncodingOptions encodingOptions) { var channels = state.OutputAudioChannels; @@ -3836,7 +3836,7 @@ namespace MediaBrowser.Controller.MediaEncoding args += " -ar " + state.OutputAudioSampleRate.Value.ToString(_usCulture); } - args += GetAudioFilterParam(state, encodingOptions, false); + args += GetAudioFilterParam(state, encodingOptions); return args; } diff --git a/MediaBrowser.Providers/TV/SeriesMetadataService.cs b/MediaBrowser.Providers/TV/SeriesMetadataService.cs index 9679081975..dcb6934086 100644 --- a/MediaBrowser.Providers/TV/SeriesMetadataService.cs +++ b/MediaBrowser.Providers/TV/SeriesMetadataService.cs @@ -187,7 +187,7 @@ namespace MediaBrowser.Providers.TV SeriesName = series.Name }; - series.AddChild(season, cancellationToken); + series.AddChild(season); await season.RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(FileSystem)), cancellationToken).ConfigureAwait(false); From 6957bc9a12caefbf091b816f77f7b1f73c456e65 Mon Sep 17 00:00:00 2001 From: natedawg Date: Sat, 10 Jul 2021 16:26:42 -0700 Subject: [PATCH 026/120] Fix spelling of artist K/DA in splitting whitelist --- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index feefd5348a..c9ad3c41eb 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -47,7 +47,7 @@ namespace MediaBrowser.MediaEncoding.Probing "LOONA 1/3", "LOONA / yyxy", "LOONA / ODD EYE CIRCLE", - "KD/A" + "K/DA" }; public MediaInfo GetMediaInfo(InternalMediaInfoResult data, VideoType? videoType, bool isAudio, string path, MediaProtocol protocol) From c6bac310427fed99b2e798cb785935c6f9f09b81 Mon Sep 17 00:00:00 2001 From: Brandon Nguyen Date: Sun, 11 Jul 2021 11:59:03 -0700 Subject: [PATCH 027/120] Add int values to HardwareEncodingType enum --- .../Session/HardwareEncodingType.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/MediaBrowser.Model/Session/HardwareEncodingType.cs b/MediaBrowser.Model/Session/HardwareEncodingType.cs index 11721f0907..0e172f35f3 100644 --- a/MediaBrowser.Model/Session/HardwareEncodingType.cs +++ b/MediaBrowser.Model/Session/HardwareEncodingType.cs @@ -8,41 +8,41 @@ /// /// AMD AMF /// - AMF, + AMF = 0, /// /// Intel Quick Sync Video /// - QSV, + QSV = 1, /// /// NVIDIA NVENC /// - NVENC, + NVENC = 2, /// /// OpenMax OMX /// - OMX, + OMX = 3, /// /// Exynos V4L2 MFC /// - V4L2M2M, + V4L2M2M = 4, /// /// MediaCodec Android /// - MediaCodec, + MediaCodec = 5, /// /// Video Acceleration API (VAAPI) /// - VAAPI, + VAAPI = 6, /// /// Video ToolBox /// - VideoToolBox + VideoToolBox = 7 } } From 8b1a211081d2f6847b34fdaef3e990058e0699a9 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 11 Jul 2021 22:06:01 +0200 Subject: [PATCH 028/120] MediaInfoControllerTests: Check Content-Length --- .../Controllers/MediaInfoControllerTests.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaInfoControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaInfoControllerTests.cs index abf03d6584..34d26680ad 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaInfoControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaInfoControllerTests.cs @@ -26,6 +26,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Application.Octet, response.Content.Headers.ContentType?.MediaType); + Assert.NotNull(response.Content.Headers.ContentLength); } [Theory] @@ -39,6 +40,8 @@ namespace Jellyfin.Server.Integration.Tests.Controllers Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Application.Octet, response.Content.Headers.ContentType?.MediaType); + Assert.NotNull(response.Content.Headers.ContentLength); + Assert.InRange(response.Content.Headers.ContentLength!.Value, size, long.MaxValue); } [Theory] From b91c4be74c7181319f45b9f1b2f157d4952f4f0d Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 11 Jul 2021 22:36:50 +0200 Subject: [PATCH 029/120] Remove old "has update available" code This is the job of a package manager (or maybe the tray app for windows) --- Emby.Notifications/NotificationEntryPoint.cs | 21 ------------------- .../ApplicationHost.cs | 21 ------------------- .../IServerApplicationHost.cs | 8 ------- MediaBrowser.Model/System/SystemInfo.cs | 1 + 4 files changed, 1 insertion(+), 50 deletions(-) diff --git a/Emby.Notifications/NotificationEntryPoint.cs b/Emby.Notifications/NotificationEntryPoint.cs index 7433d3c8ae..e8ae14ff22 100644 --- a/Emby.Notifications/NotificationEntryPoint.cs +++ b/Emby.Notifications/NotificationEntryPoint.cs @@ -77,7 +77,6 @@ namespace Emby.Notifications { _libraryManager.ItemAdded += OnLibraryManagerItemAdded; _appHost.HasPendingRestartChanged += OnAppHostHasPendingRestartChanged; - _appHost.HasUpdateAvailableChanged += OnAppHostHasUpdateAvailableChanged; _activityManager.EntryCreated += OnActivityManagerEntryCreated; return Task.CompletedTask; @@ -132,25 +131,6 @@ namespace Emby.Notifications return _config.GetConfiguration("notifications"); } - private async void OnAppHostHasUpdateAvailableChanged(object? sender, EventArgs e) - { - if (!_appHost.HasUpdateAvailable) - { - return; - } - - var type = NotificationType.ApplicationUpdateAvailable.ToString(); - - var notification = new NotificationRequest - { - Description = "Please see jellyfin.org for details.", - NotificationType = type, - Name = _localization.GetLocalizedString("NewVersionIsAvailable") - }; - - await SendNotification(notification, null).ConfigureAwait(false); - } - private void OnLibraryManagerItemAdded(object? sender, ItemChangeEventArgs e) { if (!FilterItem(e.Item)) @@ -325,7 +305,6 @@ namespace Emby.Notifications _libraryManager.ItemAdded -= OnLibraryManagerItemAdded; _appHost.HasPendingRestartChanged -= OnAppHostHasPendingRestartChanged; - _appHost.HasUpdateAvailableChanged -= OnAppHostHasUpdateAvailableChanged; _activityManager.EntryCreated -= OnActivityManagerEntryCreated; _disposed = true; diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 82995deb30..7ad7a27322 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1102,7 +1102,6 @@ namespace Emby.Server.Implementations OperatingSystemDisplayName = OperatingSystem.Name, CanSelfRestart = CanSelfRestart, CanLaunchWebBrowser = CanLaunchWebBrowser, - HasUpdateAvailable = HasUpdateAvailable, TranscodingTempPath = ConfigurationManager.GetTranscodePath(), ServerName = FriendlyName, LocalAddress = GetSmartApiUrl(source), @@ -1252,26 +1251,6 @@ namespace Emby.Server.Implementations protected abstract void ShutdownInternal(); - public event EventHandler HasUpdateAvailableChanged; - - private bool _hasUpdateAvailable; - - public bool HasUpdateAvailable - { - get => _hasUpdateAvailable; - set - { - var fireEvent = value && !_hasUpdateAvailable; - - _hasUpdateAvailable = value; - - if (fireEvent) - { - HasUpdateAvailableChanged?.Invoke(this, EventArgs.Empty); - } - } - } - public IEnumerable GetApiPluginAssemblies() { var assemblies = _allConcreteTypes diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index 0949238426..753c18bc7e 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -16,8 +16,6 @@ namespace MediaBrowser.Controller /// public interface IServerApplicationHost : IApplicationHost { - event EventHandler HasUpdateAvailableChanged; - bool CoreStartupHasCompleted { get; } bool CanLaunchWebBrowser { get; } @@ -39,12 +37,6 @@ namespace MediaBrowser.Controller /// bool ListenWithHttps { get; } - /// - /// Gets a value indicating whether this instance has update available. - /// - /// true if this instance has update available; otherwise, false. - bool HasUpdateAvailable { get; } - /// /// Gets the name of the friendly. /// diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs index d75ae91c02..e45b2f33a6 100644 --- a/MediaBrowser.Model/System/SystemInfo.cs +++ b/MediaBrowser.Model/System/SystemInfo.cs @@ -130,6 +130,7 @@ namespace MediaBrowser.Model.System /// Gets or sets a value indicating whether this instance has update available. /// /// true if this instance has update available; otherwise, false. + [Obsolete("This should be handled by the package manager")] public bool HasUpdateAvailable { get; set; } public FFmpegLocation EncoderLocation { get; set; } From 915141f196d6ec20f3f0a398d9b328f25ae71241 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 11 Jul 2021 22:32:06 +0200 Subject: [PATCH 030/120] Fix some warnings --- .../ApplicationHost.cs | 12 +-- .../Library/LibraryManager.cs | 5 +- .../Tasks/CleanActivityLogTask.cs | 2 +- MediaBrowser.Common/Net/IPHost.cs | 13 +-- MediaBrowser.Controller/Entities/BaseItem.cs | 16 +--- MediaBrowser.Controller/Entities/UserView.cs | 85 ++++++++++--------- .../FFprobeParserTests.cs | 5 +- 7 files changed, 62 insertions(+), 76 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 82995deb30..b73b6bb004 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1118,7 +1118,7 @@ namespace Emby.Server.Implementations .Select(i => new WakeOnLanInfo(i)) .ToList(); - public PublicSystemInfo GetPublicSystemInfo(IPAddress source) + public PublicSystemInfo GetPublicSystemInfo(IPAddress address) { return new PublicSystemInfo { @@ -1127,7 +1127,7 @@ namespace Emby.Server.Implementations Id = SystemId, OperatingSystem = OperatingSystem.Id.ToString(), ServerName = FriendlyName, - LocalAddress = GetSmartApiUrl(source), + LocalAddress = GetSmartApiUrl(address), StartupWizardCompleted = ConfigurationManager.CommonConfiguration.IsStartupWizardCompleted }; } @@ -1136,7 +1136,7 @@ namespace Emby.Server.Implementations public bool ListenWithHttps => Certificate != null && ConfigurationManager.GetNetworkConfiguration().EnableHttps; /// - public string GetSmartApiUrl(IPAddress ipAddress, int? port = null) + public string GetSmartApiUrl(IPAddress remoteAddr, int? port = null) { // Published server ends with a / if (!string.IsNullOrEmpty(PublishedServerUrl)) @@ -1145,7 +1145,7 @@ namespace Emby.Server.Implementations return PublishedServerUrl.Trim('/'); } - string smart = NetManager.GetBindInterface(ipAddress, out port); + string smart = NetManager.GetBindInterface(remoteAddr, out port); // If the smartAPI doesn't start with http then treat it as a host or ip. if (smart.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { @@ -1208,14 +1208,14 @@ namespace Emby.Server.Implementations } /// - public string GetLocalApiUrl(string host, string scheme = null, int? port = null) + public string GetLocalApiUrl(string hostname, string scheme = null, int? port = null) { // NOTE: If no BaseUrl is set then UriBuilder appends a trailing slash, but if there is no BaseUrl it does // not. For consistency, always trim the trailing slash. return new UriBuilder { Scheme = scheme ?? (ListenWithHttps ? Uri.UriSchemeHttps : Uri.UriSchemeHttp), - Host = host, + Host = hostname, Port = port ?? (ListenWithHttps ? HttpsPort : HttpPort), Path = ConfigurationManager.GetNetworkConfiguration().BaseUrl }.ToString().TrimEnd('/'); diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index d806373329..13fb8b2fd5 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2540,9 +2540,10 @@ namespace Emby.Server.Implementations.Library { episodeInfo = resolver.Resolve(episode.Path, isFolder, null, null, isAbsoluteNaming); // Resolve from parent folder if it's not the Season folder - if (episodeInfo == null && episode.Parent.GetType() == typeof(Folder)) + var parent = episode.GetParent(); + if (episodeInfo == null && parent.GetType() == typeof(Folder)) { - episodeInfo = resolver.Resolve(episode.Parent.Path, true, null, null, isAbsoluteNaming); + episodeInfo = resolver.Resolve(parent.Path, true, null, null, isAbsoluteNaming); if (episodeInfo != null) { // add the container diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs index 50ba9bc899..19600b1e64 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs @@ -65,7 +65,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks throw new Exception($"Activity Log Retention days must be at least 0. Currently: {retentionDays}"); } - var startDate = DateTime.UtcNow.AddDays(retentionDays.Value * -1); + var startDate = DateTime.UtcNow.AddDays(-retentionDays.Value); return _activityManager.CleanAsync(startDate); } diff --git a/MediaBrowser.Common/Net/IPHost.cs b/MediaBrowser.Common/Net/IPHost.cs index 5db8817ee6..d78d7def2b 100644 --- a/MediaBrowser.Common/Net/IPHost.cs +++ b/MediaBrowser.Common/Net/IPHost.cs @@ -79,16 +79,11 @@ namespace MediaBrowser.Common.Net /// public override byte PrefixLength { - get - { - return (byte)(ResolveHost() ? 128 : 32); - } + get => (byte)(ResolveHost() ? 128 : 32); - set - { - // Not implemented, as a host object can only have a prefix length of 128 (IPv6) or 32 (IPv4) prefix length, - // which is automatically determined by it's IP type. Anything else is meaningless. - } + // Not implemented, as a host object can only have a prefix length of 128 (IPv6) or 32 (IPv4) prefix length, + // which is automatically determined by it's IP type. Anything else is meaningless. + set => throw new NotImplementedException(); } /// diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index e5be5421a2..23b97f70c6 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -771,19 +771,6 @@ namespace MediaBrowser.Controller.Entities [JsonIgnore] public Guid ParentId { get; set; } - /// - /// Gets or sets the parent. - /// - /// The parent. - [JsonIgnore] - public Folder Parent - { - get => GetParent() as Folder; - set - { - } - } - public void SetParent(Folder parent) { ParentId = parent == null ? Guid.Empty : parent.Id; @@ -822,8 +809,7 @@ namespace MediaBrowser.Controller.Entities { foreach (var parent in GetParents()) { - var item = parent as T; - if (item != null) + if (parent is T item) { return item; } diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs index 57dc9b59ba..62f3c4b557 100644 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ b/MediaBrowser.Controller/Entities/UserView.cs @@ -15,6 +15,25 @@ namespace MediaBrowser.Controller.Entities { public class UserView : Folder, IHasCollectionType { + private static readonly string[] _viewTypesEligibleForGrouping = new string[] + { + Model.Entities.CollectionType.Movies, + Model.Entities.CollectionType.TvShows, + string.Empty + }; + + private static readonly string[] _originalFolderViewTypes = new string[] + { + Model.Entities.CollectionType.Books, + Model.Entities.CollectionType.MusicVideos, + Model.Entities.CollectionType.HomeVideos, + Model.Entities.CollectionType.Photos, + Model.Entities.CollectionType.Music, + Model.Entities.CollectionType.BoxSets + }; + + public static ITVSeriesManager TVSeriesManager { get; set; } + /// /// Gets or sets the view type. /// @@ -30,12 +49,22 @@ namespace MediaBrowser.Controller.Entities /// public Guid? UserId { get; set; } - public static ITVSeriesManager TVSeriesManager; - /// [JsonIgnore] public string CollectionType => ViewType; + /// + [JsonIgnore] + public override bool SupportsInheritedParentImages => false; + + /// + [JsonIgnore] + public override bool SupportsPlayedStatus => false; + + /// + [JsonIgnore] + public override bool SupportsPeople => false; + /// public override IEnumerable GetIdsForAncestorQuery() { @@ -53,17 +82,13 @@ namespace MediaBrowser.Controller.Entities } } - [JsonIgnore] - public override bool SupportsInheritedParentImages => false; - - [JsonIgnore] - public override bool SupportsPlayedStatus => false; - + /// public override int GetChildCount(User user) { return GetChildren(user, true).Count; } + /// protected override QueryResult GetItemsInternal(InternalItemsQuery query) { var parent = this as Folder; @@ -81,6 +106,7 @@ namespace MediaBrowser.Controller.Entities .GetUserItems(parent, this, CollectionType, query); } + /// public override List GetChildren(User user, bool includeLinkedChildren, InternalItemsQuery query) { query ??= new InternalItemsQuery(user); @@ -91,16 +117,19 @@ namespace MediaBrowser.Controller.Entities return result.ToList(); } + /// public override bool CanDelete() { return false; } + /// public override bool IsSaveLocalMetadataEnabled() { return true; } + /// public override IEnumerable GetRecursiveChildren(User user, InternalItemsQuery query) { query.SetUser(user); @@ -111,32 +140,26 @@ namespace MediaBrowser.Controller.Entities return GetItemList(query); } + /// protected override IEnumerable GetEligibleChildrenForRecursiveChildren(User user) { return GetChildren(user, false); } - private static readonly string[] UserSpecificViewTypes = new string[] - { - Model.Entities.CollectionType.Playlists - }; - public static bool IsUserSpecific(Folder folder) { - var collectionFolder = folder as ICollectionFolder; - - if (collectionFolder == null) + if (folder is not ICollectionFolder collectionFolder) { return false; } - var supportsUserSpecific = folder as ISupportsUserSpecificView; - if (supportsUserSpecific != null && supportsUserSpecific.EnableUserSpecificView) + if (folder is ISupportsUserSpecificView supportsUserSpecific + && supportsUserSpecific.EnableUserSpecificView) { return true; } - return UserSpecificViewTypes.Contains(collectionFolder.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase); + return string.Equals(Model.Entities.CollectionType.Playlists, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase); } public static bool IsEligibleForGrouping(Folder folder) @@ -145,39 +168,19 @@ namespace MediaBrowser.Controller.Entities && IsEligibleForGrouping(collectionFolder.CollectionType); } - private static string[] ViewTypesEligibleForGrouping = new string[] - { - Model.Entities.CollectionType.Movies, - Model.Entities.CollectionType.TvShows, - string.Empty - }; - public static bool IsEligibleForGrouping(string viewType) { - return ViewTypesEligibleForGrouping.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase); + return _viewTypesEligibleForGrouping.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase); } - private static string[] OriginalFolderViewTypes = new string[] - { - Model.Entities.CollectionType.Books, - Model.Entities.CollectionType.MusicVideos, - Model.Entities.CollectionType.HomeVideos, - Model.Entities.CollectionType.Photos, - Model.Entities.CollectionType.Music, - Model.Entities.CollectionType.BoxSets - }; - public static bool EnableOriginalFolder(string viewType) { - return OriginalFolderViewTypes.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase); + return _originalFolderViewTypes.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase); } protected override Task ValidateChildrenInternal(IProgress progress, bool recursive, bool refreshChildMetadata, Providers.MetadataRefreshOptions refreshOptions, Providers.IDirectoryService directoryService, System.Threading.CancellationToken cancellationToken) { return Task.CompletedTask; } - - [JsonIgnore] - public override bool SupportsPeople => false; } } diff --git a/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs index 45808375f1..2955104a27 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs @@ -14,9 +14,10 @@ namespace Jellyfin.MediaEncoding.Tests public async Task Test(string fileName) { var path = Path.Join("Test Data", fileName); - using (var stream = File.OpenRead(path)) + await using (var stream = File.OpenRead(path)) { - await JsonSerializer.DeserializeAsync(stream, JsonDefaults.Options).ConfigureAwait(false); + var res = await JsonSerializer.DeserializeAsync(stream, JsonDefaults.Options).ConfigureAwait(false); + Assert.NotNull(res); } } } From e757c58e86894b7115c6b6f72ed98e997b499e0a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Jul 2021 12:00:56 +0000 Subject: [PATCH 031/120] Bump prometheus-net from 4.1.1 to 4.2.0 Bumps [prometheus-net](https://github.com/prometheus-net/prometheus-net) from 4.1.1 to 4.2.0. - [Release notes](https://github.com/prometheus-net/prometheus-net/releases) - [Changelog](https://github.com/prometheus-net/prometheus-net/blob/master/History) - [Commits](https://github.com/prometheus-net/prometheus-net/compare/v4.1.1...v4.2.0) --- updated-dependencies: - dependency-name: prometheus-net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Jellyfin.Server/Jellyfin.Server.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 9a197e0371..6f29700b90 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -40,7 +40,7 @@ - + From 26f6c5520c9f412a6b4f59f9713bd02ab85eacc7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Jul 2021 12:00:57 +0000 Subject: [PATCH 032/120] Bump SkiaSharp from 2.80.2 to 2.80.3 Bumps SkiaSharp from 2.80.2 to 2.80.3. --- updated-dependencies: - dependency-name: SkiaSharp dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj index ee43c2159a..28e3ce55d1 100644 --- a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj +++ b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj @@ -22,7 +22,7 @@ - + From 8528e9bddb4c2dd9e1e3294649e39c7ec609bdf5 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Mon, 12 Jul 2021 20:20:50 +0200 Subject: [PATCH 033/120] Improve platform checks --- Emby.Dlna/Main/DlnaEntryPoint.cs | 13 ++++++++----- Emby.Server.Implementations/ApplicationHost.cs | 17 +++++------------ .../IO/ManagedFileSystem.cs | 7 +++---- .../Controllers/DynamicHlsController.cs | 2 +- Jellyfin.Api/Controllers/VideoHlsController.cs | 3 +-- Jellyfin.Api/Helpers/HlsHelpers.cs | 3 +-- Jellyfin.Server/Program.cs | 8 ++++---- .../MediaEncoding/EncodingHelper.cs | 17 ++++++++--------- .../IO/ManagedFileSystemTests.cs | 6 +++--- .../Location/MovieNfoLocationTests.cs | 8 ++++---- .../Parsers/MovieNfoParserTests.cs | 2 +- 11 files changed, 39 insertions(+), 47 deletions(-) diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs index 0309926abb..5d252d8dc4 100644 --- a/Emby.Dlna/Main/DlnaEntryPoint.cs +++ b/Emby.Dlna/Main/DlnaEntryPoint.cs @@ -27,11 +27,9 @@ using MediaBrowser.Controller.TV; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Net; -using MediaBrowser.Model.System; using Microsoft.Extensions.Logging; using Rssdp; using Rssdp.Infrastructure; -using OperatingSystem = MediaBrowser.Common.System.OperatingSystem; namespace Emby.Dlna.Main { @@ -204,8 +202,8 @@ namespace Emby.Dlna.Main { if (_communicationsServer == null) { - var enableMultiSocketBinding = OperatingSystem.Id == OperatingSystemId.Windows || - OperatingSystem.Id == OperatingSystemId.Linux; + var enableMultiSocketBinding = OperatingSystem.IsWindows() || + OperatingSystem.IsLinux(); _communicationsServer = new SsdpCommunicationsServer(_socketFactory, _networkManager, _logger, enableMultiSocketBinding) { @@ -268,7 +266,12 @@ namespace Emby.Dlna.Main try { - _publisher = new SsdpDevicePublisher(_communicationsServer, _networkManager, OperatingSystem.Name, Environment.OSVersion.VersionString, _config.GetDlnaConfiguration().SendOnlyMatchedHost) + _publisher = new SsdpDevicePublisher( + _communicationsServer, + _networkManager, + MediaBrowser.Common.System.OperatingSystem.Name, + Environment.OSVersion.VersionString, + _config.GetDlnaConfiguration().SendOnlyMatchedHost) { LogFunction = LogMessage, SupportPnpRootDevice = false diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 7ad7a27322..0523a3c522 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -103,7 +103,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Prometheus.DotNetRuntime; -using OperatingSystem = MediaBrowser.Common.System.OperatingSystem; using WebSocketManager = Emby.Server.Implementations.HttpServer.WebSocketManager; namespace Emby.Server.Implementations @@ -150,13 +149,7 @@ namespace Emby.Server.Implementations return false; } - if (OperatingSystem.Id == OperatingSystemId.Windows - || OperatingSystem.Id == OperatingSystemId.Darwin) - { - return true; - } - - return false; + return OperatingSystem.IsWindows() || OperatingSystem.IsMacOS(); } } @@ -721,7 +714,7 @@ namespace Emby.Server.Implementations logger.LogInformation("Environment Variables: {EnvVars}", relevantEnvVars); logger.LogInformation("Arguments: {Args}", commandLineArgs); - logger.LogInformation("Operating system: {OS}", OperatingSystem.Name); + logger.LogInformation("Operating system: {OS}", MediaBrowser.Common.System.OperatingSystem.Name); logger.LogInformation("Architecture: {Architecture}", RuntimeInformation.OSArchitecture); logger.LogInformation("64-Bit Process: {Is64Bit}", Environment.Is64BitProcess); logger.LogInformation("User Interactive: {IsUserInteractive}", Environment.UserInteractive); @@ -1098,8 +1091,8 @@ namespace Emby.Server.Implementations ItemsByNamePath = ApplicationPaths.InternalMetadataPath, InternalMetadataPath = ApplicationPaths.InternalMetadataPath, CachePath = ApplicationPaths.CachePath, - OperatingSystem = OperatingSystem.Id.ToString(), - OperatingSystemDisplayName = OperatingSystem.Name, + OperatingSystem = MediaBrowser.Common.System.OperatingSystem.Id.ToString(), + OperatingSystemDisplayName = MediaBrowser.Common.System.OperatingSystem.Name, CanSelfRestart = CanSelfRestart, CanLaunchWebBrowser = CanLaunchWebBrowser, TranscodingTempPath = ConfigurationManager.GetTranscodePath(), @@ -1124,7 +1117,7 @@ namespace Emby.Server.Implementations Version = ApplicationVersionString, ProductName = ApplicationProductName, Id = SystemId, - OperatingSystem = OperatingSystem.Id.ToString(), + OperatingSystem = MediaBrowser.Common.System.OperatingSystem.Id.ToString(), ServerName = FriendlyName, LocalAddress = GetSmartApiUrl(source), StartupWizardCompleted = ConfigurationManager.CommonConfiguration.IsStartupWizardCompleted diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index ca028a3ca2..7c3c7da230 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -11,7 +11,6 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Model.IO; using MediaBrowser.Model.System; using Microsoft.Extensions.Logging; -using OperatingSystem = MediaBrowser.Common.System.OperatingSystem; namespace Emby.Server.Implementations.IO { @@ -24,7 +23,7 @@ namespace Emby.Server.Implementations.IO private readonly List _shortcutHandlers = new List(); private readonly string _tempPath; - private static readonly bool _isEnvironmentCaseInsensitive = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + private static readonly bool _isEnvironmentCaseInsensitive = OperatingSystem.IsWindows(); public ManagedFileSystem( ILogger logger, @@ -402,7 +401,7 @@ namespace Emby.Server.Implementations.IO public virtual void SetHidden(string path, bool isHidden) { - if (OperatingSystem.Id != OperatingSystemId.Windows) + if (!OperatingSystem.IsWindows()) { return; } @@ -426,7 +425,7 @@ namespace Emby.Server.Implementations.IO public virtual void SetAttributes(string path, bool isHidden, bool isReadOnly) { - if (OperatingSystem.Id != OperatingSystemId.Windows) + if (!OperatingSystem.IsWindows()) { return; } diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index 62283d038d..dcf262e32a 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -1380,7 +1380,7 @@ namespace Jellyfin.Api.Controllers } else if (string.Equals(segmentFormat, "mp4", StringComparison.OrdinalIgnoreCase)) { - var outputFmp4HeaderArg = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) switch + var outputFmp4HeaderArg = OperatingSystem.IsWindows() switch { // on Windows, the path of fmp4 header file needs to be configured true => " -hls_fmp4_init_filename \"" + outputPrefix + "-1" + outputExtension + "\"", diff --git a/Jellyfin.Api/Controllers/VideoHlsController.cs b/Jellyfin.Api/Controllers/VideoHlsController.cs index 6a720b1a45..1e03298215 100644 --- a/Jellyfin.Api/Controllers/VideoHlsController.cs +++ b/Jellyfin.Api/Controllers/VideoHlsController.cs @@ -366,8 +366,7 @@ namespace Jellyfin.Api.Controllers else if (string.Equals(segmentFormat, "mp4", StringComparison.OrdinalIgnoreCase)) { var outputFmp4HeaderArg = string.Empty; - var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - if (isWindows) + if (OperatingSystem.IsWindows()) { // on Windows, the path of fmp4 header file needs to be configured outputFmp4HeaderArg = " -hls_fmp4_init_filename \"" + outputPrefix + "-1" + outputExtension + "\""; diff --git a/Jellyfin.Api/Helpers/HlsHelpers.cs b/Jellyfin.Api/Helpers/HlsHelpers.cs index d0666034e9..d1cdaf867e 100644 --- a/Jellyfin.Api/Helpers/HlsHelpers.cs +++ b/Jellyfin.Api/Helpers/HlsHelpers.cs @@ -99,8 +99,7 @@ namespace Jellyfin.Api.Helpers return fmp4InitFileName; } - var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - if (isWindows) + if (OperatingSystem.IsWindows()) { // on Windows // #EXT-X-MAP:URI="X:\transcodes\prefix-1.mp4" diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 3a3d7415bf..934372a94d 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -318,8 +318,8 @@ namespace Jellyfin.Server } } - // Bind to unix socket (only on macOS and Linux) - if (startupConfig.UseUnixSocket() && !RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + // Bind to unix socket (only on unix systems) + if (startupConfig.UseUnixSocket() && Environment.OSVersion.Platform == PlatformID.Unix) { var socketPath = startupConfig.GetUnixSocketPath(); if (string.IsNullOrEmpty(socketPath)) @@ -404,7 +404,7 @@ namespace Jellyfin.Server { if (options.DataDir != null || Directory.Exists(Path.Combine(dataDir, "config")) - || RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + || OperatingSystem.IsWindows()) { // Hang config folder off already set dataDir configDir = Path.Combine(dataDir, "config"); @@ -442,7 +442,7 @@ namespace Jellyfin.Server if (string.IsNullOrEmpty(cacheDir)) { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + if (OperatingSystem.IsWindows()) { // Hang cache folder off already set dataDir cacheDir = Path.Combine(dataDir, "cache"); diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 26b0bc3def..160d9d6912 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -143,8 +143,7 @@ namespace MediaBrowser.Controller.MediaEncoding } // Hybrid VPP tonemapping for QSV with VAAPI - var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); - if (isLinux && string.Equals(options.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) + if (OperatingSystem.IsLinux() && string.Equals(options.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) { // Limited to HEVC for now since the filter doesn't accept master data from VP9. return IsColorDepth10(state) @@ -503,9 +502,9 @@ namespace MediaBrowser.Controller.MediaEncoding var isQsvEncoder = outputVideoCodec.IndexOf("qsv", StringComparison.OrdinalIgnoreCase) != -1; var isNvdecDecoder = videoDecoder.Contains("cuda", StringComparison.OrdinalIgnoreCase); var isCuvidHevcDecoder = videoDecoder.Contains("hevc_cuvid", StringComparison.OrdinalIgnoreCase); - var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); - var isMacOS = RuntimeInformation.IsOSPlatform(OSPlatform.OSX); + var isWindows = OperatingSystem.IsWindows(); + var isLinux = OperatingSystem.IsLinux(); + var isMacOS = OperatingSystem.IsMacOS(); var isTonemappingSupported = IsTonemappingSupported(state, encodingOptions); var isVppTonemappingSupported = IsVppTonemappingSupported(state, encodingOptions); @@ -1983,7 +1982,7 @@ namespace MediaBrowser.Controller.MediaEncoding var videoSizeParam = string.Empty; var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, options) ?? string.Empty; - var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); + var isLinux = OperatingSystem.IsLinux(); var isVaapiDecoder = videoDecoder.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1; var isVaapiH264Encoder = outputVideoCodec.IndexOf("h264_vaapi", StringComparison.OrdinalIgnoreCase) != -1; @@ -2528,7 +2527,7 @@ namespace MediaBrowser.Controller.MediaEncoding var isCuvidHevcDecoder = videoDecoder.Contains("hevc_cuvid", StringComparison.OrdinalIgnoreCase); var isLibX264Encoder = outputVideoCodec.IndexOf("libx264", StringComparison.OrdinalIgnoreCase) != -1; var isLibX265Encoder = outputVideoCodec.IndexOf("libx265", StringComparison.OrdinalIgnoreCase) != -1; - var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); + var isLinux = OperatingSystem.IsLinux(); var isColorDepth10 = IsColorDepth10(state); var isTonemappingSupported = IsTonemappingSupported(state, options); var isVppTonemappingSupported = IsVppTonemappingSupported(state, options); @@ -3572,8 +3571,8 @@ namespace MediaBrowser.Controller.MediaEncoding /// public string GetHwaccelType(EncodingJobInfo state, EncodingOptions options, string videoCodec, bool isColorDepth10) { - var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); + var isWindows = OperatingSystem.IsWindows(); + var isLinux = OperatingSystem.IsLinux(); var isWindows8orLater = Environment.OSVersion.Version.Major > 6 || (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor > 1); var isDxvaSupported = _mediaEncoder.SupportsHwaccel("dxva2") || _mediaEncoder.SupportsHwaccel("d3d11va"); var isCodecAvailable = options.HardwareDecodingCodecs.Contains(videoCodec, StringComparer.OrdinalIgnoreCase); diff --git a/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs b/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs index 30e6542f94..d991f55748 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs @@ -1,10 +1,10 @@ +using System; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Runtime.InteropServices; using AutoFixture; using AutoFixture.AutoMoq; using Emby.Server.Implementations.IO; -using MediaBrowser.Model.System; using Xunit; namespace Jellyfin.Server.Implementations.Tests.IO @@ -31,7 +31,7 @@ namespace Jellyfin.Server.Implementations.Tests.IO { var generatedPath = _sut.MakeAbsolutePath(folderPath, filePath); - if (MediaBrowser.Common.System.OperatingSystem.Id == OperatingSystemId.Windows) + if (OperatingSystem.IsWindows()) { var expectedWindowsPath = expectedAbsolutePath.Replace('/', '\\'); Assert.Equal(expectedWindowsPath, generatedPath.Split(':')[1]); @@ -55,7 +55,7 @@ namespace Jellyfin.Server.Implementations.Tests.IO [SkippableFact] public void GetFileInfo_DanglingSymlink_ExistsFalse() { - Skip.If(RuntimeInformation.IsOSPlatform(OSPlatform.Windows)); + Skip.If(OperatingSystem.IsWindows()); string testFileDir = Path.Combine(Path.GetTempPath(), "jellyfin-test-data"); string testFileName = Path.Combine(testFileDir, Path.GetRandomFileName() + "-danglingsym.link"); diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Location/MovieNfoLocationTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Location/MovieNfoLocationTests.cs index 357d61c0bc..8019e0ab39 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Location/MovieNfoLocationTests.cs +++ b/tests/Jellyfin.XbmcMetadata.Tests/Location/MovieNfoLocationTests.cs @@ -1,8 +1,8 @@ -using System.Linq; +using System; +using System.Linq; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.System; using MediaBrowser.XbmcMetadata.Savers; using Xunit; @@ -28,7 +28,7 @@ namespace Jellyfin.XbmcMetadata.Tests.Location var path2 = "/media/movies/Avengers Endgame/movie.nfo"; // uses ContainingFolderPath which uses Operating system specific paths - if (MediaBrowser.Common.System.OperatingSystem.Id == OperatingSystemId.Windows) + if (OperatingSystem.IsWindows()) { movie.Path = movie.Path.Replace('/', '\\'); path1 = path1.Replace('/', '\\'); @@ -49,7 +49,7 @@ namespace Jellyfin.XbmcMetadata.Tests.Location var path2 = "/media/movies/Avengers Endgame/VIDEO_TS/VIDEO_TS.nfo"; // uses ContainingFolderPath which uses Operating system specific paths - if (MediaBrowser.Common.System.OperatingSystem.Id == OperatingSystemId.Windows) + if (OperatingSystem.IsWindows()) { movie.Path = movie.Path.Replace('/', '\\'); path1 = path1.Replace('/', '\\'); diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs index 30a48857a4..cbcce73eb6 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs +++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs @@ -59,7 +59,7 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers _localImageFileMetadata = new FileSystemMetadata() { Exists = true, - FullName = MediaBrowser.Common.System.OperatingSystem.Id == OperatingSystemId.Windows ? + FullName = OperatingSystem.IsWindows() ? "C:\\media\\movies\\Justice League (2017).jpg" : "/media/movies/Justice League (2017).jpg" }; From 903628af76d618801e8439335e66e5d23664e39e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Jul 2021 21:54:28 +0000 Subject: [PATCH 034/120] Bump SkiaSharp.NativeAssets.Linux from 2.80.2 to 2.80.3 Bumps SkiaSharp.NativeAssets.Linux from 2.80.2 to 2.80.3. --- updated-dependencies: - dependency-name: SkiaSharp.NativeAssets.Linux dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj index 28e3ce55d1..96fe003848 100644 --- a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj +++ b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj @@ -23,7 +23,7 @@ - + From 00b1f96ed0dfbc166476dbb7ed978b47cccafb2c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Jul 2021 21:54:28 +0000 Subject: [PATCH 035/120] Bump prometheus-net.AspNetCore from 4.1.1 to 4.2.0 Bumps [prometheus-net.AspNetCore](https://github.com/prometheus-net/prometheus-net) from 4.1.1 to 4.2.0. - [Release notes](https://github.com/prometheus-net/prometheus-net/releases) - [Changelog](https://github.com/prometheus-net/prometheus-net/blob/master/History) - [Commits](https://github.com/prometheus-net/prometheus-net/compare/v4.1.1...v4.2.0) --- updated-dependencies: - dependency-name: prometheus-net.AspNetCore dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Jellyfin.Server/Jellyfin.Server.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 6f29700b90..71ee94a3f1 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -41,7 +41,7 @@ - + From 24c861c23b6169ce0e945e3dd0c4a36b6a62ebe5 Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Mon, 12 Jul 2021 17:20:07 -0600 Subject: [PATCH 036/120] Remove extra endpoint --- .../Controllers/InstantMixController.cs | 54 ++++--------------- 1 file changed, 9 insertions(+), 45 deletions(-) diff --git a/Jellyfin.Api/Controllers/InstantMixController.cs b/Jellyfin.Api/Controllers/InstantMixController.cs index f232dffaa5..a283ffc577 100644 --- a/Jellyfin.Api/Controllers/InstantMixController.cs +++ b/Jellyfin.Api/Controllers/InstantMixController.cs @@ -228,42 +228,6 @@ namespace Jellyfin.Api.Controllers return GetResult(items, user, limit, dtoOptions); } - /// - /// Creates an instant playlist based on a given genre. - /// - /// The item id. - /// Optional. Filter by user id, and attach user data. - /// Optional. The maximum number of records to return. - /// Optional. Specify additional fields of information to return in the output. - /// Optional. Include image information in output. - /// Optional. Include user data. - /// Optional. The max number of images to return, per image type. - /// Optional. The image types to include in the output. - /// Instant playlist returned. - /// A with the playlist items. - [HttpGet("MusicGenres/{id}/InstantMix")] - [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult> GetInstantMixFromMusicGenreById( - [FromRoute, Required] Guid id, - [FromQuery] Guid? userId, - [FromQuery] int? limit, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, - [FromQuery] bool? enableImages, - [FromQuery] bool? enableUserData, - [FromQuery] int? imageTypeLimit, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes) - { - var item = _libraryManager.GetItemById(id); - var user = userId.HasValue && !userId.Equals(Guid.Empty) - ? _userManager.GetUserById(userId.Value) - : null; - var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) - .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!); - var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions); - return GetResult(items, user, limit, dtoOptions); - } - /// /// Creates an instant playlist based on a given item. /// @@ -363,15 +327,15 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? imageTypeLimit, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes) { - return GetInstantMixFromMusicGenreById( - id, - userId, - limit, - fields, - enableImages, - enableUserData, - imageTypeLimit, - enableImageTypes); + var item = _libraryManager.GetItemById(id); + var user = userId.HasValue && !userId.Equals(Guid.Empty) + ? _userManager.GetUserById(userId.Value) + : null; + var dtoOptions = new DtoOptions { Fields = fields } + .AddClientFields(Request) + .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!); + var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions); + return GetResult(items, user, limit, dtoOptions); } private QueryResult GetResult(List items, User? user, int? limit, DtoOptions dtoOptions) From 927ec5a363a1a40706a5686db4b4819b8beafdd7 Mon Sep 17 00:00:00 2001 From: hoanghuy309 Date: Sat, 10 Jul 2021 14:57:02 +0000 Subject: [PATCH 037/120] Translated using Weblate (Vietnamese) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/vi/ --- Emby.Server.Implementations/Localization/Core/vi.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/vi.json b/Emby.Server.Implementations/Localization/Core/vi.json index 58652c4693..20ab1dd7db 100644 --- a/Emby.Server.Implementations/Localization/Core/vi.json +++ b/Emby.Server.Implementations/Localization/Core/vi.json @@ -117,5 +117,7 @@ "TaskCleanActivityLog": "Xóa Nhật Ký Hoạt Động", "Undefined": "Không Xác Định", "Forced": "Bắt Buộc", - "Default": "Mặc Định" + "Default": "Mặc Định", + "TaskOptimizeDatabaseDescription": "Thu gọn cơ sở dữ liệu và cắt bớt dung lượng trống. Chạy tác vụ này sau khi quét thư viện hoặc thực hiện các thay đổi khác ngụ ý sửa đổi cơ sở dữ liệu có thể cải thiện hiệu suất.", + "TaskOptimizeDatabase": "Tối ưu hóa cơ sở dữ liệu" } From 31c65058a4a6d1746944e00165e13a06dc9992b5 Mon Sep 17 00:00:00 2001 From: Moritz Date: Mon, 12 Jul 2021 08:18:08 +0000 Subject: [PATCH 038/120] Translated using Weblate (German) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/de/ --- Emby.Server.Implementations/Localization/Core/de.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/de.json b/Emby.Server.Implementations/Localization/Core/de.json index f775ec1188..c924e5c150 100644 --- a/Emby.Server.Implementations/Localization/Core/de.json +++ b/Emby.Server.Implementations/Localization/Core/de.json @@ -118,5 +118,7 @@ "TaskCleanActivityLog": "Aktivitätsprotokoll aufräumen", "Undefined": "Undefiniert", "Forced": "Erzwungen", - "Default": "Standard" + "Default": "Standard", + "TaskOptimizeDatabaseDescription": "Komprimiert die Datenbank und trimmt den freien Speicherplatz. Die Ausführung dieser Aufgabe nach dem Scannen der Bibliothek oder nach anderen Änderungen, die Datenbankänderungen implizieren, kann die Leistung verbessern.", + "TaskOptimizeDatabase": "Datenbank optimieren" } From 502c6568745263606a2c946a638d2b72e7ebf595 Mon Sep 17 00:00:00 2001 From: Oatavandi Date: Sun, 11 Jul 2021 16:41:23 +0000 Subject: [PATCH 039/120] Translated using Weblate (Tamil) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ta/ --- Emby.Server.Implementations/Localization/Core/ta.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/ta.json b/Emby.Server.Implementations/Localization/Core/ta.json index 129986ed0e..d6e9aa8e5a 100644 --- a/Emby.Server.Implementations/Localization/Core/ta.json +++ b/Emby.Server.Implementations/Localization/Core/ta.json @@ -117,5 +117,7 @@ "TaskCleanActivityLog": "செயல்பாட்டு பதிவை அழி", "Undefined": "வரையறுக்கப்படாத", "Forced": "கட்டாயப்படுத்தப்பட்டது", - "Default": "இயல்புநிலை" + "Default": "இயல்புநிலை", + "TaskOptimizeDatabaseDescription": "தரவுத்தளத்தை சுருக்கி, இலவச இடத்தை குறைக்கிறது. நூலகத்தை ஸ்கேன் செய்தபின் அல்லது தரவுத்தள மாற்றங்களைக் குறிக்கும் பிற மாற்றங்களைச் செய்தபின் இந்த பணியை இயக்குவது செயல்திறனை மேம்படுத்தக்கூடும்.", + "TaskOptimizeDatabase": "தரவுத்தளத்தை மேம்படுத்தவும்" } From ab85baf6eb42487429d2fb8d7620ebed98c2c88a Mon Sep 17 00:00:00 2001 From: Csaba Date: Mon, 12 Jul 2021 06:13:10 +0000 Subject: [PATCH 040/120] Translated using Weblate (Hungarian) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/hu/ --- Emby.Server.Implementations/Localization/Core/hu.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/hu.json b/Emby.Server.Implementations/Localization/Core/hu.json index 85848fed60..255d5427a6 100644 --- a/Emby.Server.Implementations/Localization/Core/hu.json +++ b/Emby.Server.Implementations/Localization/Core/hu.json @@ -118,5 +118,7 @@ "TaskCleanActivityLog": "Tevékenységnapló törlése", "Undefined": "Meghatározatlan", "Forced": "Kényszerített", - "Default": "Alapértelmezett" + "Default": "Alapértelmezett", + "TaskOptimizeDatabaseDescription": "Tömöríti az adatbázist és csonkolja a szabad helyet. A feladat futtatása a könyvtár beolvasása után, vagy egyéb, adatbázis-módosítást igénylő változtatások végrehajtása javíthatja a teljesítményt.", + "TaskOptimizeDatabase": "Adatbázis optimalizálása" } From 09904857b5cdf46267b82ba85a61dddce8f82af6 Mon Sep 17 00:00:00 2001 From: danielxb-ar Date: Mon, 12 Jul 2021 17:58:12 +0000 Subject: [PATCH 041/120] Translated using Weblate (Spanish (Latin America)) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/es_419/ --- Emby.Server.Implementations/Localization/Core/es_419.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/es_419.json b/Emby.Server.Implementations/Localization/Core/es_419.json index 6d2a5c7ac0..a968c6daba 100644 --- a/Emby.Server.Implementations/Localization/Core/es_419.json +++ b/Emby.Server.Implementations/Localization/Core/es_419.json @@ -117,5 +117,7 @@ "TaskCleanActivityLog": "Limpiar Registro de Actividades", "Undefined": "Sin definir", "Forced": "Forzado", - "Default": "Por Defecto" + "Default": "Por Defecto", + "TaskOptimizeDatabaseDescription": "Compacta la base de datos y restaura el espacio libre. Ejecutar esta tarea después de actualizar las librerías o realizar otros cambios que impliquen modificar las bases de datos puede mejorar la performance.", + "TaskOptimizeDatabase": "Optimización de base de datos" } From e977665e5d6dd5a24687e35be7812e261983baab Mon Sep 17 00:00:00 2001 From: Larvitar Date: Mon, 12 Jul 2021 15:48:06 +0000 Subject: [PATCH 042/120] Translated using Weblate (Polish) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/pl/ --- Emby.Server.Implementations/Localization/Core/pl.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/pl.json b/Emby.Server.Implementations/Localization/Core/pl.json index e3da96a85a..275bdec6e6 100644 --- a/Emby.Server.Implementations/Localization/Core/pl.json +++ b/Emby.Server.Implementations/Localization/Core/pl.json @@ -118,5 +118,6 @@ "TaskCleanActivityLog": "Czyść dziennik aktywności", "Undefined": "Nieustalony", "Forced": "Wymuszony", - "Default": "Domyślne" + "Default": "Domyślne", + "TaskOptimizeDatabase": "Optymalizuj bazę danych" } From 93a6f13a3df11601bbef0c27c524b51eadebb5ed Mon Sep 17 00:00:00 2001 From: WWWesten Date: Sun, 11 Jul 2021 12:49:56 +0000 Subject: [PATCH 043/120] Translated using Weblate (Russian) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ru/ --- Emby.Server.Implementations/Localization/Core/ru.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/ru.json b/Emby.Server.Implementations/Localization/Core/ru.json index e58f8c39d0..248f06c4b2 100644 --- a/Emby.Server.Implementations/Localization/Core/ru.json +++ b/Emby.Server.Implementations/Localization/Core/ru.json @@ -118,5 +118,7 @@ "TaskCleanActivityLog": "Очистить журнал активности", "Undefined": "Не определено", "Forced": "Форсир-ые", - "Default": "По умолчанию" + "Default": "По умолчанию", + "TaskOptimizeDatabaseDescription": "Сжимает базу данных и обрезает свободное место. Выполнение этой задачи после сканирования библиотеки или внесения других изменений, предполагающих модификации базы данных, может повысить производительность.", + "TaskOptimizeDatabase": "Оптимизировать базу данных" } From 87ba51f6e4d703bfc6355e413d857b112106a5da Mon Sep 17 00:00:00 2001 From: wolong gl Date: Mon, 12 Jul 2021 09:11:42 +0000 Subject: [PATCH 044/120] Translated using Weblate (Chinese (Simplified)) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/zh_Hans/ --- Emby.Server.Implementations/Localization/Core/zh-CN.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/zh-CN.json b/Emby.Server.Implementations/Localization/Core/zh-CN.json index 12803456e3..faa9c40e27 100644 --- a/Emby.Server.Implementations/Localization/Core/zh-CN.json +++ b/Emby.Server.Implementations/Localization/Core/zh-CN.json @@ -118,5 +118,7 @@ "TaskCleanActivityLogDescription": "删除早于设置时间的活动日志条目。", "Undefined": "未定义", "Forced": "强制的", - "Default": "默认" + "Default": "默认", + "TaskOptimizeDatabaseDescription": "压缩数据库并优化可用空间,在扫描库或执行其他数据库修改后运行此任务可能会提高性能。", + "TaskOptimizeDatabase": "优化数据库" } From 39bc4bf9e3ed659f37547512d95c4e3cc621ee1b Mon Sep 17 00:00:00 2001 From: WWWesten Date: Sun, 11 Jul 2021 12:48:51 +0000 Subject: [PATCH 045/120] Translated using Weblate (Kazakh) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/kk/ --- Emby.Server.Implementations/Localization/Core/kk.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/kk.json b/Emby.Server.Implementations/Localization/Core/kk.json index 4eee369892..1b4a18deb5 100644 --- a/Emby.Server.Implementations/Localization/Core/kk.json +++ b/Emby.Server.Implementations/Localization/Core/kk.json @@ -118,5 +118,7 @@ "TaskRefreshLibraryDescription": "Tasyğyşhanadağy jaña faildardy skanerleidі jäne metaderekterdı jañğyrtady.", "TaskRefreshChapterImagesDescription": "Sahnalary bar beineler üşın nobailar jasaidy.", "TaskCleanCacheDescription": "Jüiede qajet emes keştelgen faildardy joiady.", - "TaskCleanActivityLogDescription": "Äreket jūrnalyndağy teñşelgen jasynan asqan jazbalary joiady." + "TaskCleanActivityLogDescription": "Äreket jūrnalyndağy teñşelgen jasynan asqan jazbalary joiady.", + "TaskOptimizeDatabaseDescription": "Derekqordy qysyp, bos oryndy qysqartady. Būl tapsyrmany tasyğyşhanany skanerlegennen keiın nemese derekqorğa meñzeitın basqa özgertuler ıstelgennen keiın oryndau önımdılıktı damytuy mümkın.", + "TaskOptimizeDatabase": "Derekqordy oñtailandyru" } From 5debcf076335e4d64f8ce0125c3f4b93d3728415 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Kucharczyk?= Date: Sun, 11 Jul 2021 19:20:39 +0000 Subject: [PATCH 046/120] Translated using Weblate (Czech) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/cs/ --- Emby.Server.Implementations/Localization/Core/cs.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/cs.json b/Emby.Server.Implementations/Localization/Core/cs.json index ff14c1929c..62b2b6328c 100644 --- a/Emby.Server.Implementations/Localization/Core/cs.json +++ b/Emby.Server.Implementations/Localization/Core/cs.json @@ -118,5 +118,7 @@ "TaskCleanActivityLog": "Smazat záznam aktivity", "Undefined": "Nedefinované", "Forced": "Vynucené", - "Default": "Výchozí" + "Default": "Výchozí", + "TaskOptimizeDatabaseDescription": "Zmenší databázi a odstraní prázdné místo. Spuštění této úlohy po skenování knihovny či jiných změnách databáze může zlepšit výkon.", + "TaskOptimizeDatabase": "Optimalizovat databázi" } From 1d4d508f303e27f5e8eae5b505c0785dd33e9bdd Mon Sep 17 00:00:00 2001 From: jtasseroul Date: Sun, 11 Jul 2021 07:17:14 +0000 Subject: [PATCH 047/120] Translated using Weblate (French) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/fr/ --- Emby.Server.Implementations/Localization/Core/fr.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/fr.json b/Emby.Server.Implementations/Localization/Core/fr.json index ce1493be8a..0e4c38425c 100644 --- a/Emby.Server.Implementations/Localization/Core/fr.json +++ b/Emby.Server.Implementations/Localization/Core/fr.json @@ -118,5 +118,7 @@ "TaskCleanActivityLog": "Nettoyer le journal d'activité", "Undefined": "Non défini", "Forced": "Forcé", - "Default": "Par défaut" + "Default": "Par défaut", + "TaskOptimizeDatabaseDescription": "Réduit les espaces vides/inutiles et compacte la base de données. Utiliser cette fonction après une mise à jour de la bibliothèque ou toute autre modification de la base de données peut améliorer les performances du serveur.", + "TaskOptimizeDatabase": "Optimiser la base de données" } From 74d45636b55bf8b024fc6bd1f6a791e7c754080f Mon Sep 17 00:00:00 2001 From: nextlooper42 Date: Tue, 13 Jul 2021 08:25:55 +0000 Subject: [PATCH 048/120] Translated using Weblate (Slovak) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/sk/ --- Emby.Server.Implementations/Localization/Core/sk.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/sk.json b/Emby.Server.Implementations/Localization/Core/sk.json index 99fbd39540..37da7d5ab3 100644 --- a/Emby.Server.Implementations/Localization/Core/sk.json +++ b/Emby.Server.Implementations/Localization/Core/sk.json @@ -118,5 +118,7 @@ "TaskCleanActivityLog": "Vyčistiť log aktivít", "Undefined": "Nedefinované", "Forced": "Vynútené", - "Default": "Predvolené" + "Default": "Predvolené", + "TaskOptimizeDatabaseDescription": "Zmenší databázu a odstráni prázdne miesto. Spustenie tejto úlohy po skenovaní knižnice alebo po iných zmenách zahŕňajúcich úpravy databáze môže zlepšiť výkon.", + "TaskOptimizeDatabase": "Optimalizovať databázu" } From 7f06cdc83f2ee09947541bf94beeb687d63ac453 Mon Sep 17 00:00:00 2001 From: danielxb-ar Date: Mon, 12 Jul 2021 17:58:35 +0000 Subject: [PATCH 049/120] Translated using Weblate (Spanish (Argentina)) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/es_AR/ --- Emby.Server.Implementations/Localization/Core/es-AR.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/es-AR.json b/Emby.Server.Implementations/Localization/Core/es-AR.json index 0d4a14be00..6321f695c4 100644 --- a/Emby.Server.Implementations/Localization/Core/es-AR.json +++ b/Emby.Server.Implementations/Localization/Core/es-AR.json @@ -118,5 +118,7 @@ "TaskCleanActivityLog": "Borrar log de actividades", "Undefined": "Indefinido", "Forced": "Forzado", - "Default": "Por Defecto" + "Default": "Por Defecto", + "TaskOptimizeDatabaseDescription": "Compacta la base de datos y restaura el espacio libre. Ejecutar esta tarea después de actualizar las librerías o realizar otros cambios que impliquen modificar las bases de datos puede mejorar la performance.", + "TaskOptimizeDatabase": "Optimización de base de datos" } From 273afe8a52d2987e634dac591883502a8401e003 Mon Sep 17 00:00:00 2001 From: Oatavandi Date: Sun, 11 Jul 2021 16:42:32 +0000 Subject: [PATCH 050/120] Translated using Weblate (Malayalam) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ml/ --- Emby.Server.Implementations/Localization/Core/ml.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/ml.json b/Emby.Server.Implementations/Localization/Core/ml.json index e764963cff..435f9b6305 100644 --- a/Emby.Server.Implementations/Localization/Core/ml.json +++ b/Emby.Server.Implementations/Localization/Core/ml.json @@ -117,5 +117,7 @@ "Favorites": "പ്രിയങ്കരങ്ങൾ", "Books": "പുസ്തകങ്ങൾ", "Genres": "വിഭാഗങ്ങൾ", - "Channels": "ചാനലുകൾ" + "Channels": "ചാനലുകൾ", + "TaskOptimizeDatabaseDescription": "ഡാറ്റാബേസ് ചുരുക്കുകയും സ്വതന്ത്ര ഇടം വെട്ടിച്ചുരുക്കുകയും ചെയ്യുന്നു. ലൈബ്രറി സ്‌കാൻ ചെയ്‌തതിനുശേഷം അല്ലെങ്കിൽ ഡാറ്റാബേസ് പരിഷ്‌ക്കരണങ്ങളെ സൂചിപ്പിക്കുന്ന മറ്റ് മാറ്റങ്ങൾ ചെയ്‌തതിന് ശേഷം ഈ ടാസ്‌ക് പ്രവർത്തിപ്പിക്കുന്നത് പ്രകടനം മെച്ചപ്പെടുത്തും.", + "TaskOptimizeDatabase": "ഡാറ്റാബേസ് ഒപ്റ്റിമൈസ് ചെയ്യുക" } From 75551f04ca3efa17fa1cb9f888963b65ae51cf93 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Wed, 14 Jul 2021 14:37:48 -0400 Subject: [PATCH 051/120] Disable automatic closing of PRs --- .github/stale.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/stale.yml b/.github/stale.yml index 05892c44dc..cba9c33b2a 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -17,9 +17,13 @@ staleLabel: stale # Comment to post when marking an issue as stale. Set to `false` to disable markComment: > This issue has gone 120 days without comment. To avoid abandoned issues, it will be closed in 21 days if there are no new comments. - + If you're the original submitter of this issue, please comment confirming if this issue still affects you in the latest release or nightlies, or close the issue if it has been fixed. If you're another user also affected by this bug, please comment confirming so. Either action will remove the stale label. This bot exists to prevent issues from becoming stale and forgotten. Jellyfin is always moving forward, and bugs are often fixed as side effects of other changes. We therefore ask that bug report authors remain vigilant about their issues to ensure they are closed if fixed, or re-confirmed - perhaps with fresh logs or reproduction examples - regularly. If you have any questions you can reach us on [Matrix or Social Media](https://docs.jellyfin.org/general/getting-help.html). # Comment to post when closing a stale issue. Set to `false` to disable closeComment: false + +# Disable automatic closing of pull requests +pulls: + daysUntilClose: false From 8af7e5fe3acca1eebe74ea9d0e9708266b17b2f8 Mon Sep 17 00:00:00 2001 From: artiume Date: Thu, 15 Jul 2021 09:50:38 -0400 Subject: [PATCH 052/120] update bug report to ask for hwaccel --- .github/ISSUE_TEMPLATE/bug_report.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 12f1f5ed53..5a525267a9 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -17,6 +17,7 @@ assignees: '' - Browser: [e.g. Firefox 72, Chrome 80, Safari 13] - Jellyfin Version: [e.g. 10.4.3, nightly 20191231] - Playback: [Direct Play, Remux, Direct Stream, Transcode] + - Hardware Acceleration: [e.g. none, VAAPI, NVENC, etc.] - Installed Plugins: [e.g. none, Fanart, Anime, etc.] - Reverse Proxy: [e.g. none, nginx, apache, etc.] - Base URL: [e.g. none, yes: /example] From b202bfebce6104969296c5cbbb263491fe3ebfc2 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Mon, 12 Jul 2021 23:51:36 +0200 Subject: [PATCH 053/120] Fix episode parser --- Emby.Naming/Common/NamingOptions.cs | 14 +++++++------- .../Jellyfin.Naming.Tests/TV/EpisodeNumberTests.cs | 3 ++- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Emby.Naming/Common/NamingOptions.cs b/Emby.Naming/Common/NamingOptions.cs index 22a3e8bb49..21b92b7462 100644 --- a/Emby.Naming/Common/NamingOptions.cs +++ b/Emby.Naming/Common/NamingOptions.cs @@ -277,7 +277,7 @@ namespace Emby.Naming.Common IsNamed = true }, - new EpisodeExpression("[\\\\/\\._ \\[\\(-]([0-9]+)x([0-9]+(?:(?:[a-i]|\\.[1-9])(?![0-9]))?)([^\\\\/]*)$") + new EpisodeExpression(@"[\\\/\._ \[\(-]([0-9]+)x([0-9]+(?:(?:[a-i]|\.[1-9])(?![0-9]))?)([^\\\/]*)$") { SupportsAbsoluteEpisodeNumbers = true }, @@ -305,6 +305,12 @@ namespace Emby.Naming.Common // *** End Kodi Standard Naming + // "Episode 16", "Episode 16 - Title" + new EpisodeExpression(@"[Ee]pisode (?[0-9]+)(-(?[0-9]+))?[^\\\/]*$") + { + IsNamed = true + }, + new EpisodeExpression(@".*(\\|\/)[sS]?(?[0-9]+)[xX](?[0-9]+)[^\\\/]*$") { IsNamed = true @@ -362,12 +368,6 @@ namespace Emby.Naming.Common IsOptimistic = true, IsNamed = true }, - // "Episode 16", "Episode 16 - Title" - new EpisodeExpression(@".*[\\\/][^\\\/]* (?[0-9]{1,3})(-(?[0-9]{2,3}))*[^\\\/]*$") - { - IsOptimistic = true, - IsNamed = true - } }; EpisodeWithoutSeasonExpressions = new[] diff --git a/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberTests.cs b/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberTests.cs index 921c2b1f57..2873f61613 100644 --- a/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberTests.cs +++ b/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberTests.cs @@ -70,7 +70,8 @@ namespace Jellyfin.Naming.Tests.TV [InlineData("Log Horizon 2/[HorribleSubs] Log Horizon 2 - 03 [720p].mkv", 3)] // digit in series name [InlineData("Season 1/seriesname 05.mkv", 5)] // no hyphen between series name and episode number [InlineData("[BBT-RMX] Ranma ½ - 154 [50AC421A].mkv", 154)] // hyphens in the pre-name info, triple digit episode number - // TODO: [InlineData("Case Closed (1996-2007)/Case Closed - 317.mkv", 317)] // triple digit episode number + [InlineData("Season 2/Episode 21 - 94 Meetings.mp4", 21)] // Title starts with a number + // [InlineData("Case Closed (1996-2007)/Case Closed - 317.mkv", 317)] // triple digit episode number // TODO: [InlineData("Season 2/16 12 Some Title.avi", 16)] // TODO: [InlineData("/The.Legend.of.Condor.Heroes.2017.V2.web-dl.1080p.h264.aac-hdctv/The.Legend.of.Condor.Heroes.2017.E07.V2.web-dl.1080p.h264.aac-hdctv.mkv", 7)] // TODO: [InlineData("Season 4/Uchuu.Senkan.Yamato.2199.E03.avi", 3)] From b9b4f3aa8538f7eace04a6c2d466cd342b66bd27 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Thu, 15 Jul 2021 16:20:50 +0200 Subject: [PATCH 054/120] Add h265 to CleanStrings --- Emby.Naming/Common/NamingOptions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Naming/Common/NamingOptions.cs b/Emby.Naming/Common/NamingOptions.cs index 22a3e8bb49..cc9f952c82 100644 --- a/Emby.Naming/Common/NamingOptions.cs +++ b/Emby.Naming/Common/NamingOptions.cs @@ -137,7 +137,7 @@ namespace Emby.Naming.Common CleanStrings = new[] { - @"[ _\,\.\(\)\[\]\-](3d|sbs|tab|hsbs|htab|mvc|HDR|HDC|UHD|UltraHD|4k|ac3|dts|custom|dc|divx|divx5|dsr|dsrip|dutch|dvd|dvdrip|dvdscr|dvdscreener|screener|dvdivx|cam|fragment|fs|hdtv|hdrip|hdtvrip|internal|limited|multisubs|ntsc|ogg|ogm|pal|pdtv|proper|repack|rerip|retail|cd[1-9]|r3|r5|bd5|bd|se|svcd|swedish|german|read.nfo|nfofix|unrated|ws|telesync|ts|telecine|tc|brrip|bdrip|480p|480i|576p|576i|720p|720i|1080p|1080i|2160p|hrhd|hrhdtv|hddvd|bluray|blu-ray|x264|x265|h264|xvid|xvidvd|xxx|www.www|AAC|DTS|\[.*\])([ _\,\.\(\)\[\]\-]|$)", + @"[ _\,\.\(\)\[\]\-](3d|sbs|tab|hsbs|htab|mvc|HDR|HDC|UHD|UltraHD|4k|ac3|dts|custom|dc|divx|divx5|dsr|dsrip|dutch|dvd|dvdrip|dvdscr|dvdscreener|screener|dvdivx|cam|fragment|fs|hdtv|hdrip|hdtvrip|internal|limited|multisubs|ntsc|ogg|ogm|pal|pdtv|proper|repack|rerip|retail|cd[1-9]|r3|r5|bd5|bd|se|svcd|swedish|german|read.nfo|nfofix|unrated|ws|telesync|ts|telecine|tc|brrip|bdrip|480p|480i|576p|576i|720p|720i|1080p|1080i|2160p|hrhd|hrhdtv|hddvd|bluray|blu-ray|x264|x265|h264|h265|xvid|xvidvd|xxx|www.www|AAC|DTS|\[.*\])([ _\,\.\(\)\[\]\-]|$)", @"(\[.*\])" }; From 0ad62e7af93934ef0695891bd6a6adda67feb6ff Mon Sep 17 00:00:00 2001 From: DeeJayBro Date: Fri, 16 Jul 2021 11:48:08 +0200 Subject: [PATCH 055/120] Fix ArgumentOutOfRangeException when getting PostedPlaybackInfo --- Jellyfin.Api/Controllers/MediaInfoController.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Jellyfin.Api/Controllers/MediaInfoController.cs b/Jellyfin.Api/Controllers/MediaInfoController.cs index e330f02b61..672c26ff8d 100644 --- a/Jellyfin.Api/Controllers/MediaInfoController.cs +++ b/Jellyfin.Api/Controllers/MediaInfoController.cs @@ -161,6 +161,11 @@ namespace Jellyfin.Api.Controllers liveStreamId) .ConfigureAwait(false); + if (info.ErrorCode != null) + { + return info; + } + if (profile != null) { // set device specific data From b44f191d542ffb55830871574cb87880ea457443 Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Fri, 16 Jul 2021 08:58:04 -0600 Subject: [PATCH 056/120] Remove obsolete attribute, clean controller name --- Jellyfin.Api/Controllers/InstantMixController.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Jellyfin.Api/Controllers/InstantMixController.cs b/Jellyfin.Api/Controllers/InstantMixController.cs index a283ffc577..4774ed4efa 100644 --- a/Jellyfin.Api/Controllers/InstantMixController.cs +++ b/Jellyfin.Api/Controllers/InstantMixController.cs @@ -316,8 +316,7 @@ namespace Jellyfin.Api.Controllers /// A with the playlist items. [HttpGet("MusicGenres/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] - [Obsolete("Use GetInstantMixFromMusicGenres instead")] - public ActionResult> GetInstantMixFromMusicGenreById2( + public ActionResult> GetInstantMixFromMusicGenreById( [FromQuery, Required] Guid id, [FromQuery] Guid? userId, [FromQuery] int? limit, From 5ba93da8b63448a89ae76df15ae982d7db21d272 Mon Sep 17 00:00:00 2001 From: Albert Chaos Date: Fri, 16 Jul 2021 15:04:19 +0000 Subject: [PATCH 057/120] Translated using Weblate (Catalan) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ca/ --- Emby.Server.Implementations/Localization/Core/ca.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/ca.json b/Emby.Server.Implementations/Localization/Core/ca.json index fd8437b6d9..1b612dc716 100644 --- a/Emby.Server.Implementations/Localization/Core/ca.json +++ b/Emby.Server.Implementations/Localization/Core/ca.json @@ -118,5 +118,7 @@ "TaskCleanActivityLog": "Buidar Registre d'Activitat", "Undefined": "Indefinit", "Forced": "Forçat", - "Default": "Defecto" + "Default": "Defecto", + "TaskOptimizeDatabaseDescription": "Compacta la base de dades i trunca l'espai lliure. Executar aquesta tasca després d’escanejar la biblioteca o fer altres canvis que impliquin modificacions a la base de dades pot millorar el rendiment.", + "TaskOptimizeDatabase": "Optimitzar la base de dades" } From eb9244746c6db50b233cf14abd81d44222f2901b Mon Sep 17 00:00:00 2001 From: Vorboid Date: Thu, 15 Jul 2021 13:08:34 +0000 Subject: [PATCH 058/120] Translated using Weblate (English (United Kingdom)) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/en_GB/ --- Emby.Server.Implementations/Localization/Core/en-GB.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/en-GB.json b/Emby.Server.Implementations/Localization/Core/en-GB.json index 7667612b90..8b2e8b6b1c 100644 --- a/Emby.Server.Implementations/Localization/Core/en-GB.json +++ b/Emby.Server.Implementations/Localization/Core/en-GB.json @@ -118,5 +118,7 @@ "TaskCleanActivityLog": "Clean Activity Log", "Undefined": "Undefined", "Forced": "Forced", - "Default": "Default" + "Default": "Default", + "TaskOptimizeDatabaseDescription": "Compacts database and truncates free space. Running this task after scanning the library or doing other changes that imply database modifications might improve performance.", + "TaskOptimizeDatabase": "Optimise database" } From de9c367bc3fe7092c8d04ecc24bf529611db812e Mon Sep 17 00:00:00 2001 From: memnos Date: Thu, 15 Jul 2021 11:35:16 +0000 Subject: [PATCH 059/120] Translated using Weblate (Italian) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/it/ --- Emby.Server.Implementations/Localization/Core/it.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/it.json b/Emby.Server.Implementations/Localization/Core/it.json index bd06f0a258..8b753400ef 100644 --- a/Emby.Server.Implementations/Localization/Core/it.json +++ b/Emby.Server.Implementations/Localization/Core/it.json @@ -118,5 +118,7 @@ "TaskCleanActivityLogDescription": "Elimina gli inserimenti nel registro delle attività più vecchie dell’età configurata.", "Undefined": "Non Definito", "Forced": "Forzato", - "Default": "Predefinito" + "Default": "Predefinito", + "TaskOptimizeDatabaseDescription": "Compatta Database e tronca spazi liberi. Eseguire questa azione dopo la scansione o dopo aver fatto altri cambiamenti inerenti il database potrebbe aumentarne la performance.", + "TaskOptimizeDatabase": "Ottimizza Database" } From 1dde41902a0c47446f18dead03eaf299ec4c6db9 Mon Sep 17 00:00:00 2001 From: Joost Date: Thu, 15 Jul 2021 15:38:50 +0000 Subject: [PATCH 060/120] 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 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/nl.json b/Emby.Server.Implementations/Localization/Core/nl.json index 85b8416fd9..f79840c781 100644 --- a/Emby.Server.Implementations/Localization/Core/nl.json +++ b/Emby.Server.Implementations/Localization/Core/nl.json @@ -118,5 +118,7 @@ "TaskCleanActivityLog": "Leeg activiteiten logboek", "Undefined": "Niet gedefinieerd", "Forced": "Geforceerd", - "Default": "Standaard" + "Default": "Standaard", + "TaskOptimizeDatabaseDescription": "Comprimeert de database en trimt vrije ruimte. Het uitvoeren van deze taak kan de prestaties verbeteren, na het scannen van de bibliotheek of andere aanpassingen die invloed hebben op de database.", + "TaskOptimizeDatabase": "Database optimaliseren" } From 0c26fdac3701230e5e045a2af01fc3d2494c4deb Mon Sep 17 00:00:00 2001 From: SaddFox Date: Wed, 14 Jul 2021 13:36:03 +0000 Subject: [PATCH 061/120] Translated using Weblate (Slovenian) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/sl/ --- Emby.Server.Implementations/Localization/Core/sl-SI.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/sl-SI.json b/Emby.Server.Implementations/Localization/Core/sl-SI.json index 343e067b79..1852dc89e4 100644 --- a/Emby.Server.Implementations/Localization/Core/sl-SI.json +++ b/Emby.Server.Implementations/Localization/Core/sl-SI.json @@ -118,5 +118,7 @@ "TaskCleanActivityLog": "Počisti dnevnik aktivnosti", "Undefined": "Nedoločen", "Forced": "Prisilno", - "Default": "Privzeto" + "Default": "Privzeto", + "TaskOptimizeDatabaseDescription": "Stisne bazo podatkov in uredi prazen prostor. Zagon tega opravila po iskanju predstavnosti ali drugih spremembah ki vplivajo na bazo podatkov lahko izboljša hitrost delovanja.", + "TaskOptimizeDatabase": "Optimiziraj bazo podatkov" } From 0e8537a6a56d5085ab2fedf0c435bd770e336657 Mon Sep 17 00:00:00 2001 From: Jelly Don Date: Thu, 15 Jul 2021 15:37:47 +0000 Subject: [PATCH 062/120] Translated using Weblate (Albanian) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/sq/ --- .../Localization/Core/sq.json | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/sq.json b/Emby.Server.Implementations/Localization/Core/sq.json index f611cbafaa..e36fdc43db 100644 --- a/Emby.Server.Implementations/Localization/Core/sq.json +++ b/Emby.Server.Implementations/Localization/Core/sq.json @@ -42,8 +42,8 @@ "Sync": "Sinkronizo", "SubtitleDownloadFailureFromForItem": "Titrat deshtuan të shkarkohen nga {0} për {1}", "StartupEmbyServerIsLoading": "Serveri Jellyfin po ngarkohet. Ju lutemi provoni përseri pas pak.", - "Songs": "Këngë", - "Shows": "Seriale", + "Songs": "Këngët", + "Shows": "Serialet", "ServerNameNeedsToBeRestarted": "{0} duhet të ristartoj", "ScheduledTaskStartedWithName": "{0} filloi", "ScheduledTaskFailedWithName": "{0} dështoi", @@ -74,9 +74,9 @@ "NameSeasonUnknown": "Sezon i panjohur", "NameSeasonNumber": "Sezoni {0}", "NameInstallFailed": "Instalimi i {0} dështoi", - "MusicVideos": "Video muzikore", + "MusicVideos": "Videot muzikore", "Music": "Muzikë", - "Movies": "Filma", + "Movies": "Filmat", "MixedContent": "Përmbajtje e përzier", "MessageServerConfigurationUpdated": "Konfigurimet e serverit u përditësuan", "MessageNamedServerConfigurationUpdatedWithValue": "Seksioni i konfigurimit të serverit {0} u përditësua", @@ -97,25 +97,27 @@ "HeaderFavoriteAlbums": "Albumet e preferuar", "HeaderContinueWatching": "Vazhdo të shikosh", "HeaderAlbumArtists": "Artistët e albumeve", - "Genres": "Zhanre", - "Folders": "Dosje", - "Favorites": "Të preferuara", + "Genres": "Zhanret", + "Folders": "Skedarët", + "Favorites": "Të preferuarat", "FailedLoginAttemptWithUserName": "Përpjekja për hyrje dështoi nga {0}", "DeviceOnlineWithName": "{0} u lidh", "DeviceOfflineWithName": "{0} u shkëput", - "Collections": "Koleksione", + "Collections": "Koleksionet", "ChapterNameValue": "Kapituj", - "Channels": "Kanale", + "Channels": "Kanalet", "CameraImageUploadedFrom": "Një foto e re nga kamera u ngarkua nga {0}", - "Books": "Libra", + "Books": "Librat", "AuthenticationSucceededWithUserName": "{0} u identifikua me sukses", - "Artists": "Artistë", + "Artists": "Artistët", "Application": "Aplikacioni", "AppDeviceValues": "Aplikacioni: {0}, Pajisja: {1}", - "Albums": "Albume", + "Albums": "Albumet", "TaskCleanActivityLogDescription": "Pastro të dhënat mbi aktivitetin më të vjetra sesa koha e përcaktuar.", "TaskCleanActivityLog": "Pastro të dhënat mbi aktivitetin", "Undefined": "I papërcaktuar", "Forced": "I detyruar", - "Default": "Parazgjedhur" + "Default": "Parazgjedhur", + "TaskOptimizeDatabaseDescription": "Kompakton bazën e të dhënave dhe shkurton hapësirën e lirë. Drejtimi i kësaj detyre pasi skanoni bibliotekën ose bëni ndryshime të tjera që nënkuptojnë modifikime të bazës së të dhënave mund të përmirësojë performancën.", + "TaskOptimizeDatabase": "Optimizo databazën" } From e36345b9f2cd384f1dbe405ce0ca2060b80781b0 Mon Sep 17 00:00:00 2001 From: Fawrrax Date: Sat, 17 Jul 2021 18:32:41 +0000 Subject: [PATCH 063/120] Translated using Weblate (Finnish) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/fi/ --- Emby.Server.Implementations/Localization/Core/fi.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/fi.json b/Emby.Server.Implementations/Localization/Core/fi.json index 633968d26d..4a1f4f1d52 100644 --- a/Emby.Server.Implementations/Localization/Core/fi.json +++ b/Emby.Server.Implementations/Localization/Core/fi.json @@ -117,5 +117,7 @@ "Default": "Oletus", "TaskCleanActivityLogDescription": "Poistaa määritettyä ikää vanhemmat tapahtumat toimintahistoriasta.", "TaskCleanActivityLog": "Tyhjennä toimintahistoria", - "Undefined": "Määrittelemätön" + "Undefined": "Määrittelemätön", + "TaskOptimizeDatabaseDescription": "Tiivistää ja puhdistaa tietokannan. Tämän toiminnon suorittaminen kirjastojen skannauksen tai muiden tietokantaan liittyvien muutoksien jälkeen voi parantaa suorituskykyä.", + "TaskOptimizeDatabase": "Optimoi tietokanta" } From cd541f105cd28765d10581352f7e1d04ac29cf03 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jul 2021 12:00:49 +0000 Subject: [PATCH 064/120] Bump Serilog.Sinks.Console from 3.1.1 to 4.0.0 Bumps [Serilog.Sinks.Console](https://github.com/serilog/serilog-sinks-console) from 3.1.1 to 4.0.0. - [Release notes](https://github.com/serilog/serilog-sinks-console/releases) - [Commits](https://github.com/serilog/serilog-sinks-console/compare/v3.1.1...v4.0.0) --- updated-dependencies: - dependency-name: Serilog.Sinks.Console dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- Jellyfin.Server/Jellyfin.Server.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 71ee94a3f1..cfe2f44149 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -46,7 +46,7 @@ - + From dddf216ec8c35005b0b09af5ca0234e35d152e67 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jul 2021 12:03:27 +0000 Subject: [PATCH 065/120] Bump alex-page/github-project-automation-plus from 0.7.1 to 0.8.1 Bumps [alex-page/github-project-automation-plus](https://github.com/alex-page/github-project-automation-plus) from 0.7.1 to 0.8.1. - [Release notes](https://github.com/alex-page/github-project-automation-plus/releases) - [Commits](https://github.com/alex-page/github-project-automation-plus/compare/v0.7.1...v0.8.1) --- updated-dependencies: - dependency-name: alex-page/github-project-automation-plus dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/automation.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/automation.yml b/.github/workflows/automation.yml index 38415f1c60..20294843d5 100644 --- a/.github/workflows/automation.yml +++ b/.github/workflows/automation.yml @@ -26,7 +26,7 @@ jobs: if: ${{ github.repository == 'jellyfin/jellyfin' }} steps: - name: Remove from 'Current Release' project - uses: alex-page/github-project-automation-plus@v0.7.1 + uses: alex-page/github-project-automation-plus@v0.8.1 if: (github.event.pull_request || github.event.issue.pull_request) && !contains(github.event.*.labels.*.name, 'stable backport') continue-on-error: true with: @@ -35,7 +35,7 @@ jobs: repo-token: ${{ secrets.JF_BOT_TOKEN }} - name: Add to 'Release Next' project - uses: alex-page/github-project-automation-plus@v0.7.1 + uses: alex-page/github-project-automation-plus@v0.8.1 if: (github.event.pull_request || github.event.issue.pull_request) && github.event.action == 'opened' continue-on-error: true with: @@ -44,7 +44,7 @@ jobs: repo-token: ${{ secrets.JF_BOT_TOKEN }} - name: Add to 'Current Release' project - uses: alex-page/github-project-automation-plus@v0.7.1 + uses: alex-page/github-project-automation-plus@v0.8.1 if: (github.event.pull_request || github.event.issue.pull_request) && !contains(github.event.*.labels.*.name, 'stable backport') continue-on-error: true with: @@ -58,7 +58,7 @@ jobs: run: echo "::set-output name=number::$(curl -s ${{ github.event.issue.comments_url }} | jq '.[] | select(.author_association == "MEMBER") | .author_association' | wc -l)" - name: Move issue to needs triage - uses: alex-page/github-project-automation-plus@v0.7.1 + uses: alex-page/github-project-automation-plus@v0.8.1 if: github.event.issue.pull_request == '' && github.event.comment.author_association == 'MEMBER' && steps.member_comments.outputs.number <= 1 continue-on-error: true with: @@ -67,7 +67,7 @@ jobs: repo-token: ${{ secrets.JF_BOT_TOKEN }} - name: Add issue to triage project - uses: alex-page/github-project-automation-plus@v0.7.1 + uses: alex-page/github-project-automation-plus@v0.8.1 if: github.event.issue.pull_request == '' && github.event.action == 'opened' continue-on-error: true with: From de12ee5dba3698fe96a12330a68896ed6a1fdb94 Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Mon, 19 Jul 2021 08:08:02 -0600 Subject: [PATCH 066/120] Update to dotnet 5.0.8 --- .../Emby.Server.Implementations.csproj | 4 ++-- Jellyfin.Api/Jellyfin.Api.csproj | 2 +- .../Jellyfin.Server.Implementations.csproj | 8 ++++---- Jellyfin.Server/Jellyfin.Server.csproj | 4 ++-- deployment/Dockerfile.debian.amd64 | 2 +- deployment/Dockerfile.debian.arm64 | 2 +- deployment/Dockerfile.debian.armhf | 2 +- deployment/Dockerfile.linux.amd64 | 2 +- deployment/Dockerfile.linux.amd64-musl | 2 +- deployment/Dockerfile.linux.arm64 | 2 +- deployment/Dockerfile.linux.armhf | 2 +- deployment/Dockerfile.macos | 2 +- deployment/Dockerfile.portable | 2 +- deployment/Dockerfile.ubuntu.amd64 | 2 +- deployment/Dockerfile.ubuntu.arm64 | 2 +- deployment/Dockerfile.ubuntu.armhf | 2 +- deployment/Dockerfile.windows.amd64 | 2 +- tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj | 2 +- .../Jellyfin.Extensions.Tests.csproj | 2 +- .../Jellyfin.Server.Integration.Tests.csproj | 2 +- tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj | 2 +- 21 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 9c90de1eda..fe233df6c2 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -24,11 +24,11 @@ - + - + diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index bd7da9b067..d1d0ac7084 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -15,7 +15,7 @@ - + diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index eeeb1d19bf..f73492b7c7 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -27,13 +27,13 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 71ee94a3f1..92368a180b 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -38,8 +38,8 @@ - - + + diff --git a/deployment/Dockerfile.debian.amd64 b/deployment/Dockerfile.debian.amd64 index 4c426b6d5c..67a5c9c99a 100644 --- a/deployment/Dockerfile.debian.amd64 +++ b/deployment/Dockerfile.debian.amd64 @@ -16,7 +16,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/e1c236ec-c392-4eaa-a846-c600c82bb7f6/b13bd8b69f875f87cf83fc6f5457bcdf/dotnet-sdk-5.0.301-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.debian.arm64 b/deployment/Dockerfile.debian.arm64 index 7ed6d52bc8..c341068f6f 100644 --- a/deployment/Dockerfile.debian.arm64 +++ b/deployment/Dockerfile.debian.arm64 @@ -16,7 +16,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/e1c236ec-c392-4eaa-a846-c600c82bb7f6/b13bd8b69f875f87cf83fc6f5457bcdf/dotnet-sdk-5.0.301-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.debian.armhf b/deployment/Dockerfile.debian.armhf index b46cceaa46..19be363b6f 100644 --- a/deployment/Dockerfile.debian.armhf +++ b/deployment/Dockerfile.debian.armhf @@ -16,7 +16,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/e1c236ec-c392-4eaa-a846-c600c82bb7f6/b13bd8b69f875f87cf83fc6f5457bcdf/dotnet-sdk-5.0.301-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.linux.amd64 b/deployment/Dockerfile.linux.amd64 index a0e23557aa..a89fe92893 100644 --- a/deployment/Dockerfile.linux.amd64 +++ b/deployment/Dockerfile.linux.amd64 @@ -16,7 +16,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/e1c236ec-c392-4eaa-a846-c600c82bb7f6/b13bd8b69f875f87cf83fc6f5457bcdf/dotnet-sdk-5.0.301-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.linux.amd64-musl b/deployment/Dockerfile.linux.amd64-musl index af0f55f8e3..f7fb722f25 100644 --- a/deployment/Dockerfile.linux.amd64-musl +++ b/deployment/Dockerfile.linux.amd64-musl @@ -16,7 +16,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/e1c236ec-c392-4eaa-a846-c600c82bb7f6/b13bd8b69f875f87cf83fc6f5457bcdf/dotnet-sdk-5.0.301-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.linux.arm64 b/deployment/Dockerfile.linux.arm64 index ba004bb6a8..1b57441a0f 100644 --- a/deployment/Dockerfile.linux.arm64 +++ b/deployment/Dockerfile.linux.arm64 @@ -16,7 +16,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/e1c236ec-c392-4eaa-a846-c600c82bb7f6/b13bd8b69f875f87cf83fc6f5457bcdf/dotnet-sdk-5.0.301-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.linux.armhf b/deployment/Dockerfile.linux.armhf index 0d1114c011..20cf33e13f 100644 --- a/deployment/Dockerfile.linux.armhf +++ b/deployment/Dockerfile.linux.armhf @@ -16,7 +16,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/e1c236ec-c392-4eaa-a846-c600c82bb7f6/b13bd8b69f875f87cf83fc6f5457bcdf/dotnet-sdk-5.0.301-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.macos b/deployment/Dockerfile.macos index b57dc53f50..4ddd106bba 100644 --- a/deployment/Dockerfile.macos +++ b/deployment/Dockerfile.macos @@ -16,7 +16,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/e1c236ec-c392-4eaa-a846-c600c82bb7f6/b13bd8b69f875f87cf83fc6f5457bcdf/dotnet-sdk-5.0.301-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.portable b/deployment/Dockerfile.portable index 3783dfacf0..e56a480c66 100644 --- a/deployment/Dockerfile.portable +++ b/deployment/Dockerfile.portable @@ -15,7 +15,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/e1c236ec-c392-4eaa-a846-c600c82bb7f6/b13bd8b69f875f87cf83fc6f5457bcdf/dotnet-sdk-5.0.301-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.amd64 b/deployment/Dockerfile.ubuntu.amd64 index 663a7af9e9..03d4c185cb 100644 --- a/deployment/Dockerfile.ubuntu.amd64 +++ b/deployment/Dockerfile.ubuntu.amd64 @@ -16,7 +16,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/e1c236ec-c392-4eaa-a846-c600c82bb7f6/b13bd8b69f875f87cf83fc6f5457bcdf/dotnet-sdk-5.0.301-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.arm64 b/deployment/Dockerfile.ubuntu.arm64 index 83eb24e422..9e0b60e0b7 100644 --- a/deployment/Dockerfile.ubuntu.arm64 +++ b/deployment/Dockerfile.ubuntu.arm64 @@ -16,7 +16,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/e1c236ec-c392-4eaa-a846-c600c82bb7f6/b13bd8b69f875f87cf83fc6f5457bcdf/dotnet-sdk-5.0.301-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.armhf b/deployment/Dockerfile.ubuntu.armhf index 1187f37b95..0392f7b2ff 100644 --- a/deployment/Dockerfile.ubuntu.armhf +++ b/deployment/Dockerfile.ubuntu.armhf @@ -16,7 +16,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/e1c236ec-c392-4eaa-a846-c600c82bb7f6/b13bd8b69f875f87cf83fc6f5457bcdf/dotnet-sdk-5.0.301-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.windows.amd64 b/deployment/Dockerfile.windows.amd64 index 8b2361f0bb..9c78897a40 100644 --- a/deployment/Dockerfile.windows.amd64 +++ b/deployment/Dockerfile.windows.amd64 @@ -15,7 +15,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/e1c236ec-c392-4eaa-a846-c600c82bb7f6/b13bd8b69f875f87cf83fc6f5457bcdf/dotnet-sdk-5.0.301-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index d4ea91872c..07538b38bb 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -18,7 +18,7 @@ - + diff --git a/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj index 4b6dca3777..f87e63be26 100644 --- a/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj +++ b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj @@ -10,7 +10,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj index 59f125cd01..8bbe583871 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj +++ b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj index c8e72c10dd..0bd48e8ab3 100644 --- a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj +++ b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj @@ -13,7 +13,7 @@ - + From ef3b651aade1c17b5258ce4564640e974727bb3d Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 20 Jul 2021 00:25:30 +0200 Subject: [PATCH 067/120] Improve episode parser --- Emby.Naming/Common/NamingOptions.cs | 2 +- tests/Jellyfin.Naming.Tests/TV/SimpleEpisodeTests.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Emby.Naming/Common/NamingOptions.cs b/Emby.Naming/Common/NamingOptions.cs index 5f125eb4f1..915ce42cc9 100644 --- a/Emby.Naming/Common/NamingOptions.cs +++ b/Emby.Naming/Common/NamingOptions.cs @@ -284,7 +284,7 @@ namespace Emby.Naming.Common // Not a Kodi rule as well, but below rule also causes false positives for triple-digit episode names // [bar] Foo - 1 [baz] special case of below expression to prevent false positives with digits in the series name - new EpisodeExpression(@".*?(\[.*?\])+.*?(?[\w\s]+?)[\s_]*-[\s_]*(?[0-9]+).*$") + new EpisodeExpression(@".*[\\\/]?.*?(\[.*?\])+.*?(?[-\w\s]+?)[\s_]*-[\s_]*(?[0-9]+).*$") { IsNamed = true }, diff --git a/tests/Jellyfin.Naming.Tests/TV/SimpleEpisodeTests.cs b/tests/Jellyfin.Naming.Tests/TV/SimpleEpisodeTests.cs index 89579c0376..6d49ac832d 100644 --- a/tests/Jellyfin.Naming.Tests/TV/SimpleEpisodeTests.cs +++ b/tests/Jellyfin.Naming.Tests/TV/SimpleEpisodeTests.cs @@ -21,7 +21,8 @@ namespace Jellyfin.Naming.Tests.TV [InlineData("[Baz-Bar]Foo - [1080p][Multiple Subtitle]/[Baz-Bar] Foo - 05 [1080p][Multiple Subtitle].mkv", "Foo", null, 5)] [InlineData(@"/Foo/The.Series.Name.S01E04.WEBRip.x264-Baz[Bar]/the.series.name.s01e04.webrip.x264-Baz[Bar].mkv", "The.Series.Name", 1, 4)] [InlineData(@"Love.Death.and.Robots.S01.1080p.NF.WEB-DL.DDP5.1.x264-NTG/Love.Death.and.Robots.S01E01.Sonnies.Edge.1080p.NF.WEB-DL.DDP5.1.x264-NTG.mkv", "Love.Death.and.Robots", 1, 1)] - // TODO: [InlineData("[Baz-Bar]Foo - 01 - 12[1080p][Multiple Subtitle]/[Baz-Bar] Foo - 05 [1080p][Multiple Subtitle].mkv", "Foo", null, 5)] + [InlineData("[YuiSubs] Tensura Nikki - Tensei Shitara Slime Datta Ken/[YuiSubs] Tensura Nikki - Tensei Shitara Slime Datta Ken - 12 (NVENC H.265 1080p).mkv", "Tensura Nikki - Tensei Shitara Slime Datta Ken", null, 12)] + [InlineData("[Baz-Bar]Foo - 01 - 12[1080p][Multiple Subtitle]/[Baz-Bar] Foo - 05 [1080p][Multiple Subtitle].mkv", "Foo", null, 5)] // TODO: [InlineData("E:\\Anime\\Yahari Ore no Seishun Love Comedy wa Machigatteiru\\Yahari Ore no Seishun Love Comedy wa Machigatteiru. Zoku\\Oregairu Zoku 11 - Hayama Hayato Always Renconds to Everyone's Expectations..mkv", "Yahari Ore no Seishun Love Comedy wa Machigatteiru", null, 11)] // TODO: [InlineData(@"/Library/Series/The Grand Tour (2016)/Season 1/S01E01 The Holy Trinity.mkv", "The Grand Tour", 1, 1)] public void TestSimple(string path, string seriesName, int? seasonNumber, int? episodeNumber) From 0f0c62be6850a929c9e217e50fed66cb46efec7d Mon Sep 17 00:00:00 2001 From: Shin Yunho Date: Mon, 19 Jul 2021 15:48:20 +0000 Subject: [PATCH 068/120] Translated using Weblate (Korean) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ko/ --- Emby.Server.Implementations/Localization/Core/ko.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/ko.json b/Emby.Server.Implementations/Localization/Core/ko.json index 9179bbc8de..409b4d26b3 100644 --- a/Emby.Server.Implementations/Localization/Core/ko.json +++ b/Emby.Server.Implementations/Localization/Core/ko.json @@ -118,5 +118,7 @@ "TaskCleanActivityLog": "활동내역청소", "Undefined": "일치하지 않음", "Forced": "강제하기", - "Default": "기본 설정" + "Default": "기본 설정", + "TaskOptimizeDatabaseDescription": "데이터베이스를 압축하고 사용 가능한 공간을 늘립니다. 라이브러리를 검색한 후 이 작업을 실행하거나 데이터베이스 수정같은 비슷한 작업을 수행하면 성능이 향상될 수 있습니다.", + "TaskOptimizeDatabase": "데이터베이스 최적화" } From 0512f74459f7fbde7e86d0724be6a62eca083024 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 20 Jul 2021 19:31:47 +0200 Subject: [PATCH 069/120] Add tests for GetResolutionText --- MediaBrowser.Model/Entities/MediaStream.cs | 2 +- MediaBrowser.Model/Properties/AssemblyInfo.cs | 2 + .../Entities/MediaStreamTests.cs | 75 +++++++++++++++++++ 3 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index 275b438f52..9653a8ece7 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -469,7 +469,7 @@ namespace MediaBrowser.Model.Entities /// true if this instance is anamorphic; otherwise, false. public bool? IsAnamorphic { get; set; } - private string GetResolutionText() + internal string GetResolutionText() { if (!Width.HasValue || !Height.HasValue) { diff --git a/MediaBrowser.Model/Properties/AssemblyInfo.cs b/MediaBrowser.Model/Properties/AssemblyInfo.cs index f99e9ece96..e50baf604e 100644 --- a/MediaBrowser.Model/Properties/AssemblyInfo.cs +++ b/MediaBrowser.Model/Properties/AssemblyInfo.cs @@ -1,5 +1,6 @@ using System.Reflection; using System.Resources; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following @@ -14,6 +15,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] +[assembly: InternalsVisibleTo("Jellyfin.Model.Tests")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from diff --git a/tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs b/tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs new file mode 100644 index 0000000000..43ffa84bf5 --- /dev/null +++ b/tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs @@ -0,0 +1,75 @@ +using MediaBrowser.Model.Entities; +using Xunit; + +namespace Jellyfin.Model.Tests.Entities +{ + public class MediaStreamTests + { + [Theory] + [InlineData(null, null, false, null)] + [InlineData(null, 0, false, null)] + [InlineData(0, null, false, null)] + [InlineData(640, 480, false, "480p")] + [InlineData(640, 480, true, "480i")] + [InlineData(720, 576, false, "576p")] + [InlineData(720, 576, true, "576i")] + [InlineData(960, 540, false, "540p")] + [InlineData(960, 540, true, "540i")] + [InlineData(1280, 720, false, "720p")] + [InlineData(1280, 720, true, "720i")] + [InlineData(1920, 1080, false, "1080p")] + [InlineData(1920, 1080, true, "1080i")] + [InlineData(4096, 3072, false, "4K")] + [InlineData(8192, 6144, false, "8K")] + [InlineData(512, 384, false, "480p")] + [InlineData(576, 336, false, "480p")] + [InlineData(624, 352, false, "480p")] + [InlineData(640, 352, false, "480p")] + [InlineData(704, 396, false, "480p")] + [InlineData(720, 404, false, "480p")] + [InlineData(720, 480, false, "480p")] + [InlineData(768, 576, false, "576p")] + [InlineData(960, 720, false, "720p")] + [InlineData(1280, 528, false, "720p")] + [InlineData(1280, 532, false, "720p")] + [InlineData(1280, 534, false, "720p")] + [InlineData(1280, 536, false, "720p")] + [InlineData(1280, 544, false, "720p")] + [InlineData(1280, 690, false, "720p")] + [InlineData(1280, 694, false, "720p")] + [InlineData(1280, 696, false, "720p")] + [InlineData(1280, 716, false, "720p")] + [InlineData(1280, 718, false, "720p")] + [InlineData(1912, 792, false, "1080p")] + [InlineData(1916, 1076, false, "1080p")] + [InlineData(1918, 1080, false, "1080p")] + [InlineData(1920, 796, false, "1080p")] + [InlineData(1920, 800, false, "1080p")] + [InlineData(1920, 802, false, "1080p")] + [InlineData(1920, 804, false, "1080p")] + [InlineData(1920, 808, false, "1080p")] + [InlineData(1920, 816, false, "1080p")] + [InlineData(1920, 856, false, "1080p")] + [InlineData(1920, 960, false, "1080p")] + [InlineData(1920, 1024, false, "1080p")] + [InlineData(1920, 1040, false, "1080p")] + [InlineData(1920, 1072, false, "1080p")] + [InlineData(1440, 1072, false, "1080p")] + [InlineData(1440, 1080, false, "1080p")] + [InlineData(3840, 1600, false, "4K")] + [InlineData(3840, 1606, false, "4K")] + [InlineData(3840, 1608, false, "4K")] + [InlineData(3840, 2160, false, "4K")] + public void GetResolutionText_Valid(int? width, int? height, bool interlaced, string expected) + { + var mediaStream = new MediaStream() + { + Width = width, + Height = height, + IsInterlaced = interlaced + }; + + Assert.Equal(expected, mediaStream.GetResolutionText()); + } + } +} From 67efed39f299382db11bd500cdbe09c81dab2123 Mon Sep 17 00:00:00 2001 From: Rich Lander Date: Thu, 22 Jul 2021 20:37:05 -0700 Subject: [PATCH 070/120] Fix warning in m-b/channels --- MediaBrowser.Controller/Channels/Channel.cs | 12 ++++++------ MediaBrowser.Controller/Channels/ChannelItemInfo.cs | 2 +- .../Channels/ChannelItemResult.cs | 2 +- .../Channels/IHasFolderAttributes.cs | 2 +- .../Channels/InternalChannelFeatures.cs | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/MediaBrowser.Controller/Channels/Channel.cs b/MediaBrowser.Controller/Channels/Channel.cs index 26a936be0c..e6923b55ca 100644 --- a/MediaBrowser.Controller/Channels/Channel.cs +++ b/MediaBrowser.Controller/Channels/Channel.cs @@ -17,6 +17,12 @@ namespace MediaBrowser.Controller.Channels { public class Channel : Folder { + [JsonIgnore] + public override bool SupportsInheritedParentImages => false; + + [JsonIgnore] + public override SourceType SourceType => SourceType.Channel; + public override bool IsVisible(User user) { var blockedChannelsPreference = user.GetPreferenceValues(PreferenceKind.BlockedChannels); @@ -39,12 +45,6 @@ namespace MediaBrowser.Controller.Channels return base.IsVisible(user); } - [JsonIgnore] - public override bool SupportsInheritedParentImages => false; - - [JsonIgnore] - public override SourceType SourceType => SourceType.Channel; - protected override QueryResult GetItemsInternal(InternalItemsQuery query) { try diff --git a/MediaBrowser.Controller/Channels/ChannelItemInfo.cs b/MediaBrowser.Controller/Channels/ChannelItemInfo.cs index 4d1e35f9ea..55f80b240f 100644 --- a/MediaBrowser.Controller/Channels/ChannelItemInfo.cs +++ b/MediaBrowser.Controller/Channels/ChannelItemInfo.cs @@ -1,6 +1,6 @@ #nullable disable -#pragma warning disable CS1591 +#pragma warning disable CA1002, CA2227, CS1591 using System; using System.Collections.Generic; diff --git a/MediaBrowser.Controller/Channels/ChannelItemResult.cs b/MediaBrowser.Controller/Channels/ChannelItemResult.cs index 6b20776629..7a0addd9f9 100644 --- a/MediaBrowser.Controller/Channels/ChannelItemResult.cs +++ b/MediaBrowser.Controller/Channels/ChannelItemResult.cs @@ -1,6 +1,6 @@ #nullable disable -#pragma warning disable CS1591 +#pragma warning disable CA1002, CA2227, CS1591 using System.Collections.Generic; diff --git a/MediaBrowser.Controller/Channels/IHasFolderAttributes.cs b/MediaBrowser.Controller/Channels/IHasFolderAttributes.cs index 47277a8cc8..64af8496c7 100644 --- a/MediaBrowser.Controller/Channels/IHasFolderAttributes.cs +++ b/MediaBrowser.Controller/Channels/IHasFolderAttributes.cs @@ -1,4 +1,4 @@ -#pragma warning disable CS1591 +#pragma warning disable CA1819, CS1591 namespace MediaBrowser.Controller.Channels { diff --git a/MediaBrowser.Controller/Channels/InternalChannelFeatures.cs b/MediaBrowser.Controller/Channels/InternalChannelFeatures.cs index 45cd08173a..394996868e 100644 --- a/MediaBrowser.Controller/Channels/InternalChannelFeatures.cs +++ b/MediaBrowser.Controller/Channels/InternalChannelFeatures.cs @@ -1,6 +1,6 @@ #nullable disable -#pragma warning disable CS1591 +#pragma warning disable CA1002, CA2227, CS1591 using System.Collections.Generic; using MediaBrowser.Model.Channels; From 717ff4ec623245cf59344a5898c4c8943e2c2b39 Mon Sep 17 00:00:00 2001 From: Rich Lander Date: Fri, 23 Jul 2021 09:16:48 -0700 Subject: [PATCH 071/120] Fix warnings for MediaBrowser.Controller/Providers directory --- .../Providers/AlbumInfo.cs | 2 +- .../Providers/ArtistInfo.cs | 2 +- .../Providers/EpisodeInfo.cs | 2 +- .../Providers/IDirectoryService.cs | 2 +- .../Providers/IProviderManager.cs | 15 ++++++++++++++ .../Providers/ImageRefreshOptions.cs | 20 +++++++++---------- .../Providers/ItemLookupInfo.cs | 2 +- .../Providers/MetadataRefreshOptions.cs | 2 +- .../Providers/MetadataResult.cs | 2 +- .../Providers/SeasonInfo.cs | 2 +- MediaBrowser.Controller/Providers/SongInfo.cs | 12 +++++------ 11 files changed, 39 insertions(+), 24 deletions(-) diff --git a/MediaBrowser.Controller/Providers/AlbumInfo.cs b/MediaBrowser.Controller/Providers/AlbumInfo.cs index c7fad5974a..aefa520e72 100644 --- a/MediaBrowser.Controller/Providers/AlbumInfo.cs +++ b/MediaBrowser.Controller/Providers/AlbumInfo.cs @@ -1,4 +1,4 @@ -#pragma warning disable CS1591 +#pragma warning disable CA1002, CA2227, CS1591 using System; using System.Collections.Generic; diff --git a/MediaBrowser.Controller/Providers/ArtistInfo.cs b/MediaBrowser.Controller/Providers/ArtistInfo.cs index e9181f4765..4854d1a5fa 100644 --- a/MediaBrowser.Controller/Providers/ArtistInfo.cs +++ b/MediaBrowser.Controller/Providers/ArtistInfo.cs @@ -1,4 +1,4 @@ -#pragma warning disable CS1591 +#pragma warning disable CA1002, CA2227, CS1591 using System.Collections.Generic; diff --git a/MediaBrowser.Controller/Providers/EpisodeInfo.cs b/MediaBrowser.Controller/Providers/EpisodeInfo.cs index 0c932fa877..b59a037384 100644 --- a/MediaBrowser.Controller/Providers/EpisodeInfo.cs +++ b/MediaBrowser.Controller/Providers/EpisodeInfo.cs @@ -1,6 +1,6 @@ #nullable disable -#pragma warning disable CS1591 +#pragma warning disable CA2227, CS1591 using System; using System.Collections.Generic; diff --git a/MediaBrowser.Controller/Providers/IDirectoryService.cs b/MediaBrowser.Controller/Providers/IDirectoryService.cs index b1a36e1024..e5138ca144 100644 --- a/MediaBrowser.Controller/Providers/IDirectoryService.cs +++ b/MediaBrowser.Controller/Providers/IDirectoryService.cs @@ -1,4 +1,4 @@ -#pragma warning disable CS1591 +#pragma warning disable CA1002, CS1591 using System.Collections.Generic; using MediaBrowser.Model.IO; diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs index 684bd9e681..9f7a76be64 100644 --- a/MediaBrowser.Controller/Providers/IProviderManager.cs +++ b/MediaBrowser.Controller/Providers/IProviderManager.cs @@ -31,6 +31,9 @@ namespace MediaBrowser.Controller.Providers /// /// Queues the refresh. /// + /// Item ID. + /// MetadataRefreshOptions for operation. + /// RefreshPriority for operation. void QueueRefresh(Guid itemId, MetadataRefreshOptions options, RefreshPriority priority); /// @@ -85,6 +88,13 @@ namespace MediaBrowser.Controller.Providers /// /// Saves the image. /// + /// Image to save. + /// Source of image. + /// Mime type image. + /// Type of image. + /// Index of image. + /// Option to save locally. + /// CancellationToken to use with operation. /// Task. Task SaveImage(BaseItem item, string source, string mimeType, ImageType type, int? imageIndex, bool? saveLocallyWithMedia, CancellationToken cancellationToken); @@ -93,6 +103,11 @@ namespace MediaBrowser.Controller.Providers /// /// Adds the metadata providers. /// + /// Image providers to use. + /// Metadata services to use. + /// Metadata providers to use. + /// Metadata savers to use. + /// External IDs to use. void AddParts( IEnumerable imageProviders, IEnumerable metadataServices, diff --git a/MediaBrowser.Controller/Providers/ImageRefreshOptions.cs b/MediaBrowser.Controller/Providers/ImageRefreshOptions.cs index 81a22affb0..2ac4c728ba 100644 --- a/MediaBrowser.Controller/Providers/ImageRefreshOptions.cs +++ b/MediaBrowser.Controller/Providers/ImageRefreshOptions.cs @@ -1,6 +1,6 @@ #nullable disable -#pragma warning disable CS1591 +#pragma warning disable CA1819, CS1591 using System; using System.Linq; @@ -10,6 +10,15 @@ namespace MediaBrowser.Controller.Providers { public class ImageRefreshOptions { + public ImageRefreshOptions(IDirectoryService directoryService) + { + ImageRefreshMode = MetadataRefreshMode.Default; + DirectoryService = directoryService; + + ReplaceImages = Array.Empty(); + IsAutomated = true; + } + public MetadataRefreshMode ImageRefreshMode { get; set; } public IDirectoryService DirectoryService { get; private set; } @@ -20,15 +29,6 @@ namespace MediaBrowser.Controller.Providers public bool IsAutomated { get; set; } - public ImageRefreshOptions(IDirectoryService directoryService) - { - ImageRefreshMode = MetadataRefreshMode.Default; - DirectoryService = directoryService; - - ReplaceImages = Array.Empty(); - IsAutomated = true; - } - public bool IsReplacingImage(ImageType type) { return ImageRefreshMode == MetadataRefreshMode.FullRefresh && diff --git a/MediaBrowser.Controller/Providers/ItemLookupInfo.cs b/MediaBrowser.Controller/Providers/ItemLookupInfo.cs index 2219b62b81..460f4e500f 100644 --- a/MediaBrowser.Controller/Providers/ItemLookupInfo.cs +++ b/MediaBrowser.Controller/Providers/ItemLookupInfo.cs @@ -1,6 +1,6 @@ #nullable disable -#pragma warning disable CS1591 +#pragma warning disable CA2227, CS1591 using System; using System.Collections.Generic; diff --git a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs index 2cf5367793..a42c7f8b5e 100644 --- a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs +++ b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs @@ -1,6 +1,6 @@ #nullable disable -#pragma warning disable CS1591 +#pragma warning disable CA1819, CS1591 using System; using System.Linq; diff --git a/MediaBrowser.Controller/Providers/MetadataResult.cs b/MediaBrowser.Controller/Providers/MetadataResult.cs index 7ec1eefcd6..2085ae4adf 100644 --- a/MediaBrowser.Controller/Providers/MetadataResult.cs +++ b/MediaBrowser.Controller/Providers/MetadataResult.cs @@ -1,6 +1,6 @@ #nullable disable -#pragma warning disable CS1591 +#pragma warning disable CA1002, CA2227, CS1591 using System; using System.Collections.Generic; diff --git a/MediaBrowser.Controller/Providers/SeasonInfo.cs b/MediaBrowser.Controller/Providers/SeasonInfo.cs index 7e39bc37a6..1edceb0e4a 100644 --- a/MediaBrowser.Controller/Providers/SeasonInfo.cs +++ b/MediaBrowser.Controller/Providers/SeasonInfo.cs @@ -1,4 +1,4 @@ -#pragma warning disable CS1591 +#pragma warning disable CA2227, CS1591 using System; using System.Collections.Generic; diff --git a/MediaBrowser.Controller/Providers/SongInfo.cs b/MediaBrowser.Controller/Providers/SongInfo.cs index c90717a2e1..4b64a8a982 100644 --- a/MediaBrowser.Controller/Providers/SongInfo.cs +++ b/MediaBrowser.Controller/Providers/SongInfo.cs @@ -9,16 +9,16 @@ namespace MediaBrowser.Controller.Providers { public class SongInfo : ItemLookupInfo { - public IReadOnlyList AlbumArtists { get; set; } - - public string Album { get; set; } - - public IReadOnlyList Artists { get; set; } - public SongInfo() { Artists = Array.Empty(); AlbumArtists = Array.Empty(); } + + public IReadOnlyList AlbumArtists { get; set; } + + public string Album { get; set; } + + public IReadOnlyList Artists { get; set; } } } From f3b51dd77bdb335be39f24592c97abb1d28711a5 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Sat, 24 Jul 2021 14:03:08 +0200 Subject: [PATCH 072/120] Update tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs Co-authored-by: Max Rumpf --- tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs b/tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs index 43ffa84bf5..e2274e19ee 100644 --- a/tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs +++ b/tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs @@ -60,6 +60,7 @@ namespace Jellyfin.Model.Tests.Entities [InlineData(3840, 1606, false, "4K")] [InlineData(3840, 1608, false, "4K")] [InlineData(3840, 2160, false, "4K")] + [InlineData(7680, 4320, false, "8K")] public void GetResolutionText_Valid(int? width, int? height, bool interlaced, string expected) { var mediaStream = new MediaStream() From 5920f68ca93e230dbced152a5aaac65eccb97ecd Mon Sep 17 00:00:00 2001 From: Rich Lander Date: Sat, 24 Jul 2021 10:58:50 -0700 Subject: [PATCH 073/120] Fix warnings in MediaBrowser.Controller/Library --- .../Library/ILibraryManager.cs | 79 +++++++++++++------ .../Library/ILiveStream.cs | 2 +- .../Library/IMediaSourceManager.cs | 18 ++++- .../Library/IMediaSourceProvider.cs | 6 +- .../Library/IMetadataSaver.cs | 1 - .../Library/IMusicManager.cs | 14 +++- .../Library/IUserDataManager.cs | 9 ++- .../Library/IUserManager.cs | 14 +++- .../Library/IUserViewManager.cs | 21 ++++- .../Library/ItemChangeEventArgs.cs | 2 +- .../Library/ItemResolveArgs.cs | 54 ++++++------- .../Library/PlaybackProgressEventArgs.cs | 2 +- .../Library/UserDataSaveEventArgs.cs | 2 +- 13 files changed, 161 insertions(+), 63 deletions(-) diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 7a4ba6a24a..0bd2f38437 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -1,6 +1,6 @@ #nullable disable -#pragma warning disable CS1591 +#pragma warning disable CA1002, CS1591 using System; using System.Collections.Generic; @@ -31,6 +31,29 @@ namespace MediaBrowser.Controller.Library /// public interface ILibraryManager { + /// + /// Occurs when [item added]. + /// + event EventHandler ItemAdded; + + /// + /// Occurs when [item updated]. + /// + event EventHandler ItemUpdated; + + /// + /// Occurs when [item removed]. + /// + event EventHandler ItemRemoved; + + /// + /// Gets the root folder. + /// + /// The root folder. + AggregateFolder RootFolder { get; } + + bool IsScanRunning { get; } + /// /// Resolves the path. /// @@ -57,12 +80,6 @@ namespace MediaBrowser.Controller.Library LibraryOptions libraryOptions, string collectionType = null); - /// - /// Gets the root folder. - /// - /// The root folder. - AggregateFolder RootFolder { get; } - /// /// Gets a Person. /// @@ -113,7 +130,7 @@ namespace MediaBrowser.Controller.Library /// /// The value. /// Task{Year}. - /// + /// Throws if year is invalid. Year GetYear(int value); /// @@ -205,16 +222,26 @@ namespace MediaBrowser.Controller.Library /// /// Creates the item. /// + /// Item to create. + /// Parent of new item. void CreateItem(BaseItem item, BaseItem parent); /// /// Creates the items. /// + /// Items to create. + /// Parent of new items. + /// CancellationToken to use for operation. void CreateItems(IReadOnlyList items, BaseItem parent, CancellationToken cancellationToken); /// /// Updates the item. /// + /// Items to update. + /// Parent of updated items. + /// Reason for update. + /// CancellationToken to use for operation. + /// Returns a Task that can be awaited. Task UpdateItemsAsync(IReadOnlyList items, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken); /// @@ -224,6 +251,7 @@ namespace MediaBrowser.Controller.Library /// The parent item. /// The update reason. /// The cancellation token. + /// Returns a Task that can be awaited. Task UpdateItemAsync(BaseItem item, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken); /// @@ -233,23 +261,6 @@ namespace MediaBrowser.Controller.Library /// BaseItem. BaseItem RetrieveItem(Guid id); - bool IsScanRunning { get; } - - /// - /// Occurs when [item added]. - /// - event EventHandler ItemAdded; - - /// - /// Occurs when [item updated]. - /// - event EventHandler ItemUpdated; - - /// - /// Occurs when [item removed]. - /// - event EventHandler ItemRemoved; - /// /// Finds the type of the collection. /// @@ -294,16 +305,25 @@ namespace MediaBrowser.Controller.Library /// /// Deletes the item. /// + /// Item to delete. + /// Options to use for deletion. void DeleteItem(BaseItem item, DeleteOptions options); /// /// Deletes the item. /// + /// Item to delete. + /// Options to use for deletion. + /// Notify parent of deletion. void DeleteItem(BaseItem item, DeleteOptions options, bool notifyParentItem); /// /// Deletes the item. /// + /// Item to delete. + /// Options to use for deletion. + /// Parent of item. + /// Notify parent of deletion. void DeleteItem(BaseItem item, DeleteOptions options, BaseItem parent, bool notifyParentItem); /// @@ -314,6 +334,7 @@ namespace MediaBrowser.Controller.Library /// The parent identifier. /// Type of the view. /// Name of the sort. + /// The named view. UserView GetNamedView( User user, string name, @@ -328,6 +349,7 @@ namespace MediaBrowser.Controller.Library /// The name. /// Type of the view. /// Name of the sort. + /// The named view. UserView GetNamedView( User user, string name, @@ -340,6 +362,7 @@ namespace MediaBrowser.Controller.Library /// The name. /// Type of the view. /// Name of the sort. + /// The named view. UserView GetNamedView( string name, string viewType, @@ -397,6 +420,9 @@ namespace MediaBrowser.Controller.Library /// /// Fills the missing episode numbers from path. /// + /// Episode to use. + /// Option to force refresh of episode numbers. + /// True if successful. bool FillMissingEpisodeNumbersFromPath(Episode episode, bool forceRefresh); /// @@ -539,6 +565,9 @@ namespace MediaBrowser.Controller.Library /// /// Gets the items. /// + /// The query to use. + /// Items to use for query. + /// List of items. List GetItemList(InternalItemsQuery query, List parents); /// diff --git a/MediaBrowser.Controller/Library/ILiveStream.cs b/MediaBrowser.Controller/Library/ILiveStream.cs index 85d866de5c..323aa48768 100644 --- a/MediaBrowser.Controller/Library/ILiveStream.cs +++ b/MediaBrowser.Controller/Library/ILiveStream.cs @@ -1,6 +1,6 @@ #nullable disable -#pragma warning disable CS1591 +#pragma warning disable CA1711, CS1591 using System.Threading; using System.Threading.Tasks; diff --git a/MediaBrowser.Controller/Library/IMediaSourceManager.cs b/MediaBrowser.Controller/Library/IMediaSourceManager.cs index d3d85a0563..fd3631da9c 100644 --- a/MediaBrowser.Controller/Library/IMediaSourceManager.cs +++ b/MediaBrowser.Controller/Library/IMediaSourceManager.cs @@ -1,6 +1,6 @@ #nullable disable -#pragma warning disable CS1591 +#pragma warning disable CA1002, CS1591 using System; using System.Collections.Generic; @@ -62,16 +62,32 @@ namespace MediaBrowser.Controller.Library /// /// Gets the playack media sources. /// + /// Item to use. + /// User to use for operation. + /// Option to allow media probe. + /// Option to enable path substitution. + /// CancellationToken to use for operation. + /// List of media sources wrapped in an awaitable task. Task> GetPlaybackMediaSources(BaseItem item, User user, bool allowMediaProbe, bool enablePathSubstitution, CancellationToken cancellationToken); /// /// Gets the static media sources. /// + /// Item to use. + /// Option to enable path substitution. + /// User to use for operation. + /// List of media sources. List GetStaticMediaSources(BaseItem item, bool enablePathSubstitution, User user = null); /// /// Gets the static media source. /// + /// Item to use. + /// Media source to get. + /// Live stream to use. + /// Option to enable path substitution. + /// CancellationToken to use for operation. + /// The static media source wrapped in an awaitable task. Task GetMediaSource(BaseItem item, string mediaSourceId, string liveStreamId, bool enablePathSubstitution, CancellationToken cancellationToken); /// diff --git a/MediaBrowser.Controller/Library/IMediaSourceProvider.cs b/MediaBrowser.Controller/Library/IMediaSourceProvider.cs index 5bf4acebb4..ca4b53fbee 100644 --- a/MediaBrowser.Controller/Library/IMediaSourceProvider.cs +++ b/MediaBrowser.Controller/Library/IMediaSourceProvider.cs @@ -1,4 +1,4 @@ -#pragma warning disable CS1591 +#pragma warning disable CA1002, CS1591 using System.Collections.Generic; using System.Threading; @@ -21,6 +21,10 @@ namespace MediaBrowser.Controller.Library /// /// Opens the media source. /// + /// Token to use. + /// List of live streams. + /// CancellationToken to use for operation. + /// The media source wrapped as an awaitable task. Task OpenMediaSource(string openToken, List currentLiveStreams, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.Controller/Library/IMetadataSaver.cs b/MediaBrowser.Controller/Library/IMetadataSaver.cs index 5fbfad8814..d963fd2491 100644 --- a/MediaBrowser.Controller/Library/IMetadataSaver.cs +++ b/MediaBrowser.Controller/Library/IMetadataSaver.cs @@ -29,7 +29,6 @@ namespace MediaBrowser.Controller.Library /// /// The item. /// The cancellation token. - /// Task. void Save(BaseItem item, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.Controller/Library/IMusicManager.cs b/MediaBrowser.Controller/Library/IMusicManager.cs index 5329841bf5..ec34a868b3 100644 --- a/MediaBrowser.Controller/Library/IMusicManager.cs +++ b/MediaBrowser.Controller/Library/IMusicManager.cs @@ -1,6 +1,6 @@ #nullable disable -#pragma warning disable CS1591 +#pragma warning disable CA1002, CS1591 using System.Collections.Generic; using Jellyfin.Data.Entities; @@ -15,16 +15,28 @@ namespace MediaBrowser.Controller.Library /// /// Gets the instant mix from song. /// + /// The item to use. + /// The user to use. + /// The options to use. + /// List of items. List GetInstantMixFromItem(BaseItem item, User user, DtoOptions dtoOptions); /// /// Gets the instant mix from artist. /// + /// The artist to use. + /// The user to use. + /// The options to use. + /// List of items. List GetInstantMixFromArtist(MusicArtist artist, User user, DtoOptions dtoOptions); /// /// Gets the instant mix from genre. /// + /// The genres to use. + /// The user to use. + /// The options to use. + /// List of items. List GetInstantMixFromGenres(IEnumerable genres, User user, DtoOptions dtoOptions); } } diff --git a/MediaBrowser.Controller/Library/IUserDataManager.cs b/MediaBrowser.Controller/Library/IUserDataManager.cs index e5dcfcff04..cf35b48dba 100644 --- a/MediaBrowser.Controller/Library/IUserDataManager.cs +++ b/MediaBrowser.Controller/Library/IUserDataManager.cs @@ -1,6 +1,6 @@ #nullable disable -#pragma warning disable CS1591 +#pragma warning disable CA1002, CA1707, CS1591 using System; using System.Collections.Generic; @@ -42,6 +42,9 @@ namespace MediaBrowser.Controller.Library /// /// Gets the user data dto. /// + /// Item to use. + /// User to use. + /// User data dto. UserItemDataDto GetUserDataDto(BaseItem item, User user); UserItemDataDto GetUserDataDto(BaseItem item, BaseItemDto itemDto, User user, DtoOptions dto_options); @@ -64,6 +67,10 @@ namespace MediaBrowser.Controller.Library /// /// Updates playstate for an item and returns true or false indicating if it was played to completion. /// + /// Item to update. + /// Data to update. + /// New playstate. + /// True if playstate was updated. bool UpdatePlayState(BaseItem item, UserItemData data, long? positionTicks); } } diff --git a/MediaBrowser.Controller/Library/IUserManager.cs b/MediaBrowser.Controller/Library/IUserManager.cs index 1801b1c413..21776f8915 100644 --- a/MediaBrowser.Controller/Library/IUserManager.cs +++ b/MediaBrowser.Controller/Library/IUserManager.cs @@ -38,6 +38,7 @@ namespace MediaBrowser.Controller.Library /// /// Initializes the user manager and ensures that a user exists. /// + /// Awaitable task. Task InitializeAsync(); /// @@ -109,17 +110,22 @@ namespace MediaBrowser.Controller.Library /// Resets the easy password. /// /// The user. - /// Task. void ResetEasyPassword(User user); /// /// Changes the password. /// + /// The user. + /// New password to use. + /// Awaitable task. Task ChangePassword(User user, string newPassword); /// /// Changes the easy password. /// + /// The user. + /// New password to use. + /// Hash of new password. void ChangeEasyPassword(User user, string newPassword, string newPasswordSha1); /// @@ -133,6 +139,12 @@ namespace MediaBrowser.Controller.Library /// /// Authenticates the user. /// + /// The user. + /// The password to use. + /// Hash of password. + /// Remove endpoint to use. + /// Specifies if a user session. + /// User wrapped in awaitable task. Task AuthenticateUser(string username, string password, string passwordSha1, string remoteEndPoint, bool isUserSession); /// diff --git a/MediaBrowser.Controller/Library/IUserViewManager.cs b/MediaBrowser.Controller/Library/IUserViewManager.cs index 46004e42f7..055627d3e3 100644 --- a/MediaBrowser.Controller/Library/IUserViewManager.cs +++ b/MediaBrowser.Controller/Library/IUserViewManager.cs @@ -1,6 +1,6 @@ #nullable disable -#pragma warning disable CS1591 +#pragma warning disable CA1002, CS1591 using System; using System.Collections.Generic; @@ -13,10 +13,29 @@ namespace MediaBrowser.Controller.Library { public interface IUserViewManager { + /// + /// Gets user views. + /// + /// Query to use. + /// Set of folders. Folder[] GetUserViews(UserViewQuery query); + /// + /// Gets user sub views. + /// + /// Parent to use. + /// Type to use. + /// Localization key to use. + /// Sort to use. + /// User view. UserView GetUserSubView(Guid parentId, string type, string localizationKey, string sortName); + /// + /// Gets latest items. + /// + /// Query to use. + /// Options to use. + /// Set of items. List>> GetLatestItems(LatestItemsQuery request, DtoOptions options); } } diff --git a/MediaBrowser.Controller/Library/ItemChangeEventArgs.cs b/MediaBrowser.Controller/Library/ItemChangeEventArgs.cs index a37dc7af11..3586dc69d6 100644 --- a/MediaBrowser.Controller/Library/ItemChangeEventArgs.cs +++ b/MediaBrowser.Controller/Library/ItemChangeEventArgs.cs @@ -1,6 +1,6 @@ #nullable disable -#pragma warning disable CS1591 +#pragma warning disable CA1711, CS1591 using MediaBrowser.Controller.Entities; diff --git a/MediaBrowser.Controller/Library/ItemResolveArgs.cs b/MediaBrowser.Controller/Library/ItemResolveArgs.cs index 521e372742..bfc1e4857f 100644 --- a/MediaBrowser.Controller/Library/ItemResolveArgs.cs +++ b/MediaBrowser.Controller/Library/ItemResolveArgs.cs @@ -1,6 +1,6 @@ #nullable disable -#pragma warning disable CS1591 +#pragma warning disable CA1721, CA1819, CS1591 using System; using System.Collections.Generic; @@ -109,6 +109,21 @@ namespace MediaBrowser.Controller.Library /// The additional locations. private List AdditionalLocations { get; set; } + /// + /// Gets the physical locations. + /// + /// The physical locations. + public string[] PhysicalLocations + { + get + { + var paths = string.IsNullOrEmpty(Path) ? Array.Empty() : new[] { Path }; + return AdditionalLocations == null ? paths : paths.Concat(AdditionalLocations).ToArray(); + } + } + + public string CollectionType { get; set; } + public bool HasParent() where T : Folder { @@ -138,6 +153,16 @@ namespace MediaBrowser.Controller.Library return false; } + /// + /// Determines whether the specified is equal to this instance. + /// + /// The object to compare with the current object. + /// true if the specified is equal to this instance; otherwise, false. + public override bool Equals(object obj) + { + return Equals(obj as ItemResolveArgs); + } + /// /// Adds the additional location. /// @@ -156,19 +181,6 @@ namespace MediaBrowser.Controller.Library // REVIEW: @bond - /// - /// Gets the physical locations. - /// - /// The physical locations. - public string[] PhysicalLocations - { - get - { - var paths = string.IsNullOrEmpty(Path) ? Array.Empty() : new[] { Path }; - return AdditionalLocations == null ? paths : paths.Concat(AdditionalLocations).ToArray(); - } - } - /// /// Gets the name of the file system entry by. /// @@ -190,7 +202,7 @@ namespace MediaBrowser.Controller.Library /// /// The path. /// FileSystemInfo. - /// + /// Throws if path is invalid. public FileSystemMetadata GetFileSystemEntryByPath(string path) { if (string.IsNullOrEmpty(path)) @@ -224,18 +236,6 @@ namespace MediaBrowser.Controller.Library return CollectionType; } - public string CollectionType { get; set; } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The object to compare with the current object. - /// true if the specified is equal to this instance; otherwise, false. - public override bool Equals(object obj) - { - return Equals(obj as ItemResolveArgs); - } - /// /// Returns a hash code for this instance. /// diff --git a/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs b/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs index 609336ec4d..76e9eb1f54 100644 --- a/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs +++ b/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs @@ -1,6 +1,6 @@ #nullable disable -#pragma warning disable CS1591 +#pragma warning disable CA1002, CA2227, CS1591 using System; using System.Collections.Generic; diff --git a/MediaBrowser.Controller/Library/UserDataSaveEventArgs.cs b/MediaBrowser.Controller/Library/UserDataSaveEventArgs.cs index bfe433c971..4d90346f29 100644 --- a/MediaBrowser.Controller/Library/UserDataSaveEventArgs.cs +++ b/MediaBrowser.Controller/Library/UserDataSaveEventArgs.cs @@ -1,6 +1,6 @@ #nullable disable -#pragma warning disable CS1591 +#pragma warning disable CA1002, CA2227, CS1591 using System; using System.Collections.Generic; From e91a2b1085b9e49b38f14ce22054ed08afacb80f Mon Sep 17 00:00:00 2001 From: Rich Lander Date: Sat, 24 Jul 2021 16:35:43 -0700 Subject: [PATCH 074/120] Update to later .NET SDK --- .ci/azure-pipelines-abi.yml | 2 +- .ci/azure-pipelines-main.yml | 2 +- .ci/azure-pipelines-test.yml | 2 +- .ci/azure-pipelines.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.ci/azure-pipelines-abi.yml b/.ci/azure-pipelines-abi.yml index 8d0737b66c..e58a2bdc7e 100644 --- a/.ci/azure-pipelines-abi.yml +++ b/.ci/azure-pipelines-abi.yml @@ -7,7 +7,7 @@ parameters: default: "ubuntu-latest" - name: DotNetSdkVersion type: string - default: 5.0.103 + default: 5.0.302 jobs: - job: CompatibilityCheck diff --git a/.ci/azure-pipelines-main.yml b/.ci/azure-pipelines-main.yml index 4bc72f9eb0..d2c087c14d 100644 --- a/.ci/azure-pipelines-main.yml +++ b/.ci/azure-pipelines-main.yml @@ -1,7 +1,7 @@ parameters: LinuxImage: 'ubuntu-latest' RestoreBuildProjects: 'Jellyfin.Server/Jellyfin.Server.csproj' - DotNetSdkVersion: 5.0.103 + DotNetSdkVersion: 5.0.302 jobs: - job: Build diff --git a/.ci/azure-pipelines-test.yml b/.ci/azure-pipelines-test.yml index 7838b3b026..7ec4cdad1d 100644 --- a/.ci/azure-pipelines-test.yml +++ b/.ci/azure-pipelines-test.yml @@ -10,7 +10,7 @@ parameters: default: "tests/**/*Tests.csproj" - name: DotNetSdkVersion type: string - default: 5.0.103 + default: 5.0.302 jobs: - job: Test diff --git a/.ci/azure-pipelines.yml b/.ci/azure-pipelines.yml index c028b6e3e8..4e8b6557b9 100644 --- a/.ci/azure-pipelines.yml +++ b/.ci/azure-pipelines.yml @@ -6,7 +6,7 @@ variables: - name: RestoreBuildProjects value: 'Jellyfin.Server/Jellyfin.Server.csproj' - name: DotNetSdkVersion - value: 5.0.103 + value: 5.0.302 pr: autoCancel: true From 9aebb86a68cacb2b1f8837e876fa422aa6ca2e4e Mon Sep 17 00:00:00 2001 From: Rich Lander Date: Sat, 24 Jul 2021 20:33:58 -0700 Subject: [PATCH 075/120] Fix warnings in MediaBrowser.Controller/Drawing --- MediaBrowser.Controller/Chapters/IChapterManager.cs | 2 ++ .../Collections/CollectionCreationOptions.cs | 2 +- .../Collections/ICollectionManager.cs | 1 + MediaBrowser.Controller/Drawing/IImageEncoder.cs | 9 +++++++++ MediaBrowser.Controller/Drawing/ImageStream.cs | 2 +- MediaBrowser.Controller/Dto/IDtoService.cs | 1 + .../Security/IAuthenticationRepository.cs | 2 -- 7 files changed, 15 insertions(+), 4 deletions(-) diff --git a/MediaBrowser.Controller/Chapters/IChapterManager.cs b/MediaBrowser.Controller/Chapters/IChapterManager.cs index f82e5b41a2..c049bb97e7 100644 --- a/MediaBrowser.Controller/Chapters/IChapterManager.cs +++ b/MediaBrowser.Controller/Chapters/IChapterManager.cs @@ -12,6 +12,8 @@ namespace MediaBrowser.Controller.Chapters /// /// Saves the chapters. /// + /// The item. + /// The set of chapters. void SaveChapters(Guid itemId, IReadOnlyList chapters); } } diff --git a/MediaBrowser.Controller/Collections/CollectionCreationOptions.cs b/MediaBrowser.Controller/Collections/CollectionCreationOptions.cs index 30f5f4efa2..76ad335c59 100644 --- a/MediaBrowser.Controller/Collections/CollectionCreationOptions.cs +++ b/MediaBrowser.Controller/Collections/CollectionCreationOptions.cs @@ -1,6 +1,6 @@ #nullable disable -#pragma warning disable CS1591 +#pragma warning disable CA2227, CS1591 using System; using System.Collections.Generic; diff --git a/MediaBrowser.Controller/Collections/ICollectionManager.cs b/MediaBrowser.Controller/Collections/ICollectionManager.cs index 46bc37e7f6..49cc39f047 100644 --- a/MediaBrowser.Controller/Collections/ICollectionManager.cs +++ b/MediaBrowser.Controller/Collections/ICollectionManager.cs @@ -32,6 +32,7 @@ namespace MediaBrowser.Controller.Collections /// Creates the collection. /// /// The options. + /// BoxSet wrapped in an awaitable task. Task CreateCollectionAsync(CollectionCreationOptions options); /// diff --git a/MediaBrowser.Controller/Drawing/IImageEncoder.cs b/MediaBrowser.Controller/Drawing/IImageEncoder.cs index 4e640d4215..4e67cfee4f 100644 --- a/MediaBrowser.Controller/Drawing/IImageEncoder.cs +++ b/MediaBrowser.Controller/Drawing/IImageEncoder.cs @@ -57,6 +57,15 @@ namespace MediaBrowser.Controller.Drawing /// /// Encode an image. /// + /// Input path of image. + /// Date modified. + /// Output path of image. + /// Auto-orient image. + /// Desired orientation of image. + /// Quality of encoded image. + /// Image processing options. + /// Image format of output. + /// Path of encoded image. string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation? orientation, int quality, ImageProcessingOptions options, ImageFormat outputFormat); /// diff --git a/MediaBrowser.Controller/Drawing/ImageStream.cs b/MediaBrowser.Controller/Drawing/ImageStream.cs index 5ee781ffa9..5d552170f9 100644 --- a/MediaBrowser.Controller/Drawing/ImageStream.cs +++ b/MediaBrowser.Controller/Drawing/ImageStream.cs @@ -1,4 +1,4 @@ -#pragma warning disable CS1591 +#pragma warning disable CA1711, CS1591 using System; using System.IO; diff --git a/MediaBrowser.Controller/Dto/IDtoService.cs b/MediaBrowser.Controller/Dto/IDtoService.cs index 61d7962357..89aafc84fb 100644 --- a/MediaBrowser.Controller/Dto/IDtoService.cs +++ b/MediaBrowser.Controller/Dto/IDtoService.cs @@ -1,4 +1,5 @@ #nullable disable +#pragma warning disable CA1002 using System.Collections.Generic; using Jellyfin.Data.Entities; diff --git a/MediaBrowser.Controller/Security/IAuthenticationRepository.cs b/MediaBrowser.Controller/Security/IAuthenticationRepository.cs index 1dd69ccd85..bd1289c1a6 100644 --- a/MediaBrowser.Controller/Security/IAuthenticationRepository.cs +++ b/MediaBrowser.Controller/Security/IAuthenticationRepository.cs @@ -13,14 +13,12 @@ namespace MediaBrowser.Controller.Security /// Creates the specified information. /// /// The information. - /// Task. void Create(AuthenticationInfo info); /// /// Updates the specified information. /// /// The information. - /// Task. void Update(AuthenticationInfo info); /// From b024059f7120a901974c0ec673371b819b23bdfd Mon Sep 17 00:00:00 2001 From: SaddFox Date: Sat, 24 Jul 2021 12:32:49 +0000 Subject: [PATCH 076/120] Translated using Weblate (Slovenian) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/sl/ --- Emby.Server.Implementations/Localization/Core/sl-SI.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/sl-SI.json b/Emby.Server.Implementations/Localization/Core/sl-SI.json index 1852dc89e4..a6fcbd3e29 100644 --- a/Emby.Server.Implementations/Localization/Core/sl-SI.json +++ b/Emby.Server.Implementations/Localization/Core/sl-SI.json @@ -16,7 +16,7 @@ "Folders": "Mape", "Genres": "Zvrsti", "HeaderAlbumArtists": "Izvajalci albuma", - "HeaderContinueWatching": "Nadaljuj z ogledom", + "HeaderContinueWatching": "Nadaljuj ogled", "HeaderFavoriteAlbums": "Priljubljeni albumi", "HeaderFavoriteArtists": "Priljubljeni izvajalci", "HeaderFavoriteEpisodes": "Priljubljene epizode", @@ -90,7 +90,7 @@ "UserStartedPlayingItemWithValues": "{0} predvaja {1} na {2}", "UserStoppedPlayingItemWithValues": "{0} je nehal predvajati {1} na {2}", "ValueHasBeenAddedToLibrary": "{0} je bil dodan vaši knjižnici", - "ValueSpecialEpisodeName": "Posebna - {0}", + "ValueSpecialEpisodeName": "Bonus - {0}", "VersionNumber": "Različica {0}", "TaskDownloadMissingSubtitles": "Prenesi manjkajoče podnapise", "TaskRefreshChannelsDescription": "Osveži podatke spletnih kanalov.", From 33359d45bee525045bd7ba0625d026bdf36e620c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Jul 2021 12:00:45 +0000 Subject: [PATCH 077/120] Bump coverlet.collector from 3.0.3 to 3.1.0 Bumps [coverlet.collector](https://github.com/coverlet-coverage/coverlet) from 3.0.3 to 3.1.0. - [Release notes](https://github.com/coverlet-coverage/coverlet/releases) - [Commits](https://github.com/coverlet-coverage/coverlet/commits/v3.1.0) --- updated-dependencies: - dependency-name: coverlet.collector dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj | 2 +- tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj | 2 +- .../Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj | 2 +- tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj | 2 +- .../Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj | 2 +- .../Jellyfin.MediaEncoding.Tests.csproj | 2 +- tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj | 2 +- tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj | 2 +- .../Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj | 2 +- tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj | 2 +- .../Jellyfin.Server.Implementations.Tests.csproj | 2 +- .../Jellyfin.Server.Integration.Tests.csproj | 2 +- tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj | 2 +- .../Jellyfin.XbmcMetadata.Tests.csproj | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index 07538b38bb..3cbae0863c 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -23,7 +23,7 @@ - + diff --git a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj index 546b2487e8..fa0ef25111 100644 --- a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj +++ b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj @@ -18,7 +18,7 @@ - + diff --git a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj index 9a8ddafa0b..285e9a2a9c 100644 --- a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj +++ b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj @@ -19,7 +19,7 @@ - + diff --git a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj index 1f6cd541cb..d7d0a8f439 100644 --- a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj +++ b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj index f87e63be26..c4d05b8f5f 100644 --- a/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj +++ b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj @@ -16,7 +16,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj index 6b828e1135..fcd9d6cb5f 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj +++ b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj @@ -24,7 +24,7 @@ - + diff --git a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj index 40c51e5248..7299a47dc7 100644 --- a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj +++ b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj @@ -13,7 +13,7 @@ - + diff --git a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj index e386cb8c16..d7987ba96a 100644 --- a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj +++ b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj @@ -18,7 +18,7 @@ - + diff --git a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj index 97bf673ae6..3078e648aa 100644 --- a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj +++ b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj @@ -18,7 +18,7 @@ - + diff --git a/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj b/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj index 14bd53db5f..26506a92b9 100644 --- a/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj +++ b/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj @@ -17,7 +17,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all 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 adbca83446..ae957c2ab1 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj +++ b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj @@ -29,7 +29,7 @@ - + diff --git a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj index 8bbe583871..982d2081ab 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj +++ b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj @@ -18,7 +18,7 @@ - + diff --git a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj index 0bd48e8ab3..73c1170fd2 100644 --- a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj +++ b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj @@ -18,7 +18,7 @@ - + diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj index 0a04a5c543..278e4f076a 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj +++ b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj @@ -20,7 +20,7 @@ - + From 501de7b6dcbeeb124cc0a2a84f21be4ec19be8ec Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Mon, 26 Jul 2021 23:02:32 +0200 Subject: [PATCH 078/120] Enable nullable in more files --- Emby.Dlna/Configuration/DlnaOptions.cs | 4 +-- .../ContentDirectoryService.cs | 4 +-- Emby.Dlna/ControlResponse.cs | 6 ++-- Emby.Dlna/EventSubscriptionResponse.cs | 6 ++-- Emby.Dlna/Eventing/DlnaEventManager.cs | 18 ++--------- Emby.Dlna/PlayTo/Device.cs | 21 +++--------- Emby.Dlna/PlayTo/MediaChangedEventArgs.cs | 10 ++++-- Emby.Dlna/PlayTo/PlaybackProgressEventArgs.cs | 7 ++-- Emby.Dlna/PlayTo/PlaybackStartEventArgs.cs | 7 ++-- Emby.Dlna/PlayTo/PlaybackStoppedEventArgs.cs | 7 ++-- Emby.Dlna/Service/BaseControlHandler.cs | 6 +--- Emby.Dlna/Service/ControlErrorHandler.cs | 6 +--- .../Activity/ActivityManager.cs | 5 +-- .../Activity/ActivityLogEntry.cs | 27 ++++++++++++---- .../Branding/BrandingOptions.cs | 5 ++- MediaBrowser.Model/Channels/ChannelInfo.cs | 32 ------------------- 16 files changed, 62 insertions(+), 109 deletions(-) delete mode 100644 MediaBrowser.Model/Channels/ChannelInfo.cs diff --git a/Emby.Dlna/Configuration/DlnaOptions.cs b/Emby.Dlna/Configuration/DlnaOptions.cs index 5ceeb55300..91fac4bef5 100644 --- a/Emby.Dlna/Configuration/DlnaOptions.cs +++ b/Emby.Dlna/Configuration/DlnaOptions.cs @@ -1,5 +1,3 @@ -#nullable disable - #pragma warning disable CS1591 namespace Emby.Dlna.Configuration @@ -74,7 +72,7 @@ namespace Emby.Dlna.Configuration /// /// Gets or sets the default user account that the dlna server uses. /// - public string DefaultUserId { get; set; } + public string? DefaultUserId { get; set; } /// /// Gets or sets a value indicating whether playTo device profiles should be created. diff --git a/Emby.Dlna/ContentDirectory/ContentDirectoryService.cs b/Emby.Dlna/ContentDirectory/ContentDirectoryService.cs index 7b8c504409..9020dea994 100644 --- a/Emby.Dlna/ContentDirectory/ContentDirectoryService.cs +++ b/Emby.Dlna/ContentDirectory/ContentDirectoryService.cs @@ -1,5 +1,3 @@ -#nullable disable - #pragma warning disable CS1591 using System; @@ -140,7 +138,7 @@ namespace Emby.Dlna.ContentDirectory /// /// The . /// The . - private User GetUser(DeviceProfile profile) + private User? GetUser(DeviceProfile profile) { if (!string.IsNullOrEmpty(profile.UserId)) { diff --git a/Emby.Dlna/ControlResponse.cs b/Emby.Dlna/ControlResponse.cs index a7f2d4a73b..8b09588424 100644 --- a/Emby.Dlna/ControlResponse.cs +++ b/Emby.Dlna/ControlResponse.cs @@ -1,5 +1,3 @@ -#nullable disable - #pragma warning disable CS1591 using System.Collections.Generic; @@ -8,9 +6,11 @@ namespace Emby.Dlna { public class ControlResponse { - public ControlResponse() + public ControlResponse(string xml, bool isSuccessful) { Headers = new Dictionary(); + Xml = xml; + IsSuccessful = isSuccessful; } public IDictionary Headers { get; } diff --git a/Emby.Dlna/EventSubscriptionResponse.cs b/Emby.Dlna/EventSubscriptionResponse.cs index 8c82dcbf68..635d2c47a1 100644 --- a/Emby.Dlna/EventSubscriptionResponse.cs +++ b/Emby.Dlna/EventSubscriptionResponse.cs @@ -1,5 +1,3 @@ -#nullable disable - #pragma warning disable CS1591 using System.Collections.Generic; @@ -8,8 +6,10 @@ namespace Emby.Dlna { public class EventSubscriptionResponse { - public EventSubscriptionResponse() + public EventSubscriptionResponse(string content, string contentType) { + Content = content; + ContentType = contentType; Headers = new Dictionary(); } diff --git a/Emby.Dlna/Eventing/DlnaEventManager.cs b/Emby.Dlna/Eventing/DlnaEventManager.cs index 2e672b886b..3c91360904 100644 --- a/Emby.Dlna/Eventing/DlnaEventManager.cs +++ b/Emby.Dlna/Eventing/DlnaEventManager.cs @@ -51,11 +51,7 @@ namespace Emby.Dlna.Eventing return GetEventSubscriptionResponse(subscriptionId, requestedTimeoutString, timeoutSeconds); } - return new EventSubscriptionResponse - { - Content = string.Empty, - ContentType = "text/plain" - }; + return new EventSubscriptionResponse(string.Empty, "text/plain"); } public EventSubscriptionResponse CreateEventSubscription(string notificationType, string requestedTimeoutString, string callbackUrl) @@ -103,20 +99,12 @@ namespace Emby.Dlna.Eventing _subscriptions.TryRemove(subscriptionId, out _); - return new EventSubscriptionResponse - { - Content = string.Empty, - ContentType = "text/plain" - }; + return new EventSubscriptionResponse(string.Empty, "text/plain"); } private EventSubscriptionResponse GetEventSubscriptionResponse(string subscriptionId, string requestedTimeoutString, int timeoutSeconds) { - var response = new EventSubscriptionResponse - { - Content = string.Empty, - ContentType = "text/plain" - }; + var response = new EventSubscriptionResponse(string.Empty, "text/plain"); response.Headers["SID"] = subscriptionId; response.Headers["TIMEOUT"] = string.IsNullOrEmpty(requestedTimeoutString) ? ("SECOND-" + timeoutSeconds.ToString(_usCulture)) : requestedTimeoutString; diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs index 6c580d15bd..11fcd81cff 100644 --- a/Emby.Dlna/PlayTo/Device.cs +++ b/Emby.Dlna/PlayTo/Device.cs @@ -1260,10 +1260,7 @@ namespace Emby.Dlna.PlayTo return; } - PlaybackStart?.Invoke(this, new PlaybackStartEventArgs - { - MediaInfo = mediaInfo - }); + PlaybackStart?.Invoke(this, new PlaybackStartEventArgs(mediaInfo)); } private void OnPlaybackProgress(UBaseObject mediaInfo) @@ -1273,27 +1270,17 @@ namespace Emby.Dlna.PlayTo return; } - PlaybackProgress?.Invoke(this, new PlaybackProgressEventArgs - { - MediaInfo = mediaInfo - }); + PlaybackProgress?.Invoke(this, new PlaybackProgressEventArgs(mediaInfo)); } private void OnPlaybackStop(UBaseObject mediaInfo) { - PlaybackStopped?.Invoke(this, new PlaybackStoppedEventArgs - { - MediaInfo = mediaInfo - }); + PlaybackStopped?.Invoke(this, new PlaybackStoppedEventArgs(mediaInfo)); } private void OnMediaChanged(UBaseObject old, UBaseObject newMedia) { - MediaChanged?.Invoke(this, new MediaChangedEventArgs - { - OldMediaInfo = old, - NewMediaInfo = newMedia - }); + MediaChanged?.Invoke(this, new MediaChangedEventArgs(old, newMedia)); } /// diff --git a/Emby.Dlna/PlayTo/MediaChangedEventArgs.cs b/Emby.Dlna/PlayTo/MediaChangedEventArgs.cs index 2bc4d8cc24..0f7a524d62 100644 --- a/Emby.Dlna/PlayTo/MediaChangedEventArgs.cs +++ b/Emby.Dlna/PlayTo/MediaChangedEventArgs.cs @@ -1,6 +1,4 @@ -#nullable disable - -#pragma warning disable CS1591 +#pragma warning disable CS1591 using System; @@ -8,6 +6,12 @@ namespace Emby.Dlna.PlayTo { public class MediaChangedEventArgs : EventArgs { + public MediaChangedEventArgs(UBaseObject oldMediaInfo, UBaseObject newMediaInfo) + { + OldMediaInfo = oldMediaInfo; + NewMediaInfo = newMediaInfo; + } + public UBaseObject OldMediaInfo { get; set; } public UBaseObject NewMediaInfo { get; set; } diff --git a/Emby.Dlna/PlayTo/PlaybackProgressEventArgs.cs b/Emby.Dlna/PlayTo/PlaybackProgressEventArgs.cs index c7d2b28df8..c95d8b1e84 100644 --- a/Emby.Dlna/PlayTo/PlaybackProgressEventArgs.cs +++ b/Emby.Dlna/PlayTo/PlaybackProgressEventArgs.cs @@ -1,5 +1,3 @@ -#nullable disable - #pragma warning disable CS1591 using System; @@ -8,6 +6,11 @@ namespace Emby.Dlna.PlayTo { public class PlaybackProgressEventArgs : EventArgs { + public PlaybackProgressEventArgs(UBaseObject mediaInfo) + { + MediaInfo = mediaInfo; + } + public UBaseObject MediaInfo { get; set; } } } diff --git a/Emby.Dlna/PlayTo/PlaybackStartEventArgs.cs b/Emby.Dlna/PlayTo/PlaybackStartEventArgs.cs index f8a14f411f..619c861ed9 100644 --- a/Emby.Dlna/PlayTo/PlaybackStartEventArgs.cs +++ b/Emby.Dlna/PlayTo/PlaybackStartEventArgs.cs @@ -1,5 +1,3 @@ -#nullable disable - #pragma warning disable CS1591 using System; @@ -8,6 +6,11 @@ namespace Emby.Dlna.PlayTo { public class PlaybackStartEventArgs : EventArgs { + public PlaybackStartEventArgs(UBaseObject mediaInfo) + { + MediaInfo = mediaInfo; + } + public UBaseObject MediaInfo { get; set; } } } diff --git a/Emby.Dlna/PlayTo/PlaybackStoppedEventArgs.cs b/Emby.Dlna/PlayTo/PlaybackStoppedEventArgs.cs index 6661f92ac7..d0ec250591 100644 --- a/Emby.Dlna/PlayTo/PlaybackStoppedEventArgs.cs +++ b/Emby.Dlna/PlayTo/PlaybackStoppedEventArgs.cs @@ -1,5 +1,3 @@ -#nullable disable - #pragma warning disable CS1591 using System; @@ -8,6 +6,11 @@ namespace Emby.Dlna.PlayTo { public class PlaybackStoppedEventArgs : EventArgs { + public PlaybackStoppedEventArgs(UBaseObject mediaInfo) + { + MediaInfo = mediaInfo; + } + public UBaseObject MediaInfo { get; set; } } } diff --git a/Emby.Dlna/Service/BaseControlHandler.cs b/Emby.Dlna/Service/BaseControlHandler.cs index b3ee860f4b..581e4a2861 100644 --- a/Emby.Dlna/Service/BaseControlHandler.cs +++ b/Emby.Dlna/Service/BaseControlHandler.cs @@ -95,11 +95,7 @@ namespace Emby.Dlna.Service var xml = builder.ToString().Replace("xmlns:m=", "xmlns:u=", StringComparison.Ordinal); - var controlResponse = new ControlResponse - { - Xml = xml, - IsSuccessful = true - }; + var controlResponse = new ControlResponse(xml, true); controlResponse.Headers.Add("EXT", string.Empty); diff --git a/Emby.Dlna/Service/ControlErrorHandler.cs b/Emby.Dlna/Service/ControlErrorHandler.cs index f2b5dd9ca8..3e2cd6d2e4 100644 --- a/Emby.Dlna/Service/ControlErrorHandler.cs +++ b/Emby.Dlna/Service/ControlErrorHandler.cs @@ -46,11 +46,7 @@ namespace Emby.Dlna.Service writer.WriteEndDocument(); } - return new ControlResponse - { - Xml = builder.ToString(), - IsSuccessful = false - }; + return new ControlResponse(builder.ToString(), false); } } } diff --git a/Jellyfin.Server.Implementations/Activity/ActivityManager.cs b/Jellyfin.Server.Implementations/Activity/ActivityManager.cs index 27360afb0a..a3a2a8baff 100644 --- a/Jellyfin.Server.Implementations/Activity/ActivityManager.cs +++ b/Jellyfin.Server.Implementations/Activity/ActivityManager.cs @@ -86,15 +86,12 @@ namespace Jellyfin.Server.Implementations.Activity private static ActivityLogEntry ConvertToOldModel(ActivityLog entry) { - return new ActivityLogEntry + return new ActivityLogEntry(entry.Name, entry.Type, entry.UserId) { Id = entry.Id, - Name = entry.Name, Overview = entry.Overview, ShortOverview = entry.ShortOverview, - Type = entry.Type, ItemId = entry.ItemId, - UserId = entry.UserId, Date = entry.DateCreated, Severity = entry.LogSeverity }; diff --git a/MediaBrowser.Model/Activity/ActivityLogEntry.cs b/MediaBrowser.Model/Activity/ActivityLogEntry.cs index 1d47ef9f69..f83dde56d4 100644 --- a/MediaBrowser.Model/Activity/ActivityLogEntry.cs +++ b/MediaBrowser.Model/Activity/ActivityLogEntry.cs @@ -1,13 +1,26 @@ -#nullable disable -#pragma warning disable CS1591 - using System; using Microsoft.Extensions.Logging; namespace MediaBrowser.Model.Activity { + /// + /// An activity log entry. + /// public class ActivityLogEntry { + /// + /// Initializes a new instance of the class. + /// + /// The name. + /// The type. + /// The user id. + public ActivityLogEntry(string name, string type, Guid userId) + { + Name = name; + Type = type; + UserId = userId; + } + /// /// Gets or sets the identifier. /// @@ -24,13 +37,13 @@ namespace MediaBrowser.Model.Activity /// Gets or sets the overview. /// /// The overview. - public string Overview { get; set; } + public string? Overview { get; set; } /// /// Gets or sets the short overview. /// /// The short overview. - public string ShortOverview { get; set; } + public string? ShortOverview { get; set; } /// /// Gets or sets the type. @@ -42,7 +55,7 @@ namespace MediaBrowser.Model.Activity /// Gets or sets the item identifier. /// /// The item identifier. - public string ItemId { get; set; } + public string? ItemId { get; set; } /// /// Gets or sets the date. @@ -61,7 +74,7 @@ namespace MediaBrowser.Model.Activity /// /// The user primary image tag. [Obsolete("UserPrimaryImageTag is not used.")] - public string UserPrimaryImageTag { get; set; } + public string? UserPrimaryImageTag { get; set; } /// /// Gets or sets the log severity. diff --git a/MediaBrowser.Model/Branding/BrandingOptions.cs b/MediaBrowser.Model/Branding/BrandingOptions.cs index 5ddf1e7e6e..7f19a5b852 100644 --- a/MediaBrowser.Model/Branding/BrandingOptions.cs +++ b/MediaBrowser.Model/Branding/BrandingOptions.cs @@ -1,4 +1,3 @@ -#nullable disable #pragma warning disable CS1591 namespace MediaBrowser.Model.Branding @@ -9,12 +8,12 @@ namespace MediaBrowser.Model.Branding /// Gets or sets the login disclaimer. /// /// The login disclaimer. - public string LoginDisclaimer { get; set; } + public string? LoginDisclaimer { get; set; } /// /// Gets or sets the custom CSS. /// /// The custom CSS. - public string CustomCss { get; set; } + public string? CustomCss { get; set; } } } diff --git a/MediaBrowser.Model/Channels/ChannelInfo.cs b/MediaBrowser.Model/Channels/ChannelInfo.cs deleted file mode 100644 index f2432aaeb2..0000000000 --- a/MediaBrowser.Model/Channels/ChannelInfo.cs +++ /dev/null @@ -1,32 +0,0 @@ -#nullable disable -#pragma warning disable CS1591 - -namespace MediaBrowser.Model.Channels -{ - public class ChannelInfo - { - /// - /// Gets or sets the name. - /// - /// The name. - public string Name { get; set; } - - /// - /// Gets or sets the identifier. - /// - /// The identifier. - public string Id { get; set; } - - /// - /// Gets or sets the home page URL. - /// - /// The home page URL. - public string HomePageUrl { get; set; } - - /// - /// Gets or sets the features. - /// - /// The features. - public ChannelFeatures Features { get; set; } - } -} From a13a569ca46ce4f83de4e37dd70a00680d3c665e Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Mon, 26 Jul 2021 23:25:21 +0200 Subject: [PATCH 079/120] EnsureLibraryFolder: Minor optimization --- .../Collections/CollectionManager.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs index 4fc33e2ea4..08acd17672 100644 --- a/Emby.Server.Implementations/Collections/CollectionManager.cs +++ b/Emby.Server.Implementations/Collections/CollectionManager.cs @@ -82,12 +82,10 @@ namespace Emby.Server.Implementations.Collections internal async Task EnsureLibraryFolder(string path, bool createIfNeeded) { - var existingFolders = FindFolders(path) - .ToList(); - - if (existingFolders.Count > 0) + var existingFolder = FindFolders(path).FirstOrDefault(); + if (existingFolder != null) { - return existingFolders[0]; + return existingFolder; } if (!createIfNeeded) From 0bb6999d5941638fbba7c74f05681ab9316f4f5d Mon Sep 17 00:00:00 2001 From: Rich Lander Date: Mon, 26 Jul 2021 16:02:17 -0700 Subject: [PATCH 080/120] Update ILibraryManager.cs --- MediaBrowser.Controller/Library/ILibraryManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 0bd2f38437..8043f4bd63 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -83,7 +83,7 @@ namespace MediaBrowser.Controller.Library /// /// Gets a Person. /// - /// The name. + /// The name of the person. /// Task{Person}. Person GetPerson(string name); From 5110835031d80e4e3d094b86d9962bc1708dd521 Mon Sep 17 00:00:00 2001 From: Rich Lander Date: Mon, 26 Jul 2021 16:19:50 -0700 Subject: [PATCH 081/120] Update ILibraryManager.cs --- MediaBrowser.Controller/Library/ILibraryManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 8043f4bd63..0ee1d094b0 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -98,7 +98,7 @@ namespace MediaBrowser.Controller.Library /// /// Gets the artist. /// - /// The name. + /// The name of the artist. /// Task{Artist}. MusicArtist GetArtist(string name); From dfaf89a681c02bc973bbd1c92fc7ee99888ad7f6 Mon Sep 17 00:00:00 2001 From: Rich Lander Date: Mon, 26 Jul 2021 16:31:25 -0700 Subject: [PATCH 082/120] Update ILibraryManager.cs --- MediaBrowser.Controller/Library/ILibraryManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 0ee1d094b0..18a75aacdb 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -107,7 +107,7 @@ namespace MediaBrowser.Controller.Library /// /// Gets a Studio. /// - /// The name. + /// The name of the studio. /// Task{Studio}. Studio GetStudio(string name); From 6a005f6a4ff31725f37a5330673f6d8c6bfa897b Mon Sep 17 00:00:00 2001 From: Rich Lander Date: Mon, 26 Jul 2021 16:40:05 -0700 Subject: [PATCH 083/120] Update ILibraryManager.cs --- MediaBrowser.Controller/Library/ILibraryManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 18a75aacdb..860df0ba1d 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -114,7 +114,7 @@ namespace MediaBrowser.Controller.Library /// /// Gets a Genre. /// - /// The name. + /// The name of genre. /// Task{Genre}. Genre GetGenre(string name); From 092e7c91b4cb085e1a586a254169343d8aa70c73 Mon Sep 17 00:00:00 2001 From: Rich Lander Date: Mon, 26 Jul 2021 17:07:47 -0700 Subject: [PATCH 084/120] Update ILibraryManager.cs --- MediaBrowser.Controller/Library/ILibraryManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 860df0ba1d..0c11d2f009 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -114,7 +114,7 @@ namespace MediaBrowser.Controller.Library /// /// Gets a Genre. /// - /// The name of genre. + /// The name of the genre. /// Task{Genre}. Genre GetGenre(string name); From a0678a92618fc1137bfc1606d26bd1a4c3749775 Mon Sep 17 00:00:00 2001 From: Rich Lander Date: Mon, 26 Jul 2021 17:58:56 -0700 Subject: [PATCH 085/120] Update ILibraryManager.cs --- MediaBrowser.Controller/Library/ILibraryManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 0c11d2f009..604960d8bc 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -121,7 +121,7 @@ namespace MediaBrowser.Controller.Library /// /// Gets the genre. /// - /// The name. + /// The name of the music genre. /// Task{MusicGenre}. MusicGenre GetMusicGenre(string name); From c07e83fdf87e61f30e4cca4e458113ac315918ae Mon Sep 17 00:00:00 2001 From: Rich Lander Date: Fri, 30 Jul 2021 00:49:28 -0700 Subject: [PATCH 086/120] Invert code and style analysis configuration (#6334) Co-authored-by: Bond-009 --- Directory.Build.props | 14 ++++++++++++++ DvdLib/DvdLib.csproj | 3 ++- Emby.Dlna/Emby.Dlna.csproj | 7 +------ Emby.Drawing/Emby.Drawing.csproj | 7 +------ Emby.Naming/Emby.Naming.csproj | 4 +--- Emby.Notifications/Emby.Notifications.csproj | 4 ---- Emby.Photos/Emby.Photos.csproj | 4 ---- .../Emby.Server.Implementations.csproj | 9 +++++---- Jellyfin.Api/Jellyfin.Api.csproj | 7 +------ Jellyfin.Data/Jellyfin.Data.csproj | 4 ---- Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj | 4 ---- Jellyfin.Networking/Jellyfin.Networking.csproj | 4 ---- .../Jellyfin.Server.Implementations.csproj | 8 -------- Jellyfin.Server/Jellyfin.Server.csproj | 5 ----- MediaBrowser.Common/MediaBrowser.Common.csproj | 4 ---- .../MediaBrowser.Controller.csproj | 9 +++++---- .../MediaBrowser.LocalMetadata.csproj | 4 ---- .../MediaBrowser.MediaEncoding.csproj | 4 ---- MediaBrowser.Model/MediaBrowser.Model.csproj | 9 +++++---- .../MediaBrowser.Providers.csproj | 9 ++++++--- .../MediaBrowser.XbmcMetadata.csproj | 4 ---- RSSDP/RSSDP.csproj | 4 +++- src/Jellyfin.Extensions/Jellyfin.Extensions.csproj | 4 ---- tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj | 3 --- .../Jellyfin.Common.Tests.csproj | 3 --- .../Jellyfin.Controller.Tests.csproj | 3 --- .../Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj | 3 --- .../Jellyfin.Extensions.Tests.csproj | 3 --- .../Jellyfin.MediaEncoding.Tests.csproj | 3 --- .../Jellyfin.Model.Tests.csproj | 3 --- .../Jellyfin.Naming.Tests.csproj | 3 --- .../Jellyfin.Networking.Tests.csproj | 3 --- .../Jellyfin.Providers.Tests.csproj | 3 --- .../Jellyfin.Server.Implementations.Tests.csproj | 3 --- .../Jellyfin.Server.Integration.Tests.csproj | 3 --- .../Jellyfin.Server.Tests.csproj | 3 --- .../Jellyfin.XbmcMetadata.Tests.csproj | 3 --- 37 files changed, 44 insertions(+), 133 deletions(-) create mode 100644 Directory.Build.props diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 0000000000..b899999efb --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,14 @@ + + + + + enable + true + $(MSBuildThisFileDirectory)/jellyfin.ruleset + + + + AllEnabledByDefault + + + diff --git a/DvdLib/DvdLib.csproj b/DvdLib/DvdLib.csproj index 7bbd9acf82..b8301e2f27 100644 --- a/DvdLib/DvdLib.csproj +++ b/DvdLib/DvdLib.csproj @@ -13,7 +13,8 @@ net5.0 false true - true + AllDisabledByDefault + disable diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj index a40578e403..970c16d2e6 100644 --- a/Emby.Dlna/Emby.Dlna.csproj +++ b/Emby.Dlna/Emby.Dlna.csproj @@ -20,8 +20,7 @@ net5.0 false true - true - enable + AllDisabledByDefault @@ -31,10 +30,6 @@ - - ../jellyfin.ruleset - - diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj index 5c5afe1c6e..baf350c6f1 100644 --- a/Emby.Drawing/Emby.Drawing.csproj +++ b/Emby.Drawing/Emby.Drawing.csproj @@ -9,8 +9,7 @@ net5.0 false true - true - enable + AllDisabledByDefault @@ -30,8 +29,4 @@ - - ../jellyfin.ruleset - - diff --git a/Emby.Naming/Emby.Naming.csproj b/Emby.Naming/Emby.Naming.csproj index 3224ff4129..db1b8ac9d7 100644 --- a/Emby.Naming/Emby.Naming.csproj +++ b/Emby.Naming/Emby.Naming.csproj @@ -9,12 +9,11 @@ net5.0 false true - true true true true snupkg - enable + AllDisabledByDefault @@ -51,7 +50,6 @@ - ../jellyfin.ruleset diff --git a/Emby.Notifications/Emby.Notifications.csproj b/Emby.Notifications/Emby.Notifications.csproj index 5a2aea6423..5edcf2f295 100644 --- a/Emby.Notifications/Emby.Notifications.csproj +++ b/Emby.Notifications/Emby.Notifications.csproj @@ -9,10 +9,6 @@ net5.0 false true - true - enable - AllEnabledByDefault - ../jellyfin.ruleset diff --git a/Emby.Photos/Emby.Photos.csproj b/Emby.Photos/Emby.Photos.csproj index 2b66181599..00b2f0f94c 100644 --- a/Emby.Photos/Emby.Photos.csproj +++ b/Emby.Photos/Emby.Photos.csproj @@ -22,10 +22,6 @@ net5.0 false true - true - enable - AllEnabledByDefault - ../jellyfin.ruleset diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index fe233df6c2..4c9e058212 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -44,12 +44,13 @@ net5.0 false true - true - enable AD0001 - AllEnabledByDefault - ../jellyfin.ruleset + false + + + + true diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index d1d0ac7084..2616376874 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -8,10 +8,9 @@ net5.0 true - true - enable AD0001 + AllDisabledByDefault @@ -33,10 +32,6 @@ - - ../jellyfin.ruleset - - <_Parameter1>Jellyfin.Api.Tests diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj index 3b14d33125..65bbd49da2 100644 --- a/Jellyfin.Data/Jellyfin.Data.csproj +++ b/Jellyfin.Data/Jellyfin.Data.csproj @@ -4,10 +4,6 @@ net5.0 false true - true - AllEnabledByDefault - ../jellyfin.ruleset - enable true true true diff --git a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj index 96fe003848..8cee5dcaee 100644 --- a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj +++ b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj @@ -9,10 +9,6 @@ net5.0 false true - true - enable - AllEnabledByDefault - ../jellyfin.ruleset diff --git a/Jellyfin.Networking/Jellyfin.Networking.csproj b/Jellyfin.Networking/Jellyfin.Networking.csproj index 63557e91f0..227a41ce44 100644 --- a/Jellyfin.Networking/Jellyfin.Networking.csproj +++ b/Jellyfin.Networking/Jellyfin.Networking.csproj @@ -3,10 +3,6 @@ net5.0 false true - true - enable - AllEnabledByDefault - ../jellyfin.ruleset diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index f73492b7c7..728f9021dc 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -4,14 +4,6 @@ net5.0 false true - true - enable - AllEnabledByDefault - ../jellyfin.ruleset - - - - ../jellyfin.ruleset diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 958a44fdad..49529b7944 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -12,11 +12,6 @@ false false true - true - enable - AllEnabledByDefault - ../jellyfin.ruleset - diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 0299a84563..12cfaf9789 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -32,10 +32,6 @@ net5.0 false true - true - enable - AllEnabledByDefault - ../jellyfin.ruleset true true true diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 4bed112e43..0f697bcccd 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -35,14 +35,15 @@ net5.0 false true - true - enable - AllEnabledByDefault - ../jellyfin.ruleset true true true snupkg + false + + + + true diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj index eb2077a5ff..1cf8fcd1b5 100644 --- a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj +++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj @@ -14,10 +14,6 @@ net5.0 false true - true - enable - AllEnabledByDefault - ../jellyfin.ruleset diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 7733e715f2..411b7c82ba 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -9,10 +9,6 @@ net5.0 false true - true - enable - AllEnabledByDefault - ../jellyfin.ruleset diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index c475d905a9..a371afc2cf 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -17,14 +17,15 @@ net5.0 false true - true - enable - - ../jellyfin.ruleset true true true snupkg + false + + + + true diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index cdb07a15da..6174f18b2d 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -29,9 +29,12 @@ net5.0 false true - true - AllEnabledByDefault - ../jellyfin.ruleset + false + disable + + + + true diff --git a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj index 2904b40ecf..3e2a9bacf1 100644 --- a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj +++ b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj @@ -18,10 +18,6 @@ net5.0 false true - true - enable - AllEnabledByDefault - ../jellyfin.ruleset diff --git a/RSSDP/RSSDP.csproj b/RSSDP/RSSDP.csproj index c64ee9389d..54113d4644 100644 --- a/RSSDP/RSSDP.csproj +++ b/RSSDP/RSSDP.csproj @@ -13,7 +13,9 @@ net5.0 false - true + AllDisabledByDefault + disable + CA2016 diff --git a/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj b/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj index f343be1e31..981b796e03 100644 --- a/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj +++ b/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj @@ -4,10 +4,6 @@ net5.0 false true - true - enable - AllEnabledByDefault - ../../jellyfin.ruleset diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index 3cbae0863c..4edd843841 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -8,9 +8,6 @@ net5.0 false - true - enable - AllEnabledByDefault ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj index fa0ef25111..e4350c3369 100644 --- a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj +++ b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj @@ -8,9 +8,6 @@ net5.0 false - true - enable - AllEnabledByDefault ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj index 285e9a2a9c..5b269a4b20 100644 --- a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj +++ b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj @@ -8,9 +8,6 @@ net5.0 false - true - enable - AllEnabledByDefault ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj index d7d0a8f439..713f6423c9 100644 --- a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj +++ b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj @@ -3,9 +3,6 @@ net5.0 false - true - enable - AllEnabledByDefault ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj index c4d05b8f5f..9272d5eef9 100644 --- a/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj +++ b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj @@ -3,9 +3,6 @@ net5.0 false - true - enable - AllEnabledByDefault ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj index fcd9d6cb5f..a6a948e2b7 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj +++ b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj @@ -8,9 +8,6 @@ net5.0 false - true - enable - AllEnabledByDefault ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj index 7299a47dc7..06ff22c7e0 100644 --- a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj +++ b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj @@ -3,9 +3,6 @@ net5.0 false - true - enable - AllEnabledByDefault ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj index d7987ba96a..510c8f60a3 100644 --- a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj +++ b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj @@ -8,9 +8,6 @@ net5.0 false - true - enable - AllEnabledByDefault ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj index 3078e648aa..2c6e2e5f66 100644 --- a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj +++ b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj @@ -8,9 +8,6 @@ net5.0 false - true - enable - AllEnabledByDefault ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj b/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj index 26506a92b9..195fc8801d 100644 --- a/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj +++ b/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj @@ -3,9 +3,6 @@ net5.0 false - true - enable - AllEnabledByDefault ../jellyfin-tests.ruleset 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 ae957c2ab1..387f259ce3 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj +++ b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj @@ -8,9 +8,6 @@ net5.0 false - true - enable - AllEnabledByDefault ../jellyfin-tests.ruleset Jellyfin.Server.Implementations.Tests diff --git a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj index 982d2081ab..cf42153393 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj +++ b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj @@ -2,9 +2,6 @@ net5.0 false - true - enable - AllEnabledByDefault ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj index 73c1170fd2..2f95f5c01c 100644 --- a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj +++ b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj @@ -3,9 +3,6 @@ net5.0 false - true - enable - AllEnabledByDefault ../jellyfin-tests.ruleset diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj index 278e4f076a..78837bba67 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj +++ b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj @@ -3,9 +3,6 @@ net5.0 false - true - enable - AllEnabledByDefault ../jellyfin-tests.ruleset From 448ce64a56aa7bd7be78f7ef274438149e1b844b Mon Sep 17 00:00:00 2001 From: Maxim Ivanov Date: Thu, 29 Jul 2021 09:02:09 +0000 Subject: [PATCH 087/120] Translated using Weblate (Bulgarian) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/bg/ --- .../Localization/Core/bg-BG.json | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/bg-BG.json b/Emby.Server.Implementations/Localization/Core/bg-BG.json index bc25531d30..f55287d15b 100644 --- a/Emby.Server.Implementations/Localization/Core/bg-BG.json +++ b/Emby.Server.Implementations/Localization/Core/bg-BG.json @@ -8,7 +8,7 @@ "CameraImageUploadedFrom": "Нова снимка от камера беше качена от {0}", "Channels": "Канали", "ChapterNameValue": "Глава {0}", - "Collections": "Поредици", + "Collections": "Колекции", "DeviceOfflineWithName": "{0} се разкачи", "DeviceOnlineWithName": "{0} е свързан", "FailedLoginAttemptWithUserName": "Неуспешен опит за влизане от {0}", @@ -29,13 +29,13 @@ "Inherit": "Наследяване", "ItemAddedWithName": "{0} е добавено към библиотеката", "ItemRemovedWithName": "{0} е премахнато от библиотеката", - "LabelIpAddressValue": "ИП адрес: {0}", - "LabelRunningTimeValue": "Стартирано от: {0}", + "LabelIpAddressValue": "IP адрес: {0}", + "LabelRunningTimeValue": "Продължителност: {0}", "Latest": "Последни", - "MessageApplicationUpdated": "Сървърът е обновен", - "MessageApplicationUpdatedTo": "Сървърът е обновен до {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Секцията {0} от сървърната конфигурация се актуализира", - "MessageServerConfigurationUpdated": "Конфигурацията на сървъра се актуализира", + "MessageApplicationUpdated": "Сървърът беше обновен", + "MessageApplicationUpdatedTo": "Сървърът беше обновен до {0}", + "MessageNamedServerConfigurationUpdatedWithValue": "Секцията {0} от сървърната конфигурация беше актуализирана", + "MessageServerConfigurationUpdated": "Конфигурацията на сървъра беше актуализирана", "MixedContent": "Смесено съдържание", "Movies": "Филми", "Music": "Музика", @@ -118,5 +118,7 @@ "Forced": "Принудително", "Default": "По подразбиране", "TaskCleanActivityLogDescription": "Изтрива записите в дневника с активност по стари от конфигурираната възраст.", - "TaskCleanActivityLog": "Изчисти дневника с активност" + "TaskCleanActivityLog": "Изчисти дневника с активност", + "TaskOptimizeDatabaseDescription": "Прави базата данни по-компактна и освобождава място. Пускането на тази задача след сканиране на библиотеката или правене на други промени, свързани с модификации на базата данни, може да подобри производителността.", + "TaskOptimizeDatabase": "Оптимизирай базата данни" } From 0ee74b293d1f6fa1be63b8b4e5e2498a7f18298f Mon Sep 17 00:00:00 2001 From: Sverre Date: Wed, 28 Jul 2021 09:04:09 +0000 Subject: [PATCH 088/120] =?UTF-8?q?Translated=20using=20Weblate=20(Norwegi?= =?UTF-8?q?an=20Bokm=C3=A5l)=20Translation:=20Jellyfin/Jellyfin=20Translat?= =?UTF-8?q?e-URL:=20https://translate.jellyfin.org/projects/jellyfin/jelly?= =?UTF-8?q?fin-core/nb=5FNO/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Emby.Server.Implementations/Localization/Core/nb.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/nb.json b/Emby.Server.Implementations/Localization/Core/nb.json index fbe1f7c4d5..81c1eefe74 100644 --- a/Emby.Server.Implementations/Localization/Core/nb.json +++ b/Emby.Server.Implementations/Localization/Core/nb.json @@ -118,5 +118,6 @@ "Undefined": "Udefinert", "Forced": "Tvunget", "Default": "Standard", - "TaskCleanActivityLogDescription": "Sletter oppføringer i aktivitetsloggen som er eldre enn den konfigurerte alderen." + "TaskCleanActivityLogDescription": "Sletter oppføringer i aktivitetsloggen som er eldre enn den konfigurerte alderen.", + "TaskOptimizeDatabase": "Optimiser database" } From eadad73ee7943186e3a540a49035e25a4446fb4b Mon Sep 17 00:00:00 2001 From: Ali Amer Date: Fri, 30 Jul 2021 22:08:23 +0000 Subject: [PATCH 089/120] Translated using Weblate (Arabic) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ar/ --- Emby.Server.Implementations/Localization/Core/ar.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/ar.json b/Emby.Server.Implementations/Localization/Core/ar.json index 3d6e159b13..be629c8a42 100644 --- a/Emby.Server.Implementations/Localization/Core/ar.json +++ b/Emby.Server.Implementations/Localization/Core/ar.json @@ -118,5 +118,7 @@ "TaskCleanActivityLog": "حذف سجل الأنشطة", "Default": "الإعدادات الافتراضية", "Undefined": "غير معرف", - "Forced": "ملحقة" + "Forced": "ملحقة", + "TaskOptimizeDatabaseDescription": "يضغط قاعدة البيانات ويقتطع المساحة الحرة. تشغيل هذه المهمة بعد فحص المكتبة أو إجراء تغييرات أخرى تشير ضمنًا إلى أن تعديلات قاعدة البيانات قد تؤدي إلى تحسين الأداء.", + "TaskOptimizeDatabase": "تحسين قاعدة البيانات" } From 9f378feb82f7145b060ca69cd5c69b44abd2690e Mon Sep 17 00:00:00 2001 From: TheFeelTrain Date: Fri, 30 Jul 2021 23:27:44 +0000 Subject: [PATCH 090/120] 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 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/ja.json b/Emby.Server.Implementations/Localization/Core/ja.json index fa0ab8b927..0d90ad31cc 100644 --- a/Emby.Server.Implementations/Localization/Core/ja.json +++ b/Emby.Server.Implementations/Localization/Core/ja.json @@ -117,5 +117,7 @@ "TaskCleanActivityLog": "アクティビティの履歴を消去", "Undefined": "未定義", "Forced": "強制", - "Default": "デフォルト" + "Default": "デフォルト", + "TaskOptimizeDatabaseDescription": "データベースをコンパクトにして、空き領域を切り詰めます。メディアライブラリのスキャン後でこのタスクを実行するとパフォーマンスが向上する可能性があります。", + "TaskOptimizeDatabase": "データベースの最適化" } From 3254b5f8cb89aa1f6747eb18d8ee4f3de96455c9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Aug 2021 12:00:57 +0000 Subject: [PATCH 091/120] Bump Swashbuckle.AspNetCore from 6.1.4 to 6.1.5 Bumps [Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore) from 6.1.4 to 6.1.5. - [Release notes](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/releases) - [Commits](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/compare/v6.1.4...v6.1.5) --- updated-dependencies: - dependency-name: Swashbuckle.AspNetCore dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Jellyfin.Api/Jellyfin.Api.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index 2616376874..6bb4d1da37 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -16,7 +16,7 @@ - + From 16ae8cd20044f6aecc00360fb252fc664587621f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Aug 2021 17:15:58 +0000 Subject: [PATCH 092/120] Bump Swashbuckle.AspNetCore.ReDoc from 6.1.4 to 6.1.5 Bumps [Swashbuckle.AspNetCore.ReDoc](https://github.com/domaindrivendev/Swashbuckle.AspNetCore) from 6.1.4 to 6.1.5. - [Release notes](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/releases) - [Commits](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/compare/v6.1.4...v6.1.5) --- updated-dependencies: - dependency-name: Swashbuckle.AspNetCore.ReDoc dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Jellyfin.Api/Jellyfin.Api.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index 6bb4d1da37..a527282d15 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -17,7 +17,7 @@ - + From 3daf9e5afeabdf31bc28cbe06f4bc51bdae9bdef Mon Sep 17 00:00:00 2001 From: Rich Lander Date: Mon, 2 Aug 2021 13:15:51 -0700 Subject: [PATCH 093/120] Optimize Dockerfiles --- Dockerfile | 26 ++++++++++++++------------ Dockerfile.arm | 30 +++++++++++++++--------------- Dockerfile.arm64 | 29 +++++++++++++++-------------- 3 files changed, 44 insertions(+), 41 deletions(-) diff --git a/Dockerfile b/Dockerfile index 4e2d06b82a..0859fdc4c8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,15 +8,7 @@ RUN apk add curl git zlib zlib-dev autoconf g++ make libpng-dev gifsicle alpine- && npm ci --no-audit --unsafe-perm \ && mv dist /dist -FROM mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION} as builder -WORKDIR /repo -COPY . . -ENV DOTNET_CLI_TELEMETRY_OPTOUT=1 -# because of changes in docker and systemd we need to not build in parallel at the moment -# see https://success.docker.com/article/how-to-reserve-resource-temporarily-unavailable-errors-due-to-tasksmax-setting -RUN dotnet publish Jellyfin.Server --disable-parallel --configuration Release --output="/jellyfin" --self-contained --runtime linux-x64 "-p:DebugSymbols=false;DebugType=none" - -FROM debian:buster-slim +FROM debian:buster-slim as app # https://askubuntu.com/questions/972516/debian-frontend-environment-variable ARG DEBIAN_FRONTEND="noninteractive" @@ -25,9 +17,6 @@ ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn # https://github.com/NVIDIA/nvidia-docker/wiki/Installation-(Native-GPU-Support) ENV NVIDIA_DRIVER_CAPABILITIES="compute,video,utility" -COPY --from=builder /jellyfin /jellyfin -COPY --from=web-builder /dist /jellyfin/jellyfin-web - # https://github.com/intel/compute-runtime/releases ARG GMMLIB_VERSION=20.3.2 ARG IGC_VERSION=1.0.5435 @@ -73,6 +62,19 @@ ENV LC_ALL en_US.UTF-8 ENV LANG en_US.UTF-8 ENV LANGUAGE en_US:en +FROM mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION} as builder +WORKDIR /repo +COPY . . +ENV DOTNET_CLI_TELEMETRY_OPTOUT=1 +# because of changes in docker and systemd we need to not build in parallel at the moment +# see https://success.docker.com/article/how-to-reserve-resource-temporarily-unavailable-errors-due-to-tasksmax-setting +RUN dotnet publish Jellyfin.Server --disable-parallel --configuration Release --output="/jellyfin" --self-contained --runtime linux-x64 "-p:DebugSymbols=false;DebugType=none" + +FROM app + +COPY --from=builder /jellyfin /jellyfin +COPY --from=web-builder /dist /jellyfin/jellyfin-web + EXPOSE 8096 VOLUME /cache /config /media ENTRYPOINT ["./jellyfin/jellyfin", \ diff --git a/Dockerfile.arm b/Dockerfile.arm index 25a0de7db6..cc0c79c94f 100644 --- a/Dockerfile.arm +++ b/Dockerfile.arm @@ -13,19 +13,8 @@ RUN apk add curl git zlib zlib-dev autoconf g++ make libpng-dev gifsicle alpine- && npm ci --no-audit --unsafe-perm \ && mv dist /dist - -FROM mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION} as builder -WORKDIR /repo -COPY . . -ENV DOTNET_CLI_TELEMETRY_OPTOUT=1 -# Discard objs - may cause failures if exists -RUN find . -type d -name obj | xargs -r rm -r -# Build -RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin" --self-contained --runtime linux-arm "-p:DebugSymbols=false;DebugType=none" - - FROM multiarch/qemu-user-static:x86_64-arm as qemu -FROM arm32v7/debian:buster-slim +FROM arm32v7/debian:buster-slim as app # https://askubuntu.com/questions/972516/debian-frontend-environment-variable ARG DEBIAN_FRONTEND="noninteractive" @@ -61,14 +50,25 @@ RUN apt-get update \ && chmod 777 /cache /config /media \ && sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen -COPY --from=builder /jellyfin /jellyfin -COPY --from=web-builder /dist /jellyfin/jellyfin-web - ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 ENV LC_ALL en_US.UTF-8 ENV LANG en_US.UTF-8 ENV LANGUAGE en_US:en +FROM mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION} as builder +WORKDIR /repo +COPY . . +ENV DOTNET_CLI_TELEMETRY_OPTOUT=1 +# Discard objs - may cause failures if exists +RUN find . -type d -name obj | xargs -r rm -r +# Build +RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin" --self-contained --runtime linux-arm "-p:DebugSymbols=false;DebugType=none" + +FROM app + +COPY --from=builder /jellyfin /jellyfin +COPY --from=web-builder /dist /jellyfin/jellyfin-web + EXPOSE 8096 VOLUME /cache /config /media ENTRYPOINT ["./jellyfin/jellyfin", \ diff --git a/Dockerfile.arm64 b/Dockerfile.arm64 index c9f19c5a39..64367a32da 100644 --- a/Dockerfile.arm64 +++ b/Dockerfile.arm64 @@ -13,18 +13,8 @@ RUN apk add curl git zlib zlib-dev autoconf g++ make libpng-dev gifsicle alpine- && npm ci --no-audit --unsafe-perm \ && mv dist /dist - -FROM mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION} as builder -WORKDIR /repo -COPY . . -ENV DOTNET_CLI_TELEMETRY_OPTOUT=1 -# Discard objs - may cause failures if exists -RUN find . -type d -name obj | xargs -r rm -r -# Build -RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin" --self-contained --runtime linux-arm64 "-p:DebugSymbols=false;DebugType=none" - FROM multiarch/qemu-user-static:x86_64-aarch64 as qemu -FROM arm64v8/debian:buster-slim +FROM arm64v8/debian:buster-slim as app # https://askubuntu.com/questions/972516/debian-frontend-environment-variable ARG DEBIAN_FRONTEND="noninteractive" @@ -50,14 +40,25 @@ RUN apt-get update && apt-get install --no-install-recommends --no-install-sugge && chmod 777 /cache /config /media \ && sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen -COPY --from=builder /jellyfin /jellyfin -COPY --from=web-builder /dist /jellyfin/jellyfin-web - ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 ENV LC_ALL en_US.UTF-8 ENV LANG en_US.UTF-8 ENV LANGUAGE en_US:en +FROM mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION} as builder +WORKDIR /repo +COPY . . +ENV DOTNET_CLI_TELEMETRY_OPTOUT=1 +# Discard objs - may cause failures if exists +RUN find . -type d -name obj | xargs -r rm -r +# Build +RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin" --self-contained --runtime linux-arm64 "-p:DebugSymbols=false;DebugType=none" + +FROM app + +COPY --from=builder /jellyfin /jellyfin +COPY --from=web-builder /dist /jellyfin/jellyfin-web + EXPOSE 8096 VOLUME /cache /config /media ENTRYPOINT ["./jellyfin/jellyfin", \ From a8c47159eadc92fe1aaf685303d612094fc32acb Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 1 Aug 2021 16:32:58 +0000 Subject: [PATCH 094/120] Translated using Weblate (Danish) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/da/ --- Emby.Server.Implementations/Localization/Core/da.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/da.json b/Emby.Server.Implementations/Localization/Core/da.json index 3453507d9e..b2c484a31e 100644 --- a/Emby.Server.Implementations/Localization/Core/da.json +++ b/Emby.Server.Implementations/Localization/Core/da.json @@ -118,5 +118,7 @@ "TaskCleanActivityLog": "Ryd Aktivitetslog", "Undefined": "Udefineret", "Forced": "Tvunget", - "Default": "Standard" + "Default": "Standard", + "TaskOptimizeDatabaseDescription": "Kompakter database og forkorter fri plads. Ved at køre denne proces efter at scanne biblioteket eller efter at ændre noget som kunne have indflydelse på databasen, kan forbedre ydeevne.", + "TaskOptimizeDatabase": "Optimér database" } From 8997d7ffc4dc8651e66cb5eaedbcbe174751ad4d Mon Sep 17 00:00:00 2001 From: Winnie Date: Mon, 2 Aug 2021 02:59:31 +0000 Subject: [PATCH 095/120] Translated using Weblate (Spanish) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/es/ --- Emby.Server.Implementations/Localization/Core/es.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/es.json b/Emby.Server.Implementations/Localization/Core/es.json index 91939843fa..7d42182b0c 100644 --- a/Emby.Server.Implementations/Localization/Core/es.json +++ b/Emby.Server.Implementations/Localization/Core/es.json @@ -70,7 +70,7 @@ "ScheduledTaskFailedWithName": "{0} falló", "ScheduledTaskStartedWithName": "{0} iniciada", "ServerNameNeedsToBeRestarted": "{0} necesita ser reiniciado", - "Shows": "Series de Televisión", + "Shows": "Series", "Songs": "Canciones", "StartupEmbyServerIsLoading": "Jellyfin Server se está cargando. Vuelve a intentarlo en breve.", "SubtitleDownloadFailureForItem": "Error al descargar subtítulos para {0}", From fc5841242e9c5a5d0c1c9369858aa5b6e8652a7d Mon Sep 17 00:00:00 2001 From: New Jorciks Date: Mon, 2 Aug 2021 11:30:09 +0000 Subject: [PATCH 096/120] Translated using Weblate (Latvian) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/lv/ --- Emby.Server.Implementations/Localization/Core/lv.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/lv.json b/Emby.Server.Implementations/Localization/Core/lv.json index a46bdc3ded..443a74a10f 100644 --- a/Emby.Server.Implementations/Localization/Core/lv.json +++ b/Emby.Server.Implementations/Localization/Core/lv.json @@ -117,5 +117,7 @@ "TaskCleanActivityLogDescription": "Nodzēš darbību žurnāla ierakstus, kuri ir vecāki par doto vecumu.", "TaskCleanActivityLog": "Notīrīt Darbību Žurnālu", "Undefined": "Nenoteikts", - "Default": "Noklusējums" + "Default": "Noklusējums", + "TaskOptimizeDatabaseDescription": "Saspiež datubāzi un atbrīvo atmiņu. Uzdevum palaišana pēc bibliotēku skenēšanas vai citām, ar datubāzi saistītām, izmaiņām iespējams uzlabos ātrdarbību.", + "TaskOptimizeDatabase": "Optimizēt datubāzi" } From 06679eeebf577c06c92d34046337058cade3582f Mon Sep 17 00:00:00 2001 From: Rich Lander Date: Tue, 3 Aug 2021 21:08:15 -0700 Subject: [PATCH 097/120] Fix warnings for MediaBrowser.Controller/LiveTv --- .../LiveTv/ILiveTvManager.cs | 37 +++-- MediaBrowser.Controller/LiveTv/ITunerHost.cs | 3 + .../LiveTv/LiveTvChannel.cs | 122 ++++++++--------- .../LiveTv/LiveTvProgram.cs | 128 +++++++++--------- 4 files changed, 155 insertions(+), 135 deletions(-) diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs index f4dc18e11c..bd097c90ac 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs @@ -22,12 +22,22 @@ namespace MediaBrowser.Controller.LiveTv /// public interface ILiveTvManager { + event EventHandler> SeriesTimerCancelled; + + event EventHandler> TimerCancelled; + + event EventHandler> TimerCreated; + + event EventHandler> SeriesTimerCreated; + /// /// Gets the services. /// /// The services. IReadOnlyList Services { get; } + IListingsProvider[] ListingProviders { get; } + /// /// Gets the new timer defaults asynchronous. /// @@ -86,6 +96,7 @@ namespace MediaBrowser.Controller.LiveTv /// /// The query. /// The options. + /// A recording. QueryResult GetRecordings(RecordingQuery query, DtoOptions options); /// @@ -176,11 +187,16 @@ namespace MediaBrowser.Controller.LiveTv /// The query. /// The options. /// The cancellation token. + /// Recommended programs. QueryResult GetRecommendedPrograms(InternalItemsQuery query, DtoOptions options, CancellationToken cancellationToken); /// /// Gets the recommended programs internal. /// + /// The query. + /// The options. + /// The cancellation token. + /// Recommended programs. QueryResult GetRecommendedProgramsInternal(InternalItemsQuery query, DtoOptions options, CancellationToken cancellationToken); /// @@ -202,6 +218,7 @@ namespace MediaBrowser.Controller.LiveTv /// Gets the live tv folder. /// /// The cancellation token. + /// Live TV folder. Folder GetInternalLiveTvFolder(CancellationToken cancellationToken); /// @@ -213,11 +230,18 @@ namespace MediaBrowser.Controller.LiveTv /// /// Gets the internal channels. /// + /// The query. + /// The options. + /// The cancellation token. + /// Internal channels. QueryResult GetInternalChannels(LiveTvChannelQuery query, DtoOptions dtoOptions, CancellationToken cancellationToken); /// /// Gets the channel media sources. /// + /// Item to search for. + /// CancellationToken to use for operation. + /// Channel media sources wrapped in a task. Task> GetChannelMediaSources(BaseItem item, CancellationToken cancellationToken); /// @@ -232,6 +256,9 @@ namespace MediaBrowser.Controller.LiveTv /// /// Saves the tuner host. /// + /// Turner host to save. + /// Option to specify that data source has changed. + /// Tuner host information wrapped in a task. Task SaveTunerHost(TunerHostInfo info, bool dataSourceChanged = true); /// @@ -271,20 +298,10 @@ namespace MediaBrowser.Controller.LiveTv Task> GetChannelsFromListingsProviderData(string id, CancellationToken cancellationToken); - IListingsProvider[] ListingProviders { get; } - List GetTunerHostTypes(); Task> DiscoverTuners(bool newDevicesOnly, CancellationToken cancellationToken); - event EventHandler> SeriesTimerCancelled; - - event EventHandler> TimerCancelled; - - event EventHandler> TimerCreated; - - event EventHandler> SeriesTimerCreated; - string GetEmbyTvActiveRecordingPath(string id); ActiveRecordingInfo GetActiveRecordingInfo(string path); diff --git a/MediaBrowser.Controller/LiveTv/ITunerHost.cs b/MediaBrowser.Controller/LiveTv/ITunerHost.cs index 7dced9f5ef..24820abb90 100644 --- a/MediaBrowser.Controller/LiveTv/ITunerHost.cs +++ b/MediaBrowser.Controller/LiveTv/ITunerHost.cs @@ -30,6 +30,8 @@ namespace MediaBrowser.Controller.LiveTv /// /// Gets the channels. /// + /// Option to enable using cache. + /// The CancellationToken for this operation. /// Task<IEnumerable<ChannelInfo>>. Task> GetChannels(bool enableCache, CancellationToken cancellationToken); @@ -47,6 +49,7 @@ namespace MediaBrowser.Controller.LiveTv /// The stream identifier. /// The current live streams. /// The cancellation token to cancel operation. + /// Live stream wrapped in a task. Task GetChannelStream(string channelId, string streamId, List currentLiveStreams, CancellationToken cancellationToken); /// diff --git a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs index ecd3d10d98..074e023e8d 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs @@ -18,23 +18,6 @@ namespace MediaBrowser.Controller.LiveTv { public class LiveTvChannel : BaseItem, IHasMediaSources, IHasProgramAttributes { - public override List GetUserDataKeys() - { - var list = base.GetUserDataKeys(); - - if (!ConfigurationManager.Configuration.DisableLiveTvChannelUserDataName) - { - list.Insert(0, GetClientTypeName() + "-" + Name); - } - - return list; - } - - public override UnratedItem GetBlockUnratedType() - { - return UnratedItem.LiveTvChannel; - } - [JsonIgnore] public override bool SupportsPositionTicksResume => false; @@ -59,6 +42,67 @@ namespace MediaBrowser.Controller.LiveTv [JsonIgnore] public override LocationType LocationType => LocationType.Remote; + [JsonIgnore] + public override string MediaType => ChannelType == ChannelType.Radio ? Model.Entities.MediaType.Audio : Model.Entities.MediaType.Video; + + [JsonIgnore] + public bool IsMovie { get; set; } + + /// + /// Gets or sets a value indicating whether this instance is sports. + /// + /// true if this instance is sports; otherwise, false. + [JsonIgnore] + public bool IsSports { get; set; } + + /// + /// Gets or sets a value indicating whether this instance is series. + /// + /// true if this instance is series; otherwise, false. + [JsonIgnore] + public bool IsSeries { get; set; } + + /// + /// Gets or sets a value indicating whether this instance is news. + /// + /// true if this instance is news; otherwise, false. + [JsonIgnore] + public bool IsNews { get; set; } + + /// + /// Gets a value indicating whether this instance is kids. + /// + /// true if this instance is kids; otherwise, false. + [JsonIgnore] + public bool IsKids => Tags.Contains("Kids", StringComparer.OrdinalIgnoreCase); + + [JsonIgnore] + public bool IsRepeat { get; set; } + + /// + /// Gets or sets the episode title. + /// + /// The episode title. + [JsonIgnore] + public string EpisodeTitle { get; set; } + + public override List GetUserDataKeys() + { + var list = base.GetUserDataKeys(); + + if (!ConfigurationManager.Configuration.DisableLiveTvChannelUserDataName) + { + list.Insert(0, GetClientTypeName() + "-" + Name); + } + + return list; + } + + public override UnratedItem GetBlockUnratedType() + { + return UnratedItem.LiveTvChannel; + } + protected override string CreateSortName() { if (!string.IsNullOrEmpty(Number)) @@ -74,9 +118,6 @@ namespace MediaBrowser.Controller.LiveTv return (Number ?? string.Empty) + "-" + (Name ?? string.Empty); } - [JsonIgnore] - public override string MediaType => ChannelType == ChannelType.Radio ? Model.Entities.MediaType.Audio : Model.Entities.MediaType.Video; - public override string GetClientTypeName() { return "TvChannel"; @@ -122,46 +163,5 @@ namespace MediaBrowser.Controller.LiveTv { return false; } - - [JsonIgnore] - public bool IsMovie { get; set; } - - /// - /// Gets or sets a value indicating whether this instance is sports. - /// - /// true if this instance is sports; otherwise, false. - [JsonIgnore] - public bool IsSports { get; set; } - - /// - /// Gets or sets a value indicating whether this instance is series. - /// - /// true if this instance is series; otherwise, false. - [JsonIgnore] - public bool IsSeries { get; set; } - - /// - /// Gets or sets a value indicating whether this instance is news. - /// - /// true if this instance is news; otherwise, false. - [JsonIgnore] - public bool IsNews { get; set; } - - /// - /// Gets a value indicating whether this instance is kids. - /// - /// true if this instance is kids; otherwise, false. - [JsonIgnore] - public bool IsKids => Tags.Contains("Kids", StringComparer.OrdinalIgnoreCase); - - [JsonIgnore] - public bool IsRepeat { get; set; } - - /// - /// Gets or sets the episode title. - /// - /// The episode title. - [JsonIgnore] - public string EpisodeTitle { get; set; } } } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs index 9d638a0bf6..111dc0d275 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs @@ -1,6 +1,6 @@ #nullable disable -#pragma warning disable CS1591 +#pragma warning disable CS1591, SA1306 using System; using System.Collections.Generic; @@ -19,54 +19,14 @@ namespace MediaBrowser.Controller.LiveTv { public class LiveTvProgram : BaseItem, IHasLookupInfo, IHasStartDate, IHasProgramAttributes { + private static string EmbyServiceName = "Emby"; + public LiveTvProgram() { IsVirtualItem = true; } - public override List GetUserDataKeys() - { - var list = base.GetUserDataKeys(); - - if (!IsSeries) - { - var key = this.GetProviderId(MetadataProvider.Imdb); - if (!string.IsNullOrEmpty(key)) - { - list.Insert(0, key); - } - - key = this.GetProviderId(MetadataProvider.Tmdb); - if (!string.IsNullOrEmpty(key)) - { - list.Insert(0, key); - } - } - else if (!string.IsNullOrEmpty(EpisodeTitle)) - { - var name = GetClientTypeName(); - - list.Insert(0, name + "-" + Name + (EpisodeTitle ?? string.Empty)); - } - - return list; - } - - private static string EmbyServiceName = "Emby"; - - public override double GetDefaultPrimaryImageAspectRatio() - { - var serviceName = ServiceName; - - if (string.Equals(serviceName, EmbyServiceName, StringComparison.OrdinalIgnoreCase) || string.Equals(serviceName, "Next Pvr", StringComparison.OrdinalIgnoreCase)) - { - return 2.0 / 3; - } - else - { - return 16.0 / 9; - } - } + public string SeriesName { get; set; } [JsonIgnore] public override SourceType SourceType => SourceType.LiveTV; @@ -182,6 +142,66 @@ namespace MediaBrowser.Controller.LiveTv } } + [JsonIgnore] + public override bool SupportsPeople + { + get + { + // Optimization + if (IsNews || IsSports) + { + return false; + } + + return base.SupportsPeople; + } + } + + [JsonIgnore] + public override bool SupportsAncestors => false; + + public override List GetUserDataKeys() + { + var list = base.GetUserDataKeys(); + + if (!IsSeries) + { + var key = this.GetProviderId(MetadataProvider.Imdb); + if (!string.IsNullOrEmpty(key)) + { + list.Insert(0, key); + } + + key = this.GetProviderId(MetadataProvider.Tmdb); + if (!string.IsNullOrEmpty(key)) + { + list.Insert(0, key); + } + } + else if (!string.IsNullOrEmpty(EpisodeTitle)) + { + var name = GetClientTypeName(); + + list.Insert(0, name + "-" + Name + (EpisodeTitle ?? string.Empty)); + } + + return list; + } + + public override double GetDefaultPrimaryImageAspectRatio() + { + var serviceName = ServiceName; + + if (string.Equals(serviceName, EmbyServiceName, StringComparison.OrdinalIgnoreCase) || string.Equals(serviceName, "Next Pvr", StringComparison.OrdinalIgnoreCase)) + { + return 2.0 / 3; + } + else + { + return 16.0 / 9; + } + } + public override string GetClientTypeName() { return "Program"; @@ -202,24 +222,6 @@ namespace MediaBrowser.Controller.LiveTv return false; } - [JsonIgnore] - public override bool SupportsPeople - { - get - { - // Optimization - if (IsNews || IsSports) - { - return false; - } - - return base.SupportsPeople; - } - } - - [JsonIgnore] - public override bool SupportsAncestors => false; - private LiveTvOptions GetConfiguration() { return ConfigurationManager.GetConfiguration("livetv"); @@ -273,7 +275,5 @@ namespace MediaBrowser.Controller.LiveTv return list; } - - public string SeriesName { get; set; } } } From f1f72c3060ed9c8ccd665fb86d8ddfb5e6836056 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Wed, 4 Aug 2021 14:40:09 +0200 Subject: [PATCH 098/120] Minor improvements --- Emby.Naming/Video/ExtraResolver.cs | 1 - .../ApiServiceCollectionExtensions.cs | 6 +-- .../Middleware/ExceptionMiddleware.cs | 5 -- Jellyfin.Server/Migrations/MigrationRunner.cs | 2 +- .../Routines/MigrateActivityLogDb.cs | 2 +- .../Routines/MigrateDisplayPreferencesDb.cs | 1 - Jellyfin.Server/Program.cs | 11 ++--- .../Extensions/ProcessExtensions.cs | 2 +- .../Providers/ProviderIdParsers.cs | 8 ++-- .../Parsers/BaseItemXmlParser.cs | 46 +------------------ .../Savers/BaseXmlSaver.cs | 18 +------- .../Savers/BoxSetXmlSaver.cs | 6 +-- .../Savers/PlaylistXmlSaver.cs | 6 +-- MediaBrowser.Model/Users/UserActionType.cs | 9 ---- .../Parsers/BaseNfoParser.cs | 2 +- 15 files changed, 24 insertions(+), 101 deletions(-) delete mode 100644 MediaBrowser.Model/Users/UserActionType.cs diff --git a/Emby.Naming/Video/ExtraResolver.cs b/Emby.Naming/Video/ExtraResolver.cs index 1fade985be..a32af002cc 100644 --- a/Emby.Naming/Video/ExtraResolver.cs +++ b/Emby.Naming/Video/ExtraResolver.cs @@ -1,6 +1,5 @@ using System; using System.IO; -using System.Linq; using System.Text.RegularExpressions; using Emby.Naming.Audio; using Emby.Naming.Common; diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index 15dc438561..f19e87aba5 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -303,7 +303,7 @@ namespace Jellyfin.Server.Extensions { description.TryGetMethodInfo(out MethodInfo methodInfo); // Attribute name, method name, none. - return description?.ActionDescriptor?.AttributeRouteInfo?.Name + return description?.ActionDescriptor.AttributeRouteInfo?.Name ?? methodInfo?.Name ?? null; }); @@ -341,7 +341,7 @@ namespace Jellyfin.Server.Extensions { foreach (var address in host.GetAddresses()) { - AddIpAddress(config, options, addr.Address, addr.PrefixLength); + AddIpAddress(config, options, address, address.AddressFamily == AddressFamily.InterNetwork ? 32 : 128); } } } @@ -397,7 +397,7 @@ namespace Jellyfin.Server.Extensions Type = "object", Properties = typeof(ImageType).GetEnumNames().ToDictionary( name => name, - name => new OpenApiSchema + _ => new OpenApiSchema { Type = "object", AdditionalProperties = new OpenApiSchema diff --git a/Jellyfin.Server/Middleware/ExceptionMiddleware.cs b/Jellyfin.Server/Middleware/ExceptionMiddleware.cs index f6c76e4d9e..db7877c31e 100644 --- a/Jellyfin.Server/Middleware/ExceptionMiddleware.cs +++ b/Jellyfin.Server/Middleware/ExceptionMiddleware.cs @@ -137,11 +137,6 @@ namespace Jellyfin.Server.Middleware private string NormalizeExceptionMessage(string msg) { - if (msg == null) - { - return string.Empty; - } - // Strip any information we don't want to reveal return msg.Replace( _configuration.ApplicationPaths.ProgramSystemPath, diff --git a/Jellyfin.Server/Migrations/MigrationRunner.cs b/Jellyfin.Server/Migrations/MigrationRunner.cs index cf938ab8cd..0af5cfd619 100644 --- a/Jellyfin.Server/Migrations/MigrationRunner.cs +++ b/Jellyfin.Server/Migrations/MigrationRunner.cs @@ -40,7 +40,7 @@ namespace Jellyfin.Server.Migrations .Select(m => ActivatorUtilities.CreateInstance(host.ServiceProvider, m)) .OfType() .ToArray(); - var migrationOptions = ((IConfigurationManager)host.ConfigurationManager).GetConfiguration(MigrationsListStore.StoreKey); + var migrationOptions = host.ConfigurationManager.GetConfiguration(MigrationsListStore.StoreKey); if (!host.ConfigurationManager.Configuration.IsStartupWizardCompleted && migrationOptions.Applied.Count == 0) { diff --git a/Jellyfin.Server/Migrations/Routines/MigrateActivityLogDb.cs b/Jellyfin.Server/Migrations/Routines/MigrateActivityLogDb.cs index 6048160c63..9e22978aee 100644 --- a/Jellyfin.Server/Migrations/Routines/MigrateActivityLogDb.cs +++ b/Jellyfin.Server/Migrations/Routines/MigrateActivityLogDb.cs @@ -92,7 +92,7 @@ namespace Jellyfin.Server.Migrations.Routines if (entry[6].SQLiteType != SQLiteType.Null && !Guid.TryParse(entry[6].ToString(), out guid)) { // This is not a valid Guid, see if it is an internal ID from an old Emby schema - _logger.LogWarning("Invalid Guid in UserId column: ", entry[6].ToString()); + _logger.LogWarning("Invalid Guid in UserId column: {Guid}", entry[6].ToString()); using var statement = userDbConnection.PrepareStatement("SELECT guid FROM LocalUsersv2 WHERE Id=@Id"); statement.TryBind("@Id", entry[6].ToString()); diff --git a/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs b/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs index e25d291226..6ff59626de 100644 --- a/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs +++ b/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.IO; using System.Linq; using System.Text.Json; diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 934372a94d..7018d537fd 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -5,7 +5,6 @@ using System.IO; using System.Linq; using System.Net; using System.Reflection; -using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -121,11 +120,11 @@ namespace Jellyfin.Server // Log uncaught exceptions to the logging instead of std error AppDomain.CurrentDomain.UnhandledException -= UnhandledExceptionToConsole; - AppDomain.CurrentDomain.UnhandledException += (sender, e) + AppDomain.CurrentDomain.UnhandledException += (_, e) => _logger.LogCritical((Exception)e.ExceptionObject, "Unhandled Exception"); // Intercept Ctrl+C and Ctrl+Break - Console.CancelKeyPress += (sender, e) => + Console.CancelKeyPress += (_, e) => { if (_tokenSource.IsCancellationRequested) { @@ -139,7 +138,7 @@ namespace Jellyfin.Server }; // Register a SIGTERM handler - AppDomain.CurrentDomain.ProcessExit += (sender, e) => + AppDomain.CurrentDomain.ProcessExit += (_, _) => { if (_tokenSource.IsCancellationRequested) { @@ -180,7 +179,7 @@ namespace Jellyfin.Server "The server is expected to host the web client, but the provided content directory is either " + $"invalid or empty: {webContentPath}. If you do not want to host the web client with the " + "server, you may set the '--nowebclient' command line flag, or set" + - $"'{MediaBrowser.Controller.Extensions.ConfigurationExtensions.HostWebClientKey}=false' in your config settings."); + $"'{ConfigurationExtensions.HostWebClientKey}=false' in your config settings."); } } @@ -543,7 +542,7 @@ namespace Jellyfin.Server // Get a stream of the resource contents // NOTE: The .csproj name is used instead of the assembly name in the resource path const string ResourcePath = "Jellyfin.Server.Resources.Configuration.logging.json"; - await using Stream? resource = typeof(Program).Assembly.GetManifestResourceStream(ResourcePath) + await using Stream resource = typeof(Program).Assembly.GetManifestResourceStream(ResourcePath) ?? throw new InvalidOperationException($"Invalid resource path: '{ResourcePath}'"); // Copy the resource contents to the expected file path for the config file diff --git a/MediaBrowser.Common/Extensions/ProcessExtensions.cs b/MediaBrowser.Common/Extensions/ProcessExtensions.cs index c747871222..08e01bfd65 100644 --- a/MediaBrowser.Common/Extensions/ProcessExtensions.cs +++ b/MediaBrowser.Common/Extensions/ProcessExtensions.cs @@ -40,7 +40,7 @@ namespace MediaBrowser.Common.Extensions // Add an event handler for the process exit event var tcs = new TaskCompletionSource(); - process.Exited += (sender, args) => tcs.TrySetResult(true); + process.Exited += (_, _) => tcs.TrySetResult(true); // Return immediately if the process has already exited if (process.HasExitedSafe()) diff --git a/MediaBrowser.Common/Providers/ProviderIdParsers.cs b/MediaBrowser.Common/Providers/ProviderIdParsers.cs index 33d09ed385..487b5a6d29 100644 --- a/MediaBrowser.Common/Providers/ProviderIdParsers.cs +++ b/MediaBrowser.Common/Providers/ProviderIdParsers.cs @@ -18,7 +18,7 @@ namespace MediaBrowser.Common.Providers /// The text to parse. /// The parsed IMDb id. /// True if parsing was successful, false otherwise. - public static bool TryFindImdbId(ReadOnlySpan text, [NotNullWhen(true)] out ReadOnlySpan imdbId) + public static bool TryFindImdbId(ReadOnlySpan text, out ReadOnlySpan imdbId) { // imdb id is at least 9 chars (tt + 7 numbers) while (text.Length >= 2 + ImdbMinNumbers) @@ -62,7 +62,7 @@ namespace MediaBrowser.Common.Providers /// The text with the url to parse. /// The parsed TMDb id. /// True if parsing was successful, false otherwise. - public static bool TryFindTmdbMovieId(ReadOnlySpan text, [NotNullWhen(true)] out ReadOnlySpan tmdbId) + public static bool TryFindTmdbMovieId(ReadOnlySpan text, out ReadOnlySpan tmdbId) => TryFindProviderId(text, "themoviedb.org/movie/", out tmdbId); /// @@ -71,7 +71,7 @@ namespace MediaBrowser.Common.Providers /// The text with the url to parse. /// The parsed TMDb id. /// True if parsing was successful, false otherwise. - public static bool TryFindTmdbSeriesId(ReadOnlySpan text, [NotNullWhen(true)] out ReadOnlySpan tmdbId) + public static bool TryFindTmdbSeriesId(ReadOnlySpan text, out ReadOnlySpan tmdbId) => TryFindProviderId(text, "themoviedb.org/tv/", out tmdbId); /// @@ -80,7 +80,7 @@ namespace MediaBrowser.Common.Providers /// The text with the url to parse. /// The parsed TVDb id. /// True if parsing was successful, false otherwise. - public static bool TryFindTvdbId(ReadOnlySpan text, [NotNullWhen(true)] out ReadOnlySpan tvdbId) + public static bool TryFindTvdbId(ReadOnlySpan text, out ReadOnlySpan tvdbId) => TryFindProviderId(text, "thetvdb.com/?tab=series&id=", out tvdbId); private static bool TryFindProviderId(ReadOnlySpan text, ReadOnlySpan searchString, [NotNullWhen(true)] out ReadOnlySpan providerId) diff --git a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs index 32e5ac7615..ef130ee747 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs @@ -81,7 +81,7 @@ namespace MediaBrowser.LocalMetadata.Parsers var id = info.Key + "Id"; if (!_validProviderIds.ContainsKey(id)) { - _validProviderIds.Add(id, info.Key!); + _validProviderIds.Add(id, info.Key); } } @@ -750,46 +750,6 @@ namespace MediaBrowser.LocalMetadata.Parsers item.Shares = list.ToArray(); } - private Share GetShareFromNode(XmlReader reader) - { - var share = new Share(); - - reader.MoveToContent(); - reader.Read(); - - // Loop through each element - while (!reader.EOF && reader.ReadState == ReadState.Interactive) - { - if (reader.NodeType == XmlNodeType.Element) - { - switch (reader.Name) - { - case "UserId": - { - share.UserId = reader.ReadElementContentAsString(); - break; - } - - case "CanEdit": - { - share.CanEdit = string.Equals(reader.ReadElementContentAsString(), true.ToString(CultureInfo.InvariantCulture), StringComparison.OrdinalIgnoreCase); - break; - } - - default: - reader.Skip(); - break; - } - } - else - { - reader.Read(); - } - } - - return share; - } - private void FetchFromCountriesNode(XmlReader reader) { reader.MoveToContent(); @@ -1101,7 +1061,7 @@ namespace MediaBrowser.LocalMetadata.Parsers switch (reader.Name) { case "Name": - name = reader.ReadElementContentAsString() ?? string.Empty; + name = reader.ReadElementContentAsString(); break; case "Type": @@ -1270,8 +1230,6 @@ namespace MediaBrowser.LocalMetadata.Parsers /// IEnumerable{System.String}. private IEnumerable SplitNames(string value) { - value ??= string.Empty; - // Only split by comma if there is no pipe in the string // We have to be careful to not split names like Matthew, Jr. var separator = !value.Contains('|', StringComparison.Ordinal) diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs index 98ed3dcf7d..dd824206f7 100644 --- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs @@ -33,16 +33,12 @@ namespace MediaBrowser.LocalMetadata.Savers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. - /// Instance of the interface. - /// Instance of the interface. /// Instance of the interface. - protected BaseXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger logger) + protected BaseXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, ILogger logger) { FileSystem = fileSystem; ConfigurationManager = configurationManager; LibraryManager = libraryManager; - UserManager = userManager; - UserDataManager = userDataManager; Logger = logger; } @@ -61,16 +57,6 @@ namespace MediaBrowser.LocalMetadata.Savers /// protected ILibraryManager LibraryManager { get; private set; } - /// - /// Gets the user manager. - /// - protected IUserManager UserManager { get; private set; } - - /// - /// Gets the user data manager. - /// - protected IUserDataManager UserDataManager { get; private set; } - /// /// Gets the logger. /// @@ -334,7 +320,7 @@ namespace MediaBrowser.LocalMetadata.Savers if (runTimeTicks.HasValue) { - var timespan = TimeSpan.FromTicks(runTimeTicks!.Value); + var timespan = TimeSpan.FromTicks(runTimeTicks.Value); writer.WriteElementString("RunningTime", Math.Floor(timespan.TotalMinutes).ToString(_usCulture)); } diff --git a/MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs index b08387b0c6..8a5da95bf3 100644 --- a/MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs @@ -20,11 +20,9 @@ namespace MediaBrowser.LocalMetadata.Savers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. - /// Instance of the interface. - /// Instance of the interface. /// Instance of the interface. - public BoxSetXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger logger) - : base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger) + public BoxSetXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, ILogger logger) + : base(fileSystem, configurationManager, libraryManager, logger) { } diff --git a/MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs index c2f1064238..76252bc090 100644 --- a/MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs @@ -25,11 +25,9 @@ namespace MediaBrowser.LocalMetadata.Savers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. - /// Instance of the interface. - /// Instance of the interface. /// Instance of the interface. - public PlaylistXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger logger) - : base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger) + public PlaylistXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, ILogger logger) + : base(fileSystem, configurationManager, libraryManager, logger) { } diff --git a/MediaBrowser.Model/Users/UserActionType.cs b/MediaBrowser.Model/Users/UserActionType.cs deleted file mode 100644 index dbb1513f22..0000000000 --- a/MediaBrowser.Model/Users/UserActionType.cs +++ /dev/null @@ -1,9 +0,0 @@ -#pragma warning disable CS1591 - -namespace MediaBrowser.Model.Users -{ - public enum UserActionType - { - PlayedItem = 0 - } -} diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index 302c93f0bc..2c86f9242d 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -1205,7 +1205,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers switch (reader.Name) { case "name": - name = reader.ReadElementContentAsString() ?? string.Empty; + name = reader.ReadElementContentAsString(); break; case "role": From 6a3ec7b4799222fe4c07ae1bc7dc9681083183ba Mon Sep 17 00:00:00 2001 From: h1dden-da3m0n <33120068+h1dden-da3m0n@users.noreply.github.com> Date: Wed, 4 Aug 2021 23:34:12 +0200 Subject: [PATCH 099/120] change OS packaging images to be quiet also uses the base dotnet/sdk image where possible --- deployment/Dockerfile.centos.amd64 | 18 +++++----- deployment/Dockerfile.debian.amd64 | 17 ++++----- deployment/Dockerfile.debian.arm64 | 32 ++++++++--------- deployment/Dockerfile.debian.armhf | 33 ++++++++--------- deployment/Dockerfile.fedora.amd64 | 14 ++++---- deployment/Dockerfile.linux.amd64 | 17 ++++----- deployment/Dockerfile.linux.amd64-musl | 17 ++++----- deployment/Dockerfile.linux.arm64 | 17 ++++----- deployment/Dockerfile.linux.armhf | 17 ++++----- deployment/Dockerfile.macos | 17 ++++----- deployment/Dockerfile.portable | 16 +++------ deployment/Dockerfile.ubuntu.amd64 | 15 ++++---- deployment/Dockerfile.ubuntu.arm64 | 50 ++++++++++++++------------ deployment/Dockerfile.ubuntu.armhf | 50 ++++++++++++++------------ deployment/Dockerfile.windows.amd64 | 17 ++++----- 15 files changed, 161 insertions(+), 186 deletions(-) diff --git a/deployment/Dockerfile.centos.amd64 b/deployment/Dockerfile.centos.amd64 index 01fc1aaac2..326e995be6 100644 --- a/deployment/Dockerfile.centos.amd64 +++ b/deployment/Dockerfile.centos.amd64 @@ -9,21 +9,21 @@ ENV ARTIFACT_DIR=/dist ENV IS_DOCKER=YES # Prepare CentOS environment -RUN yum update -y \ - && yum install -y epel-release \ - && yum install -y @buildsys-build rpmdevtools yum-plugins-core libcurl-devel fontconfig-devel freetype-devel openssl-devel glibc-devel libicu-devel git +RUN yum update -yq \ + && yum install -yq epel-release \ + && yum install -yq @buildsys-build rpmdevtools yum-plugins-core libcurl-devel fontconfig-devel freetype-devel openssl-devel glibc-devel libicu-devel git # Install DotNET SDK RUN rpm -Uvh https://packages.microsoft.com/config/rhel/7/packages-microsoft-prod.rpm \ - && rpmdev-setuptree \ - && yum install -y dotnet-sdk-${SDK_VERSION} + && rpmdev-setuptree \ + && yum install -yq dotnet-sdk-${SDK_VERSION} # Create symlinks and directories RUN ln -sf ${SOURCE_DIR}/deployment/build.centos.amd64 /build.sh \ - && mkdir -p ${SOURCE_DIR}/SPECS \ - && ln -s ${SOURCE_DIR}/fedora/jellyfin.spec ${SOURCE_DIR}/SPECS/jellyfin.spec \ - && mkdir -p ${SOURCE_DIR}/SOURCES \ - && ln -s ${SOURCE_DIR}/fedora ${SOURCE_DIR}/SOURCES + && mkdir -p ${SOURCE_DIR}/SPECS \ + && ln -s ${SOURCE_DIR}/fedora/jellyfin.spec ${SOURCE_DIR}/SPECS/jellyfin.spec \ + && mkdir -p ${SOURCE_DIR}/SOURCES \ + && ln -s ${SOURCE_DIR}/fedora ${SOURCE_DIR}/SOURCES VOLUME ${SOURCE_DIR}/ diff --git a/deployment/Dockerfile.debian.amd64 b/deployment/Dockerfile.debian.amd64 index 67a5c9c99a..31380452bf 100644 --- a/deployment/Dockerfile.debian.amd64 +++ b/deployment/Dockerfile.debian.amd64 @@ -1,8 +1,7 @@ -FROM debian:10 +FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim # Docker build arguments ARG SOURCE_DIR=/jellyfin ARG ARTIFACT_DIR=/dist -ARG SDK_VERSION=5.0 # Docker run environment ENV SOURCE_DIR=/jellyfin ENV ARTIFACT_DIR=/dist @@ -11,15 +10,11 @@ ENV ARCH=amd64 ENV IS_DOCKER=YES # Prepare Debian build environment -RUN apt-get update \ - && apt-get install -y apt-transport-https debhelper gnupg wget devscripts mmv libc6-dev libcurl4-openssl-dev libfontconfig1-dev libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 - -# Install dotnet repository -# https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ - && mkdir -p dotnet-sdk \ - && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ - && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet +RUN apt-get update -yqq \ + && apt-get install -yqq --no-install-recommends \ + apt-transport-https debhelper gnupg \ + wget devscripts mmv libc6-dev libcurl4-openssl-dev \ + libfontconfig1-dev libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 # Link to build script RUN ln -sf ${SOURCE_DIR}/deployment/build.debian.amd64 /build.sh diff --git a/deployment/Dockerfile.debian.arm64 b/deployment/Dockerfile.debian.arm64 index c341068f6f..42cacb6403 100644 --- a/deployment/Dockerfile.debian.arm64 +++ b/deployment/Dockerfile.debian.arm64 @@ -1,8 +1,7 @@ -FROM debian:10 +FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim # Docker build arguments ARG SOURCE_DIR=/jellyfin ARG ARTIFACT_DIR=/dist -ARG SDK_VERSION=5.0 # Docker run environment ENV SOURCE_DIR=/jellyfin ENV ARTIFACT_DIR=/dist @@ -11,23 +10,24 @@ ENV ARCH=amd64 ENV IS_DOCKER=YES # Prepare Debian build environment -RUN apt-get update \ - && apt-get install -y apt-transport-https debhelper gnupg wget devscripts mmv - -# Install dotnet repository -# https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ - && mkdir -p dotnet-sdk \ - && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ - && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet +RUN apt-get update -yqq \ + && apt-get install -yqq --no-install-recommends \ + apt-transport-https debhelper gnupg wget devscripts mmv # Prepare the cross-toolchain RUN dpkg --add-architecture arm64 \ - && apt-get update \ - && apt-get install -y cross-gcc-dev \ - && TARGET_LIST="arm64" cross-gcc-gensource 8 \ - && cd cross-gcc-packages-amd64/cross-gcc-8-arm64 \ - && apt-get install -y gcc-8-source libstdc++-8-dev-arm64-cross binutils-aarch64-linux-gnu bison flex libtool gdb sharutils netbase libmpc-dev libmpfr-dev libgmp-dev systemtap-sdt-dev autogen expect chrpath zlib1g-dev zip libc6-dev:arm64 linux-libc-dev:arm64 libgcc1:arm64 libcurl4-openssl-dev:arm64 libfontconfig1-dev:arm64 libfreetype6-dev:arm64 libssl-dev:arm64 liblttng-ust0:arm64 libstdc++-8-dev:arm64 + && apt-get update -yqq \ + && apt-get install -yqq --no-install-recommends cross-gcc-dev \ + && TARGET_LIST="arm64" cross-gcc-gensource 8 \ + && cd cross-gcc-packages-amd64/cross-gcc-8-arm64 \ + && apt-get install -yqq --no-install-recommends \ + gcc-8-source libstdc++-8-dev-arm64-cross \ + binutils-aarch64-linux-gnu bison flex libtool \ + gdb sharutils netbase libmpc-dev libmpfr-dev libgmp-dev \ + systemtap-sdt-dev autogen expect chrpath zlib1g-dev zip \ + libc6-dev:arm64 linux-libc-dev:arm64 libgcc1:arm64 \ + libcurl4-openssl-dev:arm64 libfontconfig1-dev:arm64 \ + libfreetype6-dev:arm64 libssl-dev:arm64 liblttng-ust0:arm64 libstdc++-8-dev:arm64 # Link to build script RUN ln -sf ${SOURCE_DIR}/deployment/build.debian.arm64 /build.sh diff --git a/deployment/Dockerfile.debian.armhf b/deployment/Dockerfile.debian.armhf index 19be363b6f..728d8509ef 100644 --- a/deployment/Dockerfile.debian.armhf +++ b/deployment/Dockerfile.debian.armhf @@ -1,8 +1,7 @@ -FROM debian:10 +FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim # Docker build arguments ARG SOURCE_DIR=/jellyfin ARG ARTIFACT_DIR=/dist -ARG SDK_VERSION=5.0 # Docker run environment ENV SOURCE_DIR=/jellyfin ENV ARTIFACT_DIR=/dist @@ -11,23 +10,25 @@ ENV ARCH=amd64 ENV IS_DOCKER=YES # Prepare Debian build environment -RUN apt-get update \ - && apt-get install -y apt-transport-https debhelper gnupg wget devscripts mmv - -# Install dotnet repository -# https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ - && mkdir -p dotnet-sdk \ - && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ - && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet +RUN apt-get update -yqq \ + && apt-get install -yqq --no-install-recommends \ + apt-transport-https debhelper gnupg wget devscripts mmv # Prepare the cross-toolchain RUN dpkg --add-architecture armhf \ - && apt-get update \ - && apt-get install -y cross-gcc-dev \ - && TARGET_LIST="armhf" cross-gcc-gensource 8 \ - && cd cross-gcc-packages-amd64/cross-gcc-8-armhf \ - && apt-get install -y gcc-8-source libstdc++-8-dev-armhf-cross binutils-aarch64-linux-gnu bison flex libtool gdb sharutils netbase libmpc-dev libmpfr-dev libgmp-dev systemtap-sdt-dev autogen expect chrpath zlib1g-dev zip binutils-arm-linux-gnueabihf libc6-dev:armhf linux-libc-dev:armhf libgcc1:armhf libcurl4-openssl-dev:armhf libfontconfig1-dev:armhf libfreetype6-dev:armhf libssl-dev:armhf liblttng-ust0:armhf libstdc++-8-dev:armhf + && apt-get update -yqq \ + && apt-get install -yqq --no-install-recommends cross-gcc-dev \ + && TARGET_LIST="armhf" cross-gcc-gensource 8 \ + && cd cross-gcc-packages-amd64/cross-gcc-8-armhf \ + && apt-get install -yqq --no-install-recommends\ + gcc-8-source libstdc++-8-dev-armhf-cross \ + binutils-aarch64-linux-gnu bison flex libtool gdb \ + sharutils netbase libmpc-dev libmpfr-dev libgmp-dev \ + systemtap-sdt-dev autogen expect chrpath zlib1g-dev \ + zip binutils-arm-linux-gnueabihf libc6-dev:armhf \ + linux-libc-dev:armhf libgcc1:armhf libcurl4-openssl-dev:armhf \ + libfontconfig1-dev:armhf libfreetype6-dev:armhf libssl-dev:armhf \ + liblttng-ust0:armhf libstdc++-8-dev:armhf # Link to build script RUN ln -sf ${SOURCE_DIR}/deployment/build.debian.armhf /build.sh diff --git a/deployment/Dockerfile.fedora.amd64 b/deployment/Dockerfile.fedora.amd64 index 137e56ecf2..590cde1677 100644 --- a/deployment/Dockerfile.fedora.amd64 +++ b/deployment/Dockerfile.fedora.amd64 @@ -9,18 +9,18 @@ ENV ARTIFACT_DIR=/dist ENV IS_DOCKER=YES # Prepare Fedora environment -RUN dnf update -y \ - && dnf install -y @buildsys-build rpmdevtools git dnf-plugins-core libcurl-devel fontconfig-devel freetype-devel openssl-devel glibc-devel libicu-devel systemd +RUN dnf update -yq \ + && dnf install -yq @buildsys-build rpmdevtools git dnf-plugins-core libcurl-devel fontconfig-devel freetype-devel openssl-devel glibc-devel libicu-devel systemd # Install DotNET SDK -RUN dnf install -y dotnet-sdk-${SDK_VERSION} dotnet-runtime-${SDK_VERSION} +RUN dnf install -yq dotnet-sdk-${SDK_VERSION} dotnet-runtime-${SDK_VERSION} # Create symlinks and directories RUN ln -sf ${SOURCE_DIR}/deployment/build.fedora.amd64 /build.sh \ - && mkdir -p ${SOURCE_DIR}/SPECS \ - && ln -s ${SOURCE_DIR}/fedora/jellyfin.spec ${SOURCE_DIR}/SPECS/jellyfin.spec \ - && mkdir -p ${SOURCE_DIR}/SOURCES \ - && ln -s ${SOURCE_DIR}/fedora ${SOURCE_DIR}/SOURCES + && mkdir -p ${SOURCE_DIR}/SPECS \ + && ln -s ${SOURCE_DIR}/fedora/jellyfin.spec ${SOURCE_DIR}/SPECS/jellyfin.spec \ + && mkdir -p ${SOURCE_DIR}/SOURCES \ + && ln -s ${SOURCE_DIR}/fedora ${SOURCE_DIR}/SOURCES VOLUME ${SOURCE_DIR}/ diff --git a/deployment/Dockerfile.linux.amd64 b/deployment/Dockerfile.linux.amd64 index a89fe92893..03ebbadb2e 100644 --- a/deployment/Dockerfile.linux.amd64 +++ b/deployment/Dockerfile.linux.amd64 @@ -1,8 +1,7 @@ -FROM debian:10 +FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim # Docker build arguments ARG SOURCE_DIR=/jellyfin ARG ARTIFACT_DIR=/dist -ARG SDK_VERSION=5.0 # Docker run environment ENV SOURCE_DIR=/jellyfin ENV ARTIFACT_DIR=/dist @@ -11,15 +10,11 @@ ENV ARCH=amd64 ENV IS_DOCKER=YES # Prepare Debian build environment -RUN apt-get update \ - && apt-get install -y apt-transport-https debhelper gnupg wget devscripts mmv libc6-dev libcurl4-openssl-dev libfontconfig1-dev libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 - -# Install dotnet repository -# https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ - && mkdir -p dotnet-sdk \ - && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ - && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet +RUN apt-get update -yqq \ + && apt-get install -yqq --no-install-recommends \ + apt-transport-https debhelper gnupg wget devscripts \ + mmv libc6-dev libcurl4-openssl-dev libfontconfig1-dev \ + libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 # Link to docker-build script RUN ln -sf ${SOURCE_DIR}/deployment/build.linux.amd64 /build.sh diff --git a/deployment/Dockerfile.linux.amd64-musl b/deployment/Dockerfile.linux.amd64-musl index f7fb722f25..2d0b507124 100644 --- a/deployment/Dockerfile.linux.amd64-musl +++ b/deployment/Dockerfile.linux.amd64-musl @@ -1,8 +1,7 @@ -FROM debian:10 +FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim # Docker build arguments ARG SOURCE_DIR=/jellyfin ARG ARTIFACT_DIR=/dist -ARG SDK_VERSION=5.0 # Docker run environment ENV SOURCE_DIR=/jellyfin ENV ARTIFACT_DIR=/dist @@ -11,15 +10,11 @@ ENV ARCH=amd64 ENV IS_DOCKER=YES # Prepare Debian build environment -RUN apt-get update \ - && apt-get install -y apt-transport-https debhelper gnupg wget devscripts mmv libc6-dev libcurl4-openssl-dev libfontconfig1-dev libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 - -# Install dotnet repository -# https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ - && mkdir -p dotnet-sdk \ - && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ - && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet +RUN apt-get update -yqq \ + && apt-get install -yqq --no-install-recommends \ + apt-transport-https debhelper gnupg wget devscripts \ + mmv libc6-dev libcurl4-openssl-dev libfontconfig1-dev \ + libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 # Link to docker-build script RUN ln -sf ${SOURCE_DIR}/deployment/build.linux.amd64-musl /build.sh diff --git a/deployment/Dockerfile.linux.arm64 b/deployment/Dockerfile.linux.arm64 index 1b57441a0f..c405e2631c 100644 --- a/deployment/Dockerfile.linux.arm64 +++ b/deployment/Dockerfile.linux.arm64 @@ -1,8 +1,7 @@ -FROM debian:10 +FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim # Docker build arguments ARG SOURCE_DIR=/jellyfin ARG ARTIFACT_DIR=/dist -ARG SDK_VERSION=5.0 # Docker run environment ENV SOURCE_DIR=/jellyfin ENV ARTIFACT_DIR=/dist @@ -11,15 +10,11 @@ ENV ARCH=arm64 ENV IS_DOCKER=YES # Prepare Debian build environment -RUN apt-get update \ - && apt-get install -y apt-transport-https debhelper gnupg wget devscripts mmv libc6-dev libcurl4-openssl-dev libfontconfig1-dev libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 - -# Install dotnet repository -# https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ - && mkdir -p dotnet-sdk \ - && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ - && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet +RUN apt-get update -yqq \ + && apt-get install -yqq --no-install-recommends \ + apt-transport-https debhelper gnupg wget devscripts \ + mmv libc6-dev libcurl4-openssl-dev libfontconfig1-dev \ + libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 # Link to docker-build script RUN ln -sf ${SOURCE_DIR}/deployment/build.linux.arm64 /build.sh diff --git a/deployment/Dockerfile.linux.armhf b/deployment/Dockerfile.linux.armhf index 20cf33e13f..6a5942cb79 100644 --- a/deployment/Dockerfile.linux.armhf +++ b/deployment/Dockerfile.linux.armhf @@ -1,8 +1,7 @@ -FROM debian:10 +FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim # Docker build arguments ARG SOURCE_DIR=/jellyfin ARG ARTIFACT_DIR=/dist -ARG SDK_VERSION=5.0 # Docker run environment ENV SOURCE_DIR=/jellyfin ENV ARTIFACT_DIR=/dist @@ -11,15 +10,11 @@ ENV ARCH=armhf ENV IS_DOCKER=YES # Prepare Debian build environment -RUN apt-get update \ - && apt-get install -y apt-transport-https debhelper gnupg wget devscripts mmv libc6-dev libcurl4-openssl-dev libfontconfig1-dev libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 - -# Install dotnet repository -# https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ - && mkdir -p dotnet-sdk \ - && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ - && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet +RUN apt-get update -yqq \ + && apt-get install -yqq --no-install-recommends \ + apt-transport-https debhelper gnupg wget devscripts \ + mmv libc6-dev libcurl4-openssl-dev libfontconfig1-dev \ + libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 # Link to docker-build script RUN ln -sf ${SOURCE_DIR}/deployment/build.linux.armhf /build.sh diff --git a/deployment/Dockerfile.macos b/deployment/Dockerfile.macos index 4ddd106bba..f7d7591355 100644 --- a/deployment/Dockerfile.macos +++ b/deployment/Dockerfile.macos @@ -1,8 +1,7 @@ -FROM debian:10 +FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim # Docker build arguments ARG SOURCE_DIR=/jellyfin ARG ARTIFACT_DIR=/dist -ARG SDK_VERSION=5.0 # Docker run environment ENV SOURCE_DIR=/jellyfin ENV ARTIFACT_DIR=/dist @@ -11,15 +10,11 @@ ENV ARCH=amd64 ENV IS_DOCKER=YES # Prepare Debian build environment -RUN apt-get update \ - && apt-get install -y apt-transport-https debhelper gnupg wget devscripts mmv libc6-dev libcurl4-openssl-dev libfontconfig1-dev libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 - -# Install dotnet repository -# https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ - && mkdir -p dotnet-sdk \ - && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ - && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet +RUN apt-get update -yqq \ + && apt-get install -yqq --no-install-recommends \ + apt-transport-https debhelper gnupg wget devscripts \ + mmv libc6-dev libcurl4-openssl-dev libfontconfig1-dev \ + libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 # Link to docker-build script RUN ln -sf ${SOURCE_DIR}/deployment/build.macos /build.sh diff --git a/deployment/Dockerfile.portable b/deployment/Dockerfile.portable index e56a480c66..eba8738c37 100644 --- a/deployment/Dockerfile.portable +++ b/deployment/Dockerfile.portable @@ -1,8 +1,7 @@ -FROM debian:10 +FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim # Docker build arguments ARG SOURCE_DIR=/jellyfin ARG ARTIFACT_DIR=/dist -ARG SDK_VERSION=5.0 # Docker run environment ENV SOURCE_DIR=/jellyfin ENV ARTIFACT_DIR=/dist @@ -10,15 +9,10 @@ ENV DEB_BUILD_OPTIONS=noddebs ENV IS_DOCKER=YES # Prepare Debian build environment -RUN apt-get update \ - && apt-get install -y apt-transport-https debhelper gnupg wget devscripts mmv libc6-dev libcurl4-openssl-dev libfontconfig1-dev libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 - -# Install dotnet repository -# https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ - && mkdir -p dotnet-sdk \ - && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ - && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet +RUN apt-get update -yqq \ + && apt-get install -yqq --no-install-recommends \ + apt-transport-https debhelper gnupg wget \ + devscripts mmv libc6-dev libcurl4-openssl-dev libfontconfig1-dev libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 # Link to docker-build script RUN ln -sf ${SOURCE_DIR}/deployment/build.portable /build.sh diff --git a/deployment/Dockerfile.ubuntu.amd64 b/deployment/Dockerfile.ubuntu.amd64 index 03d4c185cb..1a3f3f3744 100644 --- a/deployment/Dockerfile.ubuntu.amd64 +++ b/deployment/Dockerfile.ubuntu.amd64 @@ -11,15 +11,18 @@ ENV ARCH=amd64 ENV IS_DOCKER=YES # Prepare Debian build environment -RUN apt-get update \ - && apt-get install -y apt-transport-https debhelper gnupg wget devscripts mmv libc6-dev libcurl4-openssl-dev libfontconfig1-dev libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 +RUN apt-get update -yqq \ + && apt-get install -yqq --no-install-recommends \ + apt-transport-https debhelper gnupg wget devscripts \ + mmv libc6-dev libcurl4-openssl-dev libfontconfig1-dev \ + libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ - && mkdir -p dotnet-sdk \ - && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ - && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ + && mkdir -p dotnet-sdk \ + && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ + && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet # Link to build script RUN ln -sf ${SOURCE_DIR}/deployment/build.ubuntu.amd64 /build.sh diff --git a/deployment/Dockerfile.ubuntu.arm64 b/deployment/Dockerfile.ubuntu.arm64 index 9e0b60e0b7..574cc75587 100644 --- a/deployment/Dockerfile.ubuntu.arm64 +++ b/deployment/Dockerfile.ubuntu.arm64 @@ -11,34 +11,40 @@ ENV ARCH=amd64 ENV IS_DOCKER=YES # Prepare Debian build environment -RUN apt-get update \ - && apt-get install -y apt-transport-https debhelper gnupg wget devscripts mmv +RUN apt-get update -yqq \ + && apt-get install -yqq --no-install-recommends \ + apt-transport-https debhelper gnupg wget devscripts mmv # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ - && mkdir -p dotnet-sdk \ - && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ - && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ + && mkdir -p dotnet-sdk \ + && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ + && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet # Prepare the cross-toolchain RUN rm /etc/apt/sources.list \ - && export CODENAME="$( lsb_release -c -s )" \ - && echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ ${CODENAME} main restricted universe multiverse" >>/etc/apt/sources.list.d/amd64.list \ - && echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ ${CODENAME}-updates main restricted universe multiverse" >>/etc/apt/sources.list.d/amd64.list \ - && echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ ${CODENAME}-backports main restricted universe multiverse" >>/etc/apt/sources.list.d/amd64.list \ - && echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ ${CODENAME}-security main restricted universe multiverse" >>/etc/apt/sources.list.d/amd64.list \ - && echo "deb [arch=arm64] http://ports.ubuntu.com/ ${CODENAME} main restricted universe multiverse" >>/etc/apt/sources.list.d/arm64.list \ - && echo "deb [arch=arm64] http://ports.ubuntu.com/ ${CODENAME}-updates main restricted universe multiverse" >>/etc/apt/sources.list.d/arm64.list \ - && echo "deb [arch=arm64] http://ports.ubuntu.com/ ${CODENAME}-backports main restricted universe multiverse" >>/etc/apt/sources.list.d/arm64.list \ - && echo "deb [arch=arm64] http://ports.ubuntu.com/ ${CODENAME}-security main restricted universe multiverse" >>/etc/apt/sources.list.d/arm64.list \ - && dpkg --add-architecture arm64 \ - && apt-get update \ - && apt-get install -y cross-gcc-dev \ - && TARGET_LIST="arm64" cross-gcc-gensource 6 \ - && cd cross-gcc-packages-amd64/cross-gcc-6-arm64 \ - && ln -fs /usr/share/zoneinfo/America/Toronto /etc/localtime \ - && apt-get install -y gcc-6-source libstdc++6-arm64-cross binutils-aarch64-linux-gnu bison flex libtool gdb sharutils netbase libcloog-isl-dev libmpc-dev libmpfr-dev libgmp-dev systemtap-sdt-dev autogen expect chrpath zlib1g-dev zip libc6-dev:arm64 linux-libc-dev:arm64 libgcc1:arm64 libcurl4-openssl-dev:arm64 libfontconfig1-dev:arm64 libfreetype6-dev:arm64 liblttng-ust0:arm64 libstdc++6:arm64 libssl-dev:arm64 + && export CODENAME="$( lsb_release -c -s )" \ + && echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ ${CODENAME} main restricted universe multiverse" >>/etc/apt/sources.list.d/amd64.list \ + && echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ ${CODENAME}-updates main restricted universe multiverse" >>/etc/apt/sources.list.d/amd64.list \ + && echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ ${CODENAME}-backports main restricted universe multiverse" >>/etc/apt/sources.list.d/amd64.list \ + && echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ ${CODENAME}-security main restricted universe multiverse" >>/etc/apt/sources.list.d/amd64.list \ + && echo "deb [arch=arm64] http://ports.ubuntu.com/ ${CODENAME} main restricted universe multiverse" >>/etc/apt/sources.list.d/arm64.list \ + && echo "deb [arch=arm64] http://ports.ubuntu.com/ ${CODENAME}-updates main restricted universe multiverse" >>/etc/apt/sources.list.d/arm64.list \ + && echo "deb [arch=arm64] http://ports.ubuntu.com/ ${CODENAME}-backports main restricted universe multiverse" >>/etc/apt/sources.list.d/arm64.list \ + && echo "deb [arch=arm64] http://ports.ubuntu.com/ ${CODENAME}-security main restricted universe multiverse" >>/etc/apt/sources.list.d/arm64.list \ + && dpkg --add-architecture arm64 \ + && apt-get update -yqq \ + && apt-get install -yqq --no-install-recommends cross-gcc-dev \ + && TARGET_LIST="arm64" cross-gcc-gensource 6 \ + && cd cross-gcc-packages-amd64/cross-gcc-6-arm64 \ + && ln -fs /usr/share/zoneinfo/America/Toronto /etc/localtime \ + && apt-get install -yqq --no-install-recommends \ + gcc-6-source libstdc++6-arm64-cross binutils-aarch64-linux-gnu \ + bison flex libtool gdb sharutils netbase libcloog-isl-dev libmpc-dev \ + libmpfr-dev libgmp-dev systemtap-sdt-dev autogen expect chrpath zlib1g-dev \ + zip libc6-dev:arm64 linux-libc-dev:arm64 libgcc1:arm64 libcurl4-openssl-dev:arm64 \ + libfontconfig1-dev:arm64 libfreetype6-dev:arm64 liblttng-ust0:arm64 libstdc++6:arm64 libssl-dev:arm64 # Link to build script RUN ln -sf ${SOURCE_DIR}/deployment/build.ubuntu.arm64 /build.sh diff --git a/deployment/Dockerfile.ubuntu.armhf b/deployment/Dockerfile.ubuntu.armhf index 0392f7b2ff..ee6f083ea4 100644 --- a/deployment/Dockerfile.ubuntu.armhf +++ b/deployment/Dockerfile.ubuntu.armhf @@ -11,34 +11,40 @@ ENV ARCH=amd64 ENV IS_DOCKER=YES # Prepare Debian build environment -RUN apt-get update \ - && apt-get install -y apt-transport-https debhelper gnupg wget devscripts mmv +RUN apt-get update -yqq \ + && apt-get install -yqq --no-install-recommends \ + apt-transport-https debhelper gnupg wget devscripts mmv # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ - && mkdir -p dotnet-sdk \ - && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ - && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ + && mkdir -p dotnet-sdk \ + && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ + && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet # Prepare the cross-toolchain RUN rm /etc/apt/sources.list \ - && export CODENAME="$( lsb_release -c -s )" \ - && echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ ${CODENAME} main restricted universe multiverse" >>/etc/apt/sources.list.d/amd64.list \ - && echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ ${CODENAME}-updates main restricted universe multiverse" >>/etc/apt/sources.list.d/amd64.list \ - && echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ ${CODENAME}-backports main restricted universe multiverse" >>/etc/apt/sources.list.d/amd64.list \ - && echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ ${CODENAME}-security main restricted universe multiverse" >>/etc/apt/sources.list.d/amd64.list \ - && echo "deb [arch=armhf] http://ports.ubuntu.com/ ${CODENAME} main restricted universe multiverse" >>/etc/apt/sources.list.d/armhf.list \ - && echo "deb [arch=armhf] http://ports.ubuntu.com/ ${CODENAME}-updates main restricted universe multiverse" >>/etc/apt/sources.list.d/armhf.list \ - && echo "deb [arch=armhf] http://ports.ubuntu.com/ ${CODENAME}-backports main restricted universe multiverse" >>/etc/apt/sources.list.d/armhf.list \ - && echo "deb [arch=armhf] http://ports.ubuntu.com/ ${CODENAME}-security main restricted universe multiverse" >>/etc/apt/sources.list.d/armhf.list \ - && dpkg --add-architecture armhf \ - && apt-get update \ - && apt-get install -y cross-gcc-dev \ - && TARGET_LIST="armhf" cross-gcc-gensource 6 \ - && cd cross-gcc-packages-amd64/cross-gcc-6-armhf \ - && ln -fs /usr/share/zoneinfo/America/Toronto /etc/localtime \ - && apt-get install -y gcc-6-source libstdc++6-armhf-cross binutils-arm-linux-gnueabihf bison flex libtool gdb sharutils netbase libcloog-isl-dev libmpc-dev libmpfr-dev libgmp-dev systemtap-sdt-dev autogen expect chrpath zlib1g-dev zip libc6-dev:armhf linux-libc-dev:armhf libgcc1:armhf libcurl4-openssl-dev:armhf libfontconfig1-dev:armhf libfreetype6-dev:armhf liblttng-ust0:armhf libstdc++6:armhf libssl-dev:armhf + && export CODENAME="$( lsb_release -c -s )" \ + && echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ ${CODENAME} main restricted universe multiverse" >>/etc/apt/sources.list.d/amd64.list \ + && echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ ${CODENAME}-updates main restricted universe multiverse" >>/etc/apt/sources.list.d/amd64.list \ + && echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ ${CODENAME}-backports main restricted universe multiverse" >>/etc/apt/sources.list.d/amd64.list \ + && echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ ${CODENAME}-security main restricted universe multiverse" >>/etc/apt/sources.list.d/amd64.list \ + && echo "deb [arch=armhf] http://ports.ubuntu.com/ ${CODENAME} main restricted universe multiverse" >>/etc/apt/sources.list.d/armhf.list \ + && echo "deb [arch=armhf] http://ports.ubuntu.com/ ${CODENAME}-updates main restricted universe multiverse" >>/etc/apt/sources.list.d/armhf.list \ + && echo "deb [arch=armhf] http://ports.ubuntu.com/ ${CODENAME}-backports main restricted universe multiverse" >>/etc/apt/sources.list.d/armhf.list \ + && echo "deb [arch=armhf] http://ports.ubuntu.com/ ${CODENAME}-security main restricted universe multiverse" >>/etc/apt/sources.list.d/armhf.list \ + && dpkg --add-architecture armhf \ + && apt-get update -yqq \ + && apt-get install -yqq cross-gcc-dev \ + && TARGET_LIST="armhf" cross-gcc-gensource 6 \ + && cd cross-gcc-packages-amd64/cross-gcc-6-armhf \ + && ln -fs /usr/share/zoneinfo/America/Toronto /etc/localtime \ + && apt-get install -yqq --no-install-recommends \ + gcc-6-source libstdc++6-armhf-cross binutils-arm-linux-gnueabihf \ + bison flex libtool gdb sharutils netbase libcloog-isl-dev libmpc-dev \ + libmpfr-dev libgmp-dev systemtap-sdt-dev autogen expect chrpath zlib1g-dev \ + zip libc6-dev:armhf linux-libc-dev:armhf libgcc1:armhf libcurl4-openssl-dev:armhf \ + libfontconfig1-dev:armhf libfreetype6-dev:armhf liblttng-ust0:armhf libstdc++6:armhf libssl-dev:armhf # Link to build script RUN ln -sf ${SOURCE_DIR}/deployment/build.debian.armhf /build.sh diff --git a/deployment/Dockerfile.windows.amd64 b/deployment/Dockerfile.windows.amd64 index 9c78897a40..8336c02eee 100644 --- a/deployment/Dockerfile.windows.amd64 +++ b/deployment/Dockerfile.windows.amd64 @@ -1,8 +1,7 @@ -FROM debian:10 +FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim # Docker build arguments ARG SOURCE_DIR=/jellyfin ARG ARTIFACT_DIR=/dist -ARG SDK_VERSION=5.0 # Docker run environment ENV SOURCE_DIR=/jellyfin ENV ARTIFACT_DIR=/dist @@ -10,15 +9,11 @@ ENV DEB_BUILD_OPTIONS=noddebs ENV IS_DOCKER=YES # Prepare Debian build environment -RUN apt-get update \ - && apt-get install -y apt-transport-https debhelper gnupg wget devscripts mmv libc6-dev libcurl4-openssl-dev libfontconfig1-dev libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 zip - -# Install dotnet repository -# https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/8468e541-a99a-4191-8470-654fa0747a9a/cb32548d2fd3d60ef3fe8fc80cd735ef/dotnet-sdk-5.0.302-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ - && mkdir -p dotnet-sdk \ - && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ - && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet +RUN apt-get update -yqq \ + && apt-get install -yqq --no-install-recommends \ + apt-transport-https debhelper gnupg wget devscripts \ + mmv libc6-dev libcurl4-openssl-dev libfontconfig1-dev \ + libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 zip # Link to docker-build script RUN ln -sf ${SOURCE_DIR}/deployment/build.windows.amd64 /build.sh From ea798de61fc374438309cddb2cd4c3f066246570 Mon Sep 17 00:00:00 2001 From: h1dden-da3m0n <33120068+h1dden-da3m0n@users.noreply.github.com> Date: Thu, 5 Aug 2021 00:25:58 +0200 Subject: [PATCH 100/120] remove packages bundled in dotnet/sdk base image --- deployment/Dockerfile.debian.amd64 | 2 +- deployment/Dockerfile.debian.arm64 | 2 +- deployment/Dockerfile.debian.armhf | 2 +- deployment/Dockerfile.linux.amd64 | 4 ++-- deployment/Dockerfile.linux.amd64-musl | 4 ++-- deployment/Dockerfile.linux.arm64 | 4 ++-- deployment/Dockerfile.linux.armhf | 4 ++-- deployment/Dockerfile.macos | 4 ++-- deployment/Dockerfile.portable | 5 +++-- deployment/Dockerfile.windows.amd64 | 4 ++-- 10 files changed, 18 insertions(+), 17 deletions(-) diff --git a/deployment/Dockerfile.debian.amd64 b/deployment/Dockerfile.debian.amd64 index 31380452bf..e25b9c7561 100644 --- a/deployment/Dockerfile.debian.amd64 +++ b/deployment/Dockerfile.debian.amd64 @@ -13,7 +13,7 @@ ENV IS_DOCKER=YES RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ apt-transport-https debhelper gnupg \ - wget devscripts mmv libc6-dev libcurl4-openssl-dev \ + devscripts mmv libcurl4-openssl-dev \ libfontconfig1-dev libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 # Link to build script diff --git a/deployment/Dockerfile.debian.arm64 b/deployment/Dockerfile.debian.arm64 index 42cacb6403..198e35cf19 100644 --- a/deployment/Dockerfile.debian.arm64 +++ b/deployment/Dockerfile.debian.arm64 @@ -12,7 +12,7 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg wget devscripts mmv + apt-transport-https debhelper gnupg devscripts mmv # Prepare the cross-toolchain RUN dpkg --add-architecture arm64 \ diff --git a/deployment/Dockerfile.debian.armhf b/deployment/Dockerfile.debian.armhf index 728d8509ef..32bcff5d3f 100644 --- a/deployment/Dockerfile.debian.armhf +++ b/deployment/Dockerfile.debian.armhf @@ -12,7 +12,7 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg wget devscripts mmv + apt-transport-https debhelper gnupg devscripts mmv # Prepare the cross-toolchain RUN dpkg --add-architecture armhf \ diff --git a/deployment/Dockerfile.linux.amd64 b/deployment/Dockerfile.linux.amd64 index 03ebbadb2e..47d72f50c6 100644 --- a/deployment/Dockerfile.linux.amd64 +++ b/deployment/Dockerfile.linux.amd64 @@ -12,8 +12,8 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg wget devscripts \ - mmv libc6-dev libcurl4-openssl-dev libfontconfig1-dev \ + apt-transport-https debhelper gnupg devscripts \ + mmv libcurl4-openssl-dev libfontconfig1-dev \ libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 # Link to docker-build script diff --git a/deployment/Dockerfile.linux.amd64-musl b/deployment/Dockerfile.linux.amd64-musl index 2d0b507124..b2e971a2dc 100644 --- a/deployment/Dockerfile.linux.amd64-musl +++ b/deployment/Dockerfile.linux.amd64-musl @@ -12,8 +12,8 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg wget devscripts \ - mmv libc6-dev libcurl4-openssl-dev libfontconfig1-dev \ + apt-transport-https debhelper gnupg devscripts \ + mmv libcurl4-openssl-dev libfontconfig1-dev \ libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 # Link to docker-build script diff --git a/deployment/Dockerfile.linux.arm64 b/deployment/Dockerfile.linux.arm64 index c405e2631c..0d4b1619a7 100644 --- a/deployment/Dockerfile.linux.arm64 +++ b/deployment/Dockerfile.linux.arm64 @@ -12,8 +12,8 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg wget devscripts \ - mmv libc6-dev libcurl4-openssl-dev libfontconfig1-dev \ + apt-transport-https debhelper gnupg devscripts \ + mmv libcurl4-openssl-dev libfontconfig1-dev \ libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 # Link to docker-build script diff --git a/deployment/Dockerfile.linux.armhf b/deployment/Dockerfile.linux.armhf index 6a5942cb79..4a170ce56c 100644 --- a/deployment/Dockerfile.linux.armhf +++ b/deployment/Dockerfile.linux.armhf @@ -12,8 +12,8 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg wget devscripts \ - mmv libc6-dev libcurl4-openssl-dev libfontconfig1-dev \ + apt-transport-https debhelper gnupg devscripts \ + mmv libcurl4-openssl-dev libfontconfig1-dev \ libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 # Link to docker-build script diff --git a/deployment/Dockerfile.macos b/deployment/Dockerfile.macos index f7d7591355..fad44ef833 100644 --- a/deployment/Dockerfile.macos +++ b/deployment/Dockerfile.macos @@ -12,8 +12,8 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg wget devscripts \ - mmv libc6-dev libcurl4-openssl-dev libfontconfig1-dev \ + apt-transport-https debhelper gnupg devscripts \ + mmv libcurl4-openssl-dev libfontconfig1-dev \ libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 # Link to docker-build script diff --git a/deployment/Dockerfile.portable b/deployment/Dockerfile.portable index eba8738c37..90cc0717b7 100644 --- a/deployment/Dockerfile.portable +++ b/deployment/Dockerfile.portable @@ -11,8 +11,9 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg wget \ - devscripts mmv libc6-dev libcurl4-openssl-dev libfontconfig1-dev libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 + apt-transport-https debhelper gnupg devscripts \ + mmv libcurl4-openssl-dev libfontconfig1-dev \ + libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 # Link to docker-build script RUN ln -sf ${SOURCE_DIR}/deployment/build.portable /build.sh diff --git a/deployment/Dockerfile.windows.amd64 b/deployment/Dockerfile.windows.amd64 index 8336c02eee..f913700809 100644 --- a/deployment/Dockerfile.windows.amd64 +++ b/deployment/Dockerfile.windows.amd64 @@ -11,8 +11,8 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg wget devscripts \ - mmv libc6-dev libcurl4-openssl-dev libfontconfig1-dev \ + apt-transport-https debhelper gnupg devscripts \ + mmv libcurl4-openssl-dev libfontconfig1-dev \ libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 zip # Link to docker-build script From ed2a637ce3f94b16773fd61c362e72452f5eb9d2 Mon Sep 17 00:00:00 2001 From: h1dden-da3m0n <33120068+h1dden-da3m0n@users.noreply.github.com> Date: Fri, 6 Aug 2021 01:36:23 +0200 Subject: [PATCH 101/120] fix missing build dependencies needed by the build sh-scripts --- deployment/Dockerfile.debian.amd64 | 6 +++--- deployment/Dockerfile.debian.arm64 | 2 +- deployment/Dockerfile.debian.armhf | 2 +- deployment/Dockerfile.linux.amd64 | 2 +- deployment/Dockerfile.linux.amd64-musl | 2 +- deployment/Dockerfile.linux.arm64 | 2 +- deployment/Dockerfile.linux.armhf | 2 +- deployment/Dockerfile.ubuntu.amd64 | 4 ++-- deployment/Dockerfile.ubuntu.arm64 | 3 ++- deployment/Dockerfile.ubuntu.armhf | 3 ++- deployment/Dockerfile.windows.amd64 | 2 +- 11 files changed, 16 insertions(+), 14 deletions(-) diff --git a/deployment/Dockerfile.debian.amd64 b/deployment/Dockerfile.debian.amd64 index e25b9c7561..23b662526e 100644 --- a/deployment/Dockerfile.debian.amd64 +++ b/deployment/Dockerfile.debian.amd64 @@ -12,9 +12,9 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg \ - devscripts mmv libcurl4-openssl-dev \ - libfontconfig1-dev libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 + apt-transport-https debhelper gnupg devscripts build-essential mmv \ + libcurl4-openssl-dev libfontconfig1-dev libfreetype6-dev libssl-dev \ + libssl1.1 liblttng-ust0 # Link to build script RUN ln -sf ${SOURCE_DIR}/deployment/build.debian.amd64 /build.sh diff --git a/deployment/Dockerfile.debian.arm64 b/deployment/Dockerfile.debian.arm64 index 198e35cf19..a33099031e 100644 --- a/deployment/Dockerfile.debian.arm64 +++ b/deployment/Dockerfile.debian.arm64 @@ -12,7 +12,7 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg devscripts mmv + apt-transport-https debhelper gnupg devscripts build-essential mmv # Prepare the cross-toolchain RUN dpkg --add-architecture arm64 \ diff --git a/deployment/Dockerfile.debian.armhf b/deployment/Dockerfile.debian.armhf index 32bcff5d3f..bc5e3543fa 100644 --- a/deployment/Dockerfile.debian.armhf +++ b/deployment/Dockerfile.debian.armhf @@ -12,7 +12,7 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg devscripts mmv + apt-transport-https debhelper gnupg devscripts build-essential mmv # Prepare the cross-toolchain RUN dpkg --add-architecture armhf \ diff --git a/deployment/Dockerfile.linux.amd64 b/deployment/Dockerfile.linux.amd64 index 47d72f50c6..3c7e2b87f6 100644 --- a/deployment/Dockerfile.linux.amd64 +++ b/deployment/Dockerfile.linux.amd64 @@ -12,7 +12,7 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg devscripts \ + apt-transport-https debhelper gnupg devscripts unzip \ mmv libcurl4-openssl-dev libfontconfig1-dev \ libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 diff --git a/deployment/Dockerfile.linux.amd64-musl b/deployment/Dockerfile.linux.amd64-musl index b2e971a2dc..3cda9ad235 100644 --- a/deployment/Dockerfile.linux.amd64-musl +++ b/deployment/Dockerfile.linux.amd64-musl @@ -12,7 +12,7 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg devscripts \ + apt-transport-https debhelper gnupg devscripts unzip \ mmv libcurl4-openssl-dev libfontconfig1-dev \ libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 diff --git a/deployment/Dockerfile.linux.arm64 b/deployment/Dockerfile.linux.arm64 index 0d4b1619a7..ddf97cbd1c 100644 --- a/deployment/Dockerfile.linux.arm64 +++ b/deployment/Dockerfile.linux.arm64 @@ -12,7 +12,7 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg devscripts \ + apt-transport-https debhelper gnupg devscripts unzip \ mmv libcurl4-openssl-dev libfontconfig1-dev \ libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 diff --git a/deployment/Dockerfile.linux.armhf b/deployment/Dockerfile.linux.armhf index 4a170ce56c..49e1c7bbf5 100644 --- a/deployment/Dockerfile.linux.armhf +++ b/deployment/Dockerfile.linux.armhf @@ -12,7 +12,7 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg devscripts \ + apt-transport-https debhelper gnupg devscripts unzip \ mmv libcurl4-openssl-dev libfontconfig1-dev \ libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 diff --git a/deployment/Dockerfile.ubuntu.amd64 b/deployment/Dockerfile.ubuntu.amd64 index 1a3f3f3744..97e3ff8023 100644 --- a/deployment/Dockerfile.ubuntu.amd64 +++ b/deployment/Dockerfile.ubuntu.amd64 @@ -13,8 +13,8 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg wget devscripts \ - mmv libc6-dev libcurl4-openssl-dev libfontconfig1-dev \ + apt-transport-https debhelper gnupg wget ca-certificates devscripts \ + mmv build-essential libcurl4-openssl-dev libfontconfig1-dev \ libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 # Install dotnet repository diff --git a/deployment/Dockerfile.ubuntu.arm64 b/deployment/Dockerfile.ubuntu.arm64 index 574cc75587..c94ee91dd7 100644 --- a/deployment/Dockerfile.ubuntu.arm64 +++ b/deployment/Dockerfile.ubuntu.arm64 @@ -13,7 +13,8 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg wget devscripts mmv + apt-transport-https debhelper gnupg wget ca-certificates devscripts \ + mmv build-essential lsb-release # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current diff --git a/deployment/Dockerfile.ubuntu.armhf b/deployment/Dockerfile.ubuntu.armhf index ee6f083ea4..aaaedda82c 100644 --- a/deployment/Dockerfile.ubuntu.armhf +++ b/deployment/Dockerfile.ubuntu.armhf @@ -13,7 +13,8 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg wget devscripts mmv + apt-transport-https debhelper gnupg wget ca-certificates devscripts \ + mmv build-essential lsb-release # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current diff --git a/deployment/Dockerfile.windows.amd64 b/deployment/Dockerfile.windows.amd64 index f913700809..acd0e18549 100644 --- a/deployment/Dockerfile.windows.amd64 +++ b/deployment/Dockerfile.windows.amd64 @@ -11,7 +11,7 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg devscripts \ + apt-transport-https debhelper gnupg devscripts unzip \ mmv libcurl4-openssl-dev libfontconfig1-dev \ libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 zip From 439ae4ec6f8f56747809f83a4de39a8c3e1cf9fe Mon Sep 17 00:00:00 2001 From: Anthony Lavado Date: Fri, 6 Aug 2021 14:32:04 -0400 Subject: [PATCH 102/120] Add sponsor links Adds a horizontal line after project description and the rest of the readme, and another at the end before including DO and JB sponsorship links with images. --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index 6859a8a76f..3259777c8f 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,8 @@ Check out our Weblate instance to h Detailed Translation Status +--- + ## Jellyfin Server This repository contains the code for Jellyfin's backend server. Note that this is only one of many projects under the Jellyfin GitHub [organization](https://github.com/jellyfin/) on GitHub. If you want to contribute, you can start by checking out our [documentation](https://jellyfin.org/docs/general/contributing/index.html) to see what to work on. @@ -162,3 +164,13 @@ switch `--nowebclient` or the environment variable `JELLYFIN_NOWEBCONTENT=true`. Since this is a common scenario, there is also a separate launch profile defined for Visual Studio called `Jellyfin.Server (nowebcontent)` that can be selected from the 'Start Debugging' dropdown in the main toolbar. **NOTE:** The setup wizard can not be run if the web client is hosted separately. + +--- +

+This project is supported by: +
+
+DigitalOcean +   +JetBrains logo +

From a7585dd2d65895620ab82973c9cd72991b5ed38b Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Sat, 7 Aug 2021 07:36:45 -0600 Subject: [PATCH 103/120] Fix redirect logic if request path is exactly the base url --- Jellyfin.Server/Middleware/BaseUrlRedirectionMiddleware.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Jellyfin.Server/Middleware/BaseUrlRedirectionMiddleware.cs b/Jellyfin.Server/Middleware/BaseUrlRedirectionMiddleware.cs index 2eef223e52..e3f3911f98 100644 --- a/Jellyfin.Server/Middleware/BaseUrlRedirectionMiddleware.cs +++ b/Jellyfin.Server/Middleware/BaseUrlRedirectionMiddleware.cs @@ -58,9 +58,12 @@ namespace Jellyfin.Server.Middleware return; } - if (!startsWithBaseUrl) + if (!startsWithBaseUrl + || localPath.Equals(baseUrlPrefix, StringComparison.OrdinalIgnoreCase) + // Local path is /baseUrl/ + || (localPath.Length == baseUrlPrefix.Length + 1 && localPath[^1] == '/')) { - // Always redirect back to the default path if the base prefix is invalid or missing + // Always redirect back to the default path if the base prefix is invalid, missing, or is the full path. _logger.LogDebug("Normalizing an URL at {LocalPath}", localPath); httpContext.Response.Redirect(baseUrlPrefix + "/" + _configuration[ConfigurationExtensions.DefaultRedirectKey]); return; From bdbac12d4f35bf47e75ed25c7bb10c0074e4f4ce Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Sat, 7 Aug 2021 09:06:31 -0600 Subject: [PATCH 104/120] Update Jellyfin.Server/Middleware/BaseUrlRedirectionMiddleware.cs Co-authored-by: Claus Vium --- Jellyfin.Server/Middleware/BaseUrlRedirectionMiddleware.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jellyfin.Server/Middleware/BaseUrlRedirectionMiddleware.cs b/Jellyfin.Server/Middleware/BaseUrlRedirectionMiddleware.cs index e3f3911f98..3e5982eedf 100644 --- a/Jellyfin.Server/Middleware/BaseUrlRedirectionMiddleware.cs +++ b/Jellyfin.Server/Middleware/BaseUrlRedirectionMiddleware.cs @@ -59,7 +59,7 @@ namespace Jellyfin.Server.Middleware } if (!startsWithBaseUrl - || localPath.Equals(baseUrlPrefix, StringComparison.OrdinalIgnoreCase) + || localPath.Length == baseUrlPrefix.Length // Local path is /baseUrl/ || (localPath.Length == baseUrlPrefix.Length + 1 && localPath[^1] == '/')) { From 534e088105641d848b5469315e27b97c6aef4aca Mon Sep 17 00:00:00 2001 From: MrTimscampi Date: Mon, 5 Jul 2021 03:27:03 +0200 Subject: [PATCH 105/120] Prefer original data when getting premiere date from ffprobe --- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index c9ad3c41eb..875ee6f04c 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -121,6 +121,7 @@ namespace MediaBrowser.MediaEncoding.Probing // Several different forms of retail/premiere date info.PremiereDate = + FFProbeHelpers.GetDictionaryDateTime(tags, "originaldate") ?? FFProbeHelpers.GetDictionaryDateTime(tags, "retaildate") ?? FFProbeHelpers.GetDictionaryDateTime(tags, "retail date") ?? FFProbeHelpers.GetDictionaryDateTime(tags, "retail_date") ?? From ba609aefea484b0c10a5cf366f00a252f0402243 Mon Sep 17 00:00:00 2001 From: MrTimscampi Date: Mon, 5 Jul 2021 03:52:46 +0200 Subject: [PATCH 106/120] Attempt to parse YYYY format dates in GetDictionaryDateTime DateTime.TryParse doesn't properly parse year-only dates, so parsing results from FFProbe sometimes returns null (for example, some music tagged with Beets has yyyy format dates for release dates). As a result, Jellyfin would previously no get the date from the FFProbe results. This adds DateTime.TryParseExact with a format of 'yyyy' as a fallback, to attempt to properly parse the value, even if it's only a year. --- MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs index d0a76c4caf..f1062a4ae5 100644 --- a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs +++ b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs @@ -63,7 +63,8 @@ namespace MediaBrowser.MediaEncoding.Probing public static DateTime? GetDictionaryDateTime(IReadOnlyDictionary tags, string key) { if (tags.TryGetValue(key, out var val) - && DateTime.TryParse(val, DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AssumeUniversal, out var dateTime)) + && (DateTime.TryParse(val, DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AssumeUniversal, out var dateTime) || + DateTime.TryParseExact(val, "yyyy", DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AssumeUniversal, out dateTime))) { return dateTime.ToUniversalTime(); } From 924dfe1db0127c5494a874bae21983e59c3338a2 Mon Sep 17 00:00:00 2001 From: MrTimscampi Date: Sat, 7 Aug 2021 22:24:10 +0200 Subject: [PATCH 107/120] Add test for year-only parsing for FFProbe --- .../Probing/ProbeResultNormalizerTests.cs | 20 +++ .../Probing/music_year_only_metadata.json | 147 ++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/music_year_only_metadata.json diff --git a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs index d8089eea2d..6d6abdb900 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs @@ -71,5 +71,25 @@ namespace Jellyfin.MediaEncoding.Tests.Probing Assert.True(res.PremiereDate.HasValue); Assert.Equal(DateTime.Parse("2021-01-01T00:00Z", DateTimeFormatInfo.CurrentInfo).ToUniversalTime(), res.PremiereDate); } + + [Fact] + public void GetMediaInfo_Music_Year_Only_Success() + { + var bytes = File.ReadAllBytes("Test Data/Probing/music_year_only_metadata.json"); + var internalMediaInfoResult = JsonSerializer.Deserialize(bytes, _jsonOptions); + MediaInfo res = _probeResultNormalizer.GetMediaInfo(internalMediaInfoResult, null, true, "Test Data/Probing/music.flac", MediaProtocol.File); + + Assert.Equal("Baker Street", res.Name); + Assert.Single(res.Artists); + Assert.Equal("Gerry Rafferty", res.Artists[0]); + Assert.Equal("City to City", res.Album); + Assert.Equal(1978, res.ProductionYear); + Assert.True(res.PremiereDate.HasValue); + Assert.Equal(DateTime.Parse("1978-01-01T00:00Z", DateTimeFormatInfo.CurrentInfo).ToUniversalTime(), res.PremiereDate); + Assert.Contains("Electronic", res.Genres); + Assert.Contains("Ambient", res.Genres); + Assert.Contains("Pop", res.Genres); + Assert.Contains("Jazz", res.Genres); + } } } diff --git a/tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/music_year_only_metadata.json b/tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/music_year_only_metadata.json new file mode 100644 index 0000000000..ddf890c453 --- /dev/null +++ b/tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/music_year_only_metadata.json @@ -0,0 +1,147 @@ +{ + "streams": [ + { + "index": 0, + "codec_name": "flac", + "codec_long_name": "FLAC (Free Lossless Audio Codec)", + "codec_type": "audio", + "codec_tag_string": "[0][0][0][0]", + "codec_tag": "0x0000", + "sample_fmt": "s16", + "sample_rate": "44100", + "channels": 2, + "channel_layout": "stereo", + "bits_per_sample": 0, + "r_frame_rate": "0/0", + "avg_frame_rate": "0/0", + "time_base": "1/44100", + "start_pts": 0, + "start_time": "0.000000", + "duration_ts": 16394616, + "duration": "371.760000", + "bits_per_raw_sample": "16", + "disposition": { + "default": 0, + "dub": 0, + "original": 0, + "comment": 0, + "lyrics": 0, + "karaoke": 0, + "forced": 0, + "hearing_impaired": 0, + "visual_impaired": 0, + "clean_effects": 0, + "attached_pic": 0, + "timed_thumbnails": 0 + } + }, + { + "index": 1, + "codec_name": "mjpeg", + "codec_long_name": "Motion JPEG", + "profile": "Baseline", + "codec_type": "video", + "codec_tag_string": "[0][0][0][0]", + "codec_tag": "0x0000", + "width": 500, + "height": 498, + "coded_width": 500, + "coded_height": 498, + "closed_captions": 0, + "has_b_frames": 0, + "sample_aspect_ratio": "1:1", + "display_aspect_ratio": "250:249", + "pix_fmt": "yuvj420p", + "level": -99, + "color_range": "pc", + "color_space": "bt470bg", + "chroma_location": "center", + "refs": 1, + "r_frame_rate": "90000/1", + "avg_frame_rate": "0/0", + "time_base": "1/90000", + "start_pts": 0, + "start_time": "0.000000", + "duration_ts": 33458400, + "duration": "371.760000", + "bits_per_raw_sample": "8", + "disposition": { + "default": 0, + "dub": 0, + "original": 0, + "comment": 0, + "lyrics": 0, + "karaoke": 0, + "forced": 0, + "hearing_impaired": 0, + "visual_impaired": 0, + "clean_effects": 0, + "attached_pic": 1, + "timed_thumbnails": 0 + }, + "tags": { + "comment": "Cover (front)" + } + } + ], + "format": { + "filename": "02 Baker Street.flac", + "nb_streams": 2, + "nb_programs": 0, + "format_name": "flac", + "format_long_name": "raw FLAC", + "start_time": "0.000000", + "duration": "371.760000", + "size": "37072649", + "bit_rate": "797775", + "probe_score": 100, + "tags": { + "MUSICBRAINZ_RELEASEGROUPID": "238c3fb4-5792-342b-b217-02f66298b424", + "ORIGINALDATE": "1978", + "ORIGINALYEAR": "1978", + "RELEASETYPE": "album", + "MUSICBRAINZ_ALBUMID": "30156786-e511-3106-ac95-66f0e880b24b", + "ASIN": "B000007O5H", + "MUSICBRAINZ_ALBUMARTISTID": "563201cb-721c-4cfb-acca-c1ba69e3d1fb", + "album_artist": "Gerry Rafferty", + "ALBUMARTISTSORT": "Rafferty, Gerry", + "LABEL": "Liberty EMI Records UK", + "CATALOGNUMBER": "CDP 7 46049 2", + "DATE": "1989-07-26", + "RELEASECOUNTRY": "GB", + "BARCODE": "077774604925", + "ALBUM": "City to City", + "SCRIPT": "Latn", + "RELEASESTATUS": "official", + "TOTALDISCS": "1", + "disc": "1", + "MEDIA": "CD", + "TOTALTRACKS": "10", + "MUSICBRAINZ_TRACKID": "9235e22e-afbd-48f7-b329-21dae6da2810", + "ISRC": "GBAYE1100924;GBAYE7800619", + "PERFORMER": "Hugh Burns (electric guitar);Nigel Jenkins (electric guitar);Tommy Eyre (keyboard and Moog);Glen LeFleur (percussion);Raphael Ravenscroft (saxophone);Henry Spinetti (drums (drum set));Gary Taylor (bass);Gerry Rafferty (lead vocals)", + "ARRANGER": "Graham Preskett", + "MIXER": "Declan O’Doherty", + "PRODUCER": "Hugh Murphy;Gerry Rafferty", + "MUSICBRAINZ_WORKID": "a9eb3c45-784c-3c32-860c-4b406f03961b", + "LANGUAGE": "eng", + "WORK": "Baker Street", + "COMPOSER": "Gerry Rafferty", + "COMPOSERSORT": "Rafferty, Gerry", + "LYRICIST": "Gerry Rafferty", + "TITLE": "Baker Street", + "MUSICBRAINZ_ARTISTID": "563201cb-721c-4cfb-acca-c1ba69e3d1fb", + "ARTIST": "Gerry Rafferty", + "ARTISTSORT": "Rafferty, Gerry", + "ARTISTS": "Gerry Rafferty", + "MUSICBRAINZ_RELEASETRACKID": "407cf7f7-440d-3e76-8b89-8686198868ea", + "track": "2", + "GENRE": "Electronic;Ambient;Pop;Jazz", + "WEBSITE": "http://www.gerryrafferty.com/", + "ACOUSTID_ID": "68f8d979-a659-4aa0-a216-eb3721a951eb", + "MOOD": "Acoustic;Not aggressive;Not electronic;Not happy;Party;Relaxed;Not sad", + "TRACKTOTAL": "10", + "DISCTOTAL": "1" + } + } +} From 6c2cbafee056b425291f4e762303e5399c9fb558 Mon Sep 17 00:00:00 2001 From: Julien Machiels Date: Sun, 8 Aug 2021 16:37:35 +0200 Subject: [PATCH 108/120] Update MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs Co-authored-by: Cody Robibero --- MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs index f1062a4ae5..9196fe1397 100644 --- a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs +++ b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs @@ -63,8 +63,8 @@ namespace MediaBrowser.MediaEncoding.Probing public static DateTime? GetDictionaryDateTime(IReadOnlyDictionary tags, string key) { if (tags.TryGetValue(key, out var val) - && (DateTime.TryParse(val, DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AssumeUniversal, out var dateTime) || - DateTime.TryParseExact(val, "yyyy", DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AssumeUniversal, out dateTime))) + && (DateTime.TryParse(val, DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AssumeUniversal, out var dateTime) + || DateTime.TryParseExact(val, "yyyy", DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AssumeUniversal, out dateTime))) { return dateTime.ToUniversalTime(); } From 55389453be7cbc55343d3b58cc2f9fb9dfd14dc6 Mon Sep 17 00:00:00 2001 From: millallo Date: Sat, 7 Aug 2021 17:15:17 +0000 Subject: [PATCH 109/120] Translated using Weblate (Italian) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/it/ --- Emby.Server.Implementations/Localization/Core/it.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/it.json b/Emby.Server.Implementations/Localization/Core/it.json index 8b753400ef..0bde76e744 100644 --- a/Emby.Server.Implementations/Localization/Core/it.json +++ b/Emby.Server.Implementations/Localization/Core/it.json @@ -70,7 +70,7 @@ "ScheduledTaskFailedWithName": "{0} fallito", "ScheduledTaskStartedWithName": "{0} avviati", "ServerNameNeedsToBeRestarted": "{0} deve essere riavviato", - "Shows": "Programmi", + "Shows": "Serie TV", "Songs": "Canzoni", "StartupEmbyServerIsLoading": "Jellyfin server si sta avviando. Per favore riprova più tardi.", "SubtitleDownloadFailureForItem": "Impossibile scaricare i sottotitoli per {0}", From c4d8e6f056605b98c36c37b9be169ee1a9030c71 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Aug 2021 12:00:53 +0000 Subject: [PATCH 110/120] Bump UTF.Unknown from 2.3.0 to 2.4.0 Bumps [UTF.Unknown](https://github.com/CharsetDetector/UTF-unknown) from 2.3.0 to 2.4.0. - [Release notes](https://github.com/CharsetDetector/UTF-unknown/releases) - [Commits](https://github.com/CharsetDetector/UTF-unknown/compare/v2.3...v2.4) --- updated-dependencies: - dependency-name: UTF.Unknown dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 411b7c82ba..6da9886a4b 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -26,7 +26,7 @@ - + From 9951a5139544d0f13913eda91be29ca2eda3e8e6 Mon Sep 17 00:00:00 2001 From: Rich Lander Date: Mon, 9 Aug 2021 19:47:26 -0700 Subject: [PATCH 111/120] Fix warnings in MediaBrowser.Controller/Session --- .../Session/ISessionController.cs | 6 ++++ .../Session/ISessionManager.cs | 32 ++++++++++++++----- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/MediaBrowser.Controller/Session/ISessionController.cs b/MediaBrowser.Controller/Session/ISessionController.cs index 6bc39d6f4e..b38ee11462 100644 --- a/MediaBrowser.Controller/Session/ISessionController.cs +++ b/MediaBrowser.Controller/Session/ISessionController.cs @@ -26,6 +26,12 @@ namespace MediaBrowser.Controller.Session /// /// Sends the message. /// + /// The type of data. + /// Name of message type. + /// Message ID. + /// Data to send. + /// CancellationToken for operation. + /// A task. Task SendMessage(SessionMessageType name, Guid messageId, T data, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs index 4c3cf5ffe1..0ff32fb536 100644 --- a/MediaBrowser.Controller/Session/ISessionManager.cs +++ b/MediaBrowser.Controller/Session/ISessionManager.cs @@ -83,6 +83,7 @@ namespace MediaBrowser.Controller.Session /// Name of the device. /// The remote end point. /// The user. + /// Session information. SessionInfo LogSessionActivity(string appName, string appVersion, string deviceId, string deviceName, string remoteEndPoint, Jellyfin.Data.Entities.User user); /// @@ -105,7 +106,7 @@ namespace MediaBrowser.Controller.Session /// /// The info. /// Task. - /// + /// Throws if an argument is null. Task OnPlaybackProgress(PlaybackProgressInfo info); Task OnPlaybackProgress(PlaybackProgressInfo info, bool isAutomated); @@ -115,14 +116,13 @@ namespace MediaBrowser.Controller.Session ///
/// The info. /// Task. - /// + /// Throws if an argument is null. Task OnPlaybackStopped(PlaybackStopInfo info); /// /// Reports the session ended. /// /// The session identifier. - /// Task. void ReportSessionEnded(string sessionId); /// @@ -170,6 +170,7 @@ namespace MediaBrowser.Controller.Session /// The session. /// The group update. /// The cancellation token. + /// Type of group. /// Task. Task SendSyncPlayGroupUpdate(SessionInfo session, GroupUpdate command, CancellationToken cancellationToken); @@ -196,8 +197,8 @@ namespace MediaBrowser.Controller.Session /// /// Sends the message to admin sessions. /// - /// - /// The name. + /// Type of data. + /// Message type name. /// The data. /// The cancellation token. /// Task. @@ -206,18 +207,31 @@ namespace MediaBrowser.Controller.Session /// /// Sends the message to user sessions. /// - /// + /// Type of data. + /// Users to send messages to. + /// Message type name. + /// The data. + /// The cancellation token. /// Task. Task SendMessageToUserSessions(List userIds, SessionMessageType name, T data, CancellationToken cancellationToken); + /// + /// Sends the message to user sessions. + /// + /// Type of data. + /// Users to send messages to. + /// Message type name. + /// Data function. + /// The cancellation token. + /// Task. Task SendMessageToUserSessions(List userIds, SessionMessageType name, Func dataFn, CancellationToken cancellationToken); /// /// Sends the message to user device sessions. /// - /// + /// Type of data. /// The device identifier. - /// The name. + /// Message type name. /// The data. /// The cancellation token. /// Task. @@ -353,6 +367,8 @@ namespace MediaBrowser.Controller.Session /// /// Revokes the user tokens. /// + /// User ID. + /// Current access token. void RevokeUserTokens(Guid userId, string currentAccessToken); /// From 854bb79ae8b1e7004c731939e54e52ef937abe47 Mon Sep 17 00:00:00 2001 From: Erdinc Date: Mon, 9 Aug 2021 08:46:15 +0000 Subject: [PATCH 112/120] Translated using Weblate (Turkish) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/tr/ --- .../Localization/Core/tr.json | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/tr.json b/Emby.Server.Implementations/Localization/Core/tr.json index c6b904045b..771c91d59f 100644 --- a/Emby.Server.Implementations/Localization/Core/tr.json +++ b/Emby.Server.Implementations/Localization/Core/tr.json @@ -43,7 +43,7 @@ "NameInstallFailed": "{0} kurulumu başarısız", "NameSeasonNumber": "Sezon {0}", "NameSeasonUnknown": "Bilinmeyen Sezon", - "NewVersionIsAvailable": "Jellyfin Sunucusunun yeni bir versiyonu indirmek için hazır.", + "NewVersionIsAvailable": "Jellyfin Sunucusunun yeni bir sürümü indirmek için hazır.", "NotificationOptionApplicationUpdateAvailable": "Uygulama güncellemesi mevcut", "NotificationOptionApplicationUpdateInstalled": "Uygulama güncellemesi yüklendi", "NotificationOptionAudioPlayback": "Ses çalma başladı", @@ -75,7 +75,7 @@ "StartupEmbyServerIsLoading": "Jellyfin Sunucusu yükleniyor. Lütfen kısa süre sonra tekrar deneyin.", "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", "SubtitleDownloadFailureFromForItem": "{1} için alt yazılar {0} 'dan indirilemedi", - "Sync": "Eşitle", + "Sync": "Eşzamanlama", "System": "Sistem", "TvShows": "Diziler", "User": "Kullanıcı", @@ -89,34 +89,36 @@ "UserPolicyUpdatedWithName": "Kullanıcı politikası {0} için güncellendi", "UserStartedPlayingItemWithValues": "{0}, {2} cihazında {1} izliyor", "UserStoppedPlayingItemWithValues": "{0}, {2} cihazında {1} izlemeyi bitirdi", - "ValueHasBeenAddedToLibrary": "Medya kitaplığınıza {0} eklendi", + "ValueHasBeenAddedToLibrary": "Medya kütüphanenize {0} eklendi", "ValueSpecialEpisodeName": "Özel - {0}", - "VersionNumber": "Versiyon {0}", + "VersionNumber": "Sürüm {0}", "TaskCleanCache": "Geçici dosya klasörünü temizle", "TasksChannelsCategory": "İnternet kanalları", "TasksApplicationCategory": "Uygulama", "TasksLibraryCategory": "Kütüphane", - "TasksMaintenanceCategory": "Onarım", + "TasksMaintenanceCategory": "Bakı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.", + "TaskCleanTranscodeDescription": "Bir günden daha eski dönüştürme dosyalarını 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.", + "TaskCleanLogsDescription": "{0} günden eski günlük dosyalarını siler.", + "TaskCleanLogs": "Günlük Dizinini Temizle", + "TaskRefreshLibraryDescription": "Medya kütüphanenize eklenen yeni dosyaları arar ve ortam bilgilerini 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.", - "TaskCleanActivityLog": "İşlem Günlüğünü Temizle", - "TaskCleanActivityLogDescription": "Belirtilen sureden daha eski etkinlik log kayıtları silindi.", + "TaskCleanActivityLog": "Etkinlik Günlüğünü Temizle", + "TaskCleanActivityLogDescription": "Yapılandırılan tarihten daha eski olan etkinlik günlüğü girişlerini siler.", "Undefined": "Bilinmeyen", "Default": "Varsayılan", - "Forced": "Zorla" + "Forced": "Zorla", + "TaskOptimizeDatabaseDescription": "Veritabanını sıkıştırır ve boş alanı keser. Kitaplığı taradıktan sonra veya veritabanında değişiklik anlamına gelen diğer işlemleri yaptıktan sonra bu görevi çalıştırmak performansı artırabilir.", + "TaskOptimizeDatabase": "Veritabanını optimize et" } From 77aee515a25b04d53aea05302209121daa33923b Mon Sep 17 00:00:00 2001 From: David Ullmer Date: Tue, 10 Aug 2021 13:37:33 +0200 Subject: [PATCH 113/120] Use correct string comparison --- .../Localization/LocalizationManagerTests.cs | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs index 651957ae39..0a9f4d817a 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System; +using System.Linq; using System.Threading.Tasks; using Emby.Server.Implementations.Localization; using MediaBrowser.Controller.Configuration; @@ -23,11 +24,11 @@ namespace Jellyfin.Server.Implementations.Tests.Localization Assert.Equal(139, countryInfos.Count); - var germany = countryInfos.FirstOrDefault(x => x.Name == "DE"); + var germany = countryInfos.FirstOrDefault(x => x.Name.Equals("DE", StringComparison.Ordinal)); Assert.NotNull(germany); Assert.Equal("Germany", germany!.DisplayName); - Assert.Equal("DEU", germany!.ThreeLetterISORegionName); - Assert.Equal("DE", germany!.TwoLetterISORegionName); + Assert.Equal("DEU", germany.ThreeLetterISORegionName); + Assert.Equal("DE", germany.TwoLetterISORegionName); } [Fact] @@ -45,10 +46,10 @@ namespace Jellyfin.Server.Implementations.Tests.Localization var germany = cultures.FirstOrDefault(x => x.TwoLetterISOLanguageName == "de"); Assert.NotNull(germany); Assert.Equal("ger", germany!.ThreeLetterISOLanguageName); - Assert.Equal("German", germany!.DisplayName); - Assert.Equal("German", germany!.Name); - Assert.Contains("deu", germany!.ThreeLetterISOLanguageNames); - Assert.Contains("ger", germany!.ThreeLetterISOLanguageNames); + Assert.Equal("German", germany.DisplayName); + Assert.Equal("German", germany.Name); + Assert.Contains("deu", germany.ThreeLetterISOLanguageNames); + Assert.Contains("ger", germany.ThreeLetterISOLanguageNames); } [Theory] @@ -66,11 +67,11 @@ namespace Jellyfin.Server.Implementations.Tests.Localization var germany = localizationManager.FindLanguageInfo(identifier); Assert.NotNull(germany); - Assert.Equal("ger", germany!.ThreeLetterISOLanguageName); - Assert.Equal("German", germany!.DisplayName); - Assert.Equal("German", germany!.Name); - Assert.Contains("deu", germany!.ThreeLetterISOLanguageNames); - Assert.Contains("ger", germany!.ThreeLetterISOLanguageNames); + Assert.Equal("ger", germany.ThreeLetterISOLanguageName); + Assert.Equal("German", germany.DisplayName); + Assert.Equal("German", germany.Name); + Assert.Contains("deu", germany.ThreeLetterISOLanguageNames); + Assert.Contains("ger", germany.ThreeLetterISOLanguageNames); } [Fact] From 6b61b50b5331a3b088fa9fd5e742962dcb9b5b0b Mon Sep 17 00:00:00 2001 From: David Ullmer Date: Tue, 10 Aug 2021 13:39:51 +0200 Subject: [PATCH 114/120] Revert "Refactor LocalizationManager and remove dead method" This reverts commit db2b53a4b52d0c1e9797bfc70030b04421ba46a6. --- .../Localization/LocalizationManager.cs | 400 +++++++++--------- .../Globalization/ILocalizationManager.cs | 8 + 2 files changed, 218 insertions(+), 190 deletions(-) diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index efbccaa5b9..220e423bf5 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -25,19 +25,19 @@ namespace Emby.Server.Implementations.Localization private static readonly Assembly _assembly = typeof(LocalizationManager).Assembly; private static readonly string[] _unratedValues = { "n/a", "unrated", "not rated" }; + private readonly IServerConfigurationManager _configurationManager; + private readonly ILogger _logger; + private readonly Dictionary> _allParentalRatings = new Dictionary>(StringComparer.OrdinalIgnoreCase); - private readonly IServerConfigurationManager _configurationManager; - private readonly ConcurrentDictionary> _dictionaries = new ConcurrentDictionary>(StringComparer.OrdinalIgnoreCase); - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; - private readonly ILogger _logger; - private List _cultures; + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; + /// /// Initializes a new instance of the class. /// @@ -51,6 +51,57 @@ namespace Emby.Server.Implementations.Localization _logger = logger; } + /// + /// Loads all resources into memory. + /// + /// . + public async Task LoadAll() + { + const string RatingsResource = "Emby.Server.Implementations.Localization.Ratings."; + + // Extract from the assembly + foreach (var resource in _assembly.GetManifestResourceNames()) + { + if (!resource.StartsWith(RatingsResource, StringComparison.Ordinal)) + { + continue; + } + + string countryCode = resource.Substring(RatingsResource.Length, 2); + var dict = new Dictionary(StringComparer.OrdinalIgnoreCase); + + using (var str = _assembly.GetManifestResourceStream(resource)) + using (var reader = new StreamReader(str)) + { + await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false)) + { + if (string.IsNullOrWhiteSpace(line)) + { + continue; + } + + string[] parts = line.Split(','); + if (parts.Length == 2 + && int.TryParse(parts[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var value)) + { + var name = parts[0]; + dict.Add(name, new ParentalRating(name, value)); + } +#if DEBUG + else + { + _logger.LogWarning("Malformed line in ratings file for country {CountryCode}", countryCode); + } +#endif + } + } + + _allParentalRatings[countryCode] = dict; + } + + await LoadCultures().ConfigureAwait(false); + } + /// /// Gets the cultures. /// @@ -58,6 +109,62 @@ namespace Emby.Server.Implementations.Localization public IEnumerable GetCultures() => _cultures; + private async Task LoadCultures() + { + List list = new List(); + + const string ResourcePath = "Emby.Server.Implementations.Localization.iso6392.txt"; + + using (var stream = _assembly.GetManifestResourceStream(ResourcePath)) + using (var reader = new StreamReader(stream)) + { + await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false)) + { + if (string.IsNullOrWhiteSpace(line)) + { + continue; + } + + var parts = line.Split('|'); + + if (parts.Length == 5) + { + string name = parts[3]; + if (string.IsNullOrWhiteSpace(name)) + { + continue; + } + + string twoCharName = parts[2]; + if (string.IsNullOrWhiteSpace(twoCharName)) + { + continue; + } + + string[] threeletterNames; + if (string.IsNullOrWhiteSpace(parts[1])) + { + threeletterNames = new[] { parts[0] }; + } + else + { + threeletterNames = new[] { parts[0], parts[1] }; + } + + list.Add(new CultureDto + { + DisplayName = name, + Name = name, + ThreeLetterISOLanguageNames = threeletterNames, + TwoLetterISOLanguageName = twoCharName + }); + } + } + } + + _cultures = list; + } + /// public CultureDto FindLanguageInfo(string language) => GetCultures() @@ -79,6 +186,34 @@ namespace Emby.Server.Implementations.Localization public IEnumerable GetParentalRatings() => GetParentalRatingsDictionary().Values; + /// + /// Gets the parental ratings dictionary. + /// + /// . + private Dictionary GetParentalRatingsDictionary() + { + var countryCode = _configurationManager.Configuration.MetadataCountryCode; + + if (string.IsNullOrEmpty(countryCode)) + { + countryCode = "us"; + } + + return GetRatings(countryCode) ?? GetRatings("us"); + } + + /// + /// Gets the ratings. + /// + /// The country code. + /// The ratings. + private Dictionary GetRatings(string countryCode) + { + _allParentalRatings.TryGetValue(countryCode, out var value); + + return value; + } + /// public int? GetRatingLevel(string rating) { @@ -115,7 +250,7 @@ namespace Emby.Server.Implementations.Localization var index = rating.IndexOf(':', StringComparison.Ordinal); if (index != -1) { - rating = rating.Substring(index + 1).Trim(); + rating = rating.Substring(index).TrimStart(':').Trim(); if (!string.IsNullOrWhiteSpace(rating)) { @@ -127,6 +262,20 @@ namespace Emby.Server.Implementations.Localization return null; } + /// + public bool HasUnicodeCategory(string value, UnicodeCategory category) + { + foreach (var chr in value) + { + if (char.GetUnicodeCategory(chr) == category) + { + return true; + } + } + + return false; + } + /// public string GetLocalizedString(string phrase) { @@ -156,179 +305,6 @@ namespace Emby.Server.Implementations.Localization return phrase; } - /// - public IEnumerable GetLocalizationOptions() - { - yield return new LocalizationOption("Arabic", "ar"); - yield return new LocalizationOption("Bulgarian (Bulgaria)", "bg-BG"); - yield return new LocalizationOption("Catalan", "ca"); - yield return new LocalizationOption("Chinese Simplified", "zh-CN"); - yield return new LocalizationOption("Chinese Traditional", "zh-TW"); - yield return new LocalizationOption("Croatian", "hr"); - yield return new LocalizationOption("Czech", "cs"); - yield return new LocalizationOption("Danish", "da"); - yield return new LocalizationOption("Dutch", "nl"); - yield return new LocalizationOption("English (United Kingdom)", "en-GB"); - yield return new LocalizationOption("English (United States)", "en-US"); - yield return new LocalizationOption("French", "fr"); - yield return new LocalizationOption("French (Canada)", "fr-CA"); - yield return new LocalizationOption("German", "de"); - yield return new LocalizationOption("Greek", "el"); - yield return new LocalizationOption("Hebrew", "he"); - yield return new LocalizationOption("Hungarian", "hu"); - yield return new LocalizationOption("Italian", "it"); - yield return new LocalizationOption("Kazakh", "kk"); - yield return new LocalizationOption("Korean", "ko"); - yield return new LocalizationOption("Lithuanian", "lt-LT"); - yield return new LocalizationOption("Malay", "ms"); - yield return new LocalizationOption("Norwegian Bokmål", "nb"); - yield return new LocalizationOption("Persian", "fa"); - yield return new LocalizationOption("Polish", "pl"); - yield return new LocalizationOption("Portuguese (Brazil)", "pt-BR"); - yield return new LocalizationOption("Portuguese (Portugal)", "pt-PT"); - yield return new LocalizationOption("Russian", "ru"); - yield return new LocalizationOption("Slovak", "sk"); - yield return new LocalizationOption("Slovenian (Slovenia)", "sl-SI"); - yield return new LocalizationOption("Spanish", "es"); - yield return new LocalizationOption("Spanish (Argentina)", "es-AR"); - yield return new LocalizationOption("Spanish (Mexico)", "es-MX"); - yield return new LocalizationOption("Swedish", "sv"); - yield return new LocalizationOption("Swiss German", "gsw"); - yield return new LocalizationOption("Turkish", "tr"); - yield return new LocalizationOption("Tiếng Việt", "vi"); - } - - /// - /// Loads all resources into memory. - /// - /// . - public async Task LoadAll() - { - const string RatingsResource = "Emby.Server.Implementations.Localization.Ratings."; - - // Extract from the assembly - foreach (var resource in _assembly.GetManifestResourceNames()) - { - if (!resource.StartsWith(RatingsResource, StringComparison.Ordinal)) - { - continue; - } - - string countryCode = resource.Substring(RatingsResource.Length, 2); - var dict = new Dictionary(StringComparer.OrdinalIgnoreCase); - - await using var str = _assembly.GetManifestResourceStream(resource); - using var reader = new StreamReader(str); - await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false)) - { - if (string.IsNullOrWhiteSpace(line)) - { - continue; - } - - string[] parts = line.Split(','); - if (parts.Length == 2 - && int.TryParse(parts[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var value)) - { - var name = parts[0]; - dict.Add(name, new ParentalRating(name, value)); - } -#if DEBUG - else - { - _logger.LogWarning("Malformed line in ratings file for country {CountryCode}", countryCode); - } -#endif - } - - _allParentalRatings[countryCode] = dict; - } - - await LoadCultures().ConfigureAwait(false); - } - - private async Task LoadCultures() - { - List list = new List(); - - const string ResourcePath = "Emby.Server.Implementations.Localization.iso6392.txt"; - - await using var stream = _assembly.GetManifestResourceStream(ResourcePath); - using var reader = new StreamReader(stream); - await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false)) - { - if (string.IsNullOrWhiteSpace(line)) - { - continue; - } - - var parts = line.Split('|'); - - if (parts.Length == 5) - { - string name = parts[3]; - if (string.IsNullOrWhiteSpace(name)) - { - continue; - } - - string twoCharName = parts[2]; - if (string.IsNullOrWhiteSpace(twoCharName)) - { - continue; - } - - string[] threeletterNames; - if (string.IsNullOrWhiteSpace(parts[1])) - { - threeletterNames = new[] { parts[0] }; - } - else - { - threeletterNames = new[] { parts[0], parts[1] }; - } - - list.Add(new CultureDto - { - DisplayName = name, - Name = name, - ThreeLetterISOLanguageNames = threeletterNames, - TwoLetterISOLanguageName = twoCharName - }); - } - } - - _cultures = list; - } - - /// - /// Gets the parental ratings dictionary. - /// - /// . - private Dictionary GetParentalRatingsDictionary() - { - var countryCode = _configurationManager.Configuration.MetadataCountryCode; - - if (string.IsNullOrEmpty(countryCode)) - { - countryCode = "us"; - } - - return GetRatings(countryCode) ?? GetRatings("us"); - } - - /// - /// Gets the ratings. - /// - /// The country code. - /// The ratings. - private Dictionary GetRatings(string countryCode) - { - _allParentalRatings.TryGetValue(countryCode, out var value); - - return value; - } - private Dictionary GetLocalizationDictionary(string culture) { if (string.IsNullOrEmpty(culture)) @@ -340,7 +316,7 @@ namespace Emby.Server.Implementations.Localization return _dictionaries.GetOrAdd( culture, - _ => GetDictionary(Prefix, culture, DefaultCulture + ".json").GetAwaiter().GetResult()); + f => GetDictionary(Prefix, culture, DefaultCulture + ".json").GetAwaiter().GetResult()); } private async Task> GetDictionary(string prefix, string culture, string baseFilename) @@ -362,21 +338,23 @@ namespace Emby.Server.Implementations.Localization private async Task CopyInto(IDictionary dictionary, string resourcePath) { - await using var stream = _assembly.GetManifestResourceStream(resourcePath); - // If a Culture doesn't have a translation the stream will be null and it defaults to en-us further up the chain - if (stream != null) + using (var stream = _assembly.GetManifestResourceStream(resourcePath)) { - var dict = await JsonSerializer.DeserializeAsync>(stream, _jsonOptions).ConfigureAwait(false); + // If a Culture doesn't have a translation the stream will be null and it defaults to en-us further up the chain + if (stream != null) + { + var dict = await JsonSerializer.DeserializeAsync>(stream, _jsonOptions).ConfigureAwait(false); - foreach (var key in dict.Keys) + foreach (var key in dict.Keys) + { + dictionary[key] = dict[key]; + } + } + else { - dictionary[key] = dict[key]; + _logger.LogError("Missing translation/culture resource: {ResourcePath}", resourcePath); } } - else - { - _logger.LogError("Missing translation/culture resource: {ResourcePath}", resourcePath); - } } private static string GetResourceFilename(string culture) @@ -394,5 +372,47 @@ namespace Emby.Server.Implementations.Localization return culture + ".json"; } + + /// + public IEnumerable GetLocalizationOptions() + { + yield return new LocalizationOption("Arabic", "ar"); + yield return new LocalizationOption("Bulgarian (Bulgaria)", "bg-BG"); + yield return new LocalizationOption("Catalan", "ca"); + yield return new LocalizationOption("Chinese Simplified", "zh-CN"); + yield return new LocalizationOption("Chinese Traditional", "zh-TW"); + yield return new LocalizationOption("Croatian", "hr"); + yield return new LocalizationOption("Czech", "cs"); + yield return new LocalizationOption("Danish", "da"); + yield return new LocalizationOption("Dutch", "nl"); + yield return new LocalizationOption("English (United Kingdom)", "en-GB"); + yield return new LocalizationOption("English (United States)", "en-US"); + yield return new LocalizationOption("French", "fr"); + yield return new LocalizationOption("French (Canada)", "fr-CA"); + yield return new LocalizationOption("German", "de"); + yield return new LocalizationOption("Greek", "el"); + yield return new LocalizationOption("Hebrew", "he"); + yield return new LocalizationOption("Hungarian", "hu"); + yield return new LocalizationOption("Italian", "it"); + yield return new LocalizationOption("Kazakh", "kk"); + yield return new LocalizationOption("Korean", "ko"); + yield return new LocalizationOption("Lithuanian", "lt-LT"); + yield return new LocalizationOption("Malay", "ms"); + yield return new LocalizationOption("Norwegian Bokmål", "nb"); + yield return new LocalizationOption("Persian", "fa"); + yield return new LocalizationOption("Polish", "pl"); + yield return new LocalizationOption("Portuguese (Brazil)", "pt-BR"); + yield return new LocalizationOption("Portuguese (Portugal)", "pt-PT"); + yield return new LocalizationOption("Russian", "ru"); + yield return new LocalizationOption("Slovak", "sk"); + yield return new LocalizationOption("Slovenian (Slovenia)", "sl-SI"); + yield return new LocalizationOption("Spanish", "es"); + yield return new LocalizationOption("Spanish (Argentina)", "es-AR"); + yield return new LocalizationOption("Spanish (Mexico)", "es-MX"); + yield return new LocalizationOption("Swedish", "sv"); + yield return new LocalizationOption("Swiss German", "gsw"); + yield return new LocalizationOption("Turkish", "tr"); + yield return new LocalizationOption("Tiếng Việt", "vi"); + } } } diff --git a/MediaBrowser.Model/Globalization/ILocalizationManager.cs b/MediaBrowser.Model/Globalization/ILocalizationManager.cs index e0e7317efd..baefeb39cf 100644 --- a/MediaBrowser.Model/Globalization/ILocalizationManager.cs +++ b/MediaBrowser.Model/Globalization/ILocalizationManager.cs @@ -56,6 +56,14 @@ namespace MediaBrowser.Model.Globalization /// . IEnumerable GetLocalizationOptions(); + /// + /// Checks if the string contains a character with the specified unicode category. + /// + /// The string. + /// The unicode category. + /// Wether or not the string contains a character with the specified unicode category. + bool HasUnicodeCategory(string value, UnicodeCategory category); + /// /// Returns the correct for the given language. /// From b5880c26808a6d7f183acb3f7977b42e13ccbf8a Mon Sep 17 00:00:00 2001 From: David Ullmer Date: Tue, 10 Aug 2021 14:03:15 +0200 Subject: [PATCH 115/120] Minor improvements --- .../Localization/LocalizationManager.cs | 141 +++++++++--------- 1 file changed, 67 insertions(+), 74 deletions(-) diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index 220e423bf5..3015786162 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -22,6 +22,9 @@ namespace Emby.Server.Implementations.Localization public class LocalizationManager : ILocalizationManager { private const string DefaultCulture = "en-US"; + private const string RatingsPath = "Emby.Server.Implementations.Localization.Ratings."; + private const string CulturesPath = "Emby.Server.Implementations.Localization.iso6392.txt"; + private const string CountriesPath = "Emby.Server.Implementations.Localization.countries.json"; private static readonly Assembly _assembly = typeof(LocalizationManager).Assembly; private static readonly string[] _unratedValues = { "n/a", "unrated", "not rated" }; @@ -57,43 +60,39 @@ namespace Emby.Server.Implementations.Localization /// . public async Task LoadAll() { - const string RatingsResource = "Emby.Server.Implementations.Localization.Ratings."; - // Extract from the assembly foreach (var resource in _assembly.GetManifestResourceNames()) { - if (!resource.StartsWith(RatingsResource, StringComparison.Ordinal)) + if (!resource.StartsWith(RatingsPath, StringComparison.Ordinal)) { continue; } - string countryCode = resource.Substring(RatingsResource.Length, 2); + string countryCode = resource.Substring(RatingsPath.Length, 2); var dict = new Dictionary(StringComparer.OrdinalIgnoreCase); - using (var str = _assembly.GetManifestResourceStream(resource)) - using (var reader = new StreamReader(str)) + await using var str = _assembly.GetManifestResourceStream(resource); + using var reader = new StreamReader(str); + await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false)) { - await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false)) + if (string.IsNullOrWhiteSpace(line)) { - if (string.IsNullOrWhiteSpace(line)) - { - continue; - } - - string[] parts = line.Split(','); - if (parts.Length == 2 - && int.TryParse(parts[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var value)) - { - var name = parts[0]; - dict.Add(name, new ParentalRating(name, value)); - } + continue; + } + + string[] parts = line.Split(','); + if (parts.Length == 2 + && int.TryParse(parts[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var value)) + { + var name = parts[0]; + dict.Add(name, new ParentalRating(name, value)); + } #if DEBUG - else - { - _logger.LogWarning("Malformed line in ratings file for country {CountryCode}", countryCode); - } -#endif + else + { + _logger.LogWarning("Malformed line in ratings file for country {CountryCode}", countryCode); } +#endif } _allParentalRatings[countryCode] = dict; @@ -113,52 +112,48 @@ namespace Emby.Server.Implementations.Localization { List list = new List(); - const string ResourcePath = "Emby.Server.Implementations.Localization.iso6392.txt"; - - using (var stream = _assembly.GetManifestResourceStream(ResourcePath)) - using (var reader = new StreamReader(stream)) + await using var stream = _assembly.GetManifestResourceStream(CulturesPath); + using var reader = new StreamReader(stream); + await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false)) { - await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false)) + if (string.IsNullOrWhiteSpace(line)) { - if (string.IsNullOrWhiteSpace(line)) + continue; + } + + var parts = line.Split('|'); + + if (parts.Length == 5) + { + string name = parts[3]; + if (string.IsNullOrWhiteSpace(name)) { continue; } - var parts = line.Split('|'); + string twoCharName = parts[2]; + if (string.IsNullOrWhiteSpace(twoCharName)) + { + continue; + } - if (parts.Length == 5) + string[] threeletterNames; + if (string.IsNullOrWhiteSpace(parts[1])) + { + threeletterNames = new[] { parts[0] }; + } + else { - string name = parts[3]; - if (string.IsNullOrWhiteSpace(name)) - { - continue; - } - - string twoCharName = parts[2]; - if (string.IsNullOrWhiteSpace(twoCharName)) - { - continue; - } - - string[] threeletterNames; - if (string.IsNullOrWhiteSpace(parts[1])) - { - threeletterNames = new[] { parts[0] }; - } - else - { - threeletterNames = new[] { parts[0], parts[1] }; - } - - list.Add(new CultureDto - { - DisplayName = name, - Name = name, - ThreeLetterISOLanguageNames = threeletterNames, - TwoLetterISOLanguageName = twoCharName - }); + threeletterNames = new[] { parts[0], parts[1] }; } + + list.Add(new CultureDto + { + DisplayName = name, + Name = name, + ThreeLetterISOLanguageNames = threeletterNames, + TwoLetterISOLanguageName = twoCharName + }); } } @@ -177,7 +172,7 @@ namespace Emby.Server.Implementations.Localization /// public IEnumerable GetCountries() { - using StreamReader reader = new StreamReader(_assembly.GetManifestResourceStream("Emby.Server.Implementations.Localization.countries.json")); + using StreamReader reader = new StreamReader(_assembly.GetManifestResourceStream(CountriesPath)); return JsonSerializer.Deserialize>(reader.ReadToEnd(), _jsonOptions); } @@ -338,23 +333,21 @@ namespace Emby.Server.Implementations.Localization private async Task CopyInto(IDictionary dictionary, string resourcePath) { - using (var stream = _assembly.GetManifestResourceStream(resourcePath)) + await using var stream = _assembly.GetManifestResourceStream(resourcePath); + // If a Culture doesn't have a translation the stream will be null and it defaults to en-us further up the chain + if (stream != null) { - // If a Culture doesn't have a translation the stream will be null and it defaults to en-us further up the chain - if (stream != null) - { - var dict = await JsonSerializer.DeserializeAsync>(stream, _jsonOptions).ConfigureAwait(false); + var dict = await JsonSerializer.DeserializeAsync>(stream, _jsonOptions).ConfigureAwait(false); - foreach (var key in dict.Keys) - { - dictionary[key] = dict[key]; - } - } - else + foreach (var key in dict.Keys) { - _logger.LogError("Missing translation/culture resource: {ResourcePath}", resourcePath); + dictionary[key] = dict[key]; } } + else + { + _logger.LogError("Missing translation/culture resource: {ResourcePath}", resourcePath); + } } private static string GetResourceFilename(string culture) From d7c9b141758c0cb2d1dd708fe4ce625b95d64434 Mon Sep 17 00:00:00 2001 From: David Ullmer Date: Tue, 10 Aug 2021 20:28:57 +0200 Subject: [PATCH 116/120] Apply suggestions from code review --- .../Localization/LocalizationManagerTests.cs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs index 0a9f4d817a..e2c998b54b 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs @@ -19,12 +19,11 @@ namespace Jellyfin.Server.Implementations.Tests.Localization { UICulture = "de-DE" }); - var countries = localizationManager.GetCountries(); - var countryInfos = countries.ToList(); + var countries = localizationManager.GetCountries().ToList(); - Assert.Equal(139, countryInfos.Count); + Assert.Equal(139, countries.Count); - var germany = countryInfos.FirstOrDefault(x => x.Name.Equals("DE", StringComparison.Ordinal)); + var germany = countries.FirstOrDefault(x => x.Name.Equals("DE", StringComparison.Ordinal)); Assert.NotNull(germany); Assert.Equal("Germany", germany!.DisplayName); Assert.Equal("DEU", germany.ThreeLetterISORegionName); @@ -43,7 +42,7 @@ namespace Jellyfin.Server.Implementations.Tests.Localization Assert.Equal(189, cultures.Count); - var germany = cultures.FirstOrDefault(x => x.TwoLetterISOLanguageName == "de"); + var germany = cultures.FirstOrDefault(x => x.TwoLetterISOLanguageName.Equals("de", StringComparison.Ordinal)); Assert.NotNull(germany); Assert.Equal("ger", germany!.ThreeLetterISOLanguageName); Assert.Equal("German", germany.DisplayName); @@ -86,7 +85,7 @@ namespace Jellyfin.Server.Implementations.Tests.Localization Assert.Equal(23, ratings.Count); - var tvma = ratings.FirstOrDefault(x => x.Name == "TV-MA"); + var tvma = ratings.FirstOrDefault(x => x.Name.Equals("TV-MA", StringComparison.Ordinal)); Assert.NotNull(tvma); Assert.Equal(9, tvma!.Value); } @@ -103,7 +102,7 @@ namespace Jellyfin.Server.Implementations.Tests.Localization Assert.Equal(10, ratings.Count); - var fsk = ratings.FirstOrDefault(x => x.Name == "FSK-12"); + var fsk = ratings.FirstOrDefault(x => x.Name.Equals("FSK-12", StringComparison.Ordinal)); Assert.NotNull(fsk); Assert.Equal(7, fsk!.Value); } From 32d27d71a833f35c313f1ae284e8a74aa06b1b6c Mon Sep 17 00:00:00 2001 From: Rich Lander Date: Tue, 10 Aug 2021 14:29:48 -0700 Subject: [PATCH 117/120] Fix warnings in MediaBrowser.Controller/MediaEncoding directory --- .../MediaEncoding/BaseEncodingJobOptions.cs | 18 +- .../MediaEncoding/EncodingHelper.cs | 50 +- .../MediaEncoding/EncodingJobInfo.cs | 436 +++++++++--------- .../MediaEncoding/IEncodingManager.cs | 7 + .../MediaEncoding/IMediaEncoder.cs | 43 ++ .../MediaEncoding/ISubtitleEncoder.cs | 8 + 6 files changed, 334 insertions(+), 228 deletions(-) diff --git a/MediaBrowser.Controller/MediaEncoding/BaseEncodingJobOptions.cs b/MediaBrowser.Controller/MediaEncoding/BaseEncodingJobOptions.cs index 745ee6bdb5..dd6f468dab 100644 --- a/MediaBrowser.Controller/MediaEncoding/BaseEncodingJobOptions.cs +++ b/MediaBrowser.Controller/MediaEncoding/BaseEncodingJobOptions.cs @@ -10,6 +10,15 @@ namespace MediaBrowser.Controller.MediaEncoding { public class BaseEncodingJobOptions { + public BaseEncodingJobOptions() + { + EnableAutoStreamCopy = true; + AllowVideoStreamCopy = true; + AllowAudioStreamCopy = true; + Context = EncodingContext.Streaming; + StreamOptions = new Dictionary(StringComparer.OrdinalIgnoreCase); + } + /// /// Gets or sets the id. /// @@ -191,14 +200,5 @@ namespace MediaBrowser.Controller.MediaEncoding return null; } - - public BaseEncodingJobOptions() - { - EnableAutoStreamCopy = true; - AllowVideoStreamCopy = true; - AllowAudioStreamCopy = true; - Context = EncodingContext.Streaming; - StreamOptions = new Dictionary(StringComparer.OrdinalIgnoreCase); - } } } \ No newline at end of file diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 257cd5df6d..9bae95a272 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -161,6 +161,9 @@ namespace MediaBrowser.Controller.MediaEncoding /// /// Gets the name of the output video codec. /// + /// Encording state. + /// Encoding options. + /// Encoder string. public string GetVideoEncoder(EncodingJobInfo state, EncodingOptions encodingOptions) { var codec = state.OutputVideoCodec; @@ -315,6 +318,11 @@ namespace MediaBrowser.Controller.MediaEncoding return container; } + /// + /// Gets decoder from a codec. + /// + /// Codec to use. + /// Decoder string. public string GetDecoderFromCodec(string codec) { // For these need to find out the ffmpeg names @@ -344,6 +352,8 @@ namespace MediaBrowser.Controller.MediaEncoding /// /// Infers the audio codec based on the url. /// + /// Container to use. + /// Codec string. public string InferAudioCodec(string container) { var ext = "." + (container ?? string.Empty); @@ -489,6 +499,9 @@ namespace MediaBrowser.Controller.MediaEncoding /// /// Gets the input argument. /// + /// Encoding state. + /// Encoding options. + /// Input arguments. public string GetInputArgument(EncodingJobInfo state, EncodingOptions encodingOptions) { var arg = new StringBuilder(); @@ -965,6 +978,11 @@ namespace MediaBrowser.Controller.MediaEncoding /// /// Gets the video bitrate to specify on the command line. /// + /// Encoding state. + /// Video encoder to use. + /// Encoding options. + /// Default present to use for encoding. + /// Video bitrate. public string GetVideoQualityParam(EncodingJobInfo state, string videoEncoder, EncodingOptions encodingOptions, string defaultPreset) { var param = string.Empty; @@ -1966,8 +1984,12 @@ namespace MediaBrowser.Controller.MediaEncoding } /// - /// Gets the graphical subtitle param. + /// Gets the graphical subtitle parameter. /// + /// Encoding state. + /// Encoding options. + /// Video codec to use. + /// Graphical subtitle parameter. public string GetGraphicalSubtitleParam( EncodingJobInfo state, EncodingOptions options, @@ -2485,6 +2507,13 @@ namespace MediaBrowser.Controller.MediaEncoding return string.Format(CultureInfo.InvariantCulture, filter, widthParam, heightParam); } + /// + /// Gets the output size parameter. + /// + /// Encoding state. + /// Encoding options. + /// Video codec to use. + /// The output size parameter. public string GetOutputSizeParam( EncodingJobInfo state, EncodingOptions options, @@ -2495,8 +2524,13 @@ namespace MediaBrowser.Controller.MediaEncoding } /// + /// Gets the output size parameter. /// If we're going to put a fixed size on the command line, this will calculate it. /// + /// Encoding state. + /// Encoding options. + /// Video codec to use. + /// The output size parameter. public string GetOutputSizeParamInternal( EncodingJobInfo state, EncodingOptions options, @@ -2908,6 +2942,10 @@ namespace MediaBrowser.Controller.MediaEncoding /// /// Gets the number of threads. /// + /// Encoding state. + /// Encoding options. + /// Video codec to use. + /// Number of threads. #nullable enable public static int GetNumberOfThreads(EncodingJobInfo? state, EncodingOptions encodingOptions, string? outputVideoCodec) { @@ -3551,6 +3589,11 @@ namespace MediaBrowser.Controller.MediaEncoding /// /// Gets a hw decoder name. /// + /// Encoding options. + /// Decoder to use. + /// Video codec to use. + /// Specifies if color depth 10. + /// Hardware decoder name. public string GetHwDecoderName(EncodingOptions options, string decoder, string videoCodec, bool isColorDepth10) { var isCodecAvailable = _mediaEncoder.SupportsDecoder(decoder) && options.HardwareDecodingCodecs.Contains(videoCodec, StringComparer.OrdinalIgnoreCase); @@ -3569,6 +3612,11 @@ namespace MediaBrowser.Controller.MediaEncoding /// /// Gets a hwaccel type to use as a hardware decoder(dxva/vaapi) depending on the system. /// + /// Encoding state. + /// Encoding options. + /// Video codec to use. + /// Specifies if color depth 10. + /// Hardware accelerator type. public string GetHwaccelType(EncodingJobInfo state, EncodingOptions options, string videoCodec, bool isColorDepth10) { var isWindows = OperatingSystem.IsWindows(); diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index bc0318ad7c..fa9f40d60d 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -1,6 +1,6 @@ #nullable disable -#pragma warning disable CS1591 +#pragma warning disable CS1591, SA1401 using System; using System.Collections.Generic; @@ -20,6 +20,44 @@ namespace MediaBrowser.Controller.MediaEncoding // For now, a common base class until the API and MediaEncoding classes are unified public class EncodingJobInfo { + public int? OutputAudioBitrate; + public int? OutputAudioChannels; + + private TranscodeReason[] _transcodeReasons = null; + + public EncodingJobInfo(TranscodingJobType jobType) + { + TranscodingType = jobType; + RemoteHttpHeaders = new Dictionary(StringComparer.OrdinalIgnoreCase); + SupportedAudioCodecs = Array.Empty(); + SupportedVideoCodecs = Array.Empty(); + SupportedSubtitleCodecs = Array.Empty(); + } + + public TranscodeReason[] TranscodeReasons + { + get + { + if (_transcodeReasons == null) + { + if (BaseRequest.TranscodeReasons == null) + { + return Array.Empty(); + } + + _transcodeReasons = BaseRequest.TranscodeReasons + .Split(',') + .Where(i => !string.IsNullOrEmpty(i)) + .Select(v => (TranscodeReason)Enum.Parse(typeof(TranscodeReason), v, true)) + .ToArray(); + } + + return _transcodeReasons; + } + } + + public IProgress Progress { get; set; } + public MediaStream VideoStream { get; set; } public VideoType VideoType { get; set; } @@ -58,40 +96,6 @@ namespace MediaBrowser.Controller.MediaEncoding public string MimeType { get; set; } - public string GetMimeType(string outputPath, bool enableStreamDefault = true) - { - if (!string.IsNullOrEmpty(MimeType)) - { - return MimeType; - } - - return MimeTypes.GetMimeType(outputPath, enableStreamDefault); - } - - private TranscodeReason[] _transcodeReasons = null; - - public TranscodeReason[] TranscodeReasons - { - get - { - if (_transcodeReasons == null) - { - if (BaseRequest.TranscodeReasons == null) - { - return Array.Empty(); - } - - _transcodeReasons = BaseRequest.TranscodeReasons - .Split(',') - .Where(i => !string.IsNullOrEmpty(i)) - .Select(v => (TranscodeReason)Enum.Parse(typeof(TranscodeReason), v, true)) - .ToArray(); - } - - return _transcodeReasons; - } - } - public bool IgnoreInputDts => MediaSource.IgnoreDts; public bool IgnoreInputIndex => MediaSource.IgnoreIndex; @@ -144,196 +148,17 @@ namespace MediaBrowser.Controller.MediaEncoding public BaseEncodingJobOptions BaseRequest { get; set; } - public long? StartTimeTicks => BaseRequest.StartTimeTicks; - - public bool CopyTimestamps => BaseRequest.CopyTimestamps; - - public int? OutputAudioBitrate; - public int? OutputAudioChannels; - - public bool DeInterlace(string videoCodec, bool forceDeinterlaceIfSourceIsInterlaced) - { - var videoStream = VideoStream; - var isInputInterlaced = videoStream != null && videoStream.IsInterlaced; - - if (!isInputInterlaced) - { - return false; - } - - // Support general param - if (BaseRequest.DeInterlace) - { - return true; - } - - if (!string.IsNullOrEmpty(videoCodec)) - { - if (string.Equals(BaseRequest.GetOption(videoCodec, "deinterlace"), "true", StringComparison.OrdinalIgnoreCase)) - { - return true; - } - } - - return forceDeinterlaceIfSourceIsInterlaced && isInputInterlaced; - } - - public string[] GetRequestedProfiles(string codec) - { - if (!string.IsNullOrEmpty(BaseRequest.Profile)) - { - return BaseRequest.Profile.Split(new[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries); - } - - if (!string.IsNullOrEmpty(codec)) - { - var profile = BaseRequest.GetOption(codec, "profile"); - - if (!string.IsNullOrEmpty(profile)) - { - return profile.Split(new[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries); - } - } - - return Array.Empty(); - } - - public string GetRequestedLevel(string codec) - { - if (!string.IsNullOrEmpty(BaseRequest.Level)) - { - return BaseRequest.Level; - } - - if (!string.IsNullOrEmpty(codec)) - { - return BaseRequest.GetOption(codec, "level"); - } - - return null; - } - - public int? GetRequestedMaxRefFrames(string codec) - { - if (BaseRequest.MaxRefFrames.HasValue) - { - return BaseRequest.MaxRefFrames; - } - - if (!string.IsNullOrEmpty(codec)) - { - var value = BaseRequest.GetOption(codec, "maxrefframes"); - if (!string.IsNullOrEmpty(value) - && int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) - { - return result; - } - } - - return null; - } - - public int? GetRequestedVideoBitDepth(string codec) - { - if (BaseRequest.MaxVideoBitDepth.HasValue) - { - return BaseRequest.MaxVideoBitDepth; - } - - if (!string.IsNullOrEmpty(codec)) - { - var value = BaseRequest.GetOption(codec, "videobitdepth"); - if (!string.IsNullOrEmpty(value) - && int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) - { - return result; - } - } - - return null; - } - - public int? GetRequestedAudioBitDepth(string codec) - { - if (BaseRequest.MaxAudioBitDepth.HasValue) - { - return BaseRequest.MaxAudioBitDepth; - } - - if (!string.IsNullOrEmpty(codec)) - { - var value = BaseRequest.GetOption(codec, "audiobitdepth"); - if (!string.IsNullOrEmpty(value) - && int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) - { - return result; - } - } - - return null; - } - - public int? GetRequestedAudioChannels(string codec) - { - if (!string.IsNullOrEmpty(codec)) - { - var value = BaseRequest.GetOption(codec, "audiochannels"); - if (!string.IsNullOrEmpty(value) - && int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) - { - return result; - } - } - - if (BaseRequest.MaxAudioChannels.HasValue) - { - return BaseRequest.MaxAudioChannels; - } - - if (BaseRequest.AudioChannels.HasValue) - { - return BaseRequest.AudioChannels; - } - - if (BaseRequest.TranscodingMaxAudioChannels.HasValue) - { - return BaseRequest.TranscodingMaxAudioChannels; - } - - return null; - } - public bool IsVideoRequest { get; set; } public TranscodingJobType TranscodingType { get; set; } - public EncodingJobInfo(TranscodingJobType jobType) - { - TranscodingType = jobType; - RemoteHttpHeaders = new Dictionary(StringComparer.OrdinalIgnoreCase); - SupportedAudioCodecs = Array.Empty(); - SupportedVideoCodecs = Array.Empty(); - SupportedSubtitleCodecs = Array.Empty(); - } + public long? StartTimeTicks => BaseRequest.StartTimeTicks; + + public bool CopyTimestamps => BaseRequest.CopyTimestamps; public bool IsSegmentedLiveStream => TranscodingType != TranscodingJobType.Progressive && !RunTimeTicks.HasValue; - public bool EnableBreakOnNonKeyFrames(string videoCodec) - { - if (TranscodingType != TranscodingJobType.Progressive) - { - if (IsSegmentedLiveStream) - { - return false; - } - - return BaseRequest.BreakOnNonKeyFrames && EncodingHelper.IsCopyCodec(videoCodec); - } - - return false; - } - public int? TotalOutputBitrate => (OutputAudioBitrate ?? 0) + (OutputVideoBitrate ?? 0); public int? OutputWidth @@ -682,6 +507,21 @@ namespace MediaBrowser.Controller.MediaEncoding public int HlsListSize => 0; + public bool EnableBreakOnNonKeyFrames(string videoCodec) + { + if (TranscodingType != TranscodingJobType.Progressive) + { + if (IsSegmentedLiveStream) + { + return false; + } + + return BaseRequest.BreakOnNonKeyFrames && EncodingHelper.IsCopyCodec(videoCodec); + } + + return false; + } + private int? GetMediaStreamCount(MediaStreamType type, int limit) { var count = MediaSource.GetStreamCount(type); @@ -694,7 +534,167 @@ namespace MediaBrowser.Controller.MediaEncoding return count; } - public IProgress Progress { get; set; } + public string GetMimeType(string outputPath, bool enableStreamDefault = true) + { + if (!string.IsNullOrEmpty(MimeType)) + { + return MimeType; + } + + return MimeTypes.GetMimeType(outputPath, enableStreamDefault); + } + + public bool DeInterlace(string videoCodec, bool forceDeinterlaceIfSourceIsInterlaced) + { + var videoStream = VideoStream; + var isInputInterlaced = videoStream != null && videoStream.IsInterlaced; + + if (!isInputInterlaced) + { + return false; + } + + // Support general param + if (BaseRequest.DeInterlace) + { + return true; + } + + if (!string.IsNullOrEmpty(videoCodec)) + { + if (string.Equals(BaseRequest.GetOption(videoCodec, "deinterlace"), "true", StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } + + return forceDeinterlaceIfSourceIsInterlaced && isInputInterlaced; + } + + public string[] GetRequestedProfiles(string codec) + { + if (!string.IsNullOrEmpty(BaseRequest.Profile)) + { + return BaseRequest.Profile.Split(new[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries); + } + + if (!string.IsNullOrEmpty(codec)) + { + var profile = BaseRequest.GetOption(codec, "profile"); + + if (!string.IsNullOrEmpty(profile)) + { + return profile.Split(new[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries); + } + } + + return Array.Empty(); + } + + public string GetRequestedLevel(string codec) + { + if (!string.IsNullOrEmpty(BaseRequest.Level)) + { + return BaseRequest.Level; + } + + if (!string.IsNullOrEmpty(codec)) + { + return BaseRequest.GetOption(codec, "level"); + } + + return null; + } + + public int? GetRequestedMaxRefFrames(string codec) + { + if (BaseRequest.MaxRefFrames.HasValue) + { + return BaseRequest.MaxRefFrames; + } + + if (!string.IsNullOrEmpty(codec)) + { + var value = BaseRequest.GetOption(codec, "maxrefframes"); + if (!string.IsNullOrEmpty(value) + && int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) + { + return result; + } + } + + return null; + } + + public int? GetRequestedVideoBitDepth(string codec) + { + if (BaseRequest.MaxVideoBitDepth.HasValue) + { + return BaseRequest.MaxVideoBitDepth; + } + + if (!string.IsNullOrEmpty(codec)) + { + var value = BaseRequest.GetOption(codec, "videobitdepth"); + if (!string.IsNullOrEmpty(value) + && int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) + { + return result; + } + } + + return null; + } + + public int? GetRequestedAudioBitDepth(string codec) + { + if (BaseRequest.MaxAudioBitDepth.HasValue) + { + return BaseRequest.MaxAudioBitDepth; + } + + if (!string.IsNullOrEmpty(codec)) + { + var value = BaseRequest.GetOption(codec, "audiobitdepth"); + if (!string.IsNullOrEmpty(value) + && int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) + { + return result; + } + } + + return null; + } + + public int? GetRequestedAudioChannels(string codec) + { + if (!string.IsNullOrEmpty(codec)) + { + var value = BaseRequest.GetOption(codec, "audiochannels"); + if (!string.IsNullOrEmpty(value) + && int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) + { + return result; + } + } + + if (BaseRequest.MaxAudioChannels.HasValue) + { + return BaseRequest.MaxAudioChannels; + } + + if (BaseRequest.AudioChannels.HasValue) + { + return BaseRequest.AudioChannels; + } + + if (BaseRequest.TranscodingMaxAudioChannels.HasValue) + { + return BaseRequest.TranscodingMaxAudioChannels; + } + + return null; + } public virtual void ReportTranscodingProgress(TimeSpan? transcodingPosition, float? framerate, double? percentComplete, long? bytesTranscoded, int? bitRate) { diff --git a/MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs b/MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs index 773547872c..8ce40a58d1 100644 --- a/MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs +++ b/MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs @@ -16,6 +16,13 @@ namespace MediaBrowser.Controller.MediaEncoding /// /// Refreshes the chapter images. /// + /// Video to use. + /// Directory service to use. + /// Set of chapters to refresh. + /// Option to extract images. + /// Option to save chapters. + /// CancellationToken to use for operation. + /// true if successful, false if not. Task RefreshChapterImages(Video video, IDirectoryService directoryService, IReadOnlyList chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index 76a9fd7c74..3aacf92cdc 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -71,13 +71,42 @@ namespace MediaBrowser.Controller.MediaEncoding /// /// Extracts the video image. /// + /// Input file. + /// Video container type. + /// Media source information. + /// Media stream information. + /// Video 3D format. + /// Time offset. + /// CancellationToken to use for operation. + /// Location of video image. Task ExtractVideoImage(string inputFile, string container, MediaSourceInfo mediaSource, MediaStream videoStream, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken); + /// + /// Extracts the video image. + /// + /// Input file. + /// Video container type. + /// Media source information. + /// Media stream information. + /// Time offset. + /// CancellationToken to use for operation. + /// Location of video image. Task ExtractVideoImage(string inputFile, string container, MediaSourceInfo mediaSource, MediaStream imageStream, int? imageStreamIndex, CancellationToken cancellationToken); /// /// Extracts the video images on interval. /// + /// Input file. + /// Video container type. + /// Media stream information. + /// Media source information. + /// Video 3D format. + /// Time interval. + /// Directory to write images. + /// Filename prefix to use. + /// Maximum width of image. + /// CancellationToken to use for operation. + /// A task. Task ExtractVideoImagesOnInterval( string inputFile, string container, @@ -122,10 +151,24 @@ namespace MediaBrowser.Controller.MediaEncoding /// System.String. string EscapeSubtitleFilterPath(string path); + /// + /// Sets the path to find FFmpeg. + /// void SetFFmpegPath(); + /// + /// Updated the encoder path. + /// + /// The path. + /// The type of path. void UpdateEncoderPath(string path, string pathType); + /// + /// Gets the primary playlist of .vob files. + /// + /// The to the .vob files. + /// The title number to start with. + /// A playlist. IEnumerable GetPrimaryPlaylistVobFiles(string path, uint? titleNumber); } } diff --git a/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs b/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs index 3fb2c47e13..4483cf708a 100644 --- a/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs @@ -15,6 +15,14 @@ namespace MediaBrowser.Controller.MediaEncoding /// /// Gets the subtitles. /// + /// Item to use. + /// Media source. + /// Subtitle stream to use. + /// Output format to use. + /// Start time. + /// End time. + /// Option to preserve original timestamps. + /// The cancellation token for the operation. /// Task{Stream}. Task GetSubtitles( BaseItem item, From 8d5b87025b9e34eaa3d67c97d4a8a380b52c6830 Mon Sep 17 00:00:00 2001 From: Julien Machiels Date: Wed, 11 Aug 2021 09:42:40 +0200 Subject: [PATCH 118/120] Update tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs Co-authored-by: Claus Vium --- .../Probing/ProbeResultNormalizerTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs index 6d6abdb900..59037c2636 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs @@ -73,7 +73,7 @@ namespace Jellyfin.MediaEncoding.Tests.Probing } [Fact] - public void GetMediaInfo_Music_Year_Only_Success() + public void GetMediaInfo_GivenOriginalDateContainsOnlyYear_Success() { var bytes = File.ReadAllBytes("Test Data/Probing/music_year_only_metadata.json"); var internalMediaInfoResult = JsonSerializer.Deserialize(bytes, _jsonOptions); From 3a47ad11e9b8b229026e2fe479a0012861a4e5bd Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Wed, 11 Aug 2021 12:57:31 +0200 Subject: [PATCH 119/120] Apply suggestions from code review --- .../Localization/LocalizationManagerTests.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs index e2c998b54b..edd4b1e558 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs @@ -55,7 +55,7 @@ namespace Jellyfin.Server.Implementations.Tests.Localization [InlineData("de")] [InlineData("ger")] [InlineData("german")] - public async Task FindLanguage_Valid_Success(string identifier) + public async Task FindLanguageInfo_Valid_Success(string identifier) { var localizationManager = Setup(new ServerConfiguration { @@ -74,7 +74,7 @@ namespace Jellyfin.Server.Implementations.Tests.Localization } [Fact] - public async Task ParentalRatings_Default_Success() + public async Task GetParentalRatings_Default_Success() { var localizationManager = Setup(new ServerConfiguration { @@ -91,7 +91,7 @@ namespace Jellyfin.Server.Implementations.Tests.Localization } [Fact] - public async Task ParentalRatings_ConfiguredCountryCode_Success() + public async Task GetParentalRatings_ConfiguredCountryCode_Success() { var localizationManager = Setup(new ServerConfiguration() { @@ -115,7 +115,7 @@ namespace Jellyfin.Server.Implementations.Tests.Localization [InlineData("TV-MA", "US", 9)] [InlineData("XXX", "asdf", 100)] [InlineData("Germany: FSK-18", "DE", 9)] - public async Task GetRatingLevelFromString_Valid_Success(string value, string countryCode, int expectedLevel) + public async Task GetRatingLevel_GivenValidString_Success(string value, string countryCode, int expectedLevel) { var localizationManager = Setup(new ServerConfiguration() { @@ -128,7 +128,7 @@ namespace Jellyfin.Server.Implementations.Tests.Localization } [Fact] - public async Task GetRatingLevelFromString_Unrated_Success() + public async Task GetRatingLevel_GivenUnratedString_Success() { var localizationManager = Setup(new ServerConfiguration() { From 1ac2524844e869a7784e3bf2d5adaac81c009b81 Mon Sep 17 00:00:00 2001 From: Rich Lander Date: Wed, 11 Aug 2021 13:37:46 -0700 Subject: [PATCH 120/120] Apply suggestions from code review Co-authored-by: Claus Vium --- MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index 3aacf92cdc..ff24560703 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -88,7 +88,7 @@ namespace MediaBrowser.Controller.MediaEncoding /// Video container type. /// Media source information. /// Media stream information. - /// Time offset. + /// Index of the stream to extract from. /// CancellationToken to use for operation. /// Location of video image. Task ExtractVideoImage(string inputFile, string container, MediaSourceInfo mediaSource, MediaStream imageStream, int? imageStreamIndex, CancellationToken cancellationToken); @@ -157,7 +157,7 @@ namespace MediaBrowser.Controller.MediaEncoding void SetFFmpegPath(); /// - /// Updated the encoder path. + /// Updates the encoder path. /// /// The path. /// The type of path.