From 415b03d719e054a3cc6998d89c3f4a13806e0a9e Mon Sep 17 00:00:00 2001
From: Mason Tran
Date: Wed, 24 Mar 2021 02:35:44 -0400
Subject: Delay starting services until after network is online
---
debian/jellyfin.service | 2 +-
fedora/jellyfin.service | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/debian/jellyfin.service b/debian/jellyfin.service
index f1a8f4652..c9d1a4d13 100644
--- a/debian/jellyfin.service
+++ b/debian/jellyfin.service
@@ -1,6 +1,6 @@
[Unit]
Description = Jellyfin Media Server
-After = network.target
+After = network-online.target
[Service]
Type = simple
diff --git a/fedora/jellyfin.service b/fedora/jellyfin.service
index b092ebf2f..f706b0ad3 100644
--- a/fedora/jellyfin.service
+++ b/fedora/jellyfin.service
@@ -1,5 +1,5 @@
[Unit]
-After=network.target
+After=network-online.target
Description=Jellyfin is a free software media system that puts you in control of managing and streaming your media.
[Service]
--
cgit v1.2.3
From 88bfd1bcf45bdfa6c64e3439d7f406799645163c Mon Sep 17 00:00:00 2001
From: David Ullmer
Date: Mon, 10 May 2021 17:58:21 +0200
Subject: 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 000000000..acdf74c4f
--- /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());
+ }
+ }
+}
--
cgit v1.2.3
From db2b53a4b52d0c1e9797bfc70030b04421ba46a6 Mon Sep 17 00:00:00 2001
From: David Ullmer
Date: Mon, 10 May 2021 18:05:35 +0200
Subject: 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 220e423bf..efbccaa5b 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 baefeb39c..e0e7317ef 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.
///
--
cgit v1.2.3
From e33e3ba61037b594fd9035550e3ca646bb7f2c8f Mon Sep 17 00:00:00 2001
From: David Ullmer
Date: Tue, 25 May 2021 12:33:55 +0200
Subject: 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 acdf74c4f..651957ae3 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());
}
}
}
--
cgit v1.2.3
From 66e452422cd20e059ad9b83cc4ff71af13e0bbd1 Mon Sep 17 00:00:00 2001
From: Julien Voisin
Date: Mon, 28 Jun 2021 06:15:07 +0000
Subject: Add a LGTM.com badge
---
README.md | 3 +++
1 file changed, 3 insertions(+)
diff --git a/README.md b/README.md
index 6859a8a76..69fa8ca26 100644
--- a/README.md
+++ b/README.md
@@ -41,6 +41,9 @@
+
+
+
---
--
cgit v1.2.3
From 7e3c94d094732c3c174375b0025604f1faa28f9e Mon Sep 17 00:00:00 2001
From: Brandon Nguyen
Date: Sat, 3 Jul 2021 01:12:09 -0700
Subject: 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 b44961bf8..c2d2aff34 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 c295af7eb..9e6363890 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 064a087d5..98f3268b9 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; }
}
}
--
cgit v1.2.3
From df17c67f11468a645a2630401178bbd35b489c80 Mon Sep 17 00:00:00 2001
From: Brandon Nguyen
Date: Sat, 3 Jul 2021 15:29:07 -0700
Subject: 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 9e6363890..b8a8491ad 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 98f3268b9..57f0a322e 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; }
}
--
cgit v1.2.3
From 1f99c9b90c5b791bb41ff711ad20b390f4f2268f Mon Sep 17 00:00:00 2001
From: Bond_009
Date: Tue, 6 Jul 2021 00:01:33 +0200
Subject: Minor fixes
---
Emby.Dlna/ContentDirectory/ControlHandler.cs | 23 +++++---------
Emby.Naming/AudioBook/AudioBookInfo.cs | 8 ++---
Emby.Naming/AudioBook/AudioBookListResolver.cs | 2 +-
Emby.Naming/Emby.Naming.csproj | 5 +--
Emby.Naming/Video/VideoListResolver.cs | 2 +-
.../HttpServer/Security/AuthorizationContext.cs | 2 +-
.../ScheduledTasks/Tasks/ChapterImagesTask.cs | 37 ++++++++--------------
7 files changed, 29 insertions(+), 50 deletions(-)
diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs
index 27c5b2268..ac336e5dc 100644
--- a/Emby.Dlna/ContentDirectory/ControlHandler.cs
+++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs
@@ -288,21 +288,14 @@ namespace Emby.Dlna.ContentDirectory
/// The xml feature list.
private static string WriteFeatureListXml()
{
- // TODO: clean this up
- var builder = new StringBuilder();
-
- builder.Append("");
- builder.Append("");
-
- builder.Append("");
- builder.Append("");
- builder.Append("");
- builder.Append("");
- builder.Append("");
-
- builder.Append("");
-
- return builder.ToString();
+ return ""
+ + ""
+ + ""
+ + ""
+ + ""
+ + ""
+ + ""
+ + "";
}
///
diff --git a/Emby.Naming/AudioBook/AudioBookInfo.cs b/Emby.Naming/AudioBook/AudioBookInfo.cs
index 15702ff2c..acd8905af 100644
--- a/Emby.Naming/AudioBook/AudioBookInfo.cs
+++ b/Emby.Naming/AudioBook/AudioBookInfo.cs
@@ -15,7 +15,7 @@ namespace Emby.Naming.AudioBook
/// List of files composing the actual audiobook.
/// List of extra files.
/// Alternative version of files.
- public AudioBookInfo(string name, int? year, List files, List extras, List alternateVersions)
+ public AudioBookInfo(string name, int? year, IReadOnlyList files, IReadOnlyList extras, IReadOnlyList alternateVersions)
{
Name = name;
Year = year;
@@ -39,18 +39,18 @@ namespace Emby.Naming.AudioBook
/// Gets or sets the files.
///
/// The files.
- public List Files { get; set; }
+ public IReadOnlyList Files { get; set; }
///
/// Gets or sets the extras.
///
/// The extras.
- public List Extras { get; set; }
+ public IReadOnlyList Extras { get; set; }
///
/// Gets or sets the alternate versions.
///
/// The alternate versions.
- public List AlternateVersions { get; set; }
+ public IReadOnlyList AlternateVersions { get; set; }
}
}
diff --git a/Emby.Naming/AudioBook/AudioBookListResolver.cs b/Emby.Naming/AudioBook/AudioBookListResolver.cs
index ca5322890..1e4a8d2ed 100644
--- a/Emby.Naming/AudioBook/AudioBookListResolver.cs
+++ b/Emby.Naming/AudioBook/AudioBookListResolver.cs
@@ -87,7 +87,7 @@ namespace Emby.Naming.AudioBook
foreach (var audioFile in group)
{
var name = Path.GetFileNameWithoutExtension(audioFile.Path);
- if (name.Equals("audiobook") ||
+ if (name.Equals("audiobook", StringComparison.OrdinalIgnoreCase) ||
name.Contains(nameParserResult.Name, StringComparison.OrdinalIgnoreCase) ||
name.Contains(nameWithReplacedDots, StringComparison.OrdinalIgnoreCase))
{
diff --git a/Emby.Naming/Emby.Naming.csproj b/Emby.Naming/Emby.Naming.csproj
index 3224ff412..1802c2a59 100644
--- a/Emby.Naming/Emby.Naming.csproj
+++ b/Emby.Naming/Emby.Naming.csproj
@@ -15,6 +15,7 @@
true
snupkg
enable
+ ../jellyfin.ruleset
@@ -50,8 +51,4 @@
-
- ../jellyfin.ruleset
-
-
diff --git a/Emby.Naming/Video/VideoListResolver.cs b/Emby.Naming/Video/VideoListResolver.cs
index 7da2dcd7a..ed7d511a3 100644
--- a/Emby.Naming/Video/VideoListResolver.cs
+++ b/Emby.Naming/Video/VideoListResolver.cs
@@ -21,7 +21,7 @@ namespace Emby.Naming.Video
/// The naming options.
/// Indication we should consider multi-versions of content.
/// Returns enumerable of which groups files together when related.
- public static IEnumerable Resolve(List files, NamingOptions namingOptions, bool supportMultiVersion = true)
+ public static IEnumerable Resolve(IEnumerable files, NamingOptions namingOptions, bool supportMultiVersion = true)
{
var videoInfos = files
.Select(i => VideoResolver.Resolve(i.FullName, i.IsDirectory, namingOptions))
diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
index 488614609..b2625a68c 100644
--- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
+++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
@@ -141,7 +141,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
}
// Temporary. TODO - allow clients to specify that the token has been shared with a casting device
- var allowTokenInfoUpdate = authInfo.Client == null || authInfo.Client.IndexOf("chromecast", StringComparison.OrdinalIgnoreCase) == -1;
+ var allowTokenInfoUpdate = authInfo.Client == null || !authInfo.Client.Contains("chromecast", StringComparison.OrdinalIgnoreCase);
if (string.IsNullOrWhiteSpace(authInfo.Device))
{
diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs
index baeb86a22..b764a139c 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs
@@ -55,9 +55,19 @@ namespace Emby.Server.Implementations.ScheduledTasks
_localization = localization;
}
- ///
- /// Creates the triggers that define when the task will run.
- ///
+ ///
+ public string Name => _localization.GetLocalizedString("TaskRefreshChapterImages");
+
+ ///
+ public string Description => _localization.GetLocalizedString("TaskRefreshChapterImagesDescription");
+
+ ///
+ public string Category => _localization.GetLocalizedString("TasksLibraryCategory");
+
+ ///
+ public string Key => "RefreshChapterImages";
+
+ ///
public IEnumerable GetDefaultTriggers()
{
return new[]
@@ -162,26 +172,5 @@ namespace Emby.Server.Implementations.ScheduledTasks
}
}
}
-
- ///
- public string Name => _localization.GetLocalizedString("TaskRefreshChapterImages");
-
- ///
- public string Description => _localization.GetLocalizedString("TaskRefreshChapterImagesDescription");
-
- ///
- public string Category => _localization.GetLocalizedString("TasksLibraryCategory");
-
- ///
- public string Key => "RefreshChapterImages";
-
- ///
- public bool IsHidden => false;
-
- ///
- public bool IsEnabled => true;
-
- ///
- public bool IsLogged => true;
}
}
--
cgit v1.2.3
From d0c5e25ec05c8d2bb77cfe067db0a5ac2e338f15 Mon Sep 17 00:00:00 2001
From: Brandon Nguyen
Date: Mon, 5 Jul 2021 16:52:52 -0700
Subject: Use nullable enum type instead of strings
---
Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 12 +++---
MediaBrowser.Model/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 b8a8491ad..05fa5b135 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 000000000..11721f090
--- /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 57f0a322e..68ab691f8 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; }
}
--
cgit v1.2.3
From c6bac310427fed99b2e798cb785935c6f9f09b81 Mon Sep 17 00:00:00 2001
From: Brandon Nguyen
Date: Sun, 11 Jul 2021 11:59:03 -0700
Subject: Add int values to HardwareEncodingType enum
---
MediaBrowser.Model/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 11721f090..0e172f35f 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
}
}
--
cgit v1.2.3
From ef3b651aade1c17b5258ce4564640e974727bb3d Mon Sep 17 00:00:00 2001
From: Bond_009
Date: Tue, 20 Jul 2021 00:25:30 +0200
Subject: 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 5f125eb4f..915ce42cc 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 89579c037..6d49ac832 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)
--
cgit v1.2.3
From fb92eab69b419ce13742c8ae4c43cd47ae398db4 Mon Sep 17 00:00:00 2001
From: Rich Lander
Date: Thu, 22 Jul 2021 17:33:19 -0700
Subject: Fix analysis issues
---
.../Manager/ItemImageProvider.cs | 1 +
MediaBrowser.Providers/Manager/MetadataService.cs | 5 +
.../MediaBrowser.Providers.csproj | 2 +-
.../Plugins/AudioDb/AlbumImageProvider.cs | 110 -------
.../Plugins/AudioDb/AlbumProvider.cs | 289 -----------------
.../Plugins/AudioDb/ArtistImageProvider.cs | 151 ---------
.../Plugins/AudioDb/ArtistProvider.cs | 282 ----------------
.../Plugins/AudioDb/AudioDbAlbumImageProvider.cs | 110 +++++++
.../Plugins/AudioDb/AudioDbAlbumProvider.cs | 291 +++++++++++++++++
.../Plugins/AudioDb/AudioDbArtistImageProvider.cs | 151 +++++++++
.../Plugins/AudioDb/AudioDbArtistProvider.cs | 282 ++++++++++++++++
.../Plugins/MusicBrainz/ArtistProvider.cs | 272 ----------------
.../Plugins/MusicBrainz/ExternalIds.cs | 119 -------
.../MusicBrainzAlbumArtistExternalId.cs | 28 ++
.../MusicBrainz/MusicBrainzAlbumExternalId.cs | 28 ++
.../MusicBrainz/MusicBrainzAlbumProvider.cs | 358 +++++++++++----------
.../MusicBrainz/MusicBrainzArtistExternalId.cs | 28 ++
.../MusicBrainz/MusicBrainzArtistProvider.cs | 272 ++++++++++++++++
.../MusicBrainzOtherArtistExternalId.cs | 28 ++
.../MusicBrainzReleaseGroupExternalId.cs | 28 ++
.../Plugins/MusicBrainz/MusicBrainzTrackId.cs | 28 ++
.../Plugins/MusicBrainz/Plugin.cs | 8 +-
.../Plugins/Omdb/OmdbItemProvider.cs | 2 +-
.../Plugins/Omdb/OmdbProvider.cs | 44 ++-
.../Studios/StudioMetadataService.cs | 3 +-
25 files changed, 1512 insertions(+), 1408 deletions(-)
delete mode 100644 MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs
delete mode 100644 MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs
delete mode 100644 MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs
delete mode 100644 MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs
create mode 100644 MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumImageProvider.cs
create mode 100644 MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs
create mode 100644 MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistImageProvider.cs
create mode 100644 MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs
delete mode 100644 MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs
delete mode 100644 MediaBrowser.Providers/Plugins/MusicBrainz/ExternalIds.cs
create mode 100644 MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumArtistExternalId.cs
create mode 100644 MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumExternalId.cs
create mode 100644 MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzArtistExternalId.cs
create mode 100644 MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzArtistProvider.cs
create mode 100644 MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzOtherArtistExternalId.cs
create mode 100644 MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzReleaseGroupExternalId.cs
create mode 100644 MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzTrackId.cs
diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs
index 416723d49..fd6d7937b 100644
--- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs
+++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs
@@ -536,6 +536,7 @@ namespace MediaBrowser.Providers.Manager
return true;
}
}
+
// We always want to use prefetched images
return false;
}
diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs
index 333f47f87..3a42eb4c1 100644
--- a/MediaBrowser.Providers/Manager/MetadataService.cs
+++ b/MediaBrowser.Providers/Manager/MetadataService.cs
@@ -505,6 +505,11 @@ namespace MediaBrowser.Providers.Manager
///
/// Gets the providers.
///
+ /// A media item.
+ /// The LibraryOptions to use.
+ /// The MetadataRefreshOptions to use.
+ /// Specifies first refresh mode.
+ /// Specifies refresh mode.
/// IEnumerable{`0}.
protected IEnumerable GetProviders(BaseItem item, LibraryOptions libraryOptions, MetadataRefreshOptions options, bool isFirstRefresh, bool requiresRefresh)
{
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index cdb07a15d..c167b3473 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -29,7 +29,7 @@
net5.0
false
true
- true
+ true
AllEnabledByDefault
../jellyfin.ruleset
diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs
deleted file mode 100644
index 36d8eeb40..000000000
--- a/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs
+++ /dev/null
@@ -1,110 +0,0 @@
-#pragma warning disable CS1591
-
-using System.Collections.Generic;
-using System.IO;
-using System.Net.Http;
-using System.Text.Json;
-using System.Threading;
-using System.Threading.Tasks;
-using Jellyfin.Extensions.Json;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Providers;
-
-namespace MediaBrowser.Providers.Plugins.AudioDb
-{
- public class AudioDbAlbumImageProvider : IRemoteImageProvider, IHasOrder
- {
- private readonly IServerConfigurationManager _config;
- private readonly IHttpClientFactory _httpClientFactory;
- private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options;
-
- public AudioDbAlbumImageProvider(IServerConfigurationManager config, IHttpClientFactory httpClientFactory)
- {
- _config = config;
- _httpClientFactory = httpClientFactory;
- }
-
- ///
- public string Name => "TheAudioDB";
-
- ///
- // After embedded and fanart
- public int Order => 2;
-
- ///
- public IEnumerable GetSupportedImages(BaseItem item)
- {
- return new List
- {
- ImageType.Primary,
- ImageType.Disc
- };
- }
-
- ///
- public async Task> GetImages(BaseItem item, CancellationToken cancellationToken)
- {
- var id = item.GetProviderId(MetadataProvider.MusicBrainzReleaseGroup);
-
- if (!string.IsNullOrWhiteSpace(id))
- {
- await AudioDbAlbumProvider.Current.EnsureInfo(id, cancellationToken).ConfigureAwait(false);
-
- var path = AudioDbAlbumProvider.GetAlbumInfoPath(_config.ApplicationPaths, id);
-
- await using FileStream jsonStream = File.OpenRead(path);
- var obj = await JsonSerializer.DeserializeAsync(jsonStream, _jsonOptions, cancellationToken).ConfigureAwait(false);
-
- if (obj != null && obj.album != null && obj.album.Count > 0)
- {
- return GetImages(obj.album[0]);
- }
- }
-
- return new List();
- }
-
- private IEnumerable GetImages(AudioDbAlbumProvider.Album item)
- {
- var list = new List();
-
- if (!string.IsNullOrWhiteSpace(item.strAlbumThumb))
- {
- list.Add(new RemoteImageInfo
- {
- ProviderName = Name,
- Url = item.strAlbumThumb,
- Type = ImageType.Primary
- });
- }
-
- if (!string.IsNullOrWhiteSpace(item.strAlbumCDart))
- {
- list.Add(new RemoteImageInfo
- {
- ProviderName = Name,
- Url = item.strAlbumCDart,
- Type = ImageType.Disc
- });
- }
-
- return list;
- }
-
- ///
- public Task GetImageResponse(string url, CancellationToken cancellationToken)
- {
- var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
- return httpClient.GetAsync(url, cancellationToken);
- }
-
- ///
- public bool Supports(BaseItem item)
- => item is MusicAlbum;
- }
-}
diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs
deleted file mode 100644
index 9539c396d..000000000
--- a/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs
+++ /dev/null
@@ -1,289 +0,0 @@
-#pragma warning disable CS1591
-
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Net.Http;
-using System.Text.Json;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.Extensions;
-using Jellyfin.Extensions.Json;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Providers;
-using MediaBrowser.Providers.Music;
-
-namespace MediaBrowser.Providers.Plugins.AudioDb
-{
- public class AudioDbAlbumProvider : IRemoteMetadataProvider, IHasOrder
- {
- private readonly IServerConfigurationManager _config;
- private readonly IFileSystem _fileSystem;
- private readonly IHttpClientFactory _httpClientFactory;
- private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options;
-
- public static AudioDbAlbumProvider Current;
-
- public AudioDbAlbumProvider(IServerConfigurationManager config, IFileSystem fileSystem, IHttpClientFactory httpClientFactory)
- {
- _config = config;
- _fileSystem = fileSystem;
- _httpClientFactory = httpClientFactory;
-
- Current = this;
- }
-
- ///
- public string Name => "TheAudioDB";
-
- ///
- // After music brainz
- public int Order => 1;
-
- ///
- public Task> GetSearchResults(AlbumInfo searchInfo, CancellationToken cancellationToken)
- => Task.FromResult(Enumerable.Empty());
-
- ///
- public async Task> GetMetadata(AlbumInfo info, CancellationToken cancellationToken)
- {
- var result = new MetadataResult();
- var id = info.GetReleaseGroupId();
-
- if (!string.IsNullOrWhiteSpace(id))
- {
- await EnsureInfo(id, cancellationToken).ConfigureAwait(false);
-
- var path = GetAlbumInfoPath(_config.ApplicationPaths, id);
-
- await using FileStream jsonStream = File.OpenRead(path);
- var obj = await JsonSerializer.DeserializeAsync(jsonStream, _jsonOptions, cancellationToken).ConfigureAwait(false);
-
- if (obj != null && obj.album != null && obj.album.Count > 0)
- {
- result.Item = new MusicAlbum();
- result.HasMetadata = true;
- ProcessResult(result.Item, obj.album[0], info.MetadataLanguage);
- }
- }
-
- return result;
- }
-
- private void ProcessResult(MusicAlbum item, Album result, string preferredLanguage)
- {
- if (Plugin.Instance.Configuration.ReplaceAlbumName && !string.IsNullOrWhiteSpace(result.strAlbum))
- {
- item.Album = result.strAlbum;
- }
-
- if (!string.IsNullOrWhiteSpace(result.strArtist))
- {
- item.AlbumArtists = new string[] { result.strArtist };
- }
-
- if (!string.IsNullOrEmpty(result.intYearReleased))
- {
- item.ProductionYear = int.Parse(result.intYearReleased, CultureInfo.InvariantCulture);
- }
-
- if (!string.IsNullOrEmpty(result.strGenre))
- {
- item.Genres = new[] { result.strGenre };
- }
-
- item.SetProviderId(MetadataProvider.AudioDbArtist, result.idArtist);
- item.SetProviderId(MetadataProvider.AudioDbAlbum, result.idAlbum);
-
- item.SetProviderId(MetadataProvider.MusicBrainzAlbumArtist, result.strMusicBrainzArtistID);
- item.SetProviderId(MetadataProvider.MusicBrainzReleaseGroup, result.strMusicBrainzID);
-
- string overview = null;
-
- if (string.Equals(preferredLanguage, "de", StringComparison.OrdinalIgnoreCase))
- {
- overview = result.strDescriptionDE;
- }
- else if (string.Equals(preferredLanguage, "fr", StringComparison.OrdinalIgnoreCase))
- {
- overview = result.strDescriptionFR;
- }
- else if (string.Equals(preferredLanguage, "nl", StringComparison.OrdinalIgnoreCase))
- {
- overview = result.strDescriptionNL;
- }
- else if (string.Equals(preferredLanguage, "ru", StringComparison.OrdinalIgnoreCase))
- {
- overview = result.strDescriptionRU;
- }
- else if (string.Equals(preferredLanguage, "it", StringComparison.OrdinalIgnoreCase))
- {
- overview = result.strDescriptionIT;
- }
- else if ((preferredLanguage ?? string.Empty).StartsWith("pt", StringComparison.OrdinalIgnoreCase))
- {
- overview = result.strDescriptionPT;
- }
-
- if (string.IsNullOrWhiteSpace(overview))
- {
- overview = result.strDescriptionEN;
- }
-
- item.Overview = (overview ?? string.Empty).StripHtml();
- }
-
- internal Task EnsureInfo(string musicBrainzReleaseGroupId, CancellationToken cancellationToken)
- {
- var xmlPath = GetAlbumInfoPath(_config.ApplicationPaths, musicBrainzReleaseGroupId);
-
- var fileInfo = _fileSystem.GetFileSystemInfo(xmlPath);
-
- if (fileInfo.Exists)
- {
- if ((DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays <= 2)
- {
- return Task.CompletedTask;
- }
- }
-
- return DownloadInfo(musicBrainzReleaseGroupId, cancellationToken);
- }
-
- internal async Task DownloadInfo(string musicBrainzReleaseGroupId, CancellationToken cancellationToken)
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- var url = AudioDbArtistProvider.BaseUrl + "/album-mb.php?i=" + musicBrainzReleaseGroupId;
-
- var path = GetAlbumInfoPath(_config.ApplicationPaths, musicBrainzReleaseGroupId);
-
- Directory.CreateDirectory(Path.GetDirectoryName(path));
-
- using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false);
- await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
- // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
- await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, true);
- await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false);
- }
-
- private static string GetAlbumDataPath(IApplicationPaths appPaths, string musicBrainzReleaseGroupId)
- {
- var dataPath = Path.Combine(GetAlbumDataPath(appPaths), musicBrainzReleaseGroupId);
-
- return dataPath;
- }
-
- private static string GetAlbumDataPath(IApplicationPaths appPaths)
- {
- var dataPath = Path.Combine(appPaths.CachePath, "audiodb-album");
-
- return dataPath;
- }
-
- internal static string GetAlbumInfoPath(IApplicationPaths appPaths, string musicBrainzReleaseGroupId)
- {
- var dataPath = GetAlbumDataPath(appPaths, musicBrainzReleaseGroupId);
-
- return Path.Combine(dataPath, "album.json");
- }
-
- public class Album
- {
- public string idAlbum { get; set; }
-
- public string idArtist { get; set; }
-
- public string strAlbum { get; set; }
-
- public string strArtist { get; set; }
-
- public string intYearReleased { get; set; }
-
- public string strGenre { get; set; }
-
- public string strSubGenre { get; set; }
-
- public string strReleaseFormat { get; set; }
-
- public string intSales { get; set; }
-
- public string strAlbumThumb { get; set; }
-
- public string strAlbumCDart { get; set; }
-
- public string strDescriptionEN { get; set; }
-
- public string strDescriptionDE { get; set; }
-
- public string strDescriptionFR { get; set; }
-
- public string strDescriptionCN { get; set; }
-
- public string strDescriptionIT { get; set; }
-
- public string strDescriptionJP { get; set; }
-
- public string strDescriptionRU { get; set; }
-
- public string strDescriptionES { get; set; }
-
- public string strDescriptionPT { get; set; }
-
- public string strDescriptionSE { get; set; }
-
- public string strDescriptionNL { get; set; }
-
- public string strDescriptionHU { get; set; }
-
- public string strDescriptionNO { get; set; }
-
- public string strDescriptionIL { get; set; }
-
- public string strDescriptionPL { get; set; }
-
- public object intLoved { get; set; }
-
- public object intScore { get; set; }
-
- public string strReview { get; set; }
-
- public object strMood { get; set; }
-
- public object strTheme { get; set; }
-
- public object strSpeed { get; set; }
-
- public object strLocation { get; set; }
-
- public string strMusicBrainzID { get; set; }
-
- public string strMusicBrainzArtistID { get; set; }
-
- public object strItunesID { get; set; }
-
- public object strAmazonID { get; set; }
-
- public string strLocked { get; set; }
- }
-
- public class RootObject
- {
- public List album { get; set; }
- }
-
- ///
- public Task GetImageResponse(string url, CancellationToken cancellationToken)
- {
- throw new NotImplementedException();
- }
- }
-}
diff --git a/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs
deleted file mode 100644
index aa61a56f6..000000000
--- a/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs
+++ /dev/null
@@ -1,151 +0,0 @@
-#pragma warning disable CS1591
-
-using System.Collections.Generic;
-using System.IO;
-using System.Net.Http;
-using System.Text.Json;
-using System.Threading;
-using System.Threading.Tasks;
-using Jellyfin.Extensions.Json;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Providers;
-
-namespace MediaBrowser.Providers.Plugins.AudioDb
-{
- public class AudioDbArtistImageProvider : IRemoteImageProvider, IHasOrder
- {
- private readonly IServerConfigurationManager _config;
- private readonly IHttpClientFactory _httpClientFactory;
- private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options;
-
- public AudioDbArtistImageProvider(IServerConfigurationManager config, IHttpClientFactory httpClientFactory)
- {
- _config = config;
- _httpClientFactory = httpClientFactory;
- }
-
- ///
- public string Name => "TheAudioDB";
-
- ///
- // After fanart
- public int Order => 1;
-
- ///
- public IEnumerable GetSupportedImages(BaseItem item)
- {
- return new List
- {
- ImageType.Primary,
- ImageType.Logo,
- ImageType.Banner,
- ImageType.Backdrop
- };
- }
-
- ///
- public async Task> GetImages(BaseItem item, CancellationToken cancellationToken)
- {
- var id = item.GetProviderId(MetadataProvider.MusicBrainzArtist);
-
- if (!string.IsNullOrWhiteSpace(id))
- {
- await AudioDbArtistProvider.Current.EnsureArtistInfo(id, cancellationToken).ConfigureAwait(false);
-
- var path = AudioDbArtistProvider.GetArtistInfoPath(_config.ApplicationPaths, id);
-
- await using FileStream jsonStream = File.OpenRead(path);
- var obj = await JsonSerializer.DeserializeAsync(jsonStream, _jsonOptions, cancellationToken).ConfigureAwait(false);
-
- if (obj != null && obj.artists != null && obj.artists.Count > 0)
- {
- return GetImages(obj.artists[0]);
- }
- }
-
- return new List();
- }
-
- private IEnumerable GetImages(AudioDbArtistProvider.Artist item)
- {
- var list = new List();
-
- if (!string.IsNullOrWhiteSpace(item.strArtistThumb))
- {
- list.Add(new RemoteImageInfo
- {
- ProviderName = Name,
- Url = item.strArtistThumb,
- Type = ImageType.Primary
- });
- }
-
- if (!string.IsNullOrWhiteSpace(item.strArtistLogo))
- {
- list.Add(new RemoteImageInfo
- {
- ProviderName = Name,
- Url = item.strArtistLogo,
- Type = ImageType.Logo
- });
- }
-
- if (!string.IsNullOrWhiteSpace(item.strArtistBanner))
- {
- list.Add(new RemoteImageInfo
- {
- ProviderName = Name,
- Url = item.strArtistBanner,
- Type = ImageType.Banner
- });
- }
-
- if (!string.IsNullOrWhiteSpace(item.strArtistFanart))
- {
- list.Add(new RemoteImageInfo
- {
- ProviderName = Name,
- Url = item.strArtistFanart,
- Type = ImageType.Backdrop
- });
- }
-
- if (!string.IsNullOrWhiteSpace(item.strArtistFanart2))
- {
- list.Add(new RemoteImageInfo
- {
- ProviderName = Name,
- Url = item.strArtistFanart2,
- Type = ImageType.Backdrop
- });
- }
-
- if (!string.IsNullOrWhiteSpace(item.strArtistFanart3))
- {
- list.Add(new RemoteImageInfo
- {
- ProviderName = Name,
- Url = item.strArtistFanart3,
- Type = ImageType.Backdrop
- });
- }
-
- return list;
- }
-
- public Task GetImageResponse(string url, CancellationToken cancellationToken)
- {
- var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
- return httpClient.GetAsync(url, cancellationToken);
- }
-
- ///
- public bool Supports(BaseItem item)
- => item is MusicArtist;
- }
-}
diff --git a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs
deleted file mode 100644
index b2f05d76d..000000000
--- a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs
+++ /dev/null
@@ -1,282 +0,0 @@
-#pragma warning disable CS1591
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Net.Http;
-using System.Text.Json;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.Extensions;
-using Jellyfin.Extensions.Json;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Providers;
-using MediaBrowser.Providers.Music;
-
-namespace MediaBrowser.Providers.Plugins.AudioDb
-{
- public class AudioDbArtistProvider : IRemoteMetadataProvider, IHasOrder
- {
- private const string ApiKey = "195003";
- public const string BaseUrl = "https://www.theaudiodb.com/api/v1/json/" + ApiKey;
-
- private readonly IServerConfigurationManager _config;
- private readonly IFileSystem _fileSystem;
- private readonly IHttpClientFactory _httpClientFactory;
- private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options;
-
- public AudioDbArtistProvider(IServerConfigurationManager config, IFileSystem fileSystem, IHttpClientFactory httpClientFactory)
- {
- _config = config;
- _fileSystem = fileSystem;
- _httpClientFactory = httpClientFactory;
- Current = this;
- }
-
- public static AudioDbArtistProvider Current { get; private set; }
-
- ///
- public string Name => "TheAudioDB";
-
- ///
- // After musicbrainz
- public int Order => 1;
-
- ///
- public Task> GetSearchResults(ArtistInfo searchInfo, CancellationToken cancellationToken)
- => Task.FromResult(Enumerable.Empty());
-
- ///
- public async Task> GetMetadata(ArtistInfo info, CancellationToken cancellationToken)
- {
- var result = new MetadataResult();
- var id = info.GetMusicBrainzArtistId();
-
- if (!string.IsNullOrWhiteSpace(id))
- {
- await EnsureArtistInfo(id, cancellationToken).ConfigureAwait(false);
-
- var path = GetArtistInfoPath(_config.ApplicationPaths, id);
-
- await using FileStream jsonStream = File.OpenRead(path);
- var obj = await JsonSerializer.DeserializeAsync(jsonStream, _jsonOptions, cancellationToken).ConfigureAwait(false);
-
- if (obj != null && obj.artists != null && obj.artists.Count > 0)
- {
- result.Item = new MusicArtist();
- result.HasMetadata = true;
- ProcessResult(result.Item, obj.artists[0], info.MetadataLanguage);
- }
- }
-
- return result;
- }
-
- private void ProcessResult(MusicArtist item, Artist result, string preferredLanguage)
- {
- // item.HomePageUrl = result.strWebsite;
-
- if (!string.IsNullOrEmpty(result.strGenre))
- {
- item.Genres = new[] { result.strGenre };
- }
-
- item.SetProviderId(MetadataProvider.AudioDbArtist, result.idArtist);
- item.SetProviderId(MetadataProvider.MusicBrainzArtist, result.strMusicBrainzID);
-
- string overview = null;
-
- if (string.Equals(preferredLanguage, "de", StringComparison.OrdinalIgnoreCase))
- {
- overview = result.strBiographyDE;
- }
- else if (string.Equals(preferredLanguage, "fr", StringComparison.OrdinalIgnoreCase))
- {
- overview = result.strBiographyFR;
- }
- else if (string.Equals(preferredLanguage, "nl", StringComparison.OrdinalIgnoreCase))
- {
- overview = result.strBiographyNL;
- }
- else if (string.Equals(preferredLanguage, "ru", StringComparison.OrdinalIgnoreCase))
- {
- overview = result.strBiographyRU;
- }
- else if (string.Equals(preferredLanguage, "it", StringComparison.OrdinalIgnoreCase))
- {
- overview = result.strBiographyIT;
- }
- else if ((preferredLanguage ?? string.Empty).StartsWith("pt", StringComparison.OrdinalIgnoreCase))
- {
- overview = result.strBiographyPT;
- }
-
- if (string.IsNullOrWhiteSpace(overview))
- {
- overview = result.strBiographyEN;
- }
-
- item.Overview = (overview ?? string.Empty).StripHtml();
- }
-
- internal Task EnsureArtistInfo(string musicBrainzId, CancellationToken cancellationToken)
- {
- var xmlPath = GetArtistInfoPath(_config.ApplicationPaths, musicBrainzId);
-
- var fileInfo = _fileSystem.GetFileSystemInfo(xmlPath);
-
- if (fileInfo.Exists
- && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays <= 2)
- {
- return Task.CompletedTask;
- }
-
- return DownloadArtistInfo(musicBrainzId, cancellationToken);
- }
-
- internal async Task DownloadArtistInfo(string musicBrainzId, CancellationToken cancellationToken)
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- var url = BaseUrl + "/artist-mb.php?i=" + musicBrainzId;
-
- var path = GetArtistInfoPath(_config.ApplicationPaths, musicBrainzId);
-
- using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false);
- await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
-
- Directory.CreateDirectory(Path.GetDirectoryName(path));
-
- // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
- await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, true);
- await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false);
- }
-
- ///
- /// Gets the artist data path.
- ///
- /// The application paths.
- /// The music brainz artist identifier.
- /// System.String.
- private static string GetArtistDataPath(IApplicationPaths appPaths, string musicBrainzArtistId)
- => Path.Combine(GetArtistDataPath(appPaths), musicBrainzArtistId);
-
- ///
- /// Gets the artist data path.
- ///
- /// The application paths.
- /// System.String.
- private static string GetArtistDataPath(IApplicationPaths appPaths)
- => Path.Combine(appPaths.CachePath, "audiodb-artist");
-
- internal static string GetArtistInfoPath(IApplicationPaths appPaths, string musicBrainzArtistId)
- {
- var dataPath = GetArtistDataPath(appPaths, musicBrainzArtistId);
-
- return Path.Combine(dataPath, "artist.json");
- }
-
- public class Artist
- {
- public string idArtist { get; set; }
-
- public string strArtist { get; set; }
-
- public string strArtistAlternate { get; set; }
-
- public object idLabel { get; set; }
-
- public string intFormedYear { get; set; }
-
- public string intBornYear { get; set; }
-
- public object intDiedYear { get; set; }
-
- public object strDisbanded { get; set; }
-
- public string strGenre { get; set; }
-
- public string strSubGenre { get; set; }
-
- public string strWebsite { get; set; }
-
- public string strFacebook { get; set; }
-
- public string strTwitter { get; set; }
-
- public string strBiographyEN { get; set; }
-
- public string strBiographyDE { get; set; }
-
- public string strBiographyFR { get; set; }
-
- public string strBiographyCN { get; set; }
-
- public string strBiographyIT { get; set; }
-
- public string strBiographyJP { get; set; }
-
- public string strBiographyRU { get; set; }
-
- public string strBiographyES { get; set; }
-
- public string strBiographyPT { get; set; }
-
- public string strBiographySE { get; set; }
-
- public string strBiographyNL { get; set; }
-
- public string strBiographyHU { get; set; }
-
- public string strBiographyNO { get; set; }
-
- public string strBiographyIL { get; set; }
-
- public string strBiographyPL { get; set; }
-
- public string strGender { get; set; }
-
- public string intMembers { get; set; }
-
- public string strCountry { get; set; }
-
- public string strCountryCode { get; set; }
-
- public string strArtistThumb { get; set; }
-
- public string strArtistLogo { get; set; }
-
- public string strArtistFanart { get; set; }
-
- public string strArtistFanart2 { get; set; }
-
- public string strArtistFanart3 { get; set; }
-
- public string strArtistBanner { get; set; }
-
- public string strMusicBrainzID { get; set; }
-
- public object strLastFMChart { get; set; }
-
- public string strLocked { get; set; }
- }
-
- public class RootObject
- {
- public List artists { get; set; }
- }
-
- ///
- public Task GetImageResponse(string url, CancellationToken cancellationToken)
- {
- throw new NotImplementedException();
- }
- }
-}
diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumImageProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumImageProvider.cs
new file mode 100644
index 000000000..36d8eeb40
--- /dev/null
+++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumImageProvider.cs
@@ -0,0 +1,110 @@
+#pragma warning disable CS1591
+
+using System.Collections.Generic;
+using System.IO;
+using System.Net.Http;
+using System.Text.Json;
+using System.Threading;
+using System.Threading.Tasks;
+using Jellyfin.Extensions.Json;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+
+namespace MediaBrowser.Providers.Plugins.AudioDb
+{
+ public class AudioDbAlbumImageProvider : IRemoteImageProvider, IHasOrder
+ {
+ private readonly IServerConfigurationManager _config;
+ private readonly IHttpClientFactory _httpClientFactory;
+ private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options;
+
+ public AudioDbAlbumImageProvider(IServerConfigurationManager config, IHttpClientFactory httpClientFactory)
+ {
+ _config = config;
+ _httpClientFactory = httpClientFactory;
+ }
+
+ ///
+ public string Name => "TheAudioDB";
+
+ ///
+ // After embedded and fanart
+ public int Order => 2;
+
+ ///
+ public IEnumerable GetSupportedImages(BaseItem item)
+ {
+ return new List
+ {
+ ImageType.Primary,
+ ImageType.Disc
+ };
+ }
+
+ ///
+ public async Task> GetImages(BaseItem item, CancellationToken cancellationToken)
+ {
+ var id = item.GetProviderId(MetadataProvider.MusicBrainzReleaseGroup);
+
+ if (!string.IsNullOrWhiteSpace(id))
+ {
+ await AudioDbAlbumProvider.Current.EnsureInfo(id, cancellationToken).ConfigureAwait(false);
+
+ var path = AudioDbAlbumProvider.GetAlbumInfoPath(_config.ApplicationPaths, id);
+
+ await using FileStream jsonStream = File.OpenRead(path);
+ var obj = await JsonSerializer.DeserializeAsync(jsonStream, _jsonOptions, cancellationToken).ConfigureAwait(false);
+
+ if (obj != null && obj.album != null && obj.album.Count > 0)
+ {
+ return GetImages(obj.album[0]);
+ }
+ }
+
+ return new List();
+ }
+
+ private IEnumerable GetImages(AudioDbAlbumProvider.Album item)
+ {
+ var list = new List();
+
+ if (!string.IsNullOrWhiteSpace(item.strAlbumThumb))
+ {
+ list.Add(new RemoteImageInfo
+ {
+ ProviderName = Name,
+ Url = item.strAlbumThumb,
+ Type = ImageType.Primary
+ });
+ }
+
+ if (!string.IsNullOrWhiteSpace(item.strAlbumCDart))
+ {
+ list.Add(new RemoteImageInfo
+ {
+ ProviderName = Name,
+ Url = item.strAlbumCDart,
+ Type = ImageType.Disc
+ });
+ }
+
+ return list;
+ }
+
+ ///
+ public Task GetImageResponse(string url, CancellationToken cancellationToken)
+ {
+ var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
+ return httpClient.GetAsync(url, cancellationToken);
+ }
+
+ ///
+ public bool Supports(BaseItem item)
+ => item is MusicAlbum;
+ }
+}
diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs
new file mode 100644
index 000000000..ccf9501be
--- /dev/null
+++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs
@@ -0,0 +1,291 @@
+#pragma warning disable CS1591, SA1300
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Net.Http;
+using System.Text.Json;
+using System.Threading;
+using System.Threading.Tasks;
+using Jellyfin.Extensions.Json;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Providers;
+using MediaBrowser.Providers.Music;
+
+namespace MediaBrowser.Providers.Plugins.AudioDb
+{
+ public class AudioDbAlbumProvider : IRemoteMetadataProvider, IHasOrder
+ {
+ private readonly IServerConfigurationManager _config;
+ private readonly IFileSystem _fileSystem;
+ private readonly IHttpClientFactory _httpClientFactory;
+ private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options;
+
+#pragma warning disable SA1401
+ public static AudioDbAlbumProvider Current;
+#pragma warning restore SA1401
+
+ public AudioDbAlbumProvider(IServerConfigurationManager config, IFileSystem fileSystem, IHttpClientFactory httpClientFactory)
+ {
+ _config = config;
+ _fileSystem = fileSystem;
+ _httpClientFactory = httpClientFactory;
+
+ Current = this;
+ }
+
+ ///
+ public string Name => "TheAudioDB";
+
+ ///
+ // After music brainz
+ public int Order => 1;
+
+ ///
+ public Task> GetSearchResults(AlbumInfo searchInfo, CancellationToken cancellationToken)
+ => Task.FromResult(Enumerable.Empty());
+
+ ///
+ public async Task> GetMetadata(AlbumInfo info, CancellationToken cancellationToken)
+ {
+ var result = new MetadataResult();
+ var id = info.GetReleaseGroupId();
+
+ if (!string.IsNullOrWhiteSpace(id))
+ {
+ await EnsureInfo(id, cancellationToken).ConfigureAwait(false);
+
+ var path = GetAlbumInfoPath(_config.ApplicationPaths, id);
+
+ await using FileStream jsonStream = File.OpenRead(path);
+ var obj = await JsonSerializer.DeserializeAsync(jsonStream, _jsonOptions, cancellationToken).ConfigureAwait(false);
+
+ if (obj != null && obj.album != null && obj.album.Count > 0)
+ {
+ result.Item = new MusicAlbum();
+ result.HasMetadata = true;
+ ProcessResult(result.Item, obj.album[0], info.MetadataLanguage);
+ }
+ }
+
+ return result;
+ }
+
+ private void ProcessResult(MusicAlbum item, Album result, string preferredLanguage)
+ {
+ if (Plugin.Instance.Configuration.ReplaceAlbumName && !string.IsNullOrWhiteSpace(result.strAlbum))
+ {
+ item.Album = result.strAlbum;
+ }
+
+ if (!string.IsNullOrWhiteSpace(result.strArtist))
+ {
+ item.AlbumArtists = new string[] { result.strArtist };
+ }
+
+ if (!string.IsNullOrEmpty(result.intYearReleased))
+ {
+ item.ProductionYear = int.Parse(result.intYearReleased, CultureInfo.InvariantCulture);
+ }
+
+ if (!string.IsNullOrEmpty(result.strGenre))
+ {
+ item.Genres = new[] { result.strGenre };
+ }
+
+ item.SetProviderId(MetadataProvider.AudioDbArtist, result.idArtist);
+ item.SetProviderId(MetadataProvider.AudioDbAlbum, result.idAlbum);
+
+ item.SetProviderId(MetadataProvider.MusicBrainzAlbumArtist, result.strMusicBrainzArtistID);
+ item.SetProviderId(MetadataProvider.MusicBrainzReleaseGroup, result.strMusicBrainzID);
+
+ string overview = null;
+
+ if (string.Equals(preferredLanguage, "de", StringComparison.OrdinalIgnoreCase))
+ {
+ overview = result.strDescriptionDE;
+ }
+ else if (string.Equals(preferredLanguage, "fr", StringComparison.OrdinalIgnoreCase))
+ {
+ overview = result.strDescriptionFR;
+ }
+ else if (string.Equals(preferredLanguage, "nl", StringComparison.OrdinalIgnoreCase))
+ {
+ overview = result.strDescriptionNL;
+ }
+ else if (string.Equals(preferredLanguage, "ru", StringComparison.OrdinalIgnoreCase))
+ {
+ overview = result.strDescriptionRU;
+ }
+ else if (string.Equals(preferredLanguage, "it", StringComparison.OrdinalIgnoreCase))
+ {
+ overview = result.strDescriptionIT;
+ }
+ else if ((preferredLanguage ?? string.Empty).StartsWith("pt", StringComparison.OrdinalIgnoreCase))
+ {
+ overview = result.strDescriptionPT;
+ }
+
+ if (string.IsNullOrWhiteSpace(overview))
+ {
+ overview = result.strDescriptionEN;
+ }
+
+ item.Overview = (overview ?? string.Empty).StripHtml();
+ }
+
+ internal Task EnsureInfo(string musicBrainzReleaseGroupId, CancellationToken cancellationToken)
+ {
+ var xmlPath = GetAlbumInfoPath(_config.ApplicationPaths, musicBrainzReleaseGroupId);
+
+ var fileInfo = _fileSystem.GetFileSystemInfo(xmlPath);
+
+ if (fileInfo.Exists)
+ {
+ if ((DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays <= 2)
+ {
+ return Task.CompletedTask;
+ }
+ }
+
+ return DownloadInfo(musicBrainzReleaseGroupId, cancellationToken);
+ }
+
+ internal async Task DownloadInfo(string musicBrainzReleaseGroupId, CancellationToken cancellationToken)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ var url = AudioDbArtistProvider.BaseUrl + "/album-mb.php?i=" + musicBrainzReleaseGroupId;
+
+ var path = GetAlbumInfoPath(_config.ApplicationPaths, musicBrainzReleaseGroupId);
+
+ Directory.CreateDirectory(Path.GetDirectoryName(path));
+
+ using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false);
+ await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
+ // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
+ await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, true);
+ await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false);
+ }
+
+ private static string GetAlbumDataPath(IApplicationPaths appPaths, string musicBrainzReleaseGroupId)
+ {
+ var dataPath = Path.Combine(GetAlbumDataPath(appPaths), musicBrainzReleaseGroupId);
+
+ return dataPath;
+ }
+
+ private static string GetAlbumDataPath(IApplicationPaths appPaths)
+ {
+ var dataPath = Path.Combine(appPaths.CachePath, "audiodb-album");
+
+ return dataPath;
+ }
+
+ internal static string GetAlbumInfoPath(IApplicationPaths appPaths, string musicBrainzReleaseGroupId)
+ {
+ var dataPath = GetAlbumDataPath(appPaths, musicBrainzReleaseGroupId);
+
+ return Path.Combine(dataPath, "album.json");
+ }
+
+ ///
+ public Task GetImageResponse(string url, CancellationToken cancellationToken)
+ {
+ throw new NotImplementedException();
+ }
+
+ public class Album
+ {
+ public string idAlbum { get; set; }
+
+ public string idArtist { get; set; }
+
+ public string strAlbum { get; set; }
+
+ public string strArtist { get; set; }
+
+ public string intYearReleased { get; set; }
+
+ public string strGenre { get; set; }
+
+ public string strSubGenre { get; set; }
+
+ public string strReleaseFormat { get; set; }
+
+ public string intSales { get; set; }
+
+ public string strAlbumThumb { get; set; }
+
+ public string strAlbumCDart { get; set; }
+
+ public string strDescriptionEN { get; set; }
+
+ public string strDescriptionDE { get; set; }
+
+ public string strDescriptionFR { get; set; }
+
+ public string strDescriptionCN { get; set; }
+
+ public string strDescriptionIT { get; set; }
+
+ public string strDescriptionJP { get; set; }
+
+ public string strDescriptionRU { get; set; }
+
+ public string strDescriptionES { get; set; }
+
+ public string strDescriptionPT { get; set; }
+
+ public string strDescriptionSE { get; set; }
+
+ public string strDescriptionNL { get; set; }
+
+ public string strDescriptionHU { get; set; }
+
+ public string strDescriptionNO { get; set; }
+
+ public string strDescriptionIL { get; set; }
+
+ public string strDescriptionPL { get; set; }
+
+ public object intLoved { get; set; }
+
+ public object intScore { get; set; }
+
+ public string strReview { get; set; }
+
+ public object strMood { get; set; }
+
+ public object strTheme { get; set; }
+
+ public object strSpeed { get; set; }
+
+ public object strLocation { get; set; }
+
+ public string strMusicBrainzID { get; set; }
+
+ public string strMusicBrainzArtistID { get; set; }
+
+ public object strItunesID { get; set; }
+
+ public object strAmazonID { get; set; }
+
+ public string strLocked { get; set; }
+ }
+
+ public class RootObject
+ {
+ public List album { get; set; }
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistImageProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistImageProvider.cs
new file mode 100644
index 000000000..aa61a56f6
--- /dev/null
+++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistImageProvider.cs
@@ -0,0 +1,151 @@
+#pragma warning disable CS1591
+
+using System.Collections.Generic;
+using System.IO;
+using System.Net.Http;
+using System.Text.Json;
+using System.Threading;
+using System.Threading.Tasks;
+using Jellyfin.Extensions.Json;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+
+namespace MediaBrowser.Providers.Plugins.AudioDb
+{
+ public class AudioDbArtistImageProvider : IRemoteImageProvider, IHasOrder
+ {
+ private readonly IServerConfigurationManager _config;
+ private readonly IHttpClientFactory _httpClientFactory;
+ private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options;
+
+ public AudioDbArtistImageProvider(IServerConfigurationManager config, IHttpClientFactory httpClientFactory)
+ {
+ _config = config;
+ _httpClientFactory = httpClientFactory;
+ }
+
+ ///
+ public string Name => "TheAudioDB";
+
+ ///
+ // After fanart
+ public int Order => 1;
+
+ ///
+ public IEnumerable GetSupportedImages(BaseItem item)
+ {
+ return new List
+ {
+ ImageType.Primary,
+ ImageType.Logo,
+ ImageType.Banner,
+ ImageType.Backdrop
+ };
+ }
+
+ ///
+ public async Task> GetImages(BaseItem item, CancellationToken cancellationToken)
+ {
+ var id = item.GetProviderId(MetadataProvider.MusicBrainzArtist);
+
+ if (!string.IsNullOrWhiteSpace(id))
+ {
+ await AudioDbArtistProvider.Current.EnsureArtistInfo(id, cancellationToken).ConfigureAwait(false);
+
+ var path = AudioDbArtistProvider.GetArtistInfoPath(_config.ApplicationPaths, id);
+
+ await using FileStream jsonStream = File.OpenRead(path);
+ var obj = await JsonSerializer.DeserializeAsync(jsonStream, _jsonOptions, cancellationToken).ConfigureAwait(false);
+
+ if (obj != null && obj.artists != null && obj.artists.Count > 0)
+ {
+ return GetImages(obj.artists[0]);
+ }
+ }
+
+ return new List();
+ }
+
+ private IEnumerable GetImages(AudioDbArtistProvider.Artist item)
+ {
+ var list = new List();
+
+ if (!string.IsNullOrWhiteSpace(item.strArtistThumb))
+ {
+ list.Add(new RemoteImageInfo
+ {
+ ProviderName = Name,
+ Url = item.strArtistThumb,
+ Type = ImageType.Primary
+ });
+ }
+
+ if (!string.IsNullOrWhiteSpace(item.strArtistLogo))
+ {
+ list.Add(new RemoteImageInfo
+ {
+ ProviderName = Name,
+ Url = item.strArtistLogo,
+ Type = ImageType.Logo
+ });
+ }
+
+ if (!string.IsNullOrWhiteSpace(item.strArtistBanner))
+ {
+ list.Add(new RemoteImageInfo
+ {
+ ProviderName = Name,
+ Url = item.strArtistBanner,
+ Type = ImageType.Banner
+ });
+ }
+
+ if (!string.IsNullOrWhiteSpace(item.strArtistFanart))
+ {
+ list.Add(new RemoteImageInfo
+ {
+ ProviderName = Name,
+ Url = item.strArtistFanart,
+ Type = ImageType.Backdrop
+ });
+ }
+
+ if (!string.IsNullOrWhiteSpace(item.strArtistFanart2))
+ {
+ list.Add(new RemoteImageInfo
+ {
+ ProviderName = Name,
+ Url = item.strArtistFanart2,
+ Type = ImageType.Backdrop
+ });
+ }
+
+ if (!string.IsNullOrWhiteSpace(item.strArtistFanart3))
+ {
+ list.Add(new RemoteImageInfo
+ {
+ ProviderName = Name,
+ Url = item.strArtistFanart3,
+ Type = ImageType.Backdrop
+ });
+ }
+
+ return list;
+ }
+
+ public Task GetImageResponse(string url, CancellationToken cancellationToken)
+ {
+ var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
+ return httpClient.GetAsync(url, cancellationToken);
+ }
+
+ ///
+ public bool Supports(BaseItem item)
+ => item is MusicArtist;
+ }
+}
diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs
new file mode 100644
index 000000000..c11e7a7ff
--- /dev/null
+++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs
@@ -0,0 +1,282 @@
+#pragma warning disable CS1591, SA1300
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net.Http;
+using System.Text.Json;
+using System.Threading;
+using System.Threading.Tasks;
+using Jellyfin.Extensions.Json;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Providers;
+using MediaBrowser.Providers.Music;
+
+namespace MediaBrowser.Providers.Plugins.AudioDb
+{
+ public class AudioDbArtistProvider : IRemoteMetadataProvider, IHasOrder
+ {
+ private const string ApiKey = "195003";
+ public const string BaseUrl = "https://www.theaudiodb.com/api/v1/json/" + ApiKey;
+
+ private readonly IServerConfigurationManager _config;
+ private readonly IFileSystem _fileSystem;
+ private readonly IHttpClientFactory _httpClientFactory;
+ private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options;
+
+ public AudioDbArtistProvider(IServerConfigurationManager config, IFileSystem fileSystem, IHttpClientFactory httpClientFactory)
+ {
+ _config = config;
+ _fileSystem = fileSystem;
+ _httpClientFactory = httpClientFactory;
+ Current = this;
+ }
+
+ public static AudioDbArtistProvider Current { get; private set; }
+
+ ///
+ public string Name => "TheAudioDB";
+
+ ///
+ // After musicbrainz
+ public int Order => 1;
+
+ ///
+ public Task> GetSearchResults(ArtistInfo searchInfo, CancellationToken cancellationToken)
+ => Task.FromResult(Enumerable.Empty());
+
+ ///
+ public async Task> GetMetadata(ArtistInfo info, CancellationToken cancellationToken)
+ {
+ var result = new MetadataResult();
+ var id = info.GetMusicBrainzArtistId();
+
+ if (!string.IsNullOrWhiteSpace(id))
+ {
+ await EnsureArtistInfo(id, cancellationToken).ConfigureAwait(false);
+
+ var path = GetArtistInfoPath(_config.ApplicationPaths, id);
+
+ await using FileStream jsonStream = File.OpenRead(path);
+ var obj = await JsonSerializer.DeserializeAsync(jsonStream, _jsonOptions, cancellationToken).ConfigureAwait(false);
+
+ if (obj != null && obj.artists != null && obj.artists.Count > 0)
+ {
+ result.Item = new MusicArtist();
+ result.HasMetadata = true;
+ ProcessResult(result.Item, obj.artists[0], info.MetadataLanguage);
+ }
+ }
+
+ return result;
+ }
+
+ private void ProcessResult(MusicArtist item, Artist result, string preferredLanguage)
+ {
+ // item.HomePageUrl = result.strWebsite;
+
+ if (!string.IsNullOrEmpty(result.strGenre))
+ {
+ item.Genres = new[] { result.strGenre };
+ }
+
+ item.SetProviderId(MetadataProvider.AudioDbArtist, result.idArtist);
+ item.SetProviderId(MetadataProvider.MusicBrainzArtist, result.strMusicBrainzID);
+
+ string overview = null;
+
+ if (string.Equals(preferredLanguage, "de", StringComparison.OrdinalIgnoreCase))
+ {
+ overview = result.strBiographyDE;
+ }
+ else if (string.Equals(preferredLanguage, "fr", StringComparison.OrdinalIgnoreCase))
+ {
+ overview = result.strBiographyFR;
+ }
+ else if (string.Equals(preferredLanguage, "nl", StringComparison.OrdinalIgnoreCase))
+ {
+ overview = result.strBiographyNL;
+ }
+ else if (string.Equals(preferredLanguage, "ru", StringComparison.OrdinalIgnoreCase))
+ {
+ overview = result.strBiographyRU;
+ }
+ else if (string.Equals(preferredLanguage, "it", StringComparison.OrdinalIgnoreCase))
+ {
+ overview = result.strBiographyIT;
+ }
+ else if ((preferredLanguage ?? string.Empty).StartsWith("pt", StringComparison.OrdinalIgnoreCase))
+ {
+ overview = result.strBiographyPT;
+ }
+
+ if (string.IsNullOrWhiteSpace(overview))
+ {
+ overview = result.strBiographyEN;
+ }
+
+ item.Overview = (overview ?? string.Empty).StripHtml();
+ }
+
+ internal Task EnsureArtistInfo(string musicBrainzId, CancellationToken cancellationToken)
+ {
+ var xmlPath = GetArtistInfoPath(_config.ApplicationPaths, musicBrainzId);
+
+ var fileInfo = _fileSystem.GetFileSystemInfo(xmlPath);
+
+ if (fileInfo.Exists
+ && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays <= 2)
+ {
+ return Task.CompletedTask;
+ }
+
+ return DownloadArtistInfo(musicBrainzId, cancellationToken);
+ }
+
+ internal async Task DownloadArtistInfo(string musicBrainzId, CancellationToken cancellationToken)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ var url = BaseUrl + "/artist-mb.php?i=" + musicBrainzId;
+
+ var path = GetArtistInfoPath(_config.ApplicationPaths, musicBrainzId);
+
+ using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false);
+ await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
+
+ Directory.CreateDirectory(Path.GetDirectoryName(path));
+
+ // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
+ await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, true);
+ await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false);
+ }
+
+ ///
+ /// Gets the artist data path.
+ ///
+ /// The application paths.
+ /// The music brainz artist identifier.
+ /// System.String.
+ private static string GetArtistDataPath(IApplicationPaths appPaths, string musicBrainzArtistId)
+ => Path.Combine(GetArtistDataPath(appPaths), musicBrainzArtistId);
+
+ ///
+ /// Gets the artist data path.
+ ///
+ /// The application paths.
+ /// System.String.
+ private static string GetArtistDataPath(IApplicationPaths appPaths)
+ => Path.Combine(appPaths.CachePath, "audiodb-artist");
+
+ internal static string GetArtistInfoPath(IApplicationPaths appPaths, string musicBrainzArtistId)
+ {
+ var dataPath = GetArtistDataPath(appPaths, musicBrainzArtistId);
+
+ return Path.Combine(dataPath, "artist.json");
+ }
+
+ ///
+ public Task GetImageResponse(string url, CancellationToken cancellationToken)
+ {
+ throw new NotImplementedException();
+ }
+
+ public class Artist
+ {
+ public string idArtist { get; set; }
+
+ public string strArtist { get; set; }
+
+ public string strArtistAlternate { get; set; }
+
+ public object idLabel { get; set; }
+
+ public string intFormedYear { get; set; }
+
+ public string intBornYear { get; set; }
+
+ public object intDiedYear { get; set; }
+
+ public object strDisbanded { get; set; }
+
+ public string strGenre { get; set; }
+
+ public string strSubGenre { get; set; }
+
+ public string strWebsite { get; set; }
+
+ public string strFacebook { get; set; }
+
+ public string strTwitter { get; set; }
+
+ public string strBiographyEN { get; set; }
+
+ public string strBiographyDE { get; set; }
+
+ public string strBiographyFR { get; set; }
+
+ public string strBiographyCN { get; set; }
+
+ public string strBiographyIT { get; set; }
+
+ public string strBiographyJP { get; set; }
+
+ public string strBiographyRU { get; set; }
+
+ public string strBiographyES { get; set; }
+
+ public string strBiographyPT { get; set; }
+
+ public string strBiographySE { get; set; }
+
+ public string strBiographyNL { get; set; }
+
+ public string strBiographyHU { get; set; }
+
+ public string strBiographyNO { get; set; }
+
+ public string strBiographyIL { get; set; }
+
+ public string strBiographyPL { get; set; }
+
+ public string strGender { get; set; }
+
+ public string intMembers { get; set; }
+
+ public string strCountry { get; set; }
+
+ public string strCountryCode { get; set; }
+
+ public string strArtistThumb { get; set; }
+
+ public string strArtistLogo { get; set; }
+
+ public string strArtistFanart { get; set; }
+
+ public string strArtistFanart2 { get; set; }
+
+ public string strArtistFanart3 { get; set; }
+
+ public string strArtistBanner { get; set; }
+
+ public string strMusicBrainzID { get; set; }
+
+ public object strLastFMChart { get; set; }
+
+ public string strLocked { get; set; }
+ }
+
+ public class RootObject
+ {
+ public List artists { get; set; }
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs
deleted file mode 100644
index 7a9379af7..000000000
--- a/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs
+++ /dev/null
@@ -1,272 +0,0 @@
-#pragma warning disable CS1591
-
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Net.Http;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Xml;
-using Diacritics.Extensions;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Providers;
-using MediaBrowser.Providers.Plugins.MusicBrainz;
-
-namespace MediaBrowser.Providers.Music
-{
- public class MusicBrainzArtistProvider : IRemoteMetadataProvider
- {
- ///
- public async Task> GetSearchResults(ArtistInfo searchInfo, CancellationToken cancellationToken)
- {
- var musicBrainzId = searchInfo.GetMusicBrainzArtistId();
-
- if (!string.IsNullOrWhiteSpace(musicBrainzId))
- {
- var url = "/ws/2/artist/?query=arid:{0}" + musicBrainzId.ToString(CultureInfo.InvariantCulture);
-
- using var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
- await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
- return GetResultsFromResponse(stream);
- }
- else
- {
- // They seem to throw bad request failures on any term with a slash
- var nameToSearch = searchInfo.Name.Replace('/', ' ');
-
- var url = string.Format(CultureInfo.InvariantCulture, "/ws/2/artist/?query=\"{0}\"&dismax=true", UrlEncode(nameToSearch));
-
- using (var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false))
- await using (var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false))
- {
- var results = GetResultsFromResponse(stream).ToList();
-
- if (results.Count > 0)
- {
- return results;
- }
- }
-
- if (searchInfo.Name.HasDiacritics())
- {
- // Try again using the search with accent characters url
- url = string.Format(CultureInfo.InvariantCulture, "/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch));
-
- using var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
- await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
- return GetResultsFromResponse(stream);
- }
- }
-
- return Enumerable.Empty();
- }
-
- private IEnumerable GetResultsFromResponse(Stream stream)
- {
- using var oReader = new StreamReader(stream, Encoding.UTF8);
- var settings = new XmlReaderSettings()
- {
- ValidationType = ValidationType.None,
- CheckCharacters = false,
- IgnoreProcessingInstructions = true,
- IgnoreComments = true
- };
-
- using var reader = XmlReader.Create(oReader, settings);
- reader.MoveToContent();
- reader.Read();
-
- // Loop through each element
- while (!reader.EOF && reader.ReadState == ReadState.Interactive)
- {
- if (reader.NodeType == XmlNodeType.Element)
- {
- switch (reader.Name)
- {
- case "artist-list":
- {
- if (reader.IsEmptyElement)
- {
- reader.Read();
- continue;
- }
-
- using var subReader = reader.ReadSubtree();
- return ParseArtistList(subReader).ToList();
- }
-
- default:
- {
- reader.Skip();
- break;
- }
- }
- }
- else
- {
- reader.Read();
- }
- }
-
- return Enumerable.Empty();
- }
-
- private IEnumerable ParseArtistList(XmlReader reader)
- {
- reader.MoveToContent();
- reader.Read();
-
- // Loop through each element
- while (!reader.EOF && reader.ReadState == ReadState.Interactive)
- {
- if (reader.NodeType == XmlNodeType.Element)
- {
- switch (reader.Name)
- {
- case "artist":
- {
- if (reader.IsEmptyElement)
- {
- reader.Read();
- continue;
- }
-
- var mbzId = reader.GetAttribute("id");
-
- using var subReader = reader.ReadSubtree();
- var artist = ParseArtist(subReader, mbzId);
- if (artist != null)
- {
- yield return artist;
- }
-
- break;
- }
-
- default:
- {
- reader.Skip();
- break;
- }
- }
- }
- else
- {
- reader.Read();
- }
- }
- }
-
- private RemoteSearchResult ParseArtist(XmlReader reader, string artistId)
- {
- var result = new RemoteSearchResult();
-
- reader.MoveToContent();
- reader.Read();
-
- // http://stackoverflow.com/questions/2299632/why-does-xmlreader-skip-every-other-element-if-there-is-no-whitespace-separator
-
- // Loop through each element
- while (!reader.EOF && reader.ReadState == ReadState.Interactive)
- {
- if (reader.NodeType == XmlNodeType.Element)
- {
- switch (reader.Name)
- {
- case "name":
- {
- result.Name = reader.ReadElementContentAsString();
- break;
- }
-
- case "annotation":
- {
- result.Overview = reader.ReadElementContentAsString();
- break;
- }
-
- default:
- {
- // there is sort-name if ever needed
- reader.Skip();
- break;
- }
- }
- }
- else
- {
- reader.Read();
- }
- }
-
- result.SetProviderId(MetadataProvider.MusicBrainzArtist, artistId);
-
- if (string.IsNullOrWhiteSpace(artistId) || string.IsNullOrWhiteSpace(result.Name))
- {
- return null;
- }
-
- return result;
- }
-
- ///
- public async Task> GetMetadata(ArtistInfo info, CancellationToken cancellationToken)
- {
- var result = new MetadataResult
- {
- Item = new MusicArtist()
- };
-
- var musicBrainzId = info.GetMusicBrainzArtistId();
-
- if (string.IsNullOrWhiteSpace(musicBrainzId))
- {
- var searchResults = await GetSearchResults(info, cancellationToken).ConfigureAwait(false);
-
- var singleResult = searchResults.FirstOrDefault();
-
- if (singleResult != null)
- {
- musicBrainzId = singleResult.GetProviderId(MetadataProvider.MusicBrainzArtist);
- result.Item.Overview = singleResult.Overview;
-
- if (Plugin.Instance.Configuration.ReplaceArtistName)
- {
- result.Item.Name = singleResult.Name;
- }
- }
- }
-
- if (!string.IsNullOrWhiteSpace(musicBrainzId))
- {
- result.HasMetadata = true;
- result.Item.SetProviderId(MetadataProvider.MusicBrainzArtist, musicBrainzId);
- }
-
- return result;
- }
-
- ///
- /// Encodes an URL.
- ///
- /// The name.
- /// System.String.
- private static string UrlEncode(string name)
- {
- return WebUtility.UrlEncode(name);
- }
-
- public string Name => "MusicBrainz";
-
- public Task GetImageResponse(string url, CancellationToken cancellationToken)
- {
- throw new NotImplementedException();
- }
- }
-}
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/ExternalIds.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/ExternalIds.cs
deleted file mode 100644
index 5600c389c..000000000
--- a/MediaBrowser.Providers/Plugins/MusicBrainz/ExternalIds.cs
+++ /dev/null
@@ -1,119 +0,0 @@
-#pragma warning disable CS1591
-
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Providers;
-using MediaBrowser.Providers.Plugins.MusicBrainz;
-
-namespace MediaBrowser.Providers.Music
-{
- public class MusicBrainzReleaseGroupExternalId : IExternalId
- {
- ///
- public string ProviderName => "MusicBrainz";
-
- ///
- public string Key => MetadataProvider.MusicBrainzReleaseGroup.ToString();
-
- ///
- public ExternalIdMediaType? Type => ExternalIdMediaType.ReleaseGroup;
-
- ///
- public string UrlFormatString => Plugin.Instance.Configuration.Server + "/release-group/{0}";
-
- ///
- public bool Supports(IHasProviderIds item) => item is Audio || item is MusicAlbum;
- }
-
- public class MusicBrainzAlbumArtistExternalId : IExternalId
- {
- ///
- public string ProviderName => "MusicBrainz";
-
- ///
- public string Key => MetadataProvider.MusicBrainzAlbumArtist.ToString();
-
- ///
- public ExternalIdMediaType? Type => ExternalIdMediaType.AlbumArtist;
-
- ///
- public string UrlFormatString => Plugin.Instance.Configuration.Server + "/artist/{0}";
-
- ///
- public bool Supports(IHasProviderIds item) => item is Audio;
- }
-
- public class MusicBrainzAlbumExternalId : IExternalId
- {
- ///
- public string ProviderName => "MusicBrainz";
-
- ///
- public string Key => MetadataProvider.MusicBrainzAlbum.ToString();
-
- ///
- public ExternalIdMediaType? Type => ExternalIdMediaType.Album;
-
- ///
- public string UrlFormatString => Plugin.Instance.Configuration.Server + "/release/{0}";
-
- ///
- public bool Supports(IHasProviderIds item) => item is Audio || item is MusicAlbum;
- }
-
- public class MusicBrainzArtistExternalId : IExternalId
- {
- ///
- public string ProviderName => "MusicBrainz";
-
- ///
- public string Key => MetadataProvider.MusicBrainzArtist.ToString();
-
- ///
- public ExternalIdMediaType? Type => ExternalIdMediaType.Artist;
-
- ///
- public string UrlFormatString => Plugin.Instance.Configuration.Server + "/artist/{0}";
-
- ///
- public bool Supports(IHasProviderIds item) => item is MusicArtist;
- }
-
- public class MusicBrainzOtherArtistExternalId : IExternalId
- {
- ///
- public string ProviderName => "MusicBrainz";
-
- ///
-
- public string Key => MetadataProvider.MusicBrainzArtist.ToString();
-
- ///
- public ExternalIdMediaType? Type => ExternalIdMediaType.OtherArtist;
-
- ///
- public string UrlFormatString => Plugin.Instance.Configuration.Server + "/artist/{0}";
-
- ///
- public bool Supports(IHasProviderIds item) => item is Audio || item is MusicAlbum;
- }
-
- public class MusicBrainzTrackId : IExternalId
- {
- ///
- public string ProviderName => "MusicBrainz";
-
- ///
- public string Key => MetadataProvider.MusicBrainzTrack.ToString();
-
- ///
- public ExternalIdMediaType? Type => ExternalIdMediaType.Track;
-
- ///
- public string UrlFormatString => Plugin.Instance.Configuration.Server + "/track/{0}";
-
- ///
- public bool Supports(IHasProviderIds item) => item is Audio;
- }
-}
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumArtistExternalId.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumArtistExternalId.cs
new file mode 100644
index 000000000..1b37e2a60
--- /dev/null
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumArtistExternalId.cs
@@ -0,0 +1,28 @@
+#pragma warning disable CS1591
+
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+using MediaBrowser.Providers.Plugins.MusicBrainz;
+
+namespace MediaBrowser.Providers.Music
+{
+ public class MusicBrainzAlbumArtistExternalId : IExternalId
+ {
+ ///
+ public string ProviderName => "MusicBrainz";
+
+ ///
+ public string Key => MetadataProvider.MusicBrainzAlbumArtist.ToString();
+
+ ///
+ public ExternalIdMediaType? Type => ExternalIdMediaType.AlbumArtist;
+
+ ///
+ public string UrlFormatString => Plugin.Instance.Configuration.Server + "/artist/{0}";
+
+ ///
+ public bool Supports(IHasProviderIds item) => item is Audio;
+ }
+}
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumExternalId.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumExternalId.cs
new file mode 100644
index 000000000..ef095111a
--- /dev/null
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumExternalId.cs
@@ -0,0 +1,28 @@
+#pragma warning disable CS1591
+
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+using MediaBrowser.Providers.Plugins.MusicBrainz;
+
+namespace MediaBrowser.Providers.Music
+{
+ public class MusicBrainzAlbumExternalId : IExternalId
+ {
+ ///
+ public string ProviderName => "MusicBrainz";
+
+ ///
+ public string Key => MetadataProvider.MusicBrainzAlbum.ToString();
+
+ ///
+ public ExternalIdMediaType? Type => ExternalIdMediaType.Album;
+
+ ///
+ public string UrlFormatString => Plugin.Instance.Configuration.Server + "/release/{0}";
+
+ ///
+ public bool Supports(IHasProviderIds item) => item is Audio || item is MusicAlbum;
+ }
+}
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs
index 8db3c391e..9148e726f 100644
--- a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs
@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CS1591, SA1401
using System;
using System.Collections.Generic;
@@ -36,7 +36,7 @@ namespace MediaBrowser.Providers.Music
/// The Jellyfin user-agent is unrestricted but source IP must not exceed
/// one request per second, therefore we rate limit to avoid throttling.
/// Be prudent, use a value slightly above the minimun required.
- /// https://musicbrainz.org/doc/XML_Web_Service/Rate_Limiting
+ /// https://musicbrainz.org/doc/XML_Web_Service/Rate_Limiting.
///
private readonly long _musicBrainzQueryIntervalMs;
@@ -302,181 +302,6 @@ namespace MediaBrowser.Providers.Music
return ReleaseResult.Parse(reader).FirstOrDefault();
}
- private class ReleaseResult
- {
- public string ReleaseId;
- public string ReleaseGroupId;
- public string Title;
- public string Overview;
- public int? Year;
-
- public List> Artists = new List>();
-
- public static IEnumerable Parse(XmlReader reader)
- {
- reader.MoveToContent();
- reader.Read();
-
- // Loop through each element
- while (!reader.EOF && reader.ReadState == ReadState.Interactive)
- {
- if (reader.NodeType == XmlNodeType.Element)
- {
- switch (reader.Name)
- {
- case "release-list":
- {
- if (reader.IsEmptyElement)
- {
- reader.Read();
- continue;
- }
-
- using var subReader = reader.ReadSubtree();
- return ParseReleaseList(subReader).ToList();
- }
-
- default:
- {
- reader.Skip();
- break;
- }
- }
- }
- else
- {
- reader.Read();
- }
- }
-
- return Enumerable.Empty();
- }
-
- private static IEnumerable ParseReleaseList(XmlReader reader)
- {
- reader.MoveToContent();
- reader.Read();
-
- // Loop through each element
- while (!reader.EOF && reader.ReadState == ReadState.Interactive)
- {
- if (reader.NodeType == XmlNodeType.Element)
- {
- switch (reader.Name)
- {
- case "release":
- {
- if (reader.IsEmptyElement)
- {
- reader.Read();
- continue;
- }
-
- var releaseId = reader.GetAttribute("id");
-
- using var subReader = reader.ReadSubtree();
- var release = ParseRelease(subReader, releaseId);
- if (release != null)
- {
- yield return release;
- }
-
- break;
- }
-
- default:
- {
- reader.Skip();
- break;
- }
- }
- }
- else
- {
- reader.Read();
- }
- }
- }
-
- private static ReleaseResult ParseRelease(XmlReader reader, string releaseId)
- {
- var result = new ReleaseResult
- {
- ReleaseId = releaseId
- };
-
- reader.MoveToContent();
- reader.Read();
-
- // http://stackoverflow.com/questions/2299632/why-does-xmlreader-skip-every-other-element-if-there-is-no-whitespace-separator
-
- // Loop through each element
- while (!reader.EOF && reader.ReadState == ReadState.Interactive)
- {
- if (reader.NodeType == XmlNodeType.Element)
- {
- switch (reader.Name)
- {
- case "title":
- {
- result.Title = reader.ReadElementContentAsString();
- break;
- }
-
- case "date":
- {
- var val = reader.ReadElementContentAsString();
- if (DateTime.TryParse(val, out var date))
- {
- result.Year = date.Year;
- }
-
- break;
- }
-
- case "annotation":
- {
- result.Overview = reader.ReadElementContentAsString();
- break;
- }
-
- case "release-group":
- {
- result.ReleaseGroupId = reader.GetAttribute("id");
- reader.Skip();
- break;
- }
-
- case "artist-credit":
- {
- using var subReader = reader.ReadSubtree();
- var artist = ParseArtistCredit(subReader);
-
- if (!string.IsNullOrEmpty(artist.Item1))
- {
- result.Artists.Add(artist);
- }
-
- break;
- }
-
- default:
- {
- reader.Skip();
- break;
- }
- }
- }
- else
- {
- reader.Read();
- }
- }
-
- return result;
- }
- }
-
private static (string, string) ParseArtistCredit(XmlReader reader)
{
reader.MoveToContent();
@@ -496,6 +321,7 @@ namespace MediaBrowser.Providers.Music
using var subReader = reader.ReadSubtree();
return ParseArtistNameCredit(subReader);
}
+
default:
{
reader.Skip();
@@ -707,6 +533,9 @@ namespace MediaBrowser.Providers.Music
/// A number of retries shall be made in order to try and satisfy the request before
/// giving up and returning null.
///
+ /// Address of MusicBrainz server.
+ /// CancellationToken to use for method.
+ /// Returns response from MusicBrainz service.
internal async Task GetMusicBrainzResponse(string url, CancellationToken cancellationToken)
{
await _apiRequestLock.WaitAsync(cancellationToken).ConfigureAwait(false);
@@ -762,5 +591,180 @@ namespace MediaBrowser.Providers.Music
{
throw new NotImplementedException();
}
+
+ private class ReleaseResult
+ {
+ public string ReleaseId;
+ public string ReleaseGroupId;
+ public string Title;
+ public string Overview;
+ public int? Year;
+
+ public List> Artists = new List>();
+
+ public static IEnumerable Parse(XmlReader reader)
+ {
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "release-list":
+ {
+ if (reader.IsEmptyElement)
+ {
+ reader.Read();
+ continue;
+ }
+
+ using var subReader = reader.ReadSubtree();
+ return ParseReleaseList(subReader).ToList();
+ }
+
+ default:
+ {
+ reader.Skip();
+ break;
+ }
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+
+ return Enumerable.Empty();
+ }
+
+ private static IEnumerable ParseReleaseList(XmlReader reader)
+ {
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "release":
+ {
+ if (reader.IsEmptyElement)
+ {
+ reader.Read();
+ continue;
+ }
+
+ var releaseId = reader.GetAttribute("id");
+
+ using var subReader = reader.ReadSubtree();
+ var release = ParseRelease(subReader, releaseId);
+ if (release != null)
+ {
+ yield return release;
+ }
+
+ break;
+ }
+
+ default:
+ {
+ reader.Skip();
+ break;
+ }
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+ }
+
+ private static ReleaseResult ParseRelease(XmlReader reader, string releaseId)
+ {
+ var result = new ReleaseResult
+ {
+ ReleaseId = releaseId
+ };
+
+ reader.MoveToContent();
+ reader.Read();
+
+ // http://stackoverflow.com/questions/2299632/why-does-xmlreader-skip-every-other-element-if-there-is-no-whitespace-separator
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "title":
+ {
+ result.Title = reader.ReadElementContentAsString();
+ break;
+ }
+
+ case "date":
+ {
+ var val = reader.ReadElementContentAsString();
+ if (DateTime.TryParse(val, out var date))
+ {
+ result.Year = date.Year;
+ }
+
+ break;
+ }
+
+ case "annotation":
+ {
+ result.Overview = reader.ReadElementContentAsString();
+ break;
+ }
+
+ case "release-group":
+ {
+ result.ReleaseGroupId = reader.GetAttribute("id");
+ reader.Skip();
+ break;
+ }
+
+ case "artist-credit":
+ {
+ using var subReader = reader.ReadSubtree();
+ var artist = ParseArtistCredit(subReader);
+
+ if (!string.IsNullOrEmpty(artist.Item1))
+ {
+ result.Artists.Add(artist);
+ }
+
+ break;
+ }
+
+ default:
+ {
+ reader.Skip();
+ break;
+ }
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+
+ return result;
+ }
+ }
}
}
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzArtistExternalId.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzArtistExternalId.cs
new file mode 100644
index 000000000..d654e1372
--- /dev/null
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzArtistExternalId.cs
@@ -0,0 +1,28 @@
+#pragma warning disable CS1591
+
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+using MediaBrowser.Providers.Plugins.MusicBrainz;
+
+namespace MediaBrowser.Providers.Music
+{
+ public class MusicBrainzArtistExternalId : IExternalId
+ {
+ ///
+ public string ProviderName => "MusicBrainz";
+
+ ///
+ public string Key => MetadataProvider.MusicBrainzArtist.ToString();
+
+ ///
+ public ExternalIdMediaType? Type => ExternalIdMediaType.Artist;
+
+ ///
+ public string UrlFormatString => Plugin.Instance.Configuration.Server + "/artist/{0}";
+
+ ///
+ public bool Supports(IHasProviderIds item) => item is MusicArtist;
+ }
+}
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzArtistProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzArtistProvider.cs
new file mode 100644
index 000000000..7cff5f595
--- /dev/null
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzArtistProvider.cs
@@ -0,0 +1,272 @@
+#pragma warning disable CS1591
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Xml;
+using Diacritics.Extensions;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+using MediaBrowser.Providers.Plugins.MusicBrainz;
+
+namespace MediaBrowser.Providers.Music
+{
+ public class MusicBrainzArtistProvider : IRemoteMetadataProvider
+ {
+ public string Name => "MusicBrainz";
+
+ ///
+ public async Task> GetSearchResults(ArtistInfo searchInfo, CancellationToken cancellationToken)
+ {
+ var musicBrainzId = searchInfo.GetMusicBrainzArtistId();
+
+ if (!string.IsNullOrWhiteSpace(musicBrainzId))
+ {
+ var url = "/ws/2/artist/?query=arid:{0}" + musicBrainzId.ToString(CultureInfo.InvariantCulture);
+
+ using var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
+ await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
+ return GetResultsFromResponse(stream);
+ }
+ else
+ {
+ // They seem to throw bad request failures on any term with a slash
+ var nameToSearch = searchInfo.Name.Replace('/', ' ');
+
+ var url = string.Format(CultureInfo.InvariantCulture, "/ws/2/artist/?query=\"{0}\"&dismax=true", UrlEncode(nameToSearch));
+
+ using (var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false))
+ await using (var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false))
+ {
+ var results = GetResultsFromResponse(stream).ToList();
+
+ if (results.Count > 0)
+ {
+ return results;
+ }
+ }
+
+ if (searchInfo.Name.HasDiacritics())
+ {
+ // Try again using the search with accent characters url
+ url = string.Format(CultureInfo.InvariantCulture, "/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch));
+
+ using var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
+ await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
+ return GetResultsFromResponse(stream);
+ }
+ }
+
+ return Enumerable.Empty();
+ }
+
+ private IEnumerable GetResultsFromResponse(Stream stream)
+ {
+ using var oReader = new StreamReader(stream, Encoding.UTF8);
+ var settings = new XmlReaderSettings()
+ {
+ ValidationType = ValidationType.None,
+ CheckCharacters = false,
+ IgnoreProcessingInstructions = true,
+ IgnoreComments = true
+ };
+
+ using var reader = XmlReader.Create(oReader, settings);
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "artist-list":
+ {
+ if (reader.IsEmptyElement)
+ {
+ reader.Read();
+ continue;
+ }
+
+ using var subReader = reader.ReadSubtree();
+ return ParseArtistList(subReader).ToList();
+ }
+
+ default:
+ {
+ reader.Skip();
+ break;
+ }
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+
+ return Enumerable.Empty();
+ }
+
+ private IEnumerable ParseArtistList(XmlReader reader)
+ {
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "artist":
+ {
+ if (reader.IsEmptyElement)
+ {
+ reader.Read();
+ continue;
+ }
+
+ var mbzId = reader.GetAttribute("id");
+
+ using var subReader = reader.ReadSubtree();
+ var artist = ParseArtist(subReader, mbzId);
+ if (artist != null)
+ {
+ yield return artist;
+ }
+
+ break;
+ }
+
+ default:
+ {
+ reader.Skip();
+ break;
+ }
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+ }
+
+ private RemoteSearchResult ParseArtist(XmlReader reader, string artistId)
+ {
+ var result = new RemoteSearchResult();
+
+ reader.MoveToContent();
+ reader.Read();
+
+ // http://stackoverflow.com/questions/2299632/why-does-xmlreader-skip-every-other-element-if-there-is-no-whitespace-separator
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "name":
+ {
+ result.Name = reader.ReadElementContentAsString();
+ break;
+ }
+
+ case "annotation":
+ {
+ result.Overview = reader.ReadElementContentAsString();
+ break;
+ }
+
+ default:
+ {
+ // there is sort-name if ever needed
+ reader.Skip();
+ break;
+ }
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+
+ result.SetProviderId(MetadataProvider.MusicBrainzArtist, artistId);
+
+ if (string.IsNullOrWhiteSpace(artistId) || string.IsNullOrWhiteSpace(result.Name))
+ {
+ return null;
+ }
+
+ return result;
+ }
+
+ ///
+ public async Task> GetMetadata(ArtistInfo info, CancellationToken cancellationToken)
+ {
+ var result = new MetadataResult
+ {
+ Item = new MusicArtist()
+ };
+
+ var musicBrainzId = info.GetMusicBrainzArtistId();
+
+ if (string.IsNullOrWhiteSpace(musicBrainzId))
+ {
+ var searchResults = await GetSearchResults(info, cancellationToken).ConfigureAwait(false);
+
+ var singleResult = searchResults.FirstOrDefault();
+
+ if (singleResult != null)
+ {
+ musicBrainzId = singleResult.GetProviderId(MetadataProvider.MusicBrainzArtist);
+ result.Item.Overview = singleResult.Overview;
+
+ if (Plugin.Instance.Configuration.ReplaceArtistName)
+ {
+ result.Item.Name = singleResult.Name;
+ }
+ }
+ }
+
+ if (!string.IsNullOrWhiteSpace(musicBrainzId))
+ {
+ result.HasMetadata = true;
+ result.Item.SetProviderId(MetadataProvider.MusicBrainzArtist, musicBrainzId);
+ }
+
+ return result;
+ }
+
+ ///
+ /// Encodes an URL.
+ ///
+ /// The name.
+ /// System.String.
+ private static string UrlEncode(string name)
+ {
+ return WebUtility.UrlEncode(name);
+ }
+
+ public Task GetImageResponse(string url, CancellationToken cancellationToken)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzOtherArtistExternalId.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzOtherArtistExternalId.cs
new file mode 100644
index 000000000..f889a34b5
--- /dev/null
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzOtherArtistExternalId.cs
@@ -0,0 +1,28 @@
+#pragma warning disable CS1591
+
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+using MediaBrowser.Providers.Plugins.MusicBrainz;
+
+namespace MediaBrowser.Providers.Music
+{
+ public class MusicBrainzOtherArtistExternalId : IExternalId
+ {
+ ///
+ public string ProviderName => "MusicBrainz";
+
+ ///
+ public string Key => MetadataProvider.MusicBrainzArtist.ToString();
+
+ ///
+ public ExternalIdMediaType? Type => ExternalIdMediaType.OtherArtist;
+
+ ///
+ public string UrlFormatString => Plugin.Instance.Configuration.Server + "/artist/{0}";
+
+ ///
+ public bool Supports(IHasProviderIds item) => item is Audio || item is MusicAlbum;
+ }
+}
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzReleaseGroupExternalId.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzReleaseGroupExternalId.cs
new file mode 100644
index 000000000..53783d2c0
--- /dev/null
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzReleaseGroupExternalId.cs
@@ -0,0 +1,28 @@
+#pragma warning disable CS1591
+
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+using MediaBrowser.Providers.Plugins.MusicBrainz;
+
+namespace MediaBrowser.Providers.Music
+{
+ public class MusicBrainzReleaseGroupExternalId : IExternalId
+ {
+ ///
+ public string ProviderName => "MusicBrainz";
+
+ ///
+ public string Key => MetadataProvider.MusicBrainzReleaseGroup.ToString();
+
+ ///
+ public ExternalIdMediaType? Type => ExternalIdMediaType.ReleaseGroup;
+
+ ///
+ public string UrlFormatString => Plugin.Instance.Configuration.Server + "/release-group/{0}";
+
+ ///
+ public bool Supports(IHasProviderIds item) => item is Audio || item is MusicAlbum;
+ }
+}
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzTrackId.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzTrackId.cs
new file mode 100644
index 000000000..627f8f098
--- /dev/null
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzTrackId.cs
@@ -0,0 +1,28 @@
+#pragma warning disable CS1591
+
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+using MediaBrowser.Providers.Plugins.MusicBrainz;
+
+namespace MediaBrowser.Providers.Music
+{
+ public class MusicBrainzTrackId : IExternalId
+ {
+ ///
+ public string ProviderName => "MusicBrainz";
+
+ ///
+ public string Key => MetadataProvider.MusicBrainzTrack.ToString();
+
+ ///
+ public ExternalIdMediaType? Type => ExternalIdMediaType.Track;
+
+ ///
+ public string UrlFormatString => Plugin.Instance.Configuration.Server + "/track/{0}";
+
+ ///
+ public bool Supports(IHasProviderIds item) => item is Audio;
+ }
+}
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/Plugin.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/Plugin.cs
index 9eeb4750b..69b69be42 100644
--- a/MediaBrowser.Providers/Plugins/MusicBrainz/Plugin.cs
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/Plugin.cs
@@ -11,6 +11,10 @@ namespace MediaBrowser.Providers.Plugins.MusicBrainz
{
public class Plugin : BasePlugin, IHasWebPages
{
+ public const string DefaultServer = "https://musicbrainz.org";
+
+ public const long DefaultRateLimit = 2000u;
+
public Plugin(IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer)
: base(applicationPaths, xmlSerializer)
{
@@ -25,10 +29,6 @@ namespace MediaBrowser.Providers.Plugins.MusicBrainz
public override string Description => "Get artist and album metadata from any MusicBrainz server.";
- public const string DefaultServer = "https://musicbrainz.org";
-
- public const long DefaultRateLimit = 2000u;
-
// TODO remove when plugin removed from server.
public override string ConfigurationFileName => "Jellyfin.Plugin.MusicBrainz.xml";
diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs
index d9b0600c3..02e696de5 100644
--- a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs
@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CS1591, SA1300
using System;
using System.Collections.Generic;
diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs
index eafcae4ac..88435e2d4 100644
--- a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs
@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CS159, SA1300
using System;
using System.Collections.Generic;
@@ -20,6 +20,7 @@ using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.Plugins.Omdb
{
+ /// Provider for OMDB service.
public class OmdbProvider
{
private readonly IFileSystem _fileSystem;
@@ -29,6 +30,11 @@ namespace MediaBrowser.Providers.Plugins.Omdb
private readonly IApplicationHost _appHost;
private readonly JsonSerializerOptions _jsonOptions;
+ /// Initializes a new instance of the class.
+ /// HttpClientFactory to use for calls to OMDB service.
+ /// IFileSystem to use for store OMDB data.
+ /// IApplicationHost to use.
+ /// IServerConfigurationManager to use.
public OmdbProvider(IHttpClientFactory httpClientFactory, IFileSystem fileSystem, IApplicationHost appHost, IServerConfigurationManager configurationManager)
{
_httpClientFactory = httpClientFactory;
@@ -41,6 +47,14 @@ namespace MediaBrowser.Providers.Plugins.Omdb
_jsonOptions.Converters.Add(new JsonOmdbNotAvailableInt32Converter());
}
+ /// Fetches data from OMDB service.
+ /// Metadata about media item.
+ /// IMDB ID for media.
+ /// Media language.
+ /// Country of origin.
+ /// CancellationToken to use for operation.
+ /// The first generic type parameter.
+ /// Returns a Task object that can be awaited.
public async Task Fetch(MetadataResult itemResult, string imdbId, string language, string country, CancellationToken cancellationToken)
where T : BaseItem
{
@@ -105,6 +119,17 @@ namespace MediaBrowser.Providers.Plugins.Omdb
ParseAdditionalMetadata(itemResult, result);
}
+ /// Gets data about an episode.
+ /// Metadata about episode.
+ /// Episode number.
+ /// Season number.
+ /// Episode ID.
+ /// Season ID.
+ /// Episode language.
+ /// Country of origin.
+ /// CancellationToken to use for operation.
+ /// The first generic type parameter.
+ /// Whether operation was successful.
public async Task FetchEpisodeData(MetadataResult itemResult, int episodeNumber, int seasonNumber, string episodeImdbId, string seriesImdbId, string language, string country, CancellationToken cancellationToken)
where T : BaseItem
{
@@ -236,6 +261,9 @@ namespace MediaBrowser.Providers.Plugins.Omdb
return false;
}
+ /// Gets OMDB URL.
+ /// Appends query string to URL.
+ /// OMDB URL with optional query string.
public static string GetOmdbUrl(string query)
{
const string Url = "https://www.omdbapi.com?apikey=2c9d9507";
@@ -327,6 +355,12 @@ namespace MediaBrowser.Providers.Plugins.Omdb
return path;
}
+ /// Gets response from OMDB service as type T.
+ /// HttpClient instance to use for service call.
+ /// Http URL to use for service call.
+ /// CancellationToken to use for service call.
+ /// The first generic type parameter.
+ /// OMDB service response as type T.
public async Task GetDeserializedOmdbResponse(HttpClient httpClient, string url, CancellationToken cancellationToken)
{
using var response = await GetOmdbResponse(httpClient, url, cancellationToken).ConfigureAwait(false);
@@ -335,6 +369,11 @@ namespace MediaBrowser.Providers.Plugins.Omdb
return await JsonSerializer.DeserializeAsync(content, _jsonOptions, cancellationToken).ConfigureAwait(false);
}
+ /// Gets response from OMDB service.
+ /// HttpClient instance to use for service call.
+ /// Http URL to use for service call.
+ /// CancellationToken to use for service call.
+ /// OMDB service response as HttpResponseMessage.
public static Task GetOmdbResponse(HttpClient httpClient, string url, CancellationToken cancellationToken)
{
return httpClient.GetAsync(url, cancellationToken);
@@ -538,10 +577,13 @@ namespace MediaBrowser.Providers.Plugins.Omdb
}
}
+ /// Describes OMDB rating.
public class OmdbRating
{
+ /// Gets or sets rating source.
public string Source { get; set; }
+ /// Gets or sets rating value.
public string Value { get; set; }
}
}
diff --git a/MediaBrowser.Providers/Studios/StudioMetadataService.cs b/MediaBrowser.Providers/Studios/StudioMetadataService.cs
index 78042b40d..091b33ce0 100644
--- a/MediaBrowser.Providers/Studios/StudioMetadataService.cs
+++ b/MediaBrowser.Providers/Studios/StudioMetadataService.cs
@@ -17,7 +17,8 @@ namespace MediaBrowser.Providers.Studios
IServerConfigurationManager serverConfigurationManager,
ILogger logger,
IProviderManager providerManager,
- IFileSystem fileSystem, ILibraryManager libraryManager)
+ IFileSystem fileSystem,
+ ILibraryManager libraryManager)
: base(serverConfigurationManager, logger, providerManager, fileSystem, libraryManager)
{
}
--
cgit v1.2.3
From 927b003143f7e4772e21b767f2524f969ddf1ad8 Mon Sep 17 00:00:00 2001
From: Rich Lander
Date: Thu, 22 Jul 2021 20:16:38 -0700
Subject: Fix remaining MediaBrowser.Providers warnings
---
.../BoxSets/BoxSetMetadataService.cs | 8 ++++----
MediaBrowser.Providers/Manager/ItemImageProvider.cs | 3 ++-
.../MediaInfo/AudioImageProvider.cs | 2 +-
MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs | 2 +-
.../MediaInfo/SubtitleDownloader.cs | 3 ++-
MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs | 3 ++-
.../Plugins/AudioDb/AudioDbAlbumProvider.cs | 7 ++++---
.../Plugins/AudioDb/AudioDbArtistProvider.cs | 3 ++-
.../Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs | 17 ++++++++++++++++-
MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs | 1 +
.../Plugins/Tmdb/People/TmdbPersonProvider.cs | 10 +++++-----
.../Plugins/Tmdb/TmdbClientManager.cs | 20 +++++++++++++++++++-
MediaBrowser.Providers/Subtitles/SubtitleManager.cs | 10 ++++++++--
MediaBrowser.Providers/TV/EpisodeMetadataService.cs | 16 ++++++++--------
MediaBrowser.Providers/TV/SeasonMetadataService.cs | 14 +++++++-------
15 files changed, 82 insertions(+), 37 deletions(-)
diff --git a/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs b/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs
index e5326da71..88ce8d087 100644
--- a/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs
+++ b/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs
@@ -59,9 +59,9 @@ namespace MediaBrowser.Providers.BoxSets
}
///
- protected override ItemUpdateType BeforeSaveInternal(BoxSet item, bool isFullRefresh, ItemUpdateType currentUpdateType)
+ protected override ItemUpdateType BeforeSaveInternal(BoxSet item, bool isFullRefresh, ItemUpdateType updateType)
{
- var updateType = base.BeforeSaveInternal(item, isFullRefresh, currentUpdateType);
+ var updatedType = base.BeforeSaveInternal(item, isFullRefresh, updateType);
var libraryFolderIds = item.GetLibraryFolderIds();
@@ -69,10 +69,10 @@ namespace MediaBrowser.Providers.BoxSets
if (itemLibraryFolderIds == null || !libraryFolderIds.SequenceEqual(itemLibraryFolderIds))
{
item.LibraryFolderIds = libraryFolderIds;
- updateType |= ItemUpdateType.MetadataImport;
+ updatedType |= ItemUpdateType.MetadataImport;
}
- return updateType;
+ return updatedType;
}
}
}
diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs
index fd6d7937b..607fd127b 100644
--- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs
+++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs
@@ -1,7 +1,8 @@
-#pragma warning disable CS1591
+#pragma warning disable CA1002, CS1591
using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Net;
diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
index 03e45fb86..12125cbb9 100644
--- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CA1002, CS1591
using System;
using System.Collections.Generic;
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
index 12e1fbea5..1f17d8cd4 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CA1068, CS1591
using System;
using System.Collections.Generic;
diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs b/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs
index 44ab5aa5b..aa0743bd0 100644
--- a/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs
+++ b/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs
@@ -1,7 +1,8 @@
-#pragma warning disable CS1591
+#pragma warning disable CA1002, CS1591
using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
index 3cd7ec772..b3d065929 100644
--- a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
+++ b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
@@ -1,7 +1,8 @@
-#pragma warning disable CS1591
+#pragma warning disable CA1002, CS1591
using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.IO;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs
index ccf9501be..9f2f7fc11 100644
--- a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs
+++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs
@@ -1,4 +1,4 @@
-#pragma warning disable CS1591, SA1300
+#pragma warning disable CA1002, CS1591, SA1300
using System;
using System.Collections.Generic;
@@ -30,9 +30,9 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
private readonly IHttpClientFactory _httpClientFactory;
private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options;
-#pragma warning disable SA1401
+#pragma warning disable SA1401, CA2211
public static AudioDbAlbumProvider Current;
-#pragma warning restore SA1401
+#pragma warning restore SA1401, CA2211
public AudioDbAlbumProvider(IServerConfigurationManager config, IFileSystem fileSystem, IHttpClientFactory httpClientFactory)
{
@@ -204,6 +204,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
throw new NotImplementedException();
}
+#pragma warning disable CA1034, CA2227
public class Album
{
public string idAlbum { get; set; }
diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs
index c11e7a7ff..2857c6c13 100644
--- a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs
+++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs
@@ -1,4 +1,4 @@
-#pragma warning disable CS1591, SA1300
+#pragma warning disable CA1034, CS1591, CA1002, SA1028, SA1300
using System;
using System.Collections.Generic;
@@ -274,6 +274,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
public string strLocked { get; set; }
}
+#pragma warning disable CA2227
public class RootObject
{
public List artists { get; set; }
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs
index 9148e726f..2e1748c46 100644
--- a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs
@@ -23,7 +23,7 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.Providers.Music
{
- public class MusicBrainzAlbumProvider : IRemoteMetadataProvider, IHasOrder
+ public class MusicBrainzAlbumProvider : IRemoteMetadataProvider, IHasOrder, IDisposable
{
///
/// For each single MB lookup/search, this is the maximum number of
@@ -592,6 +592,21 @@ namespace MediaBrowser.Providers.Music
throw new NotImplementedException();
}
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ _apiRequestLock?.Dispose();
+ }
+ }
+
+ /// IDisposable implementation.
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
private class ReleaseResult
{
public string ReleaseId;
diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs
index 88435e2d4..1ae712e9e 100644
--- a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs
@@ -577,6 +577,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
}
}
+#pragma warning disable CA1034
/// Describes OMDB rating.
public class OmdbRating
{
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs
index 6db550b1d..dac118388 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs
@@ -77,14 +77,14 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
return remoteSearchResults;
}
- public async Task> GetMetadata(PersonLookupInfo id, CancellationToken cancellationToken)
+ public async Task> GetMetadata(PersonLookupInfo info, CancellationToken cancellationToken)
{
- var personTmdbId = Convert.ToInt32(id.GetProviderId(MetadataProvider.Tmdb), CultureInfo.InvariantCulture);
+ var personTmdbId = Convert.ToInt32(info.GetProviderId(MetadataProvider.Tmdb), CultureInfo.InvariantCulture);
// We don't already have an Id, need to fetch it
if (personTmdbId <= 0)
{
- var personSearchResults = await _tmdbClientManager.SearchPersonAsync(id.Name, cancellationToken).ConfigureAwait(false);
+ var personSearchResults = await _tmdbClientManager.SearchPersonAsync(info.Name, cancellationToken).ConfigureAwait(false);
if (personSearchResults.Count > 0)
{
personTmdbId = personSearchResults[0].Id;
@@ -95,7 +95,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
if (personTmdbId > 0)
{
- var person = await _tmdbClientManager.GetPersonAsync(personTmdbId, id.MetadataLanguage, cancellationToken).ConfigureAwait(false);
+ var person = await _tmdbClientManager.GetPersonAsync(personTmdbId, info.MetadataLanguage, cancellationToken).ConfigureAwait(false);
result.HasMetadata = true;
@@ -103,7 +103,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
{
// Take name from incoming info, don't rename the person
// TODO: This should go in PersonMetadataService, not each person provider
- Name = id.Name,
+ Name = info.Name,
HomePageUrl = person.Homepage,
Overview = person.Biography,
PremiereDate = person.Birthday?.ToUniversalTime(),
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs b/MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs
index 3980b7da0..999cb8e6c 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs
@@ -18,7 +18,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb
///
/// Manager class for abstracting the TMDb API client library.
///
- public class TmdbClientManager
+ public class TmdbClientManager : IDisposable
{
private const int CacheDurationInHours = 1;
@@ -532,5 +532,23 @@ namespace MediaBrowser.Providers.Plugins.Tmdb
{
return !_tmDbClient.HasConfig ? _tmDbClient.GetConfigAsync() : Task.CompletedTask;
}
+
+ /// Dispose method.
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// IDispose implementation.
+ /// Specify true to dispose.
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ _memoryCache?.Dispose();
+ _tmDbClient?.Dispose();
+ }
+ }
}
}
diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
index 13f15b173..160c64c84 100644
--- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
+++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
@@ -252,8 +252,14 @@ namespace MediaBrowser.Providers.Subtitles
}
catch (Exception ex)
{
- (exs ??= new List()).Add(ex);
- }
+#pragma warning disable CA1508
+ exs ??= new List()
+ {
+ ex
+ };
+#pragma warning restore CA1508
+
+ }
finally
{
_monitor.ReportFileSystemChangeComplete(savePath, false);
diff --git a/MediaBrowser.Providers/TV/EpisodeMetadataService.cs b/MediaBrowser.Providers/TV/EpisodeMetadataService.cs
index 170f1bdd8..08cb6ced9 100644
--- a/MediaBrowser.Providers/TV/EpisodeMetadataService.cs
+++ b/MediaBrowser.Providers/TV/EpisodeMetadataService.cs
@@ -25,46 +25,46 @@ namespace MediaBrowser.Providers.TV
}
///
- protected override ItemUpdateType BeforeSaveInternal(Episode item, bool isFullRefresh, ItemUpdateType currentUpdateType)
+ protected override ItemUpdateType BeforeSaveInternal(Episode item, bool isFullRefresh, ItemUpdateType updateType)
{
- var updateType = base.BeforeSaveInternal(item, isFullRefresh, currentUpdateType);
+ var updatedType = base.BeforeSaveInternal(item, isFullRefresh, updateType);
var seriesName = item.FindSeriesName();
if (!string.Equals(item.SeriesName, seriesName, StringComparison.Ordinal))
{
item.SeriesName = seriesName;
- updateType |= ItemUpdateType.MetadataImport;
+ updatedType |= ItemUpdateType.MetadataImport;
}
var seasonName = item.FindSeasonName();
if (!string.Equals(item.SeasonName, seasonName, StringComparison.Ordinal))
{
item.SeasonName = seasonName;
- updateType |= ItemUpdateType.MetadataImport;
+ updatedType |= ItemUpdateType.MetadataImport;
}
var seriesId = item.FindSeriesId();
if (!item.SeriesId.Equals(seriesId))
{
item.SeriesId = seriesId;
- updateType |= ItemUpdateType.MetadataImport;
+ updatedType |= ItemUpdateType.MetadataImport;
}
var seasonId = item.FindSeasonId();
if (!item.SeasonId.Equals(seasonId))
{
item.SeasonId = seasonId;
- updateType |= ItemUpdateType.MetadataImport;
+ updatedType |= ItemUpdateType.MetadataImport;
}
var seriesPresentationUniqueKey = item.FindSeriesPresentationUniqueKey();
if (!string.Equals(item.SeriesPresentationUniqueKey, seriesPresentationUniqueKey, StringComparison.Ordinal))
{
item.SeriesPresentationUniqueKey = seriesPresentationUniqueKey;
- updateType |= ItemUpdateType.MetadataImport;
+ updatedType |= ItemUpdateType.MetadataImport;
}
- return updateType;
+ return updatedType;
}
///
diff --git a/MediaBrowser.Providers/TV/SeasonMetadataService.cs b/MediaBrowser.Providers/TV/SeasonMetadataService.cs
index 4e59f78bc..0f22f8a9b 100644
--- a/MediaBrowser.Providers/TV/SeasonMetadataService.cs
+++ b/MediaBrowser.Providers/TV/SeasonMetadataService.cs
@@ -31,9 +31,9 @@ namespace MediaBrowser.Providers.TV
protected override bool EnableUpdatingPremiereDateFromChildren => true;
///
- protected override ItemUpdateType BeforeSaveInternal(Season item, bool isFullRefresh, ItemUpdateType currentUpdateType)
+ protected override ItemUpdateType BeforeSaveInternal(Season item, bool isFullRefresh, ItemUpdateType updateType)
{
- var updateType = base.BeforeSaveInternal(item, isFullRefresh, currentUpdateType);
+ var updatedType = base.BeforeSaveInternal(item, isFullRefresh, updateType);
if (item.IndexNumber.HasValue && item.IndexNumber.Value == 0)
{
@@ -42,7 +42,7 @@ namespace MediaBrowser.Providers.TV
if (!string.Equals(item.Name, seasonZeroDisplayName, StringComparison.OrdinalIgnoreCase))
{
item.Name = seasonZeroDisplayName;
- updateType = updateType | ItemUpdateType.MetadataEdit;
+ updatedType = updatedType | ItemUpdateType.MetadataEdit;
}
}
@@ -50,24 +50,24 @@ namespace MediaBrowser.Providers.TV
if (!string.Equals(item.SeriesName, seriesName, StringComparison.Ordinal))
{
item.SeriesName = seriesName;
- updateType |= ItemUpdateType.MetadataImport;
+ updatedType |= ItemUpdateType.MetadataImport;
}
var seriesPresentationUniqueKey = item.FindSeriesPresentationUniqueKey();
if (!string.Equals(item.SeriesPresentationUniqueKey, seriesPresentationUniqueKey, StringComparison.Ordinal))
{
item.SeriesPresentationUniqueKey = seriesPresentationUniqueKey;
- updateType |= ItemUpdateType.MetadataImport;
+ updatedType |= ItemUpdateType.MetadataImport;
}
var seriesId = item.FindSeriesId();
if (!item.SeriesId.Equals(seriesId))
{
item.SeriesId = seriesId;
- updateType |= ItemUpdateType.MetadataImport;
+ updatedType |= ItemUpdateType.MetadataImport;
}
- return updateType;
+ return updatedType;
}
///
--
cgit v1.2.3
From a7cc77e7fa2ba427ce2f2be2c930902c9623d008 Mon Sep 17 00:00:00 2001
From: Rich Lander
Date: Fri, 23 Jul 2021 13:07:19 -0700
Subject: Fix partial set of MediaBrowser.Controller/Entities warnings
---
.../Entities/AggregateFolder.cs | 18 ++++----
MediaBrowser.Controller/Entities/Folder.cs | 2 +-
.../Entities/ICollectionFolder.cs | 2 +-
.../Entities/InternalItemsQuery.cs | 54 +++++++++++-----------
MediaBrowser.Controller/Entities/Person.cs | 28 +++++------
MediaBrowser.Controller/Entities/PersonInfo.cs | 2 +-
MediaBrowser.Controller/Entities/Photo.cs | 48 +++++++++----------
MediaBrowser.Controller/Entities/Studio.cs | 32 ++++++-------
MediaBrowser.Controller/Entities/Trailer.cs | 8 ++--
MediaBrowser.Controller/Entities/Year.cs | 22 ++++-----
.../Providers/IDirectoryService.cs | 2 +-
11 files changed, 109 insertions(+), 109 deletions(-)
diff --git a/MediaBrowser.Controller/Entities/AggregateFolder.cs b/MediaBrowser.Controller/Entities/AggregateFolder.cs
index fe1bc62ab..4fd6cb24c 100644
--- a/MediaBrowser.Controller/Entities/AggregateFolder.cs
+++ b/MediaBrowser.Controller/Entities/AggregateFolder.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1819, CS1591
using System;
using System.Collections.Concurrent;
@@ -23,6 +23,9 @@ namespace MediaBrowser.Controller.Entities
public class AggregateFolder : Folder
{
private bool _requiresRefresh;
+ private Guid[] _childrenIds = null;
+ private readonly object _childIdsLock = new object();
+
public AggregateFolder()
{
@@ -32,11 +35,6 @@ namespace MediaBrowser.Controller.Entities
[JsonIgnore]
public override bool IsPhysicalRoot => true;
- public override bool CanDelete()
- {
- return false;
- }
-
[JsonIgnore]
public override bool SupportsPlayedStatus => false;
@@ -55,15 +53,17 @@ namespace MediaBrowser.Controller.Entities
public override string[] PhysicalLocations => PhysicalLocationsList;
public string[] PhysicalLocationsList { get; set; }
+ public override bool CanDelete()
+ {
+ return false;
+ }
+
protected override FileSystemMetadata[] GetFileSystemChildren(IDirectoryService directoryService)
{
return CreateResolveArgs(directoryService, true).FileSystemChildren;
}
- private Guid[] _childrenIds = null;
- private readonly object _childIdsLock = new object();
-
protected override List LoadChildren()
{
lock (_childIdsLock)
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index 6587eefab..1bc99e8a7 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1721, CA1819, CS1591
using System;
using System.Collections.Generic;
diff --git a/MediaBrowser.Controller/Entities/ICollectionFolder.cs b/MediaBrowser.Controller/Entities/ICollectionFolder.cs
index 2304570fd..89e494ebc 100644
--- a/MediaBrowser.Controller/Entities/ICollectionFolder.cs
+++ b/MediaBrowser.Controller/Entities/ICollectionFolder.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1819, CS1591
using System;
diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
index ebaf5506d..3462eeb63 100644
--- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
+++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CA1819, CA2227, CS1591
using System;
using System.Collections.Generic;
@@ -12,6 +12,15 @@ namespace MediaBrowser.Controller.Entities
{
public class InternalItemsQuery
{
+ public InternalItemsQuery(User? user)
+ : this()
+ {
+ if (user != null)
+ {
+ SetUser(user);
+ }
+ }
+
public bool Recursive { get; set; }
public int? StartIndex { get; set; }
@@ -186,23 +195,6 @@ namespace MediaBrowser.Controller.Entities
public Guid[] TopParentIds { get; set; }
- public BaseItem? Parent
- {
- set
- {
- if (value == null)
- {
- ParentId = Guid.Empty;
- ParentType = null;
- }
- else
- {
- ParentId = value.Id;
- ParentType = value.GetType().Name;
- }
- }
- }
-
public string[] PresetViews { get; set; }
public TrailerType[] TrailerTypes { get; set; }
@@ -270,6 +262,23 @@ namespace MediaBrowser.Controller.Entities
///
public bool? DisplayAlbumFolders { get; set; }
+ public BaseItem? Parent
+ {
+ set
+ {
+ if (value == null)
+ {
+ ParentId = Guid.Empty;
+ ParentType = null;
+ }
+ else
+ {
+ ParentId = value.Id;
+ ParentType = value.GetType().Name;
+ }
+ }
+ }
+
public InternalItemsQuery()
{
AlbumArtistIds = Array.Empty();
@@ -310,15 +319,6 @@ namespace MediaBrowser.Controller.Entities
Years = Array.Empty();
}
- public InternalItemsQuery(User? user)
- : this()
- {
- if (user != null)
- {
- SetUser(user);
- }
- }
-
public void SetUser(User user)
{
MaxParentalRating = user.MaxParentalAgeRating;
diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs
index b0ab280af..b5b94ea7a 100644
--- a/MediaBrowser.Controller/Entities/Person.cs
+++ b/MediaBrowser.Controller/Entities/Person.cs
@@ -16,6 +16,20 @@ namespace MediaBrowser.Controller.Entities
///
public class Person : BaseItem, IItemByName, IHasLookupInfo
{
+ ///
+ /// Gets the folder containing the item.
+ /// If the item is a folder, it returns the folder itself.
+ ///
+ /// The containing folder path.
+ [JsonIgnore]
+ public override string ContainingFolderPath => Path;
+
+ ///
+ /// Gets a value indicating whether to enable alpha numeric sorting.
+ ///
+ [JsonIgnore]
+ public override bool EnableAlphaNumericSorting => false;
+
public override List GetUserDataKeys()
{
var list = base.GetUserDataKeys();
@@ -49,14 +63,6 @@ namespace MediaBrowser.Controller.Entities
return LibraryManager.GetItemList(query);
}
- ///
- /// Gets the folder containing the item.
- /// If the item is a folder, it returns the folder itself.
- ///
- /// The containing folder path.
- [JsonIgnore]
- public override string ContainingFolderPath => Path;
-
public override bool CanDelete()
{
return false;
@@ -67,12 +73,6 @@ namespace MediaBrowser.Controller.Entities
return true;
}
- ///
- /// Gets a value indicating whether to enable alpha numeric sorting.
- ///
- [JsonIgnore]
- public override bool EnableAlphaNumericSorting => false;
-
[JsonIgnore]
public override bool SupportsPeople => false;
diff --git a/MediaBrowser.Controller/Entities/PersonInfo.cs b/MediaBrowser.Controller/Entities/PersonInfo.cs
index fb79323f8..2b689ae7e 100644
--- a/MediaBrowser.Controller/Entities/PersonInfo.cs
+++ b/MediaBrowser.Controller/Entities/PersonInfo.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/Entities/Photo.cs b/MediaBrowser.Controller/Entities/Photo.cs
index 3312a0e3e..ba6ce189a 100644
--- a/MediaBrowser.Controller/Entities/Photo.cs
+++ b/MediaBrowser.Controller/Entities/Photo.cs
@@ -36,6 +36,30 @@ namespace MediaBrowser.Controller.Entities
}
}
+ public string CameraMake { get; set; }
+
+ public string CameraModel { get; set; }
+
+ public string Software { get; set; }
+
+ public double? ExposureTime { get; set; }
+
+ public double? FocalLength { get; set; }
+
+ public ImageOrientation? Orientation { get; set; }
+
+ public double? Aperture { get; set; }
+
+ public double? ShutterSpeed { get; set; }
+
+ public double? Latitude { get; set; }
+
+ public double? Longitude { get; set; }
+
+ public double? Altitude { get; set; }
+
+ public int? IsoSpeedRating { get; set; }
+
public override bool CanDownload()
{
return true;
@@ -69,29 +93,5 @@ namespace MediaBrowser.Controller.Entities
return base.GetDefaultPrimaryImageAspectRatio();
}
-
- public string CameraMake { get; set; }
-
- public string CameraModel { get; set; }
-
- public string Software { get; set; }
-
- public double? ExposureTime { get; set; }
-
- public double? FocalLength { get; set; }
-
- public ImageOrientation? Orientation { get; set; }
-
- public double? Aperture { get; set; }
-
- public double? ShutterSpeed { get; set; }
-
- public double? Latitude { get; set; }
-
- public double? Longitude { get; set; }
-
- public double? Altitude { get; set; }
-
- public int? IsoSpeedRating { get; set; }
}
}
diff --git a/MediaBrowser.Controller/Entities/Studio.cs b/MediaBrowser.Controller/Entities/Studio.cs
index 888b30001..556624e14 100644
--- a/MediaBrowser.Controller/Entities/Studio.cs
+++ b/MediaBrowser.Controller/Entities/Studio.cs
@@ -15,19 +15,6 @@ namespace MediaBrowser.Controller.Entities
///
public class Studio : BaseItem, IItemByName
{
- public override List GetUserDataKeys()
- {
- var list = base.GetUserDataKeys();
-
- list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
- return list;
- }
-
- public override string CreatePresentationUniqueKey()
- {
- return GetUserDataKeys()[0];
- }
-
///
/// Gets the folder containing the item.
/// If the item is a folder, it returns the folder itself.
@@ -42,6 +29,22 @@ namespace MediaBrowser.Controller.Entities
[JsonIgnore]
public override bool SupportsAncestors => false;
+ [JsonIgnore]
+ public override bool SupportsPeople => false;
+
+ public override List GetUserDataKeys()
+ {
+ var list = base.GetUserDataKeys();
+
+ list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
+ return list;
+ }
+
+ public override string CreatePresentationUniqueKey()
+ {
+ return GetUserDataKeys()[0];
+ }
+
public override double GetDefaultPrimaryImageAspectRatio()
{
double value = 16;
@@ -67,9 +70,6 @@ namespace MediaBrowser.Controller.Entities
return LibraryManager.GetItemList(query);
}
- [JsonIgnore]
- public override bool SupportsPeople => false;
-
public static string GetPath(string name)
{
return GetPath(name, true);
diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs
index 732b45521..1c558d419 100644
--- a/MediaBrowser.Controller/Entities/Trailer.cs
+++ b/MediaBrowser.Controller/Entities/Trailer.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1819, CS1591
using System;
using System.Collections.Generic;
@@ -23,6 +23,9 @@ namespace MediaBrowser.Controller.Entities
TrailerTypes = Array.Empty();
}
+ [JsonIgnore]
+ public override bool StopRefreshIfLocalMetadataFound => false;
+
public TrailerType[] TrailerTypes { get; set; }
public override double GetDefaultPrimaryImageAspectRatio()
@@ -97,8 +100,5 @@ namespace MediaBrowser.Controller.Entities
return list;
}
-
- [JsonIgnore]
- public override bool StopRefreshIfLocalMetadataFound => false;
}
}
diff --git a/MediaBrowser.Controller/Entities/Year.cs b/MediaBrowser.Controller/Entities/Year.cs
index f268bc939..abb91cb31 100644
--- a/MediaBrowser.Controller/Entities/Year.cs
+++ b/MediaBrowser.Controller/Entities/Year.cs
@@ -15,6 +15,17 @@ namespace MediaBrowser.Controller.Entities
///
public class Year : BaseItem, IItemByName
{
+ [JsonIgnore]
+ public override bool SupportsAncestors => false;
+
+ public override bool CanDelete()
+ {
+ return false;
+ }
+
+ [JsonIgnore]
+ public override bool SupportsPeople => false;
+
public override List GetUserDataKeys()
{
var list = base.GetUserDataKeys();
@@ -39,14 +50,6 @@ namespace MediaBrowser.Controller.Entities
return value;
}
- [JsonIgnore]
- public override bool SupportsAncestors => false;
-
- public override bool CanDelete()
- {
- return false;
- }
-
public override bool IsSaveLocalMetadataEnabled()
{
return true;
@@ -76,9 +79,6 @@ namespace MediaBrowser.Controller.Entities
return null;
}
- [JsonIgnore]
- public override bool SupportsPeople => false;
-
public static string GetPath(string name)
{
return GetPath(name, true);
diff --git a/MediaBrowser.Controller/Providers/IDirectoryService.cs b/MediaBrowser.Controller/Providers/IDirectoryService.cs
index b1a36e102..c26a87d7d 100644
--- a/MediaBrowser.Controller/Providers/IDirectoryService.cs
+++ b/MediaBrowser.Controller/Providers/IDirectoryService.cs
@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CA1819, CS1591
using System.Collections.Generic;
using MediaBrowser.Model.IO;
--
cgit v1.2.3
From 32616d15f2ed2e5fef715a9b9d2510818babffa9 Mon Sep 17 00:00:00 2001
From: Rich Lander
Date: Fri, 23 Jul 2021 14:19:44 -0700
Subject: Update MediaBrowser.Controller/Entities/AggregateFolder.cs
Co-authored-by: Cody Robibero
---
MediaBrowser.Controller/Entities/AggregateFolder.cs | 1 -
1 file changed, 1 deletion(-)
diff --git a/MediaBrowser.Controller/Entities/AggregateFolder.cs b/MediaBrowser.Controller/Entities/AggregateFolder.cs
index 4fd6cb24c..67f4cd16f 100644
--- a/MediaBrowser.Controller/Entities/AggregateFolder.cs
+++ b/MediaBrowser.Controller/Entities/AggregateFolder.cs
@@ -26,7 +26,6 @@ namespace MediaBrowser.Controller.Entities
private Guid[] _childrenIds = null;
private readonly object _childIdsLock = new object();
-
public AggregateFolder()
{
PhysicalLocationsList = Array.Empty();
--
cgit v1.2.3
From a16e66615ca4b38624251b9505e20d4e5d0ab12b Mon Sep 17 00:00:00 2001
From: Rich Lander
Date: Fri, 23 Jul 2021 14:19:48 -0700
Subject: Update MediaBrowser.Controller/Entities/AggregateFolder.cs
Co-authored-by: Cody Robibero
---
MediaBrowser.Controller/Entities/AggregateFolder.cs | 1 -
1 file changed, 1 deletion(-)
diff --git a/MediaBrowser.Controller/Entities/AggregateFolder.cs b/MediaBrowser.Controller/Entities/AggregateFolder.cs
index 67f4cd16f..e60549843 100644
--- a/MediaBrowser.Controller/Entities/AggregateFolder.cs
+++ b/MediaBrowser.Controller/Entities/AggregateFolder.cs
@@ -57,7 +57,6 @@ namespace MediaBrowser.Controller.Entities
return false;
}
-
protected override FileSystemMetadata[] GetFileSystemChildren(IDirectoryService directoryService)
{
return CreateResolveArgs(directoryService, true).FileSystemChildren;
--
cgit v1.2.3
From 0ce7a15534461d70730ac8d1accfda1d45b01b55 Mon Sep 17 00:00:00 2001
From: Rich Lander
Date: Fri, 23 Jul 2021 16:36:27 -0700
Subject: Fix more warnings
---
.../Entities/AggregateFolder.cs | 27 ++---
MediaBrowser.Controller/Entities/Audio/Audio.cs | 34 +++---
.../Entities/Audio/IHasMusicGenres.cs | 2 +-
.../Entities/Audio/MusicAlbum.cs | 52 ++++-----
.../Entities/Audio/MusicArtist.cs | 62 +++++------
.../Entities/Audio/MusicGenre.cs | 34 +++---
MediaBrowser.Controller/Entities/AudioBook.cs | 2 +-
MediaBrowser.Controller/Entities/Folder.cs | 9 +-
MediaBrowser.Controller/Entities/IHasShares.cs | 2 +-
.../Entities/InternalItemsQuery.cs | 116 ++++++++++-----------
MediaBrowser.Controller/Entities/Movies/BoxSet.cs | 50 ++++-----
MediaBrowser.Controller/Entities/Person.cs | 12 +--
MediaBrowser.Controller/Entities/Year.cs | 22 ++--
13 files changed, 216 insertions(+), 208 deletions(-)
diff --git a/MediaBrowser.Controller/Entities/AggregateFolder.cs b/MediaBrowser.Controller/Entities/AggregateFolder.cs
index e60549843..1127a56b3 100644
--- a/MediaBrowser.Controller/Entities/AggregateFolder.cs
+++ b/MediaBrowser.Controller/Entities/AggregateFolder.cs
@@ -22,36 +22,37 @@ namespace MediaBrowser.Controller.Entities
///
public class AggregateFolder : Folder
{
+ private readonly object _childIdsLock = new object();
+
+ ///
+ /// The _virtual children.
+ ///
+ private readonly ConcurrentBag _virtualChildren = new ConcurrentBag();
private bool _requiresRefresh;
private Guid[] _childrenIds = null;
- private readonly object _childIdsLock = new object();
public AggregateFolder()
{
PhysicalLocationsList = Array.Empty();
}
- [JsonIgnore]
- public override bool IsPhysicalRoot => true;
-
- [JsonIgnore]
- public override bool SupportsPlayedStatus => false;
-
- ///
- /// The _virtual children.
- ///
- private readonly ConcurrentBag _virtualChildren = new ConcurrentBag();
-
///
/// Gets the virtual children.
///
/// The virtual children.
public ConcurrentBag VirtualChildren => _virtualChildren;
+ [JsonIgnore]
+ public override bool IsPhysicalRoot => true;
+
+ [JsonIgnore]
+ public override bool SupportsPlayedStatus => false;
+
[JsonIgnore]
public override string[] PhysicalLocations => PhysicalLocationsList;
public string[] PhysicalLocationsList { get; set; }
+
public override bool CanDelete()
{
return false;
@@ -167,7 +168,7 @@ namespace MediaBrowser.Controller.Entities
/// Adds the virtual child.
///
/// The child.
- ///
+ /// Throws if child is null.
public void AddVirtualChild(BaseItem child)
{
if (child == null)
diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs
index 576ab67a2..7bf1219ec 100644
--- a/MediaBrowser.Controller/Entities/Audio/Audio.cs
+++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1002, CA1724, CA1826, CS1591
using System;
using System.Collections.Generic;
@@ -25,6 +25,12 @@ namespace MediaBrowser.Controller.Entities.Audio
IHasLookupInfo,
IHasMediaSources
{
+ public Audio()
+ {
+ Artists = Array.Empty();
+ AlbumArtists = Array.Empty();
+ }
+
///
[JsonIgnore]
public IReadOnlyList Artists { get; set; }
@@ -33,17 +39,6 @@ namespace MediaBrowser.Controller.Entities.Audio
[JsonIgnore]
public IReadOnlyList AlbumArtists { get; set; }
- public Audio()
- {
- Artists = Array.Empty();
- AlbumArtists = Array.Empty();
- }
-
- public override double GetDefaultPrimaryImageAspectRatio()
- {
- return 1;
- }
-
[JsonIgnore]
public override bool SupportsPlayedStatus => true;
@@ -62,11 +57,6 @@ namespace MediaBrowser.Controller.Entities.Audio
[JsonIgnore]
public override Folder LatestItemsIndexContainer => AlbumEntity;
- public override bool CanDownload()
- {
- return IsFileProtocol;
- }
-
[JsonIgnore]
public MusicAlbum AlbumEntity => FindParent();
@@ -77,6 +67,16 @@ namespace MediaBrowser.Controller.Entities.Audio
[JsonIgnore]
public override string MediaType => Model.Entities.MediaType.Audio;
+ public override double GetDefaultPrimaryImageAspectRatio()
+ {
+ return 1;
+ }
+
+ public override bool CanDownload()
+ {
+ return IsFileProtocol;
+ }
+
///
/// Creates the name of the sort.
///
diff --git a/MediaBrowser.Controller/Entities/Audio/IHasMusicGenres.cs b/MediaBrowser.Controller/Entities/Audio/IHasMusicGenres.cs
index db60c3071..c2dae5a2d 100644
--- a/MediaBrowser.Controller/Entities/Audio/IHasMusicGenres.cs
+++ b/MediaBrowser.Controller/Entities/Audio/IHasMusicGenres.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1819, CS1591
namespace MediaBrowser.Controller.Entities.Audio
{
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
index 610bce4f5..03d1f3304 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1721, CA1826, CS1591
using System;
using System.Collections.Generic;
@@ -23,18 +23,18 @@ namespace MediaBrowser.Controller.Entities.Audio
///
public class MusicAlbum : Folder, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo, IMetadataContainer
{
- ///
- public IReadOnlyList AlbumArtists { get; set; }
-
- ///
- public IReadOnlyList Artists { get; set; }
-
public MusicAlbum()
{
Artists = Array.Empty();
AlbumArtists = Array.Empty();
}
+ ///
+ public IReadOnlyList AlbumArtists { get; set; }
+
+ ///
+ public IReadOnlyList Artists { get; set; }
+
[JsonIgnore]
public override bool SupportsAddingToPlaylist => true;
@@ -44,6 +44,25 @@ namespace MediaBrowser.Controller.Entities.Audio
[JsonIgnore]
public MusicArtist MusicArtist => GetMusicArtist(new DtoOptions(true));
+ [JsonIgnore]
+ public override bool SupportsPlayedStatus => false;
+
+ [JsonIgnore]
+ public override bool SupportsCumulativeRunTimeTicks => true;
+
+ [JsonIgnore]
+ public string AlbumArtist => AlbumArtists.FirstOrDefault();
+
+ [JsonIgnore]
+ public override bool SupportsPeople => false;
+
+ ///
+ /// Gets the tracks.
+ ///
+ /// The tracks.
+ [JsonIgnore]
+ public IEnumerable