aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller/Entities/BaseItem.cs
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Controller/Entities/BaseItem.cs')
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs560
1 files changed, 258 insertions, 302 deletions
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index de5516e29..8dcf08642 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -21,17 +21,16 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Class BaseItem
/// </summary>
- public abstract class BaseItem : IHasProviderIds, ILibraryItem, IHasImages, IHasUserData, IHasMetadata
+ public abstract class BaseItem : IHasProviderIds, ILibraryItem, IHasImages, IHasUserData, IHasMetadata, IHasLookupInfo<ItemLookupInfo>
{
protected BaseItem()
{
Genres = new List<string>();
Studios = new List<string>();
People = new List<PersonInfo>();
- BackdropImagePaths = new List<string>();
- Images = new Dictionary<ImageType, string>();
ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
LockedFields = new List<MetadataFields>();
+ ImageInfos = new List<ItemImageInfo>();
}
/// <summary>
@@ -48,6 +47,12 @@ namespace MediaBrowser.Controller.Entities
public const string ThemeVideosFolderName = "backdrops";
public const string XbmcTrailerFileSuffix = "-trailer";
+ public List<ItemImageInfo> ImageInfos { get; set; }
+
+ /// <summary>
+ /// Gets a value indicating whether this instance is in mixed folder.
+ /// </summary>
+ /// <value><c>true</c> if this instance is in mixed folder; otherwise, <c>false</c>.</value>
public bool IsInMixedFolder { get; set; }
private string _name;
@@ -119,7 +124,7 @@ namespace MediaBrowser.Controller.Entities
}
[IgnoreDataMember]
- public bool IsOwnedItem
+ public virtual bool IsOwnedItem
{
get
{
@@ -152,6 +157,16 @@ namespace MediaBrowser.Controller.Entities
}
}
+ public virtual bool SupportsLocalMetadata
+ {
+ get
+ {
+ var locationType = LocationType;
+
+ return locationType == LocationType.FileSystem || locationType == LocationType.Offline;
+ }
+ }
+
/// <summary>
/// This is just a helper for convenience
/// </summary>
@@ -160,16 +175,9 @@ namespace MediaBrowser.Controller.Entities
public string PrimaryImagePath
{
get { return this.GetImagePath(ImageType.Primary); }
- set { this.SetImagePath(ImageType.Primary, value); }
}
/// <summary>
- /// Gets or sets the images.
- /// </summary>
- /// <value>The images.</value>
- public Dictionary<ImageType, string> Images { get; set; }
-
- /// <summary>
/// Gets or sets the date created.
/// </summary>
/// <value>The date created.</value>
@@ -236,7 +244,7 @@ namespace MediaBrowser.Controller.Entities
{
var locationType = LocationType;
- if (locationType != LocationType.Remote && locationType != LocationType.Virtual)
+ if (locationType == LocationType.Remote || locationType == LocationType.Virtual)
{
return new string[] { };
}
@@ -258,7 +266,7 @@ namespace MediaBrowser.Controller.Entities
private string _sortName;
/// <summary>
- /// Gets or sets the name of the sort.
+ /// Gets the name of the sort.
/// </summary>
/// <value>The name of the sort.</value>
[IgnoreDataMember]
@@ -350,12 +358,6 @@ namespace MediaBrowser.Controller.Entities
public string DisplayMediaType { get; set; }
/// <summary>
- /// Gets or sets the backdrop image paths.
- /// </summary>
- /// <value>The backdrop image paths.</value>
- public List<string> BackdropImagePaths { get; set; }
-
- /// <summary>
/// Gets or sets the official rating.
/// </summary>
/// <value>The official rating.</value>
@@ -447,9 +449,23 @@ namespace MediaBrowser.Controller.Entities
}
[IgnoreDataMember]
- public virtual string CustomRatingForComparison
+ public string CustomRatingForComparison
{
- get { return CustomRating; }
+ get
+ {
+ if (!string.IsNullOrEmpty(CustomRating))
+ {
+ return CustomRating;
+ }
+
+ var parent = Parent;
+ if (parent != null)
+ {
+ return parent.CustomRatingForComparison;
+ }
+
+ return null;
+ }
}
/// <summary>
@@ -458,75 +474,30 @@ namespace MediaBrowser.Controller.Entities
/// <returns>List{Video}.</returns>
private IEnumerable<Trailer> LoadLocalTrailers(List<FileSystemInfo> fileSystemChildren)
{
- return new List<Trailer>();
- //ItemResolveArgs resolveArgs;
-
- //try
- //{
- // resolveArgs = ResolveArgs;
-
- // if (!resolveArgs.IsDirectory)
- // {
- // return new List<Trailer>();
- // }
- //}
- //catch (IOException ex)
- //{
- // Logger.ErrorException("Error getting ResolveArgs for {0}", ex, Path);
- // return new List<Trailer>();
- //}
-
- //var files = new List<FileSystemInfo>();
-
- //var folder = resolveArgs.GetFileSystemEntryByName(TrailerFolderName);
-
- //// Path doesn't exist. No biggie
- //if (folder != null)
- //{
- // try
- // {
- // files.AddRange(new DirectoryInfo(folder.FullName).EnumerateFiles());
- // }
- // catch (IOException ex)
- // {
- // Logger.ErrorException("Error loading trailers for {0}", ex, Name);
- // }
- //}
-
- //// Support xbmc trailers (-trailer suffix on video file names)
- //files.AddRange(resolveArgs.FileSystemChildren.Where(i =>
- //{
- // try
- // {
- // if ((i.Attributes & FileAttributes.Directory) != FileAttributes.Directory)
- // {
- // if (System.IO.Path.GetFileNameWithoutExtension(i.Name).EndsWith(XbmcTrailerFileSuffix, StringComparison.OrdinalIgnoreCase) && !string.Equals(Path, i.FullName, StringComparison.OrdinalIgnoreCase))
- // {
- // return true;
- // }
- // }
- // }
- // catch (IOException ex)
- // {
- // Logger.ErrorException("Error accessing path {0}", ex, i.FullName);
- // }
-
- // return false;
- //}));
-
- //return LibraryManager.ResolvePaths<Trailer>(files, null).Select(video =>
- //{
- // // Try to retrieve it from the db. If we don't find it, use the resolved version
- // var dbItem = LibraryManager.GetItemById(video.Id) as Trailer;
-
- // if (dbItem != null)
- // {
- // video = dbItem;
- // }
-
- // return video;
-
- //}).ToList();
+ var files = fileSystemChildren.OfType<DirectoryInfo>()
+ .Where(i => string.Equals(i.Name, TrailerFolderName, StringComparison.OrdinalIgnoreCase))
+ .SelectMany(i => i.EnumerateFiles("*", SearchOption.TopDirectoryOnly))
+ .ToList();
+
+ // Support plex/xbmc convention
+ files.AddRange(fileSystemChildren.OfType<FileInfo>()
+ .Where(i => System.IO.Path.GetFileNameWithoutExtension(i.Name).EndsWith(XbmcTrailerFileSuffix, StringComparison.OrdinalIgnoreCase) && !string.Equals(Path, i.FullName, StringComparison.OrdinalIgnoreCase))
+ );
+
+ return LibraryManager.ResolvePaths<Trailer>(files, null).Select(video =>
+ {
+ // Try to retrieve it from the db. If we don't find it, use the resolved version
+ var dbItem = LibraryManager.GetItemById(video.Id) as Trailer;
+
+ if (dbItem != null)
+ {
+ video = dbItem;
+ }
+
+ return video;
+
+ // Sort them so that the list can be easily compared for changes
+ }).OrderBy(i => i.Path).ToList();
}
/// <summary>
@@ -556,7 +527,9 @@ namespace MediaBrowser.Controller.Entities
}
return audio;
- }).ToList();
+
+ // Sort them so that the list can be easily compared for changes
+ }).OrderBy(i => i.Path).ToList();
}
/// <summary>
@@ -580,7 +553,9 @@ namespace MediaBrowser.Controller.Entities
}
return item;
- }).ToList();
+
+ // Sort them so that the list can be easily compared for changes
+ }).OrderBy(i => i.Path).ToList();
}
public Task RefreshMetadata(CancellationToken cancellationToken)
@@ -598,19 +573,44 @@ namespace MediaBrowser.Controller.Entities
{
var locationType = LocationType;
+ var requiresSave = false;
+
if (IsFolder || Parent != null)
{
+ options.DirectoryService = options.DirectoryService ?? new DirectoryService(Logger);
+
var files = locationType == LocationType.FileSystem || locationType == LocationType.Offline ?
- GetFileSystemChildren().ToList() :
+ GetFileSystemChildren(options.DirectoryService).ToList() :
new List<FileSystemInfo>();
- await BeforeRefreshMetadata(options, files, cancellationToken).ConfigureAwait(false);
+ var ownedItemsChanged = await RefreshedOwnedItems(options, files, cancellationToken).ConfigureAwait(false);
+
+ if (ownedItemsChanged)
+ {
+ requiresSave = true;
+ }
}
+ var dateLastSaved = DateLastSaved;
+
await ProviderManager.RefreshMetadata(this, options, cancellationToken).ConfigureAwait(false);
+
+ // If it wasn't saved by the provider process, save now
+ if (requiresSave && dateLastSaved == DateLastSaved)
+ {
+ await UpdateToRepository(ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false);
+ }
}
- protected virtual async Task BeforeRefreshMetadata(MetadataRefreshOptions options, List<FileSystemInfo> fileSystemChildren, CancellationToken cancellationToken)
+ /// <summary>
+ /// Refreshes owned items such as trailers, theme videos, special features, etc.
+ /// Returns true or false indicating if changes were found.
+ /// </summary>
+ /// <param name="options"></param>
+ /// <param name="fileSystemChildren"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ protected virtual async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemInfo> fileSystemChildren, CancellationToken cancellationToken)
{
var themeSongsChanged = false;
@@ -637,18 +637,15 @@ namespace MediaBrowser.Controller.Entities
localTrailersChanged = await RefreshLocalTrailers(hasTrailers, options, fileSystemChildren, cancellationToken).ConfigureAwait(false);
}
}
-
- if (themeSongsChanged || themeVideosChanged || localTrailersChanged)
- {
- options.ForceSave = true;
- }
+
+ return themeSongsChanged || themeVideosChanged || localTrailersChanged;
}
- protected virtual IEnumerable<FileSystemInfo> GetFileSystemChildren()
+ protected virtual IEnumerable<FileSystemInfo> GetFileSystemChildren(IDirectoryService directoryService)
{
var path = ContainingFolderPath;
- return new DirectoryInfo(path).EnumerateFileSystemInfos("*", SearchOption.TopDirectoryOnly);
+ return directoryService.GetFileSystemEntries(path);
}
private async Task<bool> RefreshLocalTrailers(IHasTrailers item, MetadataRefreshOptions options, List<FileSystemInfo> fileSystemChildren, CancellationToken cancellationToken)
@@ -670,6 +667,7 @@ namespace MediaBrowser.Controller.Entities
private async Task<bool> RefreshThemeVideos(IHasThemeMedia item, MetadataRefreshOptions options, IEnumerable<FileSystemInfo> fileSystemChildren, CancellationToken cancellationToken)
{
var newThemeVideos = LoadThemeVideos(fileSystemChildren).ToList();
+
var newThemeVideoIds = newThemeVideos.Select(i => i.Id).ToList();
var themeVideosChanged = !item.ThemeVideoIds.SequenceEqual(newThemeVideoIds);
@@ -885,29 +883,6 @@ namespace MediaBrowser.Controller.Entities
}
/// <summary>
- /// Finds the particular item by searching through our parents and, if not found there, loading from repo
- /// </summary>
- /// <param name="id">The id.</param>
- /// <returns>BaseItem.</returns>
- /// <exception cref="System.ArgumentException"></exception>
- protected BaseItem FindParentItem(Guid id)
- {
- if (id == Guid.Empty)
- {
- throw new ArgumentException();
- }
-
- var parent = Parent;
- while (parent != null && !parent.IsRoot)
- {
- if (parent.Id == id) return parent;
- parent = parent.Parent;
- }
-
- return null;
- }
-
- /// <summary>
/// Gets a value indicating whether this instance is folder.
/// </summary>
/// <value><c>true</c> if this instance is folder; otherwise, <c>false</c>.</value>
@@ -1188,43 +1163,31 @@ namespace MediaBrowser.Controller.Entities
/// <exception cref="System.ArgumentException">Backdrops should be accessed using Item.Backdrops</exception>
public bool HasImage(ImageType type, int imageIndex)
{
- if (type == ImageType.Backdrop)
- {
- return BackdropImagePaths.Count > imageIndex;
- }
- if (type == ImageType.Screenshot)
- {
- var hasScreenshots = this as IHasScreenshots;
- return hasScreenshots != null && hasScreenshots.ScreenshotImagePaths.Count > imageIndex;
- }
-
- return !string.IsNullOrEmpty(this.GetImagePath(type));
+ return GetImageInfo(type, imageIndex) != null;
}
- public void SetImagePath(ImageType type, int index, string path)
+ public void SetImagePath(ImageType type, int index, FileInfo file)
{
- if (type == ImageType.Backdrop)
- {
- throw new ArgumentException("Backdrops should be accessed using Item.Backdrops");
- }
- if (type == ImageType.Screenshot)
+ if (type == ImageType.Chapter)
{
- throw new ArgumentException("Screenshots should be accessed using Item.Screenshots");
+ throw new ArgumentException("Cannot set chapter images using SetImagePath");
}
- var typeKey = type;
+ var image = GetImageInfo(type, index);
- // If it's null remove the key from the dictionary
- if (string.IsNullOrEmpty(path))
+ if (image == null)
{
- if (Images.ContainsKey(typeKey))
+ ImageInfos.Add(new ItemImageInfo
{
- Images.Remove(typeKey);
- }
+ Path = file.FullName,
+ Type = type,
+ DateModified = FileSystem.GetLastWriteTimeUtc(file)
+ });
}
else
{
- Images[typeKey] = path;
+ image.Path = file.FullName;
+ image.DateModified = FileSystem.GetLastWriteTimeUtc(file);
}
}
@@ -1234,66 +1197,23 @@ namespace MediaBrowser.Controller.Entities
/// <param name="type">The type.</param>
/// <param name="index">The index.</param>
/// <returns>Task.</returns>
- public Task DeleteImage(ImageType type, int? index)
+ public Task DeleteImage(ImageType type, int index)
{
- if (type == ImageType.Backdrop)
- {
- if (!index.HasValue)
- {
- throw new ArgumentException("Please specify a backdrop image index to delete.");
- }
-
- var file = BackdropImagePaths[index.Value];
+ var info = GetImageInfo(type, index);
- BackdropImagePaths.Remove(file);
-
- // Delete the source file
- DeleteImagePath(file);
- }
- else if (type == ImageType.Screenshot)
+ if (info == null)
{
- if (!index.HasValue)
- {
- throw new ArgumentException("Please specify a screenshot image index to delete.");
- }
-
- var hasScreenshots = (IHasScreenshots)this;
- var file = hasScreenshots.ScreenshotImagePaths[index.Value];
-
- hasScreenshots.ScreenshotImagePaths.Remove(file);
-
- // Delete the source file
- DeleteImagePath(file);
+ // Nothing to do
+ return Task.FromResult(true);
}
- else
- {
- // Delete the source file
- DeleteImagePath(this.GetImagePath(type));
- // Remove it from the item
- this.SetImagePath(type, null);
- }
-
- // Refresh metadata
- // Need to disable slow providers or the image might get re-downloaded
- return RefreshMetadata(new MetadataRefreshOptions
- {
- ForceSave = true,
- ImageRefreshMode = ImageRefreshMode.ValidationOnly,
- MetadataRefreshMode = MetadataRefreshMode.None
+ // Remove it from the item
+ ImageInfos.Remove(info);
- }, CancellationToken.None);
- }
-
- /// <summary>
- /// Deletes the image path.
- /// </summary>
- /// <param name="path">The path.</param>
- private void DeleteImagePath(string path)
- {
- var currentFile = new FileInfo(path);
+ // Delete the source file
+ var currentFile = new FileInfo(info.Path);
- // This will fail if the file is hidden
+ // Deletion will fail if the file is hidden so remove the attribute first
if (currentFile.Exists)
{
if ((currentFile.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
@@ -1303,90 +1223,33 @@ namespace MediaBrowser.Controller.Entities
currentFile.Delete();
}
- }
-
- /// <summary>
- /// Validates that images within the item are still on the file system
- /// </summary>
- 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))
- .Select(i => i.Key)
- .ToList();
-
- // Now remove them from the dictionary
- foreach (var key in deletedKeys)
- {
- Images.Remove(key);
- changed = true;
- }
-
- if (ValidateBackdrops())
- {
- changed = true;
- }
- if (ValidateScreenshots())
- {
- changed = true;
- }
- return changed;
+ return UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None);
}
- /// <summary>
- /// Validates that backdrops within the item are still on the file system
- /// </summary>
- private bool ValidateBackdrops()
+ public virtual Task UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken)
{
- 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))
- .ToList();
-
- // Now remove them from the dictionary
- foreach (var path in deletedImages)
- {
- BackdropImagePaths.Remove(path);
-
- changed = true;
- }
-
- return changed;
+ return LibraryManager.UpdateItem(this, ItemUpdateType.ImageUpdate, cancellationToken);
}
/// <summary>
- /// Validates the screenshots.
+ /// Validates that images within the item are still on the file system
/// </summary>
- private bool ValidateScreenshots()
+ public bool ValidateImages(IDirectoryService directoryService)
{
- var changed = false;
+ var allDirectories = ImageInfos.Select(i => System.IO.Path.GetDirectoryName(i.Path)).Distinct(StringComparer.OrdinalIgnoreCase).ToList();
+ var allFiles = allDirectories.SelectMany(directoryService.GetFiles).Select(i => i.FullName).ToList();
- 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
- .Where(path => !File.Exists(path))
+ var deletedImages = ImageInfos
+ .Where(image => !allFiles.Contains(image.Path, StringComparer.OrdinalIgnoreCase))
.ToList();
- // Now remove them from the dictionary
- foreach (var path in deletedImages)
+ if (deletedImages.Count > 0)
{
- hasScreenshots.ScreenshotImagePaths.Remove(path);
- changed = true;
+ ImageInfos = ImageInfos.Except(deletedImages).ToList();
}
- return changed;
+ return deletedImages.Count > 0;
}
/// <summary>
@@ -1400,42 +1263,87 @@ namespace MediaBrowser.Controller.Entities
/// <exception cref="System.ArgumentNullException">item</exception>
public string GetImagePath(ImageType imageType, int imageIndex)
{
- if (imageType == ImageType.Backdrop)
- {
- return BackdropImagePaths.Count > imageIndex ? BackdropImagePaths[imageIndex] : null;
- }
+ var info = GetImageInfo(imageType, imageIndex);
+
+ return info == null ? null : info.Path;
+ }
- if (imageType == ImageType.Screenshot)
+ /// <summary>
+ /// Gets the image information.
+ /// </summary>
+ /// <param name="imageType">Type of the image.</param>
+ /// <param name="imageIndex">Index of the image.</param>
+ /// <returns>ItemImageInfo.</returns>
+ public ItemImageInfo GetImageInfo(ImageType imageType, int imageIndex)
+ {
+ if (imageType == ImageType.Chapter)
{
- var hasScreenshots = (IHasScreenshots)this;
- return hasScreenshots.ScreenshotImagePaths.Count > imageIndex ? hasScreenshots.ScreenshotImagePaths[imageIndex] : null;
+ var chapter = ItemRepository.GetChapter(Id, imageIndex);
+
+ if (chapter == null)
+ {
+ return null;
+ }
+
+ var path = chapter.ImagePath;
+
+ if (string.IsNullOrWhiteSpace(path))
+ {
+ return null;
+ }
+
+ return new ItemImageInfo
+ {
+ Path = path,
+ DateModified = FileSystem.GetLastWriteTimeUtc(path),
+ Type = imageType
+ };
}
+ return GetImages(imageType)
+ .ElementAtOrDefault(imageIndex);
+ }
+
+ public IEnumerable<ItemImageInfo> GetImages(ImageType imageType)
+ {
if (imageType == ImageType.Chapter)
{
- return ItemRepository.GetChapter(Id, imageIndex).ImagePath;
+ throw new ArgumentException("No image info for chapter images");
}
- string val;
- Images.TryGetValue(imageType, out val);
- return val;
+ return ImageInfos.Where(i => i.Type == imageType);
}
/// <summary>
- /// Gets the image date modified.
+ /// Adds the images.
/// </summary>
- /// <param name="imagePath">The image path.</param>
- /// <returns>DateTime.</returns>
- /// <exception cref="System.ArgumentNullException">item</exception>
- public DateTime GetImageDateModified(string imagePath)
+ /// <param name="imageType">Type of the image.</param>
+ /// <param name="images">The images.</param>
+ /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
+ /// <exception cref="System.ArgumentException">Cannot call AddImages with chapter images</exception>
+ public bool AddImages(ImageType imageType, IEnumerable<FileInfo> images)
{
- if (string.IsNullOrEmpty(imagePath))
+ if (imageType == ImageType.Chapter)
{
- throw new ArgumentNullException("imagePath");
+ throw new ArgumentException("Cannot call AddImages with chapter images");
}
- // See if we can avoid a file system lookup by looking for the file in ResolveArgs
- return FileSystem.GetLastWriteTimeUtc(imagePath);
+ var existingImagePaths = GetImages(imageType)
+ .Select(i => i.Path)
+ .ToList();
+
+ var newImages = images
+ .Where(i => !existingImagePaths.Contains(i.FullName, StringComparer.OrdinalIgnoreCase))
+ .ToList();
+
+ ImageInfos.AddRange(newImages.Select(i => new ItemImageInfo
+ {
+ Path = i.FullName,
+ Type = imageType,
+ DateModified = FileSystem.GetLastWriteTimeUtc(i)
+ }));
+
+ return newImages.Count > 0;
}
/// <summary>
@@ -1447,25 +1355,37 @@ namespace MediaBrowser.Controller.Entities
return new[] { Path };
}
+ public bool AllowsMultipleImages(ImageType type)
+ {
+ return type == ImageType.Backdrop || type == ImageType.Screenshot || type == ImageType.Chapter;
+ }
+
public Task SwapImages(ImageType type, int index1, int index2)
{
- if (type != ImageType.Screenshot && type != ImageType.Backdrop)
+ if (!AllowsMultipleImages(type))
{
throw new ArgumentException("The change index operation is only applicable to backdrops and screenshots");
}
- var file1 = GetImagePath(type, index1);
- var file2 = GetImagePath(type, index2);
-
- FileSystem.SwapFiles(file1, file2);
+ var info1 = GetImageInfo(type, index1);
+ var info2 = GetImageInfo(type, index2);
- // Directory watchers should repeat this, but do a quick refresh first
- return RefreshMetadata(new MetadataRefreshOptions
+ if (info1 == null || info2 == null)
{
- ForceSave = true,
- MetadataRefreshMode = MetadataRefreshMode.None
+ // Nothing to do
+ return Task.FromResult(true);
+ }
- }, CancellationToken.None);
+ var path1 = info1.Path;
+ var path2 = info2.Path;
+
+ FileSystem.SwapFiles(path1, path2);
+
+ // Refresh these values
+ info1.DateModified = FileSystem.GetLastWriteTimeUtc(info1.Path);
+ info2.DateModified = FileSystem.GetLastWriteTimeUtc(info2.Path);
+
+ return UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None);
}
public virtual bool IsPlayed(User user)
@@ -1481,5 +1401,41 @@ namespace MediaBrowser.Controller.Entities
return userdata == null || !userdata.Played;
}
+
+ ItemLookupInfo IHasLookupInfo<ItemLookupInfo>.GetLookupInfo()
+ {
+ return GetItemLookupInfo<ItemLookupInfo>();
+ }
+
+ protected T GetItemLookupInfo<T>()
+ where T : ItemLookupInfo, new()
+ {
+ return new T
+ {
+ MetadataCountryCode = GetPreferredMetadataCountryCode(),
+ MetadataLanguage = GetPreferredMetadataLanguage(),
+ Name = Name,
+ ProviderIds = ProviderIds,
+ IndexNumber = IndexNumber,
+ ParentIndexNumber = ParentIndexNumber
+ };
+ }
+
+ /// <summary>
+ /// This is called before any metadata refresh and returns ItemUpdateType indictating if changes were made, and what.
+ /// </summary>
+ /// <returns>ItemUpdateType.</returns>
+ public virtual ItemUpdateType BeforeMetadataRefresh()
+ {
+ var updateType = ItemUpdateType.None;
+
+ if (string.IsNullOrEmpty(Name) && !string.IsNullOrEmpty(Path))
+ {
+ Name = System.IO.Path.GetFileNameWithoutExtension(Path);
+ updateType = updateType | ItemUpdateType.MetadataEdit;
+ }
+
+ return updateType;
+ }
}
}