aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Controller')
-rw-r--r--MediaBrowser.Controller/Drawing/ImageExtensions.cs8
-rw-r--r--MediaBrowser.Controller/Drawing/ImageFormat.cs11
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs122
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs13
-rw-r--r--MediaBrowser.Controller/Entities/IHasImages.cs27
-rw-r--r--MediaBrowser.Controller/Entities/IHasScreenshots.cs6
-rw-r--r--MediaBrowser.Controller/Entities/Movies/Movie.cs19
-rw-r--r--MediaBrowser.Controller/Entities/User.cs20
-rw-r--r--MediaBrowser.Controller/Entities/Video.cs16
-rw-r--r--MediaBrowser.Controller/IO/IDirectoryWatchers.cs29
-rw-r--r--MediaBrowser.Controller/Library/ILibraryMonitor.cs36
-rw-r--r--MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs5
-rw-r--r--MediaBrowser.Controller/LiveTv/StreamResponseInfo.cs5
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj12
-rw-r--r--MediaBrowser.Controller/Persistence/IItemRepository.cs17
-rw-r--r--MediaBrowser.Controller/Providers/IHasMetadata.cs31
-rw-r--r--MediaBrowser.Controller/Providers/IImageProvider.cs28
-rw-r--r--MediaBrowser.Controller/Providers/ILocalImageProvider.cs66
-rw-r--r--MediaBrowser.Controller/Providers/IMetadataProvider.cs68
-rw-r--r--MediaBrowser.Controller/Providers/IMetadataService.cs38
-rw-r--r--MediaBrowser.Controller/Providers/IProviderManager.cs20
-rw-r--r--MediaBrowser.Controller/Providers/IProviderRepository.cs48
-rw-r--r--MediaBrowser.Controller/Providers/IRemoteImageProvider.cs48
-rw-r--r--MediaBrowser.Controller/Providers/ItemId.cs35
-rw-r--r--MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs49
-rw-r--r--MediaBrowser.Controller/Providers/MetadataStatus.cs122
26 files changed, 761 insertions, 138 deletions
diff --git a/MediaBrowser.Controller/Drawing/ImageExtensions.cs b/MediaBrowser.Controller/Drawing/ImageExtensions.cs
index 9dc58b3d2..c7e1968e7 100644
--- a/MediaBrowser.Controller/Drawing/ImageExtensions.cs
+++ b/MediaBrowser.Controller/Drawing/ImageExtensions.cs
@@ -18,17 +18,17 @@ namespace MediaBrowser.Controller.Drawing
/// <param name="image">The image.</param>
/// <param name="toStream">To stream.</param>
/// <param name="quality">The quality.</param>
- public static void Save(this Image image, ImageFormat outputFormat, Stream toStream, int quality)
+ public static void Save(this Image image, System.Drawing.Imaging.ImageFormat outputFormat, Stream toStream, int quality)
{
// Use special save methods for jpeg and png that will result in a much higher quality image
// All other formats use the generic Image.Save
- if (ImageFormat.Jpeg.Equals(outputFormat))
+ if (System.Drawing.Imaging.ImageFormat.Jpeg.Equals(outputFormat))
{
SaveAsJpeg(image, toStream, quality);
}
- else if (ImageFormat.Png.Equals(outputFormat))
+ else if (System.Drawing.Imaging.ImageFormat.Png.Equals(outputFormat))
{
- image.Save(toStream, ImageFormat.Png);
+ image.Save(toStream, System.Drawing.Imaging.ImageFormat.Png);
}
else
{
diff --git a/MediaBrowser.Controller/Drawing/ImageFormat.cs b/MediaBrowser.Controller/Drawing/ImageFormat.cs
new file mode 100644
index 000000000..f78562556
--- /dev/null
+++ b/MediaBrowser.Controller/Drawing/ImageFormat.cs
@@ -0,0 +1,11 @@
+
+namespace MediaBrowser.Controller.Drawing
+{
+ public enum ImageFormat
+ {
+ Jpg,
+ Png,
+ Gif,
+ Bmp
+ }
+}
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index 7840fb3f0..06ebe8905 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -23,7 +23,7 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Class BaseItem
/// </summary>
- public abstract class BaseItem : IHasProviderIds, ILibraryItem, IHasImages, IHasUserData
+ public abstract class BaseItem : IHasProviderIds, ILibraryItem, IHasImages, IHasUserData, IHasMetadata
{
protected BaseItem()
{
@@ -364,11 +364,16 @@ namespace MediaBrowser.Controller.Entities
}
}
+ private string _forcedSortName;
/// <summary>
/// Gets or sets the name of the forced sort.
/// </summary>
/// <value>The name of the forced sort.</value>
- public string ForcedSortName { get; set; }
+ public string ForcedSortName
+ {
+ get { return _forcedSortName; }
+ set { _forcedSortName = value; _sortName = null; }
+ }
private string _sortName;
/// <summary>
@@ -767,25 +772,35 @@ namespace MediaBrowser.Controller.Entities
}).ToList();
}
+ public Task<bool> RefreshMetadata(CancellationToken cancellationToken, bool resetResolveArgs = true)
+ {
+ return RefreshMetadata(new MetadataRefreshOptions { ResetResolveArgs = resetResolveArgs }, cancellationToken);
+ }
+
/// <summary>
/// Overrides the base implementation to refresh metadata for local trailers
/// </summary>
+ /// <param name="options">The options.</param>
/// <param name="cancellationToken">The cancellation token.</param>
- /// <param name="forceSave">if set to <c>true</c> [is new item].</param>
- /// <param name="forceRefresh">if set to <c>true</c> [force].</param>
- /// <param name="allowSlowProviders">if set to <c>true</c> [allow slow providers].</param>
- /// <param name="resetResolveArgs">if set to <c>true</c> [reset resolve args].</param>
/// <returns>true if a provider reports we changed</returns>
- public virtual async Task<bool> RefreshMetadata(CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false, bool allowSlowProviders = true, bool resetResolveArgs = true)
+ public async Task<bool> RefreshMetadata(MetadataRefreshOptions options, CancellationToken cancellationToken)
{
- if (resetResolveArgs)
+ if (options.ResetResolveArgs)
{
// Reload this
ResetResolveArgs();
}
+ await ProviderManager.RefreshMetadata(this, options, cancellationToken).ConfigureAwait(false);
+
+ return false;
+ }
+
+ [Obsolete]
+ public virtual async Task<bool> RefreshMetadataDirect(CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false)
+ {
// Refresh for the item
- var itemRefreshTask = ProviderManager.ExecuteMetadataProviders(this, cancellationToken, forceRefresh, allowSlowProviders);
+ var itemRefreshTask = ProviderManager.ExecuteMetadataProviders(this, cancellationToken, forceRefresh);
cancellationToken.ThrowIfCancellationRequested();
@@ -800,15 +815,15 @@ namespace MediaBrowser.Controller.Entities
var hasThemeMedia = this as IHasThemeMedia;
if (hasThemeMedia != null)
{
- themeSongsChanged = await RefreshThemeSongs(hasThemeMedia, cancellationToken, forceSave, forceRefresh, allowSlowProviders).ConfigureAwait(false);
+ themeSongsChanged = await RefreshThemeSongs(hasThemeMedia, cancellationToken, forceSave, forceRefresh).ConfigureAwait(false);
- themeVideosChanged = await RefreshThemeVideos(hasThemeMedia, cancellationToken, forceSave, forceRefresh, allowSlowProviders).ConfigureAwait(false);
+ themeVideosChanged = await RefreshThemeVideos(hasThemeMedia, cancellationToken, forceSave, forceRefresh).ConfigureAwait(false);
}
var hasTrailers = this as IHasTrailers;
if (hasTrailers != null)
{
- localTrailersChanged = await RefreshLocalTrailers(hasTrailers, cancellationToken, forceSave, forceRefresh, allowSlowProviders).ConfigureAwait(false);
+ localTrailersChanged = await RefreshLocalTrailers(hasTrailers, cancellationToken, forceSave, forceRefresh).ConfigureAwait(false);
}
}
@@ -829,14 +844,20 @@ namespace MediaBrowser.Controller.Entities
return changed;
}
- private async Task<bool> RefreshLocalTrailers(IHasTrailers item, CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false, bool allowSlowProviders = true)
+ private async Task<bool> RefreshLocalTrailers(IHasTrailers item, CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false)
{
var newItems = LoadLocalTrailers().ToList();
var newItemIds = newItems.Select(i => i.Id).ToList();
var itemsChanged = !item.LocalTrailerIds.SequenceEqual(newItemIds);
- var tasks = newItems.Select(i => i.RefreshMetadata(cancellationToken, forceSave, forceRefresh, allowSlowProviders, resetResolveArgs: false));
+ var tasks = newItems.Select(i => i.RefreshMetadata(new MetadataRefreshOptions
+ {
+ ForceSave = forceSave,
+ ReplaceAllMetadata = forceRefresh,
+ ResetResolveArgs = false
+
+ }, cancellationToken));
var results = await Task.WhenAll(tasks).ConfigureAwait(false);
@@ -845,14 +866,20 @@ namespace MediaBrowser.Controller.Entities
return itemsChanged || results.Contains(true);
}
- private async Task<bool> RefreshThemeVideos(IHasThemeMedia item, CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false, bool allowSlowProviders = true)
+ private async Task<bool> RefreshThemeVideos(IHasThemeMedia item, CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false)
{
var newThemeVideos = LoadThemeVideos().ToList();
var newThemeVideoIds = newThemeVideos.Select(i => i.Id).ToList();
var themeVideosChanged = !item.ThemeVideoIds.SequenceEqual(newThemeVideoIds);
- var tasks = newThemeVideos.Select(i => i.RefreshMetadata(cancellationToken, forceSave, forceRefresh, allowSlowProviders, resetResolveArgs: false));
+ var tasks = newThemeVideos.Select(i => i.RefreshMetadata(new MetadataRefreshOptions
+ {
+ ForceSave = forceSave,
+ ReplaceAllMetadata = forceRefresh,
+ ResetResolveArgs = false
+
+ }, cancellationToken));
var results = await Task.WhenAll(tasks).ConfigureAwait(false);
@@ -864,14 +891,20 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Refreshes the theme songs.
/// </summary>
- private async Task<bool> RefreshThemeSongs(IHasThemeMedia item, CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false, bool allowSlowProviders = true)
+ private async Task<bool> RefreshThemeSongs(IHasThemeMedia item, CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false)
{
var newThemeSongs = LoadThemeSongs().ToList();
var newThemeSongIds = newThemeSongs.Select(i => i.Id).ToList();
var themeSongsChanged = !item.ThemeSongIds.SequenceEqual(newThemeSongIds);
- var tasks = newThemeSongs.Select(i => i.RefreshMetadata(cancellationToken, forceSave, forceRefresh, allowSlowProviders, resetResolveArgs: false));
+ var tasks = newThemeSongs.Select(i => i.RefreshMetadata(new MetadataRefreshOptions
+ {
+ ForceSave = forceSave,
+ ReplaceAllMetadata = forceRefresh,
+ ResetResolveArgs = false
+
+ }, cancellationToken));
var results = await Task.WhenAll(tasks).ConfigureAwait(false);
@@ -1456,7 +1489,13 @@ namespace MediaBrowser.Controller.Entities
// Refresh metadata
// Need to disable slow providers or the image might get re-downloaded
- return RefreshMetadata(CancellationToken.None, forceSave: true, allowSlowProviders: false);
+ return RefreshMetadata(new MetadataRefreshOptions
+ {
+ ForceSave = true,
+ ImageRefreshMode = MetadataRefreshMode.None,
+ MetadataRefreshMode = MetadataRefreshMode.None
+
+ }, CancellationToken.None);
}
/// <summary>
@@ -1482,8 +1521,10 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Validates that images within the item are still on the file system
/// </summary>
- public void ValidateImages()
+ public bool ValidateImages()
{
+ var changed = false;
+
// Only validate paths from the same directory - need to copy to a list because we are going to potentially modify the collection below
var deletedKeys = Images
.Where(image => !File.Exists(image.Value))
@@ -1494,14 +1535,28 @@ namespace MediaBrowser.Controller.Entities
foreach (var key in deletedKeys)
{
Images.Remove(key);
+ changed = true;
}
+
+ if (ValidateBackdrops())
+ {
+ changed = true;
+ }
+ if (ValidateScreenshots())
+ {
+ changed = true;
+ }
+
+ return changed;
}
/// <summary>
/// Validates that backdrops within the item are still on the file system
/// </summary>
- public void ValidateBackdrops()
+ private bool ValidateBackdrops()
{
+ var changed = false;
+
// Only validate paths from the same directory - need to copy to a list because we are going to potentially modify the collection below
var deletedImages = BackdropImagePaths
.Where(path => !File.Exists(path))
@@ -1513,7 +1568,11 @@ namespace MediaBrowser.Controller.Entities
BackdropImagePaths.Remove(path);
RemoveImageSourceForPath(path);
+
+ changed = true;
}
+
+ return changed;
}
/// <summary>
@@ -1593,9 +1652,16 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Validates the screenshots.
/// </summary>
- public void ValidateScreenshots()
+ private bool ValidateScreenshots()
{
- var hasScreenshots = (IHasScreenshots)this;
+ var changed = false;
+
+ var hasScreenshots = this as IHasScreenshots;
+
+ if (hasScreenshots == null)
+ {
+ return changed;
+ }
// Only validate paths from the same directory - need to copy to a list because we are going to potentially modify the collection below
var deletedImages = hasScreenshots.ScreenshotImagePaths
@@ -1606,7 +1672,10 @@ namespace MediaBrowser.Controller.Entities
foreach (var path in deletedImages)
{
hasScreenshots.ScreenshotImagePaths.Remove(path);
+ changed = true;
}
+
+ return changed;
}
/// <summary>
@@ -1699,7 +1768,12 @@ namespace MediaBrowser.Controller.Entities
FileSystem.SwapFiles(file1, file2);
// Directory watchers should repeat this, but do a quick refresh first
- return RefreshMetadata(CancellationToken.None, forceSave: true, allowSlowProviders: false);
+ return RefreshMetadata(new MetadataRefreshOptions
+ {
+ ForceSave = true,
+ MetadataRefreshMode = MetadataRefreshMode.None
+
+ }, CancellationToken.None);
}
public virtual bool IsPlayed(User user)
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index a0fefeac7..a4257b2a5 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -3,6 +3,7 @@ using MediaBrowser.Common.Progress;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Localization;
+using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Model.Entities;
using MoreLinq;
@@ -535,7 +536,13 @@ namespace MediaBrowser.Controller.Entities
try
{
//refresh it
- await child.RefreshMetadata(cancellationToken, forceSave: currentTuple.Item2, forceRefresh: forceRefreshMetadata, resetResolveArgs: false).ConfigureAwait(false);
+ await child.RefreshMetadata(new MetadataRefreshOptions
+ {
+ ForceSave = currentTuple.Item2,
+ ReplaceAllMetadata = forceRefreshMetadata,
+ ResetResolveArgs = false
+
+ }, cancellationToken).ConfigureAwait(false);
}
catch (IOException ex)
{
@@ -907,9 +914,9 @@ namespace MediaBrowser.Controller.Entities
return item;
}
- public override async Task<bool> RefreshMetadata(CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false, bool allowSlowProviders = true, bool resetResolveArgs = true)
+ public override async Task<bool> RefreshMetadataDirect(CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false)
{
- var changed = await base.RefreshMetadata(cancellationToken, forceSave, forceRefresh, allowSlowProviders, resetResolveArgs).ConfigureAwait(false);
+ var changed = await base.RefreshMetadataDirect(cancellationToken, forceSave, forceRefresh).ConfigureAwait(false);
return (SupportsShortcutChildren && LocationType == LocationType.FileSystem && RefreshLinkedChildren()) || changed;
}
diff --git a/MediaBrowser.Controller/Entities/IHasImages.cs b/MediaBrowser.Controller/Entities/IHasImages.cs
index a7cd76a66..784337e3b 100644
--- a/MediaBrowser.Controller/Entities/IHasImages.cs
+++ b/MediaBrowser.Controller/Entities/IHasImages.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Model.Entities;
using System;
+using System.Collections.Generic;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.Entities
@@ -10,7 +11,7 @@ namespace MediaBrowser.Controller.Entities
/// Gets the name.
/// </summary>
/// <value>The name.</value>
- string Name { get; }
+ string Name { get; set; }
/// <summary>
/// Gets the path.
@@ -25,6 +26,12 @@ namespace MediaBrowser.Controller.Entities
Guid Id { get; }
/// <summary>
+ /// Gets the type of the location.
+ /// </summary>
+ /// <value>The type of the location.</value>
+ LocationType LocationType { get; }
+
+ /// <summary>
/// Gets the image path.
/// </summary>
/// <param name="imageType">Type of the image.</param>
@@ -81,6 +88,24 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
/// <returns>System.String.</returns>
string GetPreferredMetadataLanguage();
+
+ /// <summary>
+ /// Validates the images and returns true or false indicating if any were removed.
+ /// </summary>
+ bool ValidateImages();
+
+ /// <summary>
+ /// Gets or sets the backdrop image paths.
+ /// </summary>
+ /// <value>The backdrop image paths.</value>
+ List<string> BackdropImagePaths { get; set; }
+
+ /// <summary>
+ /// Determines whether [contains image with source URL] [the specified URL].
+ /// </summary>
+ /// <param name="url">The URL.</param>
+ /// <returns><c>true</c> if [contains image with source URL] [the specified URL]; otherwise, <c>false</c>.</returns>
+ bool ContainsImageWithSourceUrl(string url);
}
public static class HasImagesExtensions
diff --git a/MediaBrowser.Controller/Entities/IHasScreenshots.cs b/MediaBrowser.Controller/Entities/IHasScreenshots.cs
index 2276c707a..70d154a95 100644
--- a/MediaBrowser.Controller/Entities/IHasScreenshots.cs
+++ b/MediaBrowser.Controller/Entities/IHasScreenshots.cs
@@ -14,8 +14,10 @@ namespace MediaBrowser.Controller.Entities
List<string> ScreenshotImagePaths { get; set; }
/// <summary>
- /// Validates the screenshots.
+ /// Determines whether [contains image with source URL] [the specified URL].
/// </summary>
- void ValidateScreenshots();
+ /// <param name="url">The URL.</param>
+ /// <returns><c>true</c> if [contains image with source URL] [the specified URL]; otherwise, <c>false</c>.</returns>
+ bool ContainsImageWithSourceUrl(string url);
}
}
diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs
index 2b252a6c2..dbbe5ce01 100644
--- a/MediaBrowser.Controller/Entities/Movies/Movie.cs
+++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Model.Configuration;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
@@ -108,13 +109,11 @@ namespace MediaBrowser.Controller.Entities.Movies
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="forceSave">if set to <c>true</c> [is new item].</param>
/// <param name="forceRefresh">if set to <c>true</c> [force].</param>
- /// <param name="allowSlowProviders">if set to <c>true</c> [allow slow providers].</param>
- /// <param name="resetResolveArgs">The reset resolve args.</param>
/// <returns>Task{System.Boolean}.</returns>
- public override async Task<bool> RefreshMetadata(CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false, bool allowSlowProviders = true, bool resetResolveArgs = true)
+ public override async Task<bool> RefreshMetadataDirect(CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false)
{
// Kick off a task to refresh the main item
- var result = await base.RefreshMetadata(cancellationToken, forceSave, forceRefresh, allowSlowProviders, resetResolveArgs).ConfigureAwait(false);
+ var result = await base.RefreshMetadataDirect(cancellationToken, forceSave, forceRefresh).ConfigureAwait(false);
var specialFeaturesChanged = false;
@@ -122,7 +121,7 @@ namespace MediaBrowser.Controller.Entities.Movies
// In other words, it must be part of the Parent/Child tree
if (LocationType == LocationType.FileSystem && Parent != null && !IsInMixedFolder)
{
- specialFeaturesChanged = await RefreshSpecialFeatures(cancellationToken, forceSave, forceRefresh, allowSlowProviders).ConfigureAwait(false);
+ specialFeaturesChanged = await RefreshSpecialFeatures(cancellationToken, forceSave, forceRefresh).ConfigureAwait(false);
}
return specialFeaturesChanged || result;
@@ -135,7 +134,13 @@ namespace MediaBrowser.Controller.Entities.Movies
var itemsChanged = !SpecialFeatureIds.SequenceEqual(newItemIds);
- var tasks = newItems.Select(i => i.RefreshMetadata(cancellationToken, forceSave, forceRefresh, allowSlowProviders, resetResolveArgs: false));
+ var tasks = newItems.Select(i => i.RefreshMetadata(new MetadataRefreshOptions
+ {
+ ForceSave = forceSave,
+ ReplaceAllMetadata = forceRefresh,
+ ResetResolveArgs = false
+
+ }, cancellationToken));
var results = await Task.WhenAll(tasks).ConfigureAwait(false);
diff --git a/MediaBrowser.Controller/Entities/User.cs b/MediaBrowser.Controller/Entities/User.cs
index 466e709dd..c109e1d0c 100644
--- a/MediaBrowser.Controller/Entities/User.cs
+++ b/MediaBrowser.Controller/Entities/User.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Serialization;
using System;
@@ -212,7 +213,12 @@ namespace MediaBrowser.Controller.Entities
// Kick off a task to validate the media library
Task.Run(() => ValidateMediaLibrary(new Progress<double>(), CancellationToken.None));
- return RefreshMetadata(CancellationToken.None, forceSave: true, forceRefresh: true);
+ return RefreshMetadata(new MetadataRefreshOptions
+ {
+ ForceSave = true,
+ ReplaceAllMetadata = true
+
+ }, CancellationToken.None);
}
/// <summary>
@@ -275,17 +281,13 @@ namespace MediaBrowser.Controller.Entities
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="forceSave">if set to <c>true</c> [is new item].</param>
/// <param name="forceRefresh">if set to <c>true</c> [force].</param>
- /// <param name="allowSlowProviders">if set to <c>true</c> [allow slow providers].</param>
/// <returns>true if a provider reports we changed</returns>
- public override async Task<bool> RefreshMetadata(CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false, bool allowSlowProviders = true, bool resetResolveArgs = true)
+ public override async Task<bool> RefreshMetadataDirect(CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false)
{
- if (resetResolveArgs)
- {
- // Reload this
- ResetResolveArgs();
- }
+ // Reload this
+ ResetResolveArgs();
- var updateReason = await ProviderManager.ExecuteMetadataProviders(this, cancellationToken, forceRefresh, allowSlowProviders).ConfigureAwait(false);
+ var updateReason = await ProviderManager.ExecuteMetadataProviders(this, cancellationToken, forceRefresh).ConfigureAwait(false);
var changed = updateReason.HasValue;
diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs
index e663c8353..9c9466766 100644
--- a/MediaBrowser.Controller/Entities/Video.cs
+++ b/MediaBrowser.Controller/Entities/Video.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Model.Entities;
using System;
@@ -164,13 +165,11 @@ namespace MediaBrowser.Controller.Entities
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="forceSave">if set to <c>true</c> [is new item].</param>
/// <param name="forceRefresh">if set to <c>true</c> [force].</param>
- /// <param name="allowSlowProviders">if set to <c>true</c> [allow slow providers].</param>
- /// <param name="resetResolveArgs">The reset resolve args.</param>
/// <returns>true if a provider reports we changed</returns>
- public override async Task<bool> RefreshMetadata(CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false, bool allowSlowProviders = true, bool resetResolveArgs = true)
+ public override async Task<bool> RefreshMetadataDirect(CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false)
{
// Kick off a task to refresh the main item
- var result = await base.RefreshMetadata(cancellationToken, forceSave, forceRefresh, allowSlowProviders, resetResolveArgs).ConfigureAwait(false);
+ var result = await base.RefreshMetadataDirect(cancellationToken, forceSave, forceRefresh).ConfigureAwait(false);
var additionalPartsChanged = false;
@@ -181,7 +180,7 @@ namespace MediaBrowser.Controller.Entities
{
try
{
- additionalPartsChanged = await RefreshAdditionalParts(cancellationToken, forceSave, forceRefresh, allowSlowProviders).ConfigureAwait(false);
+ additionalPartsChanged = await RefreshAdditionalParts(cancellationToken, forceSave, forceRefresh).ConfigureAwait(false);
}
catch (IOException ex)
{
@@ -208,7 +207,12 @@ namespace MediaBrowser.Controller.Entities
var itemsChanged = !AdditionalPartIds.SequenceEqual(newItemIds);
- var tasks = newItems.Select(i => i.RefreshMetadata(cancellationToken, forceSave, forceRefresh, allowSlowProviders));
+ var tasks = newItems.Select(i => i.RefreshMetadata(new MetadataRefreshOptions
+ {
+ ForceSave = forceSave,
+ ReplaceAllMetadata = forceRefresh
+
+ }, cancellationToken));
var results = await Task.WhenAll(tasks).ConfigureAwait(false);
diff --git a/MediaBrowser.Controller/IO/IDirectoryWatchers.cs b/MediaBrowser.Controller/IO/IDirectoryWatchers.cs
deleted file mode 100644
index 9a43ee8ac..000000000
--- a/MediaBrowser.Controller/IO/IDirectoryWatchers.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using System;
-
-namespace MediaBrowser.Controller.IO
-{
- public interface IDirectoryWatchers : IDisposable
- {
- /// <summary>
- /// Add the path to our temporary ignore list. Use when writing to a path within our listening scope.
- /// </summary>
- /// <param name="path">The path.</param>
- void TemporarilyIgnore(string path);
-
- /// <summary>
- /// Removes the temp ignore.
- /// </summary>
- /// <param name="path">The path.</param>
- void RemoveTempIgnore(string path);
-
- /// <summary>
- /// Starts this instance.
- /// </summary>
- void Start();
-
- /// <summary>
- /// Stops this instance.
- /// </summary>
- void Stop();
- }
-} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Library/ILibraryMonitor.cs b/MediaBrowser.Controller/Library/ILibraryMonitor.cs
new file mode 100644
index 000000000..918382f04
--- /dev/null
+++ b/MediaBrowser.Controller/Library/ILibraryMonitor.cs
@@ -0,0 +1,36 @@
+using System;
+
+namespace MediaBrowser.Controller.Library
+{
+ public interface ILibraryMonitor : IDisposable
+ {
+ /// <summary>
+ /// Starts this instance.
+ /// </summary>
+ void Start();
+
+ /// <summary>
+ /// Stops this instance.
+ /// </summary>
+ void Stop();
+
+ /// <summary>
+ /// Reports the file system change beginning.
+ /// </summary>
+ /// <param name="path">The path.</param>
+ void ReportFileSystemChangeBeginning(string path);
+
+ /// <summary>
+ /// Reports the file system change complete.
+ /// </summary>
+ /// <param name="path">The path.</param>
+ /// <param name="refreshPath">if set to <c>true</c> [refresh path].</param>
+ void ReportFileSystemChangeComplete(string path, bool refreshPath);
+
+ /// <summary>
+ /// Reports the file system changed.
+ /// </summary>
+ /// <param name="path">The path.</param>
+ void ReportFileSystemChanged(string path);
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs b/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs
index d9bceb6ca..c94a25a30 100644
--- a/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs
+++ b/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using System.Threading;
using System.Threading.Tasks;
@@ -11,8 +12,6 @@ namespace MediaBrowser.Controller.LiveTv
string MediaType { get; }
- LocationType LocationType { get; }
-
RecordingInfo RecordingInfo { get; set; }
string GetClientTypeName();
@@ -21,6 +20,6 @@ namespace MediaBrowser.Controller.LiveTv
bool IsParentalAllowed(User user);
- Task<bool> RefreshMetadata(CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false, bool allowSlowProviders = true, bool resetResolveArgs = true);
+ Task<bool> RefreshMetadata(MetadataRefreshOptions options, CancellationToken cancellationToken);
}
}
diff --git a/MediaBrowser.Controller/LiveTv/StreamResponseInfo.cs b/MediaBrowser.Controller/LiveTv/StreamResponseInfo.cs
index c3b438c5e..b133874d0 100644
--- a/MediaBrowser.Controller/LiveTv/StreamResponseInfo.cs
+++ b/MediaBrowser.Controller/LiveTv/StreamResponseInfo.cs
@@ -1,4 +1,5 @@
-using System.IO;
+using MediaBrowser.Controller.Drawing;
+using System.IO;
namespace MediaBrowser.Controller.LiveTv
{
@@ -14,6 +15,6 @@ namespace MediaBrowser.Controller.LiveTv
/// Gets or sets the type of the MIME.
/// </summary>
/// <value>The type of the MIME.</value>
- public string MimeType { get; set; }
+ public ImageFormat Format { get; set; }
}
}
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index 56ac695a2..ee8bb2761 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -69,6 +69,7 @@
<Link>Properties\SharedVersion.cs</Link>
</Compile>
<Compile Include="Drawing\IImageProcessor.cs" />
+ <Compile Include="Drawing\ImageFormat.cs" />
<Compile Include="Drawing\ImageProcessingOptions.cs" />
<Compile Include="Dto\IDtoService.cs" />
<Compile Include="Entities\AdultVideo.cs" />
@@ -143,8 +144,17 @@
<Compile Include="Persistence\IFileOrganizationRepository.cs" />
<Compile Include="Persistence\MediaStreamQuery.cs" />
<Compile Include="Providers\IDynamicInfoProvider.cs" />
+ <Compile Include="Providers\IHasMetadata.cs" />
<Compile Include="Providers\IImageProvider.cs" />
+ <Compile Include="Providers\IProviderRepository.cs" />
+ <Compile Include="Providers\IRemoteImageProvider.cs" />
+ <Compile Include="Providers\ILocalImageProvider.cs" />
+ <Compile Include="Providers\IMetadataProvider.cs" />
+ <Compile Include="Providers\IMetadataService.cs" />
+ <Compile Include="Providers\ItemId.cs" />
+ <Compile Include="Providers\MetadataRefreshOptions.cs" />
<Compile Include="Providers\NameParser.cs" />
+ <Compile Include="Providers\MetadataStatus.cs" />
<Compile Include="Session\ISessionManager.cs" />
<Compile Include="Drawing\ImageExtensions.cs" />
<Compile Include="Entities\AggregateFolder.cs" />
@@ -174,7 +184,7 @@
<Compile Include="Entities\Video.cs" />
<Compile Include="Entities\CollectionFolder.cs" />
<Compile Include="Entities\Year.cs" />
- <Compile Include="IO\IDirectoryWatchers.cs" />
+ <Compile Include="Library\ILibraryMonitor.cs" />
<Compile Include="IServerApplicationHost.cs" />
<Compile Include="IServerApplicationPaths.cs" />
<Compile Include="Library\SearchHintInfo.cs" />
diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs
index 3affe48e7..3a5cb4e87 100644
--- a/MediaBrowser.Controller/Persistence/IItemRepository.cs
+++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs
@@ -1,5 +1,4 @@
using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
@@ -112,22 +111,6 @@ namespace MediaBrowser.Controller.Persistence
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task SaveMediaStreams(Guid id, IEnumerable<MediaStream> streams, CancellationToken cancellationToken);
-
- /// <summary>
- /// Gets the provider history.
- /// </summary>
- /// <param name="itemId">The item identifier.</param>
- /// <returns>IEnumerable{BaseProviderInfo}.</returns>
- IEnumerable<BaseProviderInfo> GetProviderHistory(Guid itemId);
-
- /// <summary>
- /// Saves the provider history.
- /// </summary>
- /// <param name="id">The identifier.</param>
- /// <param name="history">The history.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task.</returns>
- Task SaveProviderHistory(Guid id, IEnumerable<BaseProviderInfo> history, CancellationToken cancellationToken);
}
}
diff --git a/MediaBrowser.Controller/Providers/IHasMetadata.cs b/MediaBrowser.Controller/Providers/IHasMetadata.cs
new file mode 100644
index 000000000..33c5184b8
--- /dev/null
+++ b/MediaBrowser.Controller/Providers/IHasMetadata.cs
@@ -0,0 +1,31 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Model.Entities;
+using System;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Controller.Providers
+{
+ /// <summary>
+ /// Interface IHasMetadata
+ /// </summary>
+ public interface IHasMetadata : IHasImages, IHasProviderIds
+ {
+ /// <summary>
+ /// Gets the preferred metadata country code.
+ /// </summary>
+ /// <returns>System.String.</returns>
+ string GetPreferredMetadataCountryCode();
+
+ /// <summary>
+ /// Gets the locked fields.
+ /// </summary>
+ /// <value>The locked fields.</value>
+ List<MetadataFields> LockedFields { get; }
+
+ /// <summary>
+ /// Gets or sets the date last saved.
+ /// </summary>
+ /// <value>The date last saved.</value>
+ DateTime DateLastSaved { get; set; }
+ }
+}
diff --git a/MediaBrowser.Controller/Providers/IImageProvider.cs b/MediaBrowser.Controller/Providers/IImageProvider.cs
index ccf199844..61f5579f4 100644
--- a/MediaBrowser.Controller/Providers/IImageProvider.cs
+++ b/MediaBrowser.Controller/Providers/IImageProvider.cs
@@ -1,9 +1,4 @@
using MediaBrowser.Controller.Entities;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Providers;
-using System.Collections.Generic;
-using System.Threading;
-using System.Threading.Tasks;
namespace MediaBrowser.Controller.Providers
{
@@ -26,26 +21,9 @@ namespace MediaBrowser.Controller.Providers
bool Supports(IHasImages item);
/// <summary>
- /// Gets the images.
+ /// Gets the order.
/// </summary>
- /// <param name="item">The item.</param>
- /// <param name="imageType">Type of the image.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task{IEnumerable{RemoteImageInfo}}.</returns>
- Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken);
-
- /// <summary>
- /// Gets the images.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task{IEnumerable{RemoteImageInfo}}.</returns>
- Task<IEnumerable<RemoteImageInfo>> GetAllImages(IHasImages item, CancellationToken cancellationToken);
-
- /// <summary>
- /// Gets the priority.
- /// </summary>
- /// <value>The priority.</value>
- int Priority { get; }
+ /// <value>The order.</value>
+ int Order { get; }
}
}
diff --git a/MediaBrowser.Controller/Providers/ILocalImageProvider.cs b/MediaBrowser.Controller/Providers/ILocalImageProvider.cs
new file mode 100644
index 000000000..5c3ebd9ac
--- /dev/null
+++ b/MediaBrowser.Controller/Providers/ILocalImageProvider.cs
@@ -0,0 +1,66 @@
+using MediaBrowser.Controller.Drawing;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Model.Entities;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Providers
+{
+ /// <summary>
+ /// This is just a marker interface
+ /// </summary>
+ public interface ILocalImageProvider : IImageProvider
+ {
+ }
+
+ public interface IImageFileProvider : ILocalImageProvider
+ {
+ List<LocalImageInfo> GetImages(IHasImages item);
+ }
+
+ public class LocalImageInfo
+ {
+ public string Path { get; set; }
+ public ImageType Type { get; set; }
+ }
+
+ public interface IDynamicImageProvider : ILocalImageProvider
+ {
+ /// <summary>
+ /// Gets the supported images.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <returns>IEnumerable{ImageType}.</returns>
+ IEnumerable<ImageType> GetSupportedImages(IHasImages item);
+
+ /// <summary>
+ /// Gets the image.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="type">The type.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task{DynamicImageResponse}.</returns>
+ Task<DynamicImageResponse> GetImage(IHasImages item, ImageType type, CancellationToken cancellationToken);
+ }
+
+ public class DynamicImageInfo
+ {
+ public string ImageId { get; set; }
+ public ImageType Type { get; set; }
+ }
+
+ public class DynamicImageResponse
+ {
+ public string Path { get; set; }
+ public Stream Stream { get; set; }
+ public ImageFormat Format { get; set; }
+ public bool HasImage { get; set; }
+
+ public void SetFormatFromMimeType(string mimeType)
+ {
+
+ }
+ }
+}
diff --git a/MediaBrowser.Controller/Providers/IMetadataProvider.cs b/MediaBrowser.Controller/Providers/IMetadataProvider.cs
new file mode 100644
index 000000000..843ba263b
--- /dev/null
+++ b/MediaBrowser.Controller/Providers/IMetadataProvider.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Providers
+{
+ /// <summary>
+ /// Marker interface
+ /// </summary>
+ public interface IMetadataProvider
+ {
+ /// <summary>
+ /// Gets the name.
+ /// </summary>
+ /// <value>The name.</value>
+ string Name { get; }
+ }
+
+ public interface IMetadataProvider<TItemType> : IMetadataProvider
+ where TItemType : IHasMetadata
+ {
+ }
+
+ public interface ILocalMetadataProvider : IMetadataProvider
+ {
+ /// <summary>
+ /// Determines whether [has local metadata] [the specified item].
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <returns><c>true</c> if [has local metadata] [the specified item]; otherwise, <c>false</c>.</returns>
+ bool HasLocalMetadata(IHasMetadata item);
+ }
+
+ public interface IRemoteMetadataProvider : IMetadataProvider
+ {
+ }
+
+ public interface IRemoteMetadataProvider<TItemType> : IMetadataProvider<TItemType>, IRemoteMetadataProvider
+ where TItemType : IHasMetadata
+ {
+ Task<MetadataResult<TItemType>> GetMetadata(ItemId id, CancellationToken cancellationToken);
+ }
+
+ public interface ILocalMetadataProvider<TItemType> : IMetadataProvider<TItemType>, ILocalMetadataProvider
+ where TItemType : IHasMetadata
+ {
+ Task<MetadataResult<TItemType>> GetMetadata(string path, CancellationToken cancellationToken);
+ }
+
+ public interface IHasChangeMonitor
+ {
+ /// <summary>
+ /// Determines whether the specified item has changed.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="date">The date.</param>
+ /// <returns><c>true</c> if the specified item has changed; otherwise, <c>false</c>.</returns>
+ bool HasChanged(IHasMetadata item, DateTime date);
+ }
+
+ public class MetadataResult<T>
+ where T : IHasMetadata
+ {
+ public bool HasMetadata { get; set; }
+ public T Item { get; set; }
+ }
+
+}
diff --git a/MediaBrowser.Controller/Providers/IMetadataService.cs b/MediaBrowser.Controller/Providers/IMetadataService.cs
new file mode 100644
index 000000000..c6cc2b716
--- /dev/null
+++ b/MediaBrowser.Controller/Providers/IMetadataService.cs
@@ -0,0 +1,38 @@
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Providers
+{
+ public interface IMetadataService
+ {
+ /// <summary>
+ /// Adds the parts.
+ /// </summary>
+ /// <param name="providers">The providers.</param>
+ /// <param name="imageProviders">The image providers.</param>
+ void AddParts(IEnumerable<IMetadataProvider> providers, IEnumerable<IImageProvider> imageProviders);
+
+ /// <summary>
+ /// Determines whether this instance can refresh the specified item.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <returns><c>true</c> if this instance can refresh the specified item; otherwise, <c>false</c>.</returns>
+ bool CanRefresh(IHasMetadata item);
+
+ /// <summary>
+ /// Refreshes the metadata.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="options">The options.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ Task RefreshMetadata(IHasMetadata item, MetadataRefreshOptions options, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Gets the order.
+ /// </summary>
+ /// <value>The order.</value>
+ int Order { get; }
+ }
+}
diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs
index 728030ecc..dc57552c4 100644
--- a/MediaBrowser.Controller/Providers/IProviderManager.cs
+++ b/MediaBrowser.Controller/Providers/IProviderManager.cs
@@ -15,14 +15,22 @@ namespace MediaBrowser.Controller.Providers
public interface IProviderManager
{
/// <summary>
+ /// Refreshes the metadata.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="options">The options.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ Task RefreshMetadata(IHasMetadata item, MetadataRefreshOptions options, CancellationToken cancellationToken);
+
+ /// <summary>
/// Executes the metadata providers.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="force">if set to <c>true</c> [force].</param>
- /// <param name="allowSlowProviders">if set to <c>true</c> [allow slow providers].</param>
/// <returns>Task{System.Boolean}.</returns>
- Task<ItemUpdateType?> ExecuteMetadataProviders(BaseItem item, CancellationToken cancellationToken, bool force = false, bool allowSlowProviders = true);
+ Task<ItemUpdateType?> ExecuteMetadataProviders(BaseItem item, CancellationToken cancellationToken, bool force = false);
/// <summary>
/// Saves the image.
@@ -54,7 +62,9 @@ namespace MediaBrowser.Controller.Providers
/// </summary>
/// <param name="providers">The providers.</param>
/// <param name="imageProviders">The image providers.</param>
- void AddParts(IEnumerable<BaseMetadataProvider> providers, IEnumerable<IImageProvider> imageProviders);
+ /// <param name="metadataServices">The metadata services.</param>
+ /// <param name="metadataProviders">The metadata providers.</param>
+ void AddParts(IEnumerable<BaseMetadataProvider> providers, IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices, IEnumerable<IMetadataProvider> metadataProviders);
/// <summary>
/// Gets the available remote images.
@@ -70,7 +80,7 @@ namespace MediaBrowser.Controller.Providers
/// Gets the image providers.
/// </summary>
/// <param name="item">The item.</param>
- /// <returns>IEnumerable{IImageProvider}.</returns>
- IEnumerable<IImageProvider> GetImageProviders(BaseItem item);
+ /// <returns>IEnumerable{ImageProviderInfo}.</returns>
+ IEnumerable<ImageProviderInfo> GetImageProviderInfo(BaseItem item);
}
} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Providers/IProviderRepository.cs b/MediaBrowser.Controller/Providers/IProviderRepository.cs
new file mode 100644
index 000000000..1c0ad2cd7
--- /dev/null
+++ b/MediaBrowser.Controller/Providers/IProviderRepository.cs
@@ -0,0 +1,48 @@
+using MediaBrowser.Controller.Persistence;
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Providers
+{
+ public interface IProviderRepository : IRepository
+ {
+ /// <summary>
+ /// Gets the provider history.
+ /// </summary>
+ /// <param name="itemId">The item identifier.</param>
+ /// <returns>IEnumerable{BaseProviderInfo}.</returns>
+ IEnumerable<BaseProviderInfo> GetProviderHistory(Guid itemId);
+
+ /// <summary>
+ /// Saves the provider history.
+ /// </summary>
+ /// <param name="id">The identifier.</param>
+ /// <param name="history">The history.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ Task SaveProviderHistory(Guid id, IEnumerable<BaseProviderInfo> history, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Gets the metadata status.
+ /// </summary>
+ /// <param name="itemId">The item identifier.</param>
+ /// <returns>MetadataStatus.</returns>
+ MetadataStatus GetMetadataStatus(Guid itemId);
+
+ /// <summary>
+ /// Saves the metadata status.
+ /// </summary>
+ /// <param name="status">The status.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ Task SaveMetadataStatus(MetadataStatus status, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Initializes this instance.
+ /// </summary>
+ /// <returns>Task.</returns>
+ Task Initialize();
+ }
+}
diff --git a/MediaBrowser.Controller/Providers/IRemoteImageProvider.cs b/MediaBrowser.Controller/Providers/IRemoteImageProvider.cs
new file mode 100644
index 000000000..23fda2bfa
--- /dev/null
+++ b/MediaBrowser.Controller/Providers/IRemoteImageProvider.cs
@@ -0,0 +1,48 @@
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Providers
+{
+ /// <summary>
+ /// Interface IImageProvider
+ /// </summary>
+ public interface IRemoteImageProvider : IImageProvider
+ {
+ /// <summary>
+ /// Gets the supported images.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <returns>IEnumerable{ImageType}.</returns>
+ IEnumerable<ImageType> GetSupportedImages(IHasImages item);
+
+ /// <summary>
+ /// Gets the images.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="imageType">Type of the image.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task{IEnumerable{RemoteImageInfo}}.</returns>
+ Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Gets the images.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task{IEnumerable{RemoteImageInfo}}.</returns>
+ Task<IEnumerable<RemoteImageInfo>> GetAllImages(IHasImages item, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Gets the image response.
+ /// </summary>
+ /// <param name="url">The URL.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task{HttpResponseInfo}.</returns>
+ Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken);
+ }
+}
diff --git a/MediaBrowser.Controller/Providers/ItemId.cs b/MediaBrowser.Controller/Providers/ItemId.cs
new file mode 100644
index 000000000..1116eb8b5
--- /dev/null
+++ b/MediaBrowser.Controller/Providers/ItemId.cs
@@ -0,0 +1,35 @@
+using MediaBrowser.Model.Entities;
+using System;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Controller.Providers
+{
+ public class ItemId : IHasProviderIds
+ {
+ /// <summary>
+ /// Gets or sets the name.
+ /// </summary>
+ /// <value>The name.</value>
+ public string Name { get; set; }
+ /// <summary>
+ /// Gets or sets the metadata language.
+ /// </summary>
+ /// <value>The metadata language.</value>
+ public string MetadataLanguage { get; set; }
+ /// <summary>
+ /// Gets or sets the metadata country code.
+ /// </summary>
+ /// <value>The metadata country code.</value>
+ public string MetadataCountryCode { get; set; }
+ /// <summary>
+ /// Gets or sets the provider ids.
+ /// </summary>
+ /// <value>The provider ids.</value>
+ public Dictionary<string, string> ProviderIds { get; set; }
+
+ public ItemId()
+ {
+ ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+ }
+ }
+}
diff --git a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs
new file mode 100644
index 000000000..d6e8a3afe
--- /dev/null
+++ b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs
@@ -0,0 +1,49 @@
+using System;
+
+namespace MediaBrowser.Controller.Providers
+{
+ public class MetadataRefreshOptions : ImageRefreshOptions
+ {
+ /// <summary>
+ /// When paired with MetadataRefreshMode=FullRefresh, all existing data will be overwritten with new data from the providers.
+ /// </summary>
+ public bool ReplaceAllMetadata { get; set; }
+
+ public MetadataRefreshMode MetadataRefreshMode { get; set; }
+
+ /// <summary>
+ /// TODO: deprecate. Keeping this for now, for api compatibility
+ /// </summary>
+ [Obsolete]
+ public bool ForceSave { get; set; }
+
+ /// <summary>
+ /// TODO: deprecate. Keeping this for now, for api compatibility
+ /// </summary>
+ [Obsolete]
+ public bool ResetResolveArgs { get; set; }
+ }
+
+ public class ImageRefreshOptions
+ {
+ public MetadataRefreshMode ImageRefreshMode { get; set; }
+ }
+
+ public enum MetadataRefreshMode
+ {
+ /// <summary>
+ /// Providers will be executed based on default rules
+ /// </summary>
+ EnsureMetadata,
+
+ /// <summary>
+ /// No providers will be executed
+ /// </summary>
+ None,
+
+ /// <summary>
+ /// All providers will be executed to search for new metadata
+ /// </summary>
+ FullRefresh
+ }
+}
diff --git a/MediaBrowser.Controller/Providers/MetadataStatus.cs b/MediaBrowser.Controller/Providers/MetadataStatus.cs
new file mode 100644
index 000000000..834d8ec35
--- /dev/null
+++ b/MediaBrowser.Controller/Providers/MetadataStatus.cs
@@ -0,0 +1,122 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using MediaBrowser.Common.Extensions;
+
+namespace MediaBrowser.Controller.Providers
+{
+ public class MetadataStatus
+ {
+ /// <summary>
+ /// Gets or sets the item identifier.
+ /// </summary>
+ /// <value>The item identifier.</value>
+ public Guid ItemId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the date last metadata refresh.
+ /// </summary>
+ /// <value>The date last metadata refresh.</value>
+ public DateTime? DateLastMetadataRefresh { get; set; }
+
+ /// <summary>
+ /// Gets or sets the date last images refresh.
+ /// </summary>
+ /// <value>The date last images refresh.</value>
+ public DateTime? DateLastImagesRefresh { get; set; }
+
+ /// <summary>
+ /// Gets or sets the last result.
+ /// </summary>
+ /// <value>The last result.</value>
+ public ProviderRefreshStatus LastStatus { get; set; }
+
+ /// <summary>
+ /// Gets or sets the last result error message.
+ /// </summary>
+ /// <value>The last result error message.</value>
+ public string LastErrorMessage { get; set; }
+
+ /// <summary>
+ /// Gets or sets the providers refreshed.
+ /// </summary>
+ /// <value>The providers refreshed.</value>
+ public List<Guid> MetadataProvidersRefreshed { get; set; }
+ public List<Guid> ImageProvidersRefreshed { get; set; }
+
+ public void AddStatus(ProviderRefreshStatus status, string errorMessage)
+ {
+ if (LastStatus != status)
+ {
+ IsDirty = true;
+ }
+
+ if (string.IsNullOrEmpty(LastErrorMessage))
+ {
+ LastErrorMessage = errorMessage;
+ }
+ if (LastStatus == ProviderRefreshStatus.Success)
+ {
+ LastStatus = status;
+ }
+ }
+
+ public MetadataStatus()
+ {
+ LastStatus = ProviderRefreshStatus.Success;
+
+ MetadataProvidersRefreshed = new List<Guid>();
+ ImageProvidersRefreshed = new List<Guid>();
+ }
+
+ public bool IsDirty { get; private set; }
+
+ public void SetDateLastMetadataRefresh(DateTime date)
+ {
+ if (date != (DateLastMetadataRefresh ?? DateTime.MinValue))
+ {
+ IsDirty = true;
+ }
+
+ DateLastMetadataRefresh = date;
+ }
+
+ public void SetDateLastImagesRefresh(DateTime date)
+ {
+ if (date != (DateLastImagesRefresh ?? DateTime.MinValue))
+ {
+ IsDirty = true;
+ }
+
+ DateLastImagesRefresh = date;
+ }
+
+ public void AddImageProvidersRefreshed(List<Guid> providerIds)
+ {
+ var count = ImageProvidersRefreshed.Count;
+
+ providerIds.AddRange(ImageProvidersRefreshed);
+
+ ImageProvidersRefreshed = providerIds.Distinct().ToList();
+
+ if (ImageProvidersRefreshed.Count != count)
+ {
+ IsDirty = true;
+ }
+ }
+
+ public void AddMetadataProvidersRefreshed(List<Guid> providerIds)
+ {
+ var count = MetadataProvidersRefreshed.Count;
+
+ providerIds.AddRange(MetadataProvidersRefreshed);
+
+ MetadataProvidersRefreshed = providerIds.Distinct().ToList();
+
+ if (MetadataProvidersRefreshed.Count != count)
+ {
+ IsDirty = true;
+ }
+ }
+ }
+}