diff options
Diffstat (limited to 'MediaBrowser.Controller/Entities')
25 files changed, 489 insertions, 214 deletions
diff --git a/MediaBrowser.Controller/Entities/Audio/Artist.cs b/MediaBrowser.Controller/Entities/Audio/Artist.cs deleted file mode 100644 index 947ee11227..0000000000 --- a/MediaBrowser.Controller/Entities/Audio/Artist.cs +++ /dev/null @@ -1,86 +0,0 @@ -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Runtime.Serialization; - -namespace MediaBrowser.Controller.Entities.Audio -{ - /// <summary> - /// Class Artist - /// </summary> - public class Artist : BaseItem, IItemByName, IHasMusicGenres - { - public Artist() - { - UserItemCounts = new Dictionary<Guid, ItemByNameCounts>(); - } - - public string LastFmImageUrl { get; set; } - public string LastFmImageSize { get; set; } - - /// <summary> - /// Gets the user data key. - /// </summary> - /// <returns>System.String.</returns> - public override string GetUserDataKey() - { - return GetUserDataKey(this); - } - - [IgnoreDataMember] - public Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; } - - /// <summary> - /// Finds the music artist. - /// </summary> - /// <param name="artist">The artist.</param> - /// <param name="libraryManager">The library manager.</param> - /// <returns>MusicArtist.</returns> - public static MusicArtist FindMusicArtist(Artist artist, ILibraryManager libraryManager) - { - return FindMusicArtist(artist, libraryManager.RootFolder.RecursiveChildren.OfType<MusicArtist>()); - } - - /// <summary> - /// Finds the music artist. - /// </summary> - /// <param name="artist">The artist.</param> - /// <param name="allMusicArtists">All music artists.</param> - /// <returns>MusicArtist.</returns> - public static MusicArtist FindMusicArtist(Artist artist, IEnumerable<MusicArtist> allMusicArtists) - { - var musicBrainzId = artist.GetProviderId(MetadataProviders.Musicbrainz); - - return allMusicArtists.FirstOrDefault(i => - { - if (!string.IsNullOrWhiteSpace(musicBrainzId) && string.Equals(musicBrainzId, i.GetProviderId(MetadataProviders.Musicbrainz), StringComparison.OrdinalIgnoreCase)) - { - return true; - } - - return string.Compare(i.Name, artist.Name, CultureInfo.CurrentCulture, CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols) == 0; - }); - } - - /// <summary> - /// Gets the user data key. - /// </summary> - /// <param name="item">The item.</param> - /// <returns>System.String.</returns> - public static string GetUserDataKey(BaseItem item) - { - var id = item.GetProviderId(MetadataProviders.Musicbrainz); - - if (!string.IsNullOrEmpty(id)) - { - return "Artist-Musicbrainz-" + id; - } - - return "Artist-" + item.Name; - } - } -} diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs index d791c92ae9..d5572b9a5e 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs @@ -1,11 +1,65 @@ - +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.Threading; +using System.Threading.Tasks; + namespace MediaBrowser.Controller.Entities.Audio { /// <summary> /// Class MusicArtist /// </summary> - public class MusicArtist : Folder + public class MusicArtist : Folder, IItemByName, IHasMusicGenres, IHasDualAccess { + [IgnoreDataMember] + public List<ItemByNameCounts> UserItemCountList { get; set; } + + public bool IsAccessedByName { get; set; } + + public override bool IsFolder + { + get + { + return !IsAccessedByName; + } + } + + protected override IEnumerable<BaseItem> ActualChildren + { + get + { + if (IsAccessedByName) + { + return new List<BaseItem>(); + } + + return base.ActualChildren; + } + } + + protected override Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool? recursive = null, bool forceRefreshMetadata = false) + { + if (IsAccessedByName) + { + // Should never get in here anyway + return Task.FromResult(true); + } + + return base.ValidateChildrenInternal(progress, cancellationToken, recursive, forceRefreshMetadata); + } + + public override string GetClientTypeName() + { + if (IsAccessedByName) + { + //return "Artist"; + } + + return base.GetClientTypeName(); + } + /// <summary> /// Gets or sets the last fm image URL. /// </summary> @@ -13,13 +67,35 @@ namespace MediaBrowser.Controller.Entities.Audio public string LastFmImageUrl { get; set; } public string LastFmImageSize { get; set; } + public MusicArtist() + { + UserItemCountList = new List<ItemByNameCounts>(); + } + /// <summary> /// Gets the user data key. /// </summary> /// <returns>System.String.</returns> public override string GetUserDataKey() { - return Artist.GetUserDataKey(this); + return GetUserDataKey(this); + } + + /// <summary> + /// Gets the user data key. + /// </summary> + /// <param name="item">The item.</param> + /// <returns>System.String.</returns> + public static string GetUserDataKey(BaseItem item) + { + var id = item.GetProviderId(MetadataProviders.Musicbrainz); + + if (!string.IsNullOrEmpty(id)) + { + return "Artist-Musicbrainz-" + id; + } + + return "Artist-" + item.Name; } } } diff --git a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs index ec2995fb2f..b54e14f2da 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs @@ -12,7 +12,7 @@ namespace MediaBrowser.Controller.Entities.Audio { public MusicGenre() { - UserItemCounts = new Dictionary<Guid, ItemByNameCounts>(); + UserItemCountList = new List<ItemByNameCounts>(); } /// <summary> @@ -25,6 +25,6 @@ namespace MediaBrowser.Controller.Entities.Audio } [IgnoreDataMember] - public Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; } + public List<ItemByNameCounts> UserItemCountList { get; set; } } } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index a6178536c6..4f7889f975 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1,7 +1,6 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Common.IO; using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Localization; @@ -38,10 +37,8 @@ namespace MediaBrowser.Controller.Entities Tags = new List<string>(); ThemeSongIds = new List<Guid>(); ThemeVideoIds = new List<Guid>(); - LocalTrailerIds = new List<Guid>(); LockedFields = new List<MetadataFields>(); Taglines = new List<string>(); - RemoteTrailers = new List<MediaUrl>(); ImageSources = new List<ImageSourceInfo>(); } @@ -88,30 +85,12 @@ namespace MediaBrowser.Controller.Entities public Guid Id { get; set; } /// <summary> - /// Gets or sets the budget. - /// </summary> - /// <value>The budget.</value> - public double? Budget { get; set; } - - /// <summary> /// Gets or sets the taglines. /// </summary> /// <value>The taglines.</value> public List<string> Taglines { get; set; } /// <summary> - /// Gets or sets the revenue. - /// </summary> - /// <value>The revenue.</value> - public double? Revenue { get; set; } - - /// <summary> - /// Gets or sets the trailer URL. - /// </summary> - /// <value>The trailer URL.</value> - public List<MediaUrl> RemoteTrailers { get; set; } - - /// <summary> /// Return the id that should be used to key display prefs for this item. /// Default is based on the type for everything except actual generic folders. /// </summary> @@ -139,6 +118,7 @@ namespace MediaBrowser.Controller.Entities /// Gets or sets the type of the location. /// </summary> /// <value>The type of the location.</value> + [IgnoreDataMember] public virtual LocationType LocationType { get @@ -483,6 +463,22 @@ namespace MediaBrowser.Controller.Entities [IgnoreDataMember] public Folder Parent { get; set; } + [IgnoreDataMember] + public IEnumerable<Folder> Parents + { + get + { + var parent = Parent; + + while (parent != null) + { + yield return parent; + + parent = parent.Parent; + } + } + } + /// <summary> /// When the item first debuted. For movies this could be premiere date, episodes would be first aired /// </summary> @@ -630,11 +626,6 @@ namespace MediaBrowser.Controller.Entities /// <value>The original run time ticks.</value> public long? OriginalRunTimeTicks { get; set; } /// <summary> - /// Gets or sets the aspect ratio. - /// </summary> - /// <value>The aspect ratio.</value> - public string AspectRatio { get; set; } - /// <summary> /// Gets or sets the production year. /// </summary> /// <value>The production year.</value> @@ -655,7 +646,6 @@ namespace MediaBrowser.Controller.Entities public List<Guid> ThemeSongIds { get; set; } public List<Guid> ThemeVideoIds { get; set; } - public List<Guid> LocalTrailerIds { get; set; } [IgnoreDataMember] public virtual string OfficialRatingForComparison @@ -898,7 +888,11 @@ namespace MediaBrowser.Controller.Entities themeVideosChanged = await RefreshThemeVideos(cancellationToken, forceSave, forceRefresh, allowSlowProviders).ConfigureAwait(false); - localTrailersChanged = await RefreshLocalTrailers(cancellationToken, forceSave, forceRefresh, allowSlowProviders).ConfigureAwait(false); + var hasTrailers = this as IHasTrailers; + if (hasTrailers != null) + { + localTrailersChanged = await RefreshLocalTrailers(hasTrailers, cancellationToken, forceSave, forceRefresh, allowSlowProviders).ConfigureAwait(false); + } } cancellationToken.ThrowIfCancellationRequested(); @@ -918,18 +912,18 @@ namespace MediaBrowser.Controller.Entities return changed; } - private async Task<bool> RefreshLocalTrailers(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, bool allowSlowProviders = true) { var newItems = LoadLocalTrailers().ToList(); var newItemIds = newItems.Select(i => i.Id).ToList(); - var itemsChanged = !LocalTrailerIds.SequenceEqual(newItemIds); + var itemsChanged = !item.LocalTrailerIds.SequenceEqual(newItemIds); var tasks = newItems.Select(i => i.RefreshMetadata(cancellationToken, forceSave, forceRefresh, allowSlowProviders, resetResolveArgs: false)); var results = await Task.WhenAll(tasks).ConfigureAwait(false); - LocalTrailerIds = newItemIds; + item.LocalTrailerIds = newItemIds; return itemsChanged || results.Contains(true); } @@ -1134,6 +1128,11 @@ namespace MediaBrowser.Controller.Entities return changed; } + public virtual string GetClientTypeName() + { + return GetType().Name; + } + /// <summary> /// Determines if the item is considered new based on user settings /// </summary> @@ -1187,6 +1186,7 @@ namespace MediaBrowser.Controller.Entities if (existing != null) { existing.Type = PersonType.GuestStar; + existing.SortOrder = person.SortOrder ?? existing.SortOrder; return; } } @@ -1203,23 +1203,35 @@ namespace MediaBrowser.Controller.Entities else { // Was there, if no role and we have one - fill it in - if (string.IsNullOrWhiteSpace(existing.Role) && !string.IsNullOrWhiteSpace(person.Role)) existing.Role = person.Role; + if (string.IsNullOrWhiteSpace(existing.Role) && !string.IsNullOrWhiteSpace(person.Role)) + { + existing.Role = person.Role; + } + + existing.SortOrder = person.SortOrder ?? existing.SortOrder; } } else { + var existing = People.FirstOrDefault(p => + string.Equals(p.Name, person.Name, StringComparison.OrdinalIgnoreCase) && + string.Equals(p.Type, person.Type, StringComparison.OrdinalIgnoreCase)); + // Check for dupes based on the combination of Name and Type - if (!People.Any(p => string.Equals(p.Name, person.Name, StringComparison.OrdinalIgnoreCase) && string.Equals(p.Type, person.Type, StringComparison.OrdinalIgnoreCase))) + if (existing == null) { People.Add(person); } + else + { + existing.SortOrder = person.SortOrder ?? existing.SortOrder; + } } } /// <summary> /// Adds the tagline. /// </summary> - /// <param name="item">The item.</param> /// <param name="tagline">The tagline.</param> /// <exception cref="System.ArgumentNullException">tagline</exception> public void AddTagline(string tagline) @@ -1737,5 +1749,14 @@ namespace MediaBrowser.Controller.Entities // See if we can avoid a file system lookup by looking for the file in ResolveArgs return metaFileEntry == null ? FileSystem.GetLastWriteTimeUtc(imagePath) : FileSystem.GetLastWriteTimeUtc(metaFileEntry); } + + /// <summary> + /// Gets the file system path to delete when the item is to be deleted + /// </summary> + /// <returns></returns> + public virtual IEnumerable<string> GetDeletePaths() + { + return new[] { Path }; + } } } diff --git a/MediaBrowser.Controller/Entities/Extensions.cs b/MediaBrowser.Controller/Entities/Extensions.cs index d189f4e71b..2a64bd3a41 100644 --- a/MediaBrowser.Controller/Entities/Extensions.cs +++ b/MediaBrowser.Controller/Entities/Extensions.cs @@ -16,7 +16,7 @@ namespace MediaBrowser.Controller.Entities /// <param name="url">The URL.</param> /// <param name="isDirectLink">if set to <c>true</c> [is direct link].</param> /// <exception cref="System.ArgumentNullException">url</exception> - public static void AddTrailerUrl(this BaseItem item, string url, bool isDirectLink) + public static void AddTrailerUrl(this IHasTrailers item, string url, bool isDirectLink) { if (string.IsNullOrWhiteSpace(url)) { diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 8dbc981938..e8b5831813 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -90,7 +90,7 @@ namespace MediaBrowser.Controller.Entities item.Id = item.Path.GetMBId(item.GetType()); } - if (_children.Any(i => i.Id == item.Id)) + if (ActualChildren.Any(i => i.Id == item.Id)) { throw new ArgumentException(string.Format("A child with the Id {0} already exists.", item.Id)); } @@ -108,14 +108,14 @@ namespace MediaBrowser.Controller.Entities await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false); - await ItemRepository.SaveChildren(Id, _children.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false); + await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false); } protected void AddChildrenInternal(IEnumerable<BaseItem> children) { lock (_childrenSyncLock) { - var newChildren = _children.ToList(); + var newChildren = ActualChildren.ToList(); newChildren.AddRange(children); _children = newChildren; } @@ -124,7 +124,7 @@ namespace MediaBrowser.Controller.Entities { lock (_childrenSyncLock) { - var newChildren = _children.ToList(); + var newChildren = ActualChildren.ToList(); newChildren.Add(child); _children = newChildren; } @@ -134,7 +134,7 @@ namespace MediaBrowser.Controller.Entities { lock (_childrenSyncLock) { - _children = _children.Except(children).ToList(); + _children = ActualChildren.Except(children).ToList(); } } @@ -519,7 +519,7 @@ namespace MediaBrowser.Controller.Entities /// <summary> /// The children /// </summary> - private IReadOnlyList<BaseItem> _children = new List<BaseItem>(); + private IReadOnlyList<BaseItem> _children; /// <summary> /// The _children sync lock /// </summary> @@ -532,15 +532,10 @@ namespace MediaBrowser.Controller.Entities { get { - return _children; + return _children ?? (_children = LoadChildrenInternal()); } } - public void LoadSavedChildren() - { - _children = LoadChildrenInternal(); - } - /// <summary> /// thread-safe access to the actual children of this folder - without regard to user /// </summary> @@ -758,7 +753,7 @@ namespace MediaBrowser.Controller.Entities AddChildrenInternal(newItems); - await ItemRepository.SaveChildren(Id, _children.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false); + await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false); //force the indexes to rebuild next time if (IndexCache != null) @@ -1007,8 +1002,7 @@ namespace MediaBrowser.Controller.Entities return result; } - var initialCount = _children.Count; - var list = new List<BaseItem>(initialCount); + var list = new List<BaseItem>(); AddChildrenToList(user, includeLinkedChildren, list, false, null); @@ -1038,16 +1032,13 @@ namespace MediaBrowser.Controller.Entities } } - if (recursive) + if (recursive && child.IsFolder) { - var folder = child as Folder; + var folder = (Folder)child; - if (folder != null) + if (folder.AddChildrenToList(user, includeLinkedChildren, list, true, filter)) { - if (folder.AddChildrenToList(user, includeLinkedChildren, list, true, filter)) - { - hasLinkedChildren = true; - } + hasLinkedChildren = true; } } } @@ -1073,7 +1064,6 @@ namespace MediaBrowser.Controller.Entities return hasLinkedChildren; } - private int _lastRecursiveCount; /// <summary> /// Gets allowed recursive children of an item /// </summary> @@ -1101,13 +1091,10 @@ namespace MediaBrowser.Controller.Entities throw new ArgumentNullException("user"); } - var initialCount = _lastRecursiveCount == 0 ? _children.Count : _lastRecursiveCount; - var list = new List<BaseItem>(initialCount); + var list = new List<BaseItem>(); var hasLinkedChildren = AddChildrenToList(user, includeLinkedChildren, list, true, filter); - _lastRecursiveCount = list.Count; - return hasLinkedChildren ? list.DistinctBy(i => i.Id).ToList() : list; } @@ -1127,8 +1114,7 @@ namespace MediaBrowser.Controller.Entities /// <returns>IEnumerable{BaseItem}.</returns> public IList<BaseItem> GetRecursiveChildren(Func<BaseItem, bool> filter) { - var initialCount = _lastRecursiveCount == 0 ? _children.Count : _lastRecursiveCount; - var list = new List<BaseItem>(initialCount); + var list = new List<BaseItem>(); AddChildrenToList(list, true, filter); @@ -1150,14 +1136,11 @@ namespace MediaBrowser.Controller.Entities list.Add(child); } - if (recursive) + if (recursive && child.IsFolder) { - var folder = child as Folder; + var folder = (Folder)child; - if (folder != null) - { - folder.AddChildrenToList(list, true, filter); - } + folder.AddChildrenToList(list, true, filter); } } } diff --git a/MediaBrowser.Controller/Entities/Game.cs b/MediaBrowser.Controller/Entities/Game.cs index e8374c2743..e15b7e4c9d 100644 --- a/MediaBrowser.Controller/Entities/Game.cs +++ b/MediaBrowser.Controller/Entities/Game.cs @@ -4,16 +4,26 @@ using System.Collections.Generic; namespace MediaBrowser.Controller.Entities { - public class Game : BaseItem, IHasSoundtracks + public class Game : BaseItem, IHasSoundtracks, IHasTrailers { public List<Guid> SoundtrackIds { get; set; } - + public Game() { MultiPartGameFiles = new List<string>(); SoundtrackIds = new List<Guid>(); + RemoteTrailers = new List<MediaUrl>(); + LocalTrailerIds = new List<Guid>(); } + public List<Guid> LocalTrailerIds { get; set; } + + /// <summary> + /// Gets or sets the remote trailers. + /// </summary> + /// <value>The remote trailers.</value> + public List<MediaUrl> RemoteTrailers { get; set; } + /// <summary> /// Gets the type of the media. /// </summary> @@ -84,5 +94,15 @@ namespace MediaBrowser.Controller.Entities } return base.GetUserDataKey(); } + + public override IEnumerable<string> GetDeletePaths() + { + if (!IsInMixedFolder) + { + return new[] { System.IO.Path.GetDirectoryName(Path) }; + } + + return base.GetDeletePaths(); + } } } diff --git a/MediaBrowser.Controller/Entities/GameGenre.cs b/MediaBrowser.Controller/Entities/GameGenre.cs index 0c877782e6..ffe62ba03f 100644 --- a/MediaBrowser.Controller/Entities/GameGenre.cs +++ b/MediaBrowser.Controller/Entities/GameGenre.cs @@ -9,7 +9,7 @@ namespace MediaBrowser.Controller.Entities { public GameGenre() { - UserItemCounts = new Dictionary<Guid, ItemByNameCounts>(); + UserItemCountList = new List<ItemByNameCounts>(); } /// <summary> @@ -22,6 +22,6 @@ namespace MediaBrowser.Controller.Entities } [IgnoreDataMember] - public Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; } + public List<ItemByNameCounts> UserItemCountList { get; set; } } } diff --git a/MediaBrowser.Controller/Entities/Genre.cs b/MediaBrowser.Controller/Entities/Genre.cs index 71fa057206..0fa49639bf 100644 --- a/MediaBrowser.Controller/Entities/Genre.cs +++ b/MediaBrowser.Controller/Entities/Genre.cs @@ -1,7 +1,7 @@ -using System.Runtime.Serialization; -using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Dto; using System; using System.Collections.Generic; +using System.Runtime.Serialization; namespace MediaBrowser.Controller.Entities { @@ -12,7 +12,7 @@ namespace MediaBrowser.Controller.Entities { public Genre() { - UserItemCounts = new Dictionary<Guid, ItemByNameCounts>(); + UserItemCountList = new List<ItemByNameCounts>(); } /// <summary> @@ -25,6 +25,6 @@ namespace MediaBrowser.Controller.Entities } [IgnoreDataMember] - public Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; } + public List<ItemByNameCounts> UserItemCountList { get; set; } } } diff --git a/MediaBrowser.Controller/Entities/IHasAspectRatio.cs b/MediaBrowser.Controller/Entities/IHasAspectRatio.cs new file mode 100644 index 0000000000..5aecf4eac1 --- /dev/null +++ b/MediaBrowser.Controller/Entities/IHasAspectRatio.cs @@ -0,0 +1,14 @@ +namespace MediaBrowser.Controller.Entities +{ + /// <summary> + /// Interface IHasAspectRatio + /// </summary> + public interface IHasAspectRatio + { + /// <summary> + /// Gets or sets the aspect ratio. + /// </summary> + /// <value>The aspect ratio.</value> + string AspectRatio { get; set; } + } +} diff --git a/MediaBrowser.Controller/Entities/IHasBudget.cs b/MediaBrowser.Controller/Entities/IHasBudget.cs new file mode 100644 index 0000000000..f697715c16 --- /dev/null +++ b/MediaBrowser.Controller/Entities/IHasBudget.cs @@ -0,0 +1,18 @@ + +namespace MediaBrowser.Controller.Entities +{ + public interface IHasBudget + { + /// <summary> + /// Gets or sets the budget. + /// </summary> + /// <value>The budget.</value> + double? Budget { get; set; } + + /// <summary> + /// Gets or sets the revenue. + /// </summary> + /// <value>The revenue.</value> + double? Revenue { get; set; } + } +} diff --git a/MediaBrowser.Controller/Entities/IHasTrailers.cs b/MediaBrowser.Controller/Entities/IHasTrailers.cs new file mode 100644 index 0000000000..47779064b4 --- /dev/null +++ b/MediaBrowser.Controller/Entities/IHasTrailers.cs @@ -0,0 +1,21 @@ +using MediaBrowser.Model.Entities; +using System; +using System.Collections.Generic; + +namespace MediaBrowser.Controller.Entities +{ + public interface IHasTrailers + { + /// <summary> + /// Gets or sets the remote trailers. + /// </summary> + /// <value>The remote trailers.</value> + List<MediaUrl> RemoteTrailers { get; set; } + + /// <summary> + /// Gets or sets the local trailer ids. + /// </summary> + /// <value>The local trailer ids.</value> + List<Guid> LocalTrailerIds { get; set; } + } +} diff --git a/MediaBrowser.Controller/Entities/IItemByName.cs b/MediaBrowser.Controller/Entities/IItemByName.cs index 7284bf101d..1e83c7466e 100644 --- a/MediaBrowser.Controller/Entities/IItemByName.cs +++ b/MediaBrowser.Controller/Entities/IItemByName.cs @@ -1,6 +1,7 @@ using MediaBrowser.Model.Dto; using System; using System.Collections.Generic; +using System.Linq; namespace MediaBrowser.Controller.Entities { @@ -9,26 +10,37 @@ namespace MediaBrowser.Controller.Entities /// </summary> public interface IItemByName { - Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; } + List<ItemByNameCounts> UserItemCountList { get; set; } } - public static class IItemByNameExtensions + public interface IHasDualAccess : IItemByName { - public static ItemByNameCounts GetItemByNameCounts(this IItemByName item, User user) + bool IsAccessedByName { get; } + } + + public static class ItemByNameExtensions + { + public static ItemByNameCounts GetItemByNameCounts(this IItemByName item, Guid userId) { - if (user == null) + if (userId == Guid.Empty) { - throw new ArgumentNullException("user"); + throw new ArgumentNullException("userId"); } - ItemByNameCounts counts; + return item.UserItemCountList.FirstOrDefault(i => i.UserId == userId); + } + + public static void SetItemByNameCounts(this IItemByName item, Guid userId, ItemByNameCounts counts) + { + var current = item.UserItemCountList.FirstOrDefault(i => i.UserId == userId); - if (item.UserItemCounts.TryGetValue(user.Id, out counts)) + if (current != null) { - return counts; + item.UserItemCountList.Remove(current); } - return null; + counts.UserId = userId; + item.UserItemCountList.Add(counts); } } } diff --git a/MediaBrowser.Controller/Entities/IndexFolder.cs b/MediaBrowser.Controller/Entities/IndexFolder.cs index 35c11ef5ca..57e4a35d3f 100644 --- a/MediaBrowser.Controller/Entities/IndexFolder.cs +++ b/MediaBrowser.Controller/Entities/IndexFolder.cs @@ -40,7 +40,6 @@ namespace MediaBrowser.Controller.Entities IndexName = indexName; Parent = parent; - LoadSavedChildren(); } /// <summary> diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs index e52ece502b..4a6221ee98 100644 --- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs +++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs @@ -1,10 +1,26 @@ - +using System; +using MediaBrowser.Model.Entities; +using System.Collections.Generic; + namespace MediaBrowser.Controller.Entities.Movies { /// <summary> /// Class BoxSet /// </summary> - public class BoxSet : Folder + public class BoxSet : Folder, IHasTrailers { + public BoxSet() + { + RemoteTrailers = new List<MediaUrl>(); + LocalTrailerIds = new List<Guid>(); + } + + public List<Guid> LocalTrailerIds { get; set; } + + /// <summary> + /// Gets or sets the remote trailers. + /// </summary> + /// <value>The remote trailers.</value> + public List<MediaUrl> RemoteTrailers { get; set; } } } diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs index eef348f61c..473ea4996d 100644 --- a/MediaBrowser.Controller/Entities/Movies/Movie.cs +++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs @@ -11,7 +11,7 @@ namespace MediaBrowser.Controller.Entities.Movies /// <summary> /// Class Movie /// </summary> - public class Movie : Video, IHasCriticRating, IHasSoundtracks + public class Movie : Video, IHasCriticRating, IHasSoundtracks, IHasBudget, IHasTrailers { public List<Guid> SpecialFeatureIds { get; set; } @@ -21,8 +21,26 @@ namespace MediaBrowser.Controller.Entities.Movies { SpecialFeatureIds = new List<Guid>(); SoundtrackIds = new List<Guid>(); + RemoteTrailers = new List<MediaUrl>(); + LocalTrailerIds = new List<Guid>(); } + public List<Guid> LocalTrailerIds { get; set; } + + public List<MediaUrl> RemoteTrailers { get; set; } + + /// <summary> + /// Gets or sets the budget. + /// </summary> + /// <value>The budget.</value> + public double? Budget { get; set; } + + /// <summary> + /// Gets or sets the revenue. + /// </summary> + /// <value>The revenue.</value> + public double? Revenue { get; set; } + /// <summary> /// Gets or sets the critic rating. /// </summary> diff --git a/MediaBrowser.Controller/Entities/MusicVideo.cs b/MediaBrowser.Controller/Entities/MusicVideo.cs index 207f76efda..68ad4630a5 100644 --- a/MediaBrowser.Controller/Entities/MusicVideo.cs +++ b/MediaBrowser.Controller/Entities/MusicVideo.cs @@ -4,7 +4,7 @@ using System; namespace MediaBrowser.Controller.Entities { - public class MusicVideo : Video, IHasArtist, IHasMusicGenres + public class MusicVideo : Video, IHasArtist, IHasMusicGenres, IHasBudget { /// <summary> /// Gets or sets the artist. @@ -19,6 +19,18 @@ namespace MediaBrowser.Controller.Entities public string Album { get; set; } /// <summary> + /// Gets or sets the budget. + /// </summary> + /// <value>The budget.</value> + public double? Budget { get; set; } + + /// <summary> + /// Gets or sets the revenue. + /// </summary> + /// <value>The revenue.</value> + public double? Revenue { get; set; } + + /// <summary> /// Determines whether the specified name has artist. /// </summary> /// <param name="name">The name.</param> diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs index e5cf48ad08..243861da76 100644 --- a/MediaBrowser.Controller/Entities/Person.cs +++ b/MediaBrowser.Controller/Entities/Person.cs @@ -1,7 +1,7 @@ -using System.Runtime.Serialization; -using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Dto; using System; using System.Collections.Generic; +using System.Runtime.Serialization; namespace MediaBrowser.Controller.Entities { @@ -12,11 +12,11 @@ namespace MediaBrowser.Controller.Entities { public Person() { - UserItemCounts = new Dictionary<Guid, ItemByNameCounts>(); + UserItemCountList = new List<ItemByNameCounts>(); } [IgnoreDataMember] - public Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; } + public List<ItemByNameCounts> UserItemCountList { get; set; } /// <summary> /// Gets the user data key. @@ -50,6 +50,12 @@ namespace MediaBrowser.Controller.Entities public string Type { get; set; } /// <summary> + /// Gets or sets the sort order - ascending + /// </summary> + /// <value>The sort order.</value> + public int? SortOrder { get; set; } + + /// <summary> /// Returns a <see cref="System.String" /> that represents this instance. /// </summary> /// <returns>A <see cref="System.String" /> that represents this instance.</returns> diff --git a/MediaBrowser.Controller/Entities/Studio.cs b/MediaBrowser.Controller/Entities/Studio.cs index bbe96a88b9..7bc17549f3 100644 --- a/MediaBrowser.Controller/Entities/Studio.cs +++ b/MediaBrowser.Controller/Entities/Studio.cs @@ -12,7 +12,7 @@ namespace MediaBrowser.Controller.Entities { public Studio() { - UserItemCounts = new Dictionary<Guid, ItemByNameCounts>(); + UserItemCountList = new List<ItemByNameCounts>(); } /// <summary> @@ -25,6 +25,6 @@ namespace MediaBrowser.Controller.Entities } [IgnoreDataMember] - public Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; } + public List<ItemByNameCounts> UserItemCountList { get; set; } } } diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index c68ba0ad1f..e9f250d2a4 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -50,6 +50,33 @@ namespace MediaBrowser.Controller.Entities.TV get { return true; } } + [IgnoreDataMember] + public int? AiredSeasonNumber + { + get + { + return AirsAfterSeasonNumber ?? AirsBeforeSeasonNumber ?? PhysicalSeasonNumber; + } + } + + [IgnoreDataMember] + public int? PhysicalSeasonNumber + { + get + { + var value = ParentIndexNumber; + + if (value.HasValue) + { + return value; + } + + var season = Parent as Season; + + return season != null ? season.IndexNumber : null; + } + } + /// <summary> /// We roll up into series /// </summary> @@ -59,7 +86,7 @@ namespace MediaBrowser.Controller.Entities.TV { get { - return Season; + return FindParent<Season>(); } } @@ -152,20 +179,6 @@ namespace MediaBrowser.Controller.Entities.TV } /// <summary> - /// The _season - /// </summary> - private Season _season; - /// <summary> - /// This Episode's Season Instance - /// </summary> - /// <value>The season.</value> - [IgnoreDataMember] - public Season Season - { - get { return _season ?? (_season = FindParent<Season>()); } - } - - /// <summary> /// This is the ending episode number for double episodes. /// </summary> /// <value>The index number.</value> @@ -221,5 +234,46 @@ namespace MediaBrowser.Controller.Entities.TV { get { return LocationType == Model.Entities.LocationType.Virtual && IsUnaired; } } + + [IgnoreDataMember] + public Guid? SeasonId + { + get + { + // First see if the parent is a Season + var season = Parent as Season; + + if (season != null) + { + return season.Id; + } + + var seasonNumber = ParentIndexNumber; + + // Parent is a Series + if (seasonNumber.HasValue) + { + var series = Parent as Series; + + if (series != null) + { + season = series.Children.OfType<Season>() + .FirstOrDefault(i => i.IndexNumber.HasValue && i.IndexNumber.Value == seasonNumber.Value); + + if (season != null) + { + return season.Id; + } + } + } + + return null; + } + } + + public override IEnumerable<string> GetDeletePaths() + { + return new[] { Path }; + } } } diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index 97a09b7b55..78e0b8bc4a 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -1,9 +1,9 @@ -using System.Linq; -using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Localization; using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Runtime.Serialization; namespace MediaBrowser.Controller.Entities.TV @@ -94,6 +94,22 @@ namespace MediaBrowser.Controller.Entities.TV get { return _series ?? (_series = FindParent<Series>()); } } + [IgnoreDataMember] + public string SeriesPath + { + get + { + var series = Series; + + if (series != null) + { + return series.Path; + } + + return System.IO.Path.GetDirectoryName(Path); + } + } + /// <summary> /// Our rating comes from our series /// </summary> @@ -149,16 +165,34 @@ namespace MediaBrowser.Controller.Entities.TV return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name; } + private IEnumerable<Episode> GetEpisodes() + { + var series = Series; + + if (series != null && series.ContainsEpisodesWithoutSeasonFolders) + { + var seasonNumber = IndexNumber; + + if (seasonNumber.HasValue) + { + return series.RecursiveChildren.OfType<Episode>() + .Where(i => i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == seasonNumber.Value); + } + } + + return Children.OfType<Episode>(); + } + [IgnoreDataMember] public bool IsMissingSeason { - get { return LocationType == Model.Entities.LocationType.Virtual && Children.OfType<Episode>().All(i => i.IsMissingEpisode); } + get { return LocationType == Model.Entities.LocationType.Virtual && GetEpisodes().All(i => i.IsMissingEpisode); } } [IgnoreDataMember] public bool IsUnaired { - get { return Children.OfType<Episode>().All(i => i.IsUnaired); } + get { return GetEpisodes().All(i => i.IsUnaired); } } [IgnoreDataMember] @@ -170,7 +204,13 @@ namespace MediaBrowser.Controller.Entities.TV [IgnoreDataMember] public bool IsMissingOrVirtualUnaired { - get { return LocationType == Model.Entities.LocationType.Virtual && Children.OfType<Episode>().All(i => i.IsVirtualUnaired || i.IsMissingEpisode); } + get { return LocationType == Model.Entities.LocationType.Virtual && GetEpisodes().All(i => i.IsVirtualUnaired || i.IsMissingEpisode); } + } + + [IgnoreDataMember] + public bool IsSpecialSeason + { + get { return (IndexNumber ?? -1) == 0; } } } } diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 02ea50c6b5..b4a3fc811f 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -4,6 +4,7 @@ using MediaBrowser.Model.Entities; using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Runtime.Serialization; namespace MediaBrowser.Controller.Entities.TV @@ -11,7 +12,7 @@ namespace MediaBrowser.Controller.Entities.TV /// <summary> /// Class Series /// </summary> - public class Series : Folder, IHasSoundtracks + public class Series : Folder, IHasSoundtracks, IHasTrailers { public List<Guid> SpecialFeatureIds { get; set; } public List<Guid> SoundtrackIds { get; set; } @@ -24,8 +25,14 @@ namespace MediaBrowser.Controller.Entities.TV SpecialFeatureIds = new List<Guid>(); SoundtrackIds = new List<Guid>(); + RemoteTrailers = new List<MediaUrl>(); + LocalTrailerIds = new List<Guid>(); } + public List<Guid> LocalTrailerIds { get; set; } + + public List<MediaUrl> RemoteTrailers { get; set; } + /// <summary> /// Gets or sets the status. /// </summary> @@ -94,5 +101,14 @@ namespace MediaBrowser.Controller.Entities.TV return args; } + + [IgnoreDataMember] + public bool ContainsEpisodesWithoutSeasonFolders + { + get + { + return Children.OfType<Video>().Any(); + } + } } } diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs index 26814ad40b..77efe8e8c1 100644 --- a/MediaBrowser.Controller/Entities/Trailer.cs +++ b/MediaBrowser.Controller/Entities/Trailer.cs @@ -8,7 +8,7 @@ namespace MediaBrowser.Controller.Entities /// <summary> /// Class Trailer /// </summary> - public class Trailer : Video, IHasCriticRating, IHasSoundtracks + public class Trailer : Video, IHasCriticRating, IHasSoundtracks, IHasBudget, IHasTrailers { public List<Guid> SoundtrackIds { get; set; } @@ -17,8 +17,25 @@ namespace MediaBrowser.Controller.Entities RemoteTrailers = new List<MediaUrl>(); Taglines = new List<string>(); SoundtrackIds = new List<Guid>(); + LocalTrailerIds = new List<Guid>(); } + public List<Guid> LocalTrailerIds { get; set; } + + public List<MediaUrl> RemoteTrailers { get; set; } + + /// <summary> + /// Gets or sets the budget. + /// </summary> + /// <value>The budget.</value> + public double? Budget { get; set; } + + /// <summary> + /// Gets or sets the revenue. + /// </summary> + /// <value>The revenue.</value> + public double? Revenue { get; set; } + /// <summary> /// Gets or sets the critic rating. /// </summary> diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index e900dd77e9..9b02571b00 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -14,7 +14,7 @@ namespace MediaBrowser.Controller.Entities /// <summary> /// Class Video /// </summary> - public class Video : BaseItem, IHasMediaStreams + public class Video : BaseItem, IHasMediaStreams, IHasAspectRatio { public bool IsMultiPart { get; set; } @@ -66,6 +66,12 @@ namespace MediaBrowser.Controller.Entities } /// <summary> + /// Gets or sets the aspect ratio. + /// </summary> + /// <value>The aspect ratio.</value> + public string AspectRatio { get; set; } + + /// <summary> /// Should be overridden to return the proper folder where metadata lives /// </summary> /// <value>The meta location.</value> @@ -252,5 +258,17 @@ namespace MediaBrowser.Controller.Entities }).ToList(); } + public override IEnumerable<string> GetDeletePaths() + { + if (!IsInMixedFolder) + { + if (VideoType == VideoType.VideoFile || VideoType == VideoType.Iso) + { + return new[] { System.IO.Path.GetDirectoryName(Path) }; + } + } + + return base.GetDeletePaths(); + } } } diff --git a/MediaBrowser.Controller/Entities/Year.cs b/MediaBrowser.Controller/Entities/Year.cs index d0f4577183..cd50a1c60c 100644 --- a/MediaBrowser.Controller/Entities/Year.cs +++ b/MediaBrowser.Controller/Entities/Year.cs @@ -12,11 +12,11 @@ namespace MediaBrowser.Controller.Entities { public Year() { - UserItemCounts = new Dictionary<Guid, ItemByNameCounts>(); + UserItemCountList = new List<ItemByNameCounts>(); } [IgnoreDataMember] - public Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; } + public List<ItemByNameCounts> UserItemCountList { get; set; } /// <summary> /// Gets the user data key. |
