Merge pull request #2436 from dkanada/music
Add config options for MusicBrainz
This commit is contained in:
commit
13d30a0a79
|
@ -8,7 +8,6 @@ namespace Emby.Server.Implementations
|
||||||
public static Dictionary<string, string> Configuration => new Dictionary<string, string>
|
public static Dictionary<string, string> Configuration => new Dictionary<string, string>
|
||||||
{
|
{
|
||||||
{ "HttpListenerHost:DefaultRedirectPath", "web/index.html" },
|
{ "HttpListenerHost:DefaultRedirectPath", "web/index.html" },
|
||||||
{ "MusicBrainz:BaseUrl", "https://www.musicbrainz.org" },
|
|
||||||
{ FfmpegProbeSizeKey, "1G" },
|
{ FfmpegProbeSizeKey, "1G" },
|
||||||
{ FfmpegAnalyzeDurationKey, "200M" }
|
{ FfmpegAnalyzeDurationKey, "200M" }
|
||||||
};
|
};
|
||||||
|
|
|
@ -944,7 +944,6 @@ namespace Emby.Server.Implementations.Library
|
||||||
IncludeItemTypes = new[] { typeof(T).Name },
|
IncludeItemTypes = new[] { typeof(T).Name },
|
||||||
Name = name,
|
Name = name,
|
||||||
DtoOptions = options
|
DtoOptions = options
|
||||||
|
|
||||||
}).Cast<MusicArtist>()
|
}).Cast<MusicArtist>()
|
||||||
.OrderBy(i => i.IsAccessedByName ? 1 : 0)
|
.OrderBy(i => i.IsAccessedByName ? 1 : 0)
|
||||||
.Cast<T>()
|
.Cast<T>()
|
||||||
|
@ -1080,7 +1079,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
|
|
||||||
var innerProgress = new ActionableProgress<double>();
|
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
|
// Validate the entire media library
|
||||||
await RootFolder.ValidateChildren(innerProgress, cancellationToken, new MetadataRefreshOptions(new DirectoryService(_fileSystem)), recursive: true).ConfigureAwait(false);
|
await RootFolder.ValidateChildren(innerProgress, cancellationToken, new MetadataRefreshOptions(new DirectoryService(_fileSystem)), recursive: true).ConfigureAwait(false);
|
||||||
|
|
|
@ -198,6 +198,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.RequiresRefresh();
|
return base.RequiresRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -322,10 +322,10 @@ namespace MediaBrowser.Controller.Entities
|
||||||
ProviderManager.OnRefreshProgress(this, 5);
|
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();
|
var currentChildren = GetActualChildrenDictionary();
|
||||||
|
|
||||||
//create a list for our validated children
|
// Create a list for our validated children
|
||||||
var newItems = new List<BaseItem>();
|
var newItems = new List<BaseItem>();
|
||||||
|
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
@ -391,7 +391,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
var folder = this;
|
var folder = this;
|
||||||
innerProgress.RegisterAction(p =>
|
innerProgress.RegisterAction(p =>
|
||||||
{
|
{
|
||||||
double newPct = .80 * p + 10;
|
double newPct = 0.80 * p + 10;
|
||||||
progress.Report(newPct);
|
progress.Report(newPct);
|
||||||
ProviderManager.OnRefreshProgress(folder, newPct);
|
ProviderManager.OnRefreshProgress(folder, newPct);
|
||||||
});
|
});
|
||||||
|
@ -421,7 +421,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
var folder = this;
|
var folder = this;
|
||||||
innerProgress.RegisterAction(p =>
|
innerProgress.RegisterAction(p =>
|
||||||
{
|
{
|
||||||
double newPct = .10 * p + 90;
|
double newPct = 0.10 * p + 90;
|
||||||
progress.Report(newPct);
|
progress.Report(newPct);
|
||||||
if (recursive)
|
if (recursive)
|
||||||
{
|
{
|
||||||
|
|
|
@ -238,7 +238,7 @@ namespace MediaBrowser.Model.Configuration
|
||||||
CodecsUsed = Array.Empty<string>();
|
CodecsUsed = Array.Empty<string>();
|
||||||
PathSubstitutions = Array.Empty<PathSubstitution>();
|
PathSubstitutions = Array.Empty<PathSubstitution>();
|
||||||
IgnoreVirtualInterfaces = false;
|
IgnoreVirtualInterfaces = false;
|
||||||
EnableSimpleArtistDetection = true;
|
EnableSimpleArtistDetection = false;
|
||||||
|
|
||||||
DisplaySpecialsWithinSeasons = true;
|
DisplaySpecialsWithinSeasons = true;
|
||||||
EnableExternalContentInSuggestions = true;
|
EnableExternalContentInSuggestions = true;
|
||||||
|
|
|
@ -24,4 +24,9 @@
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="Plugins\MusicBrainz\Configuration\config.html" />
|
||||||
|
<EmbeddedResource Include="Plugins\MusicBrainz\Configuration\config.html" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1,105 +1,9 @@
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.Audio;
|
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
|
|
||||||
namespace MediaBrowser.Providers.Music
|
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
|
public class ImvdbId : IExternalId
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|
|
@ -15,7 +15,7 @@ using MediaBrowser.Controller.Entities.Audio;
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Providers;
|
using MediaBrowser.Model.Providers;
|
||||||
using Microsoft.Extensions.Configuration;
|
using MediaBrowser.Providers.Plugins.MusicBrainz;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace MediaBrowser.Providers.Music
|
namespace MediaBrowser.Providers.Music
|
||||||
|
@ -28,7 +28,7 @@ namespace MediaBrowser.Providers.Music
|
||||||
/// Be prudent, use a value slightly above the minimun required.
|
/// 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
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private const long MusicBrainzQueryIntervalMs = 1050u;
|
private readonly long _musicBrainzQueryIntervalMs;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// For each single MB lookup/search, this is the maximum number of
|
/// For each single MB lookup/search, this is the maximum number of
|
||||||
|
@ -50,14 +50,14 @@ namespace MediaBrowser.Providers.Music
|
||||||
public MusicBrainzAlbumProvider(
|
public MusicBrainzAlbumProvider(
|
||||||
IHttpClient httpClient,
|
IHttpClient httpClient,
|
||||||
IApplicationHost appHost,
|
IApplicationHost appHost,
|
||||||
ILogger logger,
|
ILogger logger)
|
||||||
IConfiguration configuration)
|
|
||||||
{
|
{
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
_appHost = appHost;
|
_appHost = appHost;
|
||||||
_logger = logger;
|
_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
|
// Use a stopwatch to ensure we don't exceed the MusicBrainz rate limit
|
||||||
_stopWatchMusicBrainz.Start();
|
_stopWatchMusicBrainz.Start();
|
||||||
|
@ -74,6 +74,12 @@ namespace MediaBrowser.Providers.Music
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(AlbumInfo searchInfo, CancellationToken cancellationToken)
|
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 releaseId = searchInfo.GetReleaseId();
|
||||||
var releaseGroupId = searchInfo.GetReleaseGroupId();
|
var releaseGroupId = searchInfo.GetReleaseGroupId();
|
||||||
|
|
||||||
|
@ -107,8 +113,8 @@ namespace MediaBrowser.Providers.Music
|
||||||
url = string.Format(
|
url = string.Format(
|
||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
"/ws/2/release/?query=\"{0}\" AND artist:\"{1}\"",
|
"/ws/2/release/?query=\"{0}\" AND artist:\"{1}\"",
|
||||||
WebUtility.UrlEncode(queryName),
|
WebUtility.UrlEncode(queryName),
|
||||||
WebUtility.UrlEncode(searchInfo.GetAlbumArtist()));
|
WebUtility.UrlEncode(searchInfo.GetAlbumArtist()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,7 +176,6 @@ namespace MediaBrowser.Providers.Music
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,6 +192,12 @@ namespace MediaBrowser.Providers.Music
|
||||||
Item = new MusicAlbum()
|
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 we have a release group Id but not a release Id...
|
||||||
if (string.IsNullOrWhiteSpace(releaseId) && !string.IsNullOrWhiteSpace(releaseGroupId))
|
if (string.IsNullOrWhiteSpace(releaseId) && !string.IsNullOrWhiteSpace(releaseGroupId))
|
||||||
{
|
{
|
||||||
|
@ -456,18 +467,6 @@ namespace MediaBrowser.Providers.Music
|
||||||
}
|
}
|
||||||
case "artist-credit":
|
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())
|
using (var subReader = reader.ReadSubtree())
|
||||||
{
|
{
|
||||||
var artist = ParseArtistCredit(subReader);
|
var artist = ParseArtistCredit(subReader);
|
||||||
|
@ -764,10 +763,10 @@ namespace MediaBrowser.Providers.Music
|
||||||
{
|
{
|
||||||
attempts++;
|
attempts++;
|
||||||
|
|
||||||
if (_stopWatchMusicBrainz.ElapsedMilliseconds < MusicBrainzQueryIntervalMs)
|
if (_stopWatchMusicBrainz.ElapsedMilliseconds < _musicBrainzQueryIntervalMs)
|
||||||
{
|
{
|
||||||
// MusicBrainz is extremely adamant about limiting to one request per second
|
// 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);
|
await Task.Delay((int)delayMs, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -778,7 +777,7 @@ namespace MediaBrowser.Providers.Music
|
||||||
|
|
||||||
response = await _httpClient.SendAsync(options, "GET").ConfigureAwait(false);
|
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);
|
while (attempts < MusicBrainzQueryAttempts && response.StatusCode == HttpStatusCode.ServiceUnavailable);
|
||||||
|
|
|
@ -14,6 +14,7 @@ using MediaBrowser.Controller.Extensions;
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Providers;
|
using MediaBrowser.Model.Providers;
|
||||||
|
using MediaBrowser.Providers.Plugins.MusicBrainz;
|
||||||
|
|
||||||
namespace MediaBrowser.Providers.Music
|
namespace MediaBrowser.Providers.Music
|
||||||
{
|
{
|
||||||
|
@ -22,6 +23,12 @@ namespace MediaBrowser.Providers.Music
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(ArtistInfo searchInfo, CancellationToken cancellationToken)
|
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();
|
var musicBrainzId = searchInfo.GetMusicBrainzArtistId();
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(musicBrainzId))
|
if (!string.IsNullOrWhiteSpace(musicBrainzId))
|
||||||
|
@ -226,6 +233,12 @@ namespace MediaBrowser.Providers.Music
|
||||||
Item = new MusicArtist()
|
Item = new MusicArtist()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO maybe remove when artist metadata can be disabled
|
||||||
|
if (!Plugin.Instance.Configuration.Enable)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
var musicBrainzId = id.GetMusicBrainzArtistId();
|
var musicBrainzId = id.GetMusicBrainzArtistId();
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(musicBrainzId))
|
if (string.IsNullOrWhiteSpace(musicBrainzId))
|
||||||
|
@ -237,8 +250,12 @@ namespace MediaBrowser.Providers.Music
|
||||||
if (singleResult != null)
|
if (singleResult != null)
|
||||||
{
|
{
|
||||||
musicBrainzId = singleResult.GetProviderId(MetadataProviders.MusicBrainzArtist);
|
musicBrainzId = singleResult.GetProviderId(MetadataProviders.MusicBrainzArtist);
|
||||||
//result.Item.Name = singleResult.Name;
|
|
||||||
result.Item.Overview = singleResult.Overview;
|
result.Item.Overview = singleResult.Overview;
|
||||||
|
|
||||||
|
if (Plugin.Instance.Configuration.ReplaceArtistName)
|
||||||
|
{
|
||||||
|
result.Item.Name = singleResult.Name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
using MediaBrowser.Model.Plugins;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Providers.Plugins.MusicBrainz
|
||||||
|
{
|
||||||
|
public class PluginConfiguration : BasePluginConfiguration
|
||||||
|
{
|
||||||
|
private string _server = Plugin.DefaultServer;
|
||||||
|
|
||||||
|
private long _rateLimit = Plugin.DefaultRateLimit;
|
||||||
|
|
||||||
|
public string Server
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _server;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_server = value.TrimEnd('/');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public long RateLimit
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _rateLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value < Plugin.DefaultRateLimit && _server == Plugin.DefaultServer)
|
||||||
|
{
|
||||||
|
RateLimit = Plugin.DefaultRateLimit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Enable { get; set; }
|
||||||
|
|
||||||
|
public bool ReplaceArtistName { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -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" required label="Server" />
|
||||||
|
<div class="fieldDescription">This can be a mirror of the official server or even a custom server.</div>
|
||||||
|
</div>
|
||||||
|
<div class="inputContainer">
|
||||||
|
<input is="emby-input" type="number" id="rateLimit" pattern="[0-9]*" required min="0" max="10000" label="Rate Limit" />
|
||||||
|
<div class="fieldDescription">Span of time between requests in milliseconds. The official server is limited to one request every two seconds.</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>
|
98
MediaBrowser.Providers/Plugins/MusicBrainz/ExternalIds.cs
Normal file
98
MediaBrowser.Providers/Plugins/MusicBrainz/ExternalIds.cs
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
using MediaBrowser.Controller.Entities.Audio;
|
||||||
|
using MediaBrowser.Controller.Providers;
|
||||||
|
using MediaBrowser.Model.Entities;
|
||||||
|
using MediaBrowser.Providers.Plugins.MusicBrainz;
|
||||||
|
|
||||||
|
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 => Plugin.Instance.Configuration.Server + "/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 => Plugin.Instance.Configuration.Server + "/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 => Plugin.Instance.Configuration.Server + "/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 => Plugin.Instance.Configuration.Server + "/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 => Plugin.Instance.Configuration.Server + "/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 => Plugin.Instance.Configuration.Server + "/track/{0}";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public bool Supports(IHasProviderIds item) => item is Audio;
|
||||||
|
}
|
||||||
|
}
|
39
MediaBrowser.Providers/Plugins/MusicBrainz/Plugin.cs
Normal file
39
MediaBrowser.Providers/Plugins/MusicBrainz/Plugin.cs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
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 static Plugin Instance { get; private set; }
|
||||||
|
|
||||||
|
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 const string DefaultServer = "https://musicbrainz.org";
|
||||||
|
|
||||||
|
public const long DefaultRateLimit = 2000u;
|
||||||
|
|
||||||
|
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"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user