aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Emby.Server.Implementations/ConfigurationOptions.cs1
-rw-r--r--Emby.Server.Implementations/Library/LibraryManager.cs3
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicArtist.cs1
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs8
-rw-r--r--MediaBrowser.Providers/MediaBrowser.Providers.csproj5
-rw-r--r--MediaBrowser.Providers/Music/MusicExternalIds.cs95
-rw-r--r--MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs (renamed from MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs)45
-rw-r--r--MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs (renamed from MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs)19
-rw-r--r--MediaBrowser.Providers/Plugins/MusicBrainz/Configuration/PluginConfiguration.cs16
-rw-r--r--MediaBrowser.Providers/Plugins/MusicBrainz/Configuration/config.html69
-rw-r--r--MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzExternalIds.cs102
-rw-r--r--MediaBrowser.Providers/Plugins/MusicBrainz/Plugin.cs35
12 files changed, 273 insertions, 126 deletions
diff --git a/Emby.Server.Implementations/ConfigurationOptions.cs b/Emby.Server.Implementations/ConfigurationOptions.cs
index 2ea7ff6e9..d0f3d6723 100644
--- a/Emby.Server.Implementations/ConfigurationOptions.cs
+++ b/Emby.Server.Implementations/ConfigurationOptions.cs
@@ -8,7 +8,6 @@ namespace Emby.Server.Implementations
public static Dictionary<string, string> Configuration => new Dictionary<string, string>
{
{ "HttpListenerHost:DefaultRedirectPath", "web/index.html" },
- { "MusicBrainz:BaseUrl", "https://www.musicbrainz.org" },
{ FfmpegProbeSizeKey, "1G" },
{ FfmpegAnalyzeDurationKey, "200M" }
};
diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs
index 55566ed51..8a66ffdaa 100644
--- a/Emby.Server.Implementations/Library/LibraryManager.cs
+++ b/Emby.Server.Implementations/Library/LibraryManager.cs
@@ -944,7 +944,6 @@ namespace Emby.Server.Implementations.Library
IncludeItemTypes = new[] { typeof(T).Name },
Name = name,
DtoOptions = options
-
}).Cast<MusicArtist>()
.OrderBy(i => i.IsAccessedByName ? 1 : 0)
.Cast<T>()
@@ -1080,7 +1079,7 @@ namespace Emby.Server.Implementations.Library
var innerProgress = new ActionableProgress<double>();
- innerProgress.RegisterAction(pct => progress.Report(pct * pct * 0.96));
+ innerProgress.RegisterAction(pct => progress.Report(pct * 0.96));
// Validate the entire media library
await RootFolder.ValidateChildren(innerProgress, cancellationToken, new MetadataRefreshOptions(new DirectoryService(_fileSystem)), recursive: true).ConfigureAwait(false);
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
index efe0d3cf7..5e3056ccb 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
@@ -198,6 +198,7 @@ namespace MediaBrowser.Controller.Entities.Audio
return true;
}
}
+
return base.RequiresRefresh();
}
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index 07fbe6035..a892be7a9 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -322,10 +322,10 @@ namespace MediaBrowser.Controller.Entities
ProviderManager.OnRefreshProgress(this, 5);
}
- //build a dictionary of the current children we have now by Id so we can compare quickly and easily
+ // Build a dictionary of the current children we have now by Id so we can compare quickly and easily
var currentChildren = GetActualChildrenDictionary();
- //create a list for our validated children
+ // Create a list for our validated children
var newItems = new List<BaseItem>();
cancellationToken.ThrowIfCancellationRequested();
@@ -391,7 +391,7 @@ namespace MediaBrowser.Controller.Entities
var folder = this;
innerProgress.RegisterAction(p =>
{
- double newPct = .80 * p + 10;
+ double newPct = 0.80 * p + 10;
progress.Report(newPct);
ProviderManager.OnRefreshProgress(folder, newPct);
});
@@ -421,7 +421,7 @@ namespace MediaBrowser.Controller.Entities
var folder = this;
innerProgress.RegisterAction(p =>
{
- double newPct = .10 * p + 90;
+ double newPct = 0.10 * p + 90;
progress.Report(newPct);
if (recursive)
{
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index 5593c5036..48c16b643 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -24,4 +24,9 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
+ <ItemGroup>
+ <None Remove="Plugins\MusicBrainz\Configuration\config.html" />
+ <EmbeddedResource Include="Plugins\MusicBrainz\Configuration\config.html" />
+ </ItemGroup>
+
</Project>
diff --git a/MediaBrowser.Providers/Music/MusicExternalIds.cs b/MediaBrowser.Providers/Music/MusicExternalIds.cs
index 585c98af9..b431c1e41 100644
--- a/MediaBrowser.Providers/Music/MusicExternalIds.cs
+++ b/MediaBrowser.Providers/Music/MusicExternalIds.cs
@@ -5,101 +5,6 @@ using MediaBrowser.Model.Entities;
namespace MediaBrowser.Providers.Music
{
- public class MusicBrainzReleaseGroupExternalId : IExternalId
- {
- /// <inheritdoc />
- public string Name => "MusicBrainz Release Group";
-
- /// <inheritdoc />
- public string Key => MetadataProviders.MusicBrainzReleaseGroup.ToString();
-
- /// <inheritdoc />
- public string UrlFormatString => "https://musicbrainz.org/release-group/{0}";
-
- /// <inheritdoc />
- public bool Supports(IHasProviderIds item)
- => item is Audio || item is MusicAlbum;
- }
-
- public class MusicBrainzAlbumArtistExternalId : IExternalId
- {
- /// <inheritdoc />
- public string Name => "MusicBrainz Album Artist";
-
- /// <inheritdoc />
- public string Key => MetadataProviders.MusicBrainzAlbumArtist.ToString();
-
- /// <inheritdoc />
- public string UrlFormatString => "https://musicbrainz.org/artist/{0}";
-
- /// <inheritdoc />
- public bool Supports(IHasProviderIds item)
- => item is Audio;
- }
-
- public class MusicBrainzAlbumExternalId : IExternalId
- {
- /// <inheritdoc />
- public string Name => "MusicBrainz Album";
-
- /// <inheritdoc />
- public string Key => MetadataProviders.MusicBrainzAlbum.ToString();
-
- /// <inheritdoc />
- public string UrlFormatString => "https://musicbrainz.org/release/{0}";
-
- /// <inheritdoc />
- public bool Supports(IHasProviderIds item)
- => item is Audio || item is MusicAlbum;
- }
-
- public class MusicBrainzArtistExternalId : IExternalId
- {
- /// <inheritdoc />
- public string Name => "MusicBrainz";
-
- /// <inheritdoc />
- public string Key => MetadataProviders.MusicBrainzArtist.ToString();
-
- /// <inheritdoc />
- public string UrlFormatString => "https://musicbrainz.org/artist/{0}";
-
- /// <inheritdoc />
- public bool Supports(IHasProviderIds item) => item is MusicArtist;
- }
-
- public class MusicBrainzOtherArtistExternalId : IExternalId
- {
- /// <inheritdoc />
- public string Name => "MusicBrainz Artist";
-
- /// <inheritdoc />
-
- public string Key => MetadataProviders.MusicBrainzArtist.ToString();
-
- /// <inheritdoc />
- public string UrlFormatString => "https://musicbrainz.org/artist/{0}";
-
- /// <inheritdoc />
- public bool Supports(IHasProviderIds item)
- => item is Audio || item is MusicAlbum;
- }
-
- public class MusicBrainzTrackId : IExternalId
- {
- /// <inheritdoc />
- public string Name => "MusicBrainz Track";
-
- /// <inheritdoc />
- public string Key => MetadataProviders.MusicBrainzTrack.ToString();
-
- /// <inheritdoc />
- public string UrlFormatString => "https://musicbrainz.org/track/{0}";
-
- /// <inheritdoc />
- public bool Supports(IHasProviderIds item) => item is Audio;
- }
-
public class ImvdbId : IExternalId
{
/// <inheritdoc />
diff --git a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs
index 8e71b625e..0fddb0557 100644
--- a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs
@@ -15,7 +15,7 @@ using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
-using Microsoft.Extensions.Configuration;
+using MediaBrowser.Providers.Plugins.MusicBrainz;
using Microsoft.Extensions.Logging;
namespace MediaBrowser.Providers.Music
@@ -28,7 +28,7 @@ namespace MediaBrowser.Providers.Music
/// Be prudent, use a value slightly above the minimun required.
/// https://musicbrainz.org/doc/XML_Web_Service/Rate_Limiting
/// </summary>
- private const long MusicBrainzQueryIntervalMs = 1050u;
+ private readonly long _musicBrainzQueryIntervalMs = 1050u;
/// <summary>
/// For each single MB lookup/search, this is the maximum number of
@@ -50,14 +50,14 @@ namespace MediaBrowser.Providers.Music
public MusicBrainzAlbumProvider(
IHttpClient httpClient,
IApplicationHost appHost,
- ILogger logger,
- IConfiguration configuration)
+ ILogger logger)
{
_httpClient = httpClient;
_appHost = appHost;
_logger = logger;
- _musicBrainzBaseUrl = configuration["MusicBrainz:BaseUrl"];
+ _musicBrainzBaseUrl = Plugin.Instance.Configuration.Server;
+ _musicBrainzQueryIntervalMs = Plugin.Instance.Configuration.RateLimit;
// Use a stopwatch to ensure we don't exceed the MusicBrainz rate limit
_stopWatchMusicBrainz.Start();
@@ -74,6 +74,12 @@ namespace MediaBrowser.Providers.Music
/// <inheritdoc />
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(AlbumInfo searchInfo, CancellationToken cancellationToken)
{
+ // TODO maybe remove when artist metadata can be disabled
+ if (!Plugin.Instance.Configuration.Enable)
+ {
+ return Enumerable.Empty<RemoteSearchResult>();
+ }
+
var releaseId = searchInfo.GetReleaseId();
var releaseGroupId = searchInfo.GetReleaseGroupId();
@@ -107,8 +113,8 @@ namespace MediaBrowser.Providers.Music
url = string.Format(
CultureInfo.InvariantCulture,
"/ws/2/release/?query=\"{0}\" AND artist:\"{1}\"",
- WebUtility.UrlEncode(queryName),
- WebUtility.UrlEncode(searchInfo.GetAlbumArtist()));
+ WebUtility.UrlEncode(queryName),
+ WebUtility.UrlEncode(searchInfo.GetAlbumArtist()));
}
}
@@ -170,7 +176,6 @@ namespace MediaBrowser.Providers.Music
}
return result;
-
});
}
}
@@ -187,6 +192,12 @@ namespace MediaBrowser.Providers.Music
Item = new MusicAlbum()
};
+ // TODO maybe remove when artist metadata can be disabled
+ if (!Plugin.Instance.Configuration.Enable)
+ {
+ return result;
+ }
+
// If we have a release group Id but not a release Id...
if (string.IsNullOrWhiteSpace(releaseId) && !string.IsNullOrWhiteSpace(releaseGroupId))
{
@@ -456,18 +467,6 @@ namespace MediaBrowser.Providers.Music
}
case "artist-credit":
{
- // TODO
-
- /*
- * <artist-credit>
-<name-credit>
-<artist id="e225cda5-882d-4b80-b8a3-b36d7175b1ea">
-<name>SARCASTIC+ZOOKEEPER</name>
-<sort-name>SARCASTIC+ZOOKEEPER</sort-name>
-</artist>
-</name-credit>
-</artist-credit>
- */
using (var subReader = reader.ReadSubtree())
{
var artist = ParseArtistCredit(subReader);
@@ -764,10 +763,10 @@ namespace MediaBrowser.Providers.Music
{
attempts++;
- if (_stopWatchMusicBrainz.ElapsedMilliseconds < MusicBrainzQueryIntervalMs)
+ if (_stopWatchMusicBrainz.ElapsedMilliseconds < _musicBrainzQueryIntervalMs)
{
// MusicBrainz is extremely adamant about limiting to one request per second
- var delayMs = MusicBrainzQueryIntervalMs - _stopWatchMusicBrainz.ElapsedMilliseconds;
+ var delayMs = _musicBrainzQueryIntervalMs - _stopWatchMusicBrainz.ElapsedMilliseconds;
await Task.Delay((int)delayMs, cancellationToken).ConfigureAwait(false);
}
@@ -778,7 +777,7 @@ namespace MediaBrowser.Providers.Music
response = await _httpClient.SendAsync(options, "GET").ConfigureAwait(false);
- // We retry a finite number of times, and only whilst MB is indcating 503 (throttling)
+ // We retry a finite number of times, and only whilst MB is indicating 503 (throttling)
}
while (attempts < MusicBrainzQueryAttempts && response.StatusCode == HttpStatusCode.ServiceUnavailable);
diff --git a/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs
index 5d675392c..260a3b6e7 100644
--- a/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs
@@ -14,6 +14,7 @@ using MediaBrowser.Controller.Extensions;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
+using MediaBrowser.Providers.Plugins.MusicBrainz;
namespace MediaBrowser.Providers.Music
{
@@ -22,6 +23,12 @@ namespace MediaBrowser.Providers.Music
/// <inheritdoc />
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(ArtistInfo searchInfo, CancellationToken cancellationToken)
{
+ // TODO maybe remove when artist metadata can be disabled
+ if (!Plugin.Instance.Configuration.Enable)
+ {
+ return Enumerable.Empty<RemoteSearchResult>();
+ }
+
var musicBrainzId = searchInfo.GetMusicBrainzArtistId();
if (!string.IsNullOrWhiteSpace(musicBrainzId))
@@ -226,6 +233,12 @@ namespace MediaBrowser.Providers.Music
Item = new MusicArtist()
};
+ // TODO maybe remove when artist metadata can be disabled
+ if (!Plugin.Instance.Configuration.Enable)
+ {
+ return result;
+ }
+
var musicBrainzId = id.GetMusicBrainzArtistId();
if (string.IsNullOrWhiteSpace(musicBrainzId))
@@ -237,8 +250,12 @@ namespace MediaBrowser.Providers.Music
if (singleResult != null)
{
musicBrainzId = singleResult.GetProviderId(MetadataProviders.MusicBrainzArtist);
- //result.Item.Name = singleResult.Name;
result.Item.Overview = singleResult.Overview;
+
+ if (Plugin.Instance.Configuration.ReplaceArtistName)
+ {
+ result.Item.Name = singleResult.Name;
+ }
}
}
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/Configuration/PluginConfiguration.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/Configuration/PluginConfiguration.cs
new file mode 100644
index 000000000..6bce0b447
--- /dev/null
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/Configuration/PluginConfiguration.cs
@@ -0,0 +1,16 @@
+using System.Collections.Generic;
+using MediaBrowser.Model.Plugins;
+
+namespace MediaBrowser.Providers.Plugins.MusicBrainz
+{
+ public class PluginConfiguration : BasePluginConfiguration
+ {
+ public bool Enable { get; set; } = false;
+
+ public bool ReplaceArtistName { get; set; } = false;
+
+ public string Server { get; set; } = "https://www.musicbrainz.org";
+
+ public long RateLimit { get; set; } = 1000u;
+ }
+}
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/Configuration/config.html b/MediaBrowser.Providers/Plugins/MusicBrainz/Configuration/config.html
new file mode 100644
index 000000000..dfffa9065
--- /dev/null
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/Configuration/config.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>MusicBrainz</title>
+</head>
+<body>
+ <div data-role="page" class="page type-interior pluginConfigurationPage musicBrainzConfigPage" data-require="emby-input,emby-button,emby-checkbox">
+ <div data-role="content">
+ <div class="content-primary">
+ <form class="musicBrainzConfigForm">
+ <div class="inputContainer">
+ <input is="emby-input" type="text" id="server" label="Server:" />
+ <div class="fieldDescription">This can either be a mirror of the official server or a custom server.</div>
+ </div>
+ <div class="inputContainer">
+ <input is="emby-input" type="number" id="rateLimit" pattern="[0-9]*" required min="400" max="10000" label="Rate Limit:" />
+ <div class="fieldDescription">Span of time between each request in milliseconds.</div>
+ </div>
+ <label class="checkboxContainer">
+ <input is="emby-checkbox" type="checkbox" id="enable" />
+ <span>Enable this provider for metadata searches on artists and albums.</span>
+ </label>
+ <label class="checkboxContainer">
+ <input is="emby-checkbox" type="checkbox" id="replaceArtistName" />
+ <span>When an artist is found during a metadata search, replace the artist name with the value on the server.</span>
+ </label>
+ <br />
+ <div>
+ <button is="emby-button" type="submit" class="raised button-submit block"><span>Save</span></button>
+ </div>
+ </form>
+ </div>
+ </div>
+ <script type="text/javascript">
+ var MusicBrainzPluginConfig = {
+ uniquePluginId: "8c95c4d2-e50c-4fb0-a4f3-6c06ff0f9a1a"
+ };
+
+ $('.musicBrainzConfigPage').on('pageshow', function () {
+ Dashboard.showLoadingMsg();
+ ApiClient.getPluginConfiguration(MusicBrainzPluginConfig.uniquePluginId).then(function (config) {
+ $('#server').val(config.Server).change();
+ $('#rateLimit').val(config.RateLimit).change();
+ $('#enable').checked(config.Enable);
+ $('#replaceArtistName').checked(config.ReplaceArtistName);
+
+ Dashboard.hideLoadingMsg();
+ });
+ });
+
+ $('.musicBrainzConfigForm').on('submit', function (e) {
+ Dashboard.showLoadingMsg();
+
+ var form = this;
+ ApiClient.getPluginConfiguration(MusicBrainzPluginConfig.uniquePluginId).then(function (config) {
+ config.Server = $('#server', form).val();
+ config.RateLimit = $('#rateLimit', form).val();
+ config.Enable = $('#enable', form).checked();
+ config.ReplaceArtistName = $('#replaceArtistName', form).checked();
+
+ ApiClient.updatePluginConfiguration(MusicBrainzPluginConfig.uniquePluginId, config).then(Dashboard.processPluginConfigurationUpdateResult);
+ });
+
+ return false;
+ });
+ </script>
+ </div>
+</body>
+</html>
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzExternalIds.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzExternalIds.cs
new file mode 100644
index 000000000..0184d4241
--- /dev/null
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzExternalIds.cs
@@ -0,0 +1,102 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+
+namespace MediaBrowser.Providers.Music
+{
+ public class MusicBrainzReleaseGroupExternalId : IExternalId
+ {
+ /// <inheritdoc />
+ public string Name => "MusicBrainz Release Group";
+
+ /// <inheritdoc />
+ public string Key => MetadataProviders.MusicBrainzReleaseGroup.ToString();
+
+ /// <inheritdoc />
+ public string UrlFormatString => "https://musicbrainz.org/release-group/{0}";
+
+ /// <inheritdoc />
+ public bool Supports(IHasProviderIds item)
+ => item is Audio || item is MusicAlbum;
+ }
+
+ public class MusicBrainzAlbumArtistExternalId : IExternalId
+ {
+ /// <inheritdoc />
+ public string Name => "MusicBrainz Album Artist";
+
+ /// <inheritdoc />
+ public string Key => MetadataProviders.MusicBrainzAlbumArtist.ToString();
+
+ /// <inheritdoc />
+ public string UrlFormatString => "https://musicbrainz.org/artist/{0}";
+
+ /// <inheritdoc />
+ public bool Supports(IHasProviderIds item)
+ => item is Audio;
+ }
+
+ public class MusicBrainzAlbumExternalId : IExternalId
+ {
+ /// <inheritdoc />
+ public string Name => "MusicBrainz Album";
+
+ /// <inheritdoc />
+ public string Key => MetadataProviders.MusicBrainzAlbum.ToString();
+
+ /// <inheritdoc />
+ public string UrlFormatString => "https://musicbrainz.org/release/{0}";
+
+ /// <inheritdoc />
+ public bool Supports(IHasProviderIds item)
+ => item is Audio || item is MusicAlbum;
+ }
+
+ public class MusicBrainzArtistExternalId : IExternalId
+ {
+ /// <inheritdoc />
+ public string Name => "MusicBrainz";
+
+ /// <inheritdoc />
+ public string Key => MetadataProviders.MusicBrainzArtist.ToString();
+
+ /// <inheritdoc />
+ public string UrlFormatString => "https://musicbrainz.org/artist/{0}";
+
+ /// <inheritdoc />
+ public bool Supports(IHasProviderIds item) => item is MusicArtist;
+ }
+
+ public class MusicBrainzOtherArtistExternalId : IExternalId
+ {
+ /// <inheritdoc />
+ public string Name => "MusicBrainz Artist";
+
+ /// <inheritdoc />
+
+ public string Key => MetadataProviders.MusicBrainzArtist.ToString();
+
+ /// <inheritdoc />
+ public string UrlFormatString => "https://musicbrainz.org/artist/{0}";
+
+ /// <inheritdoc />
+ public bool Supports(IHasProviderIds item)
+ => item is Audio || item is MusicAlbum;
+ }
+
+ public class MusicBrainzTrackId : IExternalId
+ {
+ /// <inheritdoc />
+ public string Name => "MusicBrainz Track";
+
+ /// <inheritdoc />
+ public string Key => MetadataProviders.MusicBrainzTrack.ToString();
+
+ /// <inheritdoc />
+ public string UrlFormatString => "https://musicbrainz.org/track/{0}";
+
+ /// <inheritdoc />
+ public bool Supports(IHasProviderIds item) => item is Audio;
+ }
+}
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/Plugin.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/Plugin.cs
new file mode 100644
index 000000000..2211d513f
--- /dev/null
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/Plugin.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Plugins;
+using MediaBrowser.Model.Plugins;
+using MediaBrowser.Model.Serialization;
+
+namespace MediaBrowser.Providers.Plugins.MusicBrainz
+{
+ public class Plugin : BasePlugin<PluginConfiguration>, IHasWebPages
+ {
+ public Plugin(IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer)
+ : base(applicationPaths, xmlSerializer)
+ {
+ Instance = this;
+ }
+
+ public IEnumerable<PluginPageInfo> GetPages()
+ {
+ yield return new PluginPageInfo
+ {
+ Name = Name,
+ EmbeddedResourcePath = GetType().Namespace + ".Configuration.config.html"
+ };
+ }
+
+ public override Guid Id => new Guid("8c95c4d2-e50c-4fb0-a4f3-6c06ff0f9a1a");
+
+ public override string Name => "MusicBrainz";
+
+ public override string Description => "Get artist and album metadata from any MusicBrainz server.";
+
+ public static Plugin Instance { get; private set; }
+ }
+}