diff options
Diffstat (limited to 'MediaBrowser.Controller/Entities')
28 files changed, 588 insertions, 509 deletions
diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index 43b980c20..766f1e5ed 100644 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs @@ -27,9 +27,22 @@ namespace MediaBrowser.Controller.Entities.Audio public long? Size { get; set; } public string Container { get; set; } public int? TotalBitrate { get; set; } - public List<string> Tags { get; set; } public ExtraType? ExtraType { get; set; } + /// <summary> + /// Gets or sets the artist. + /// </summary> + /// <value>The artist.</value> + public List<string> Artists { get; set; } + + public List<string> AlbumArtists { get; set; } + + /// <summary> + /// Gets or sets the album. + /// </summary> + /// <value>The album.</value> + public string Album { get; set; } + [IgnoreDataMember] public bool IsThemeMedia { @@ -43,7 +56,6 @@ namespace MediaBrowser.Controller.Entities.Audio { Artists = new List<string>(); AlbumArtists = new List<string>(); - Tags = new List<string>(); } [IgnoreDataMember] @@ -92,14 +104,6 @@ namespace MediaBrowser.Controller.Entities.Audio locationType != LocationType.Virtual; } - /// <summary> - /// Gets or sets the artist. - /// </summary> - /// <value>The artist.</value> - public List<string> Artists { get; set; } - - public List<string> AlbumArtists { get; set; } - [IgnoreDataMember] public List<string> AllArtists { @@ -114,12 +118,6 @@ namespace MediaBrowser.Controller.Entities.Audio } } - /// <summary> - /// Gets or sets the album. - /// </summary> - /// <value>The album.</value> - public string Album { get; set; } - [IgnoreDataMember] public MusicAlbum AlbumEntity { @@ -173,9 +171,9 @@ namespace MediaBrowser.Controller.Entities.Audio return base.CreateUserDataKey(); } - protected override bool GetBlockUnratedValue(UserPolicy config) + public override UnratedItem GetBlockUnratedType() { - return config.BlockUnratedItems.Contains(UnratedItem.Music); + return UnratedItem.Music; } public SongInfo GetLookupInfo() diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs index 98d1eb4ce..9a38912ea 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs @@ -30,7 +30,7 @@ namespace MediaBrowser.Controller.Entities.Audio { get { - return Parents.OfType<MusicArtist>().FirstOrDefault(); + return GetParents().OfType<MusicArtist>().FirstOrDefault(); } } @@ -110,13 +110,18 @@ namespace MediaBrowser.Controller.Entities.Audio return config.BlockUnratedItems.Contains(UnratedItem.Music); } + public override UnratedItem GetBlockUnratedType() + { + return UnratedItem.Music; + } + public AlbumInfo GetLookupInfo() { var id = GetItemLookupInfo<AlbumInfo>(); id.AlbumArtists = AlbumArtists; - var artist = Parents.OfType<MusicArtist>().FirstOrDefault(); + var artist = GetParents().OfType<MusicArtist>().FirstOrDefault(); if (artist != null) { diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs index f6d1d32a4..02bcceada 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs @@ -138,6 +138,11 @@ namespace MediaBrowser.Controller.Entities.Audio return config.BlockUnratedItems.Contains(UnratedItem.Music); } + public override UnratedItem GetBlockUnratedType() + { + return UnratedItem.Music; + } + public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken) { var items = GetRecursiveChildren().ToList(); diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 7086ac743..379697b81 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1,5 +1,4 @@ using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.IO; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Collections; using MediaBrowser.Controller.Configuration; @@ -24,6 +23,7 @@ using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; using CommonIO; +using MediaBrowser.Model.LiveTv; namespace MediaBrowser.Controller.Entities { @@ -34,6 +34,7 @@ namespace MediaBrowser.Controller.Entities { protected BaseItem() { + Tags = new List<string>(); Genres = new List<string>(); Studios = new List<string>(); ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); @@ -44,7 +45,7 @@ namespace MediaBrowser.Controller.Entities /// <summary> /// The supported image extensions /// </summary> - public static readonly string[] SupportedImageExtensions = { ".png", ".jpg", ".jpeg" }; + public static readonly string[] SupportedImageExtensions = { ".png", ".jpg", ".jpeg", ".tbn", ".gif" }; public static readonly List<string> SupportedImageExtensionsList = SupportedImageExtensions.ToList(); @@ -103,7 +104,8 @@ namespace MediaBrowser.Controller.Entities /// Gets or sets the name. /// </summary> /// <value>The name.</value> - public string Name + [IgnoreDataMember] + public virtual string Name { get { @@ -122,15 +124,24 @@ namespace MediaBrowser.Controller.Entities /// Gets or sets the id. /// </summary> /// <value>The id.</value> + [IgnoreDataMember] public Guid Id { get; set; } /// <summary> /// Gets or sets a value indicating whether this instance is hd. /// </summary> /// <value><c>true</c> if this instance is hd; otherwise, <c>false</c>.</value> + [IgnoreDataMember] public bool? IsHD { get; set; } /// <summary> + /// Gets or sets the audio. + /// </summary> + /// <value>The audio.</value> + [IgnoreDataMember] + public ProgramAudio? Audio { 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> @@ -149,6 +160,7 @@ namespace MediaBrowser.Controller.Entities /// Gets or sets the path. /// </summary> /// <value>The path.</value> + [IgnoreDataMember] public virtual string Path { get; set; } [IgnoreDataMember] @@ -173,7 +185,7 @@ namespace MediaBrowser.Controller.Entities } /// <summary> - /// Id of the program. + /// If this content came from an external service, the id of the content on that service /// </summary> [IgnoreDataMember] public string ExternalId @@ -201,11 +213,6 @@ namespace MediaBrowser.Controller.Entities } } - public virtual bool IsHiddenFromUser(User user) - { - return false; - } - [IgnoreDataMember] public virtual bool IsOwnedItem { @@ -325,12 +332,14 @@ namespace MediaBrowser.Controller.Entities /// Gets or sets the date created. /// </summary> /// <value>The date created.</value> + [IgnoreDataMember] public DateTime DateCreated { get; set; } /// <summary> /// Gets or sets the date modified. /// </summary> /// <value>The date modified.</value> + [IgnoreDataMember] public DateTime DateModified { get; set; } public DateTime DateLastSaved { get; set; } @@ -407,6 +416,7 @@ namespace MediaBrowser.Controller.Entities /// Gets or sets the name of the forced sort. /// </summary> /// <value>The name of the forced sort.</value> + [IgnoreDataMember] public string ForcedSortName { get { return _forcedSortName; } @@ -447,10 +457,7 @@ namespace MediaBrowser.Controller.Entities { var idString = Id.ToString("N"); - if (ConfigurationManager.Configuration.EnableLibraryMetadataSubFolder) - { - basePath = System.IO.Path.Combine(basePath, "library"); - } + basePath = System.IO.Path.Combine(basePath, "library"); return System.IO.Path.Combine(basePath, idString.Substring(0, 2), idString); } @@ -493,6 +500,7 @@ namespace MediaBrowser.Controller.Entities return sortable; } + [IgnoreDataMember] public Guid ParentId { get; set; } /// <summary> @@ -502,15 +510,7 @@ namespace MediaBrowser.Controller.Entities [IgnoreDataMember] public Folder Parent { - get - { - if (ParentId != Guid.Empty) - { - return LibraryManager.GetItemById(ParentId) as Folder; - } - - return null; - } + get { return GetParent() as Folder; } set { @@ -525,16 +525,28 @@ namespace MediaBrowser.Controller.Entities [IgnoreDataMember] public IEnumerable<Folder> Parents { - get + get { return GetParents().OfType<Folder>(); } + } + + public BaseItem GetParent() + { + if (ParentId != Guid.Empty) { - var parent = Parent; + return LibraryManager.GetItemById(ParentId); + } - while (parent != null) - { - yield return parent; + return null; + } - parent = parent.Parent; - } + public IEnumerable<BaseItem> GetParents() + { + var parent = GetParent(); + + while (parent != null) + { + yield return parent; + + parent = parent.GetParent(); } } @@ -546,19 +558,20 @@ namespace MediaBrowser.Controller.Entities public T FindParent<T>() where T : Folder { - return Parents.OfType<T>().FirstOrDefault(); + return GetParents().OfType<T>().FirstOrDefault(); } [IgnoreDataMember] public virtual BaseItem DisplayParent { - get { return Parent; } + get { return GetParent(); } } /// <summary> /// When the item first debuted. For movies this could be premiere date, episodes would be first aired /// </summary> /// <value>The premiere date.</value> + [IgnoreDataMember] public DateTime? PremiereDate { get; set; } /// <summary> @@ -572,31 +585,35 @@ namespace MediaBrowser.Controller.Entities /// Gets or sets the display type of the media. /// </summary> /// <value>The display type of the media.</value> + [IgnoreDataMember] public string DisplayMediaType { get; set; } /// <summary> /// Gets or sets the official rating. /// </summary> /// <value>The official rating.</value> + [IgnoreDataMember] public string OfficialRating { get; set; } /// <summary> /// Gets or sets the official rating description. /// </summary> /// <value>The official rating description.</value> + [IgnoreDataMember] public string OfficialRatingDescription { get; set; } /// <summary> /// Gets or sets the custom rating. /// </summary> /// <value>The custom rating.</value> - //[IgnoreDataMember] + [IgnoreDataMember] public string CustomRating { get; set; } /// <summary> /// Gets or sets the overview. /// </summary> /// <value>The overview.</value> + [IgnoreDataMember] public string Overview { get; set; } /// <summary> @@ -609,37 +626,48 @@ namespace MediaBrowser.Controller.Entities /// Gets or sets the genres. /// </summary> /// <value>The genres.</value> + [IgnoreDataMember] public List<string> Genres { get; set; } /// <summary> + /// Gets or sets the tags. + /// </summary> + /// <value>The tags.</value> + public List<string> Tags { get; set; } + + /// <summary> /// Gets or sets the home page URL. /// </summary> /// <value>The home page URL.</value> + [IgnoreDataMember] public string HomePageUrl { get; set; } /// <summary> /// Gets or sets the community rating. /// </summary> /// <value>The community rating.</value> - //[IgnoreDataMember] + [IgnoreDataMember] public float? CommunityRating { get; set; } /// <summary> /// Gets or sets the community rating vote count. /// </summary> /// <value>The community rating vote count.</value> + [IgnoreDataMember] public int? VoteCount { get; set; } /// <summary> /// Gets or sets the run time ticks. /// </summary> /// <value>The run time ticks.</value> + [IgnoreDataMember] public long? RunTimeTicks { get; set; } /// <summary> /// Gets or sets the production year. /// </summary> /// <value>The production year.</value> + [IgnoreDataMember] public int? ProductionYear { get; set; } /// <summary> @@ -647,19 +675,34 @@ namespace MediaBrowser.Controller.Entities /// This could be episode number, album track number, etc. /// </summary> /// <value>The index number.</value> - //[IgnoreDataMember] + [IgnoreDataMember] public int? IndexNumber { get; set; } /// <summary> /// For an episode this could be the season number, or for a song this could be the disc number. /// </summary> /// <value>The parent index number.</value> + [IgnoreDataMember] public int? ParentIndexNumber { get; set; } [IgnoreDataMember] - public virtual string OfficialRatingForComparison + public string OfficialRatingForComparison { - get { return OfficialRating; } + get + { + if (!string.IsNullOrWhiteSpace(OfficialRating)) + { + return OfficialRating; + } + + var parent = DisplayParent; + if (parent != null) + { + return parent.OfficialRatingForComparison; + } + + return null; + } } [IgnoreDataMember] @@ -721,21 +764,21 @@ namespace MediaBrowser.Controller.Entities return LibraryManager.ResolvePaths(files, directoryService, null) .OfType<Audio.Audio>() .Select(audio => - { - // Try to retrieve it from the db. If we don't find it, use the resolved version - var dbItem = LibraryManager.GetItemById(audio.Id) as Audio.Audio; - - if (dbItem != null) { - audio = dbItem; - } + // Try to retrieve it from the db. If we don't find it, use the resolved version + var dbItem = LibraryManager.GetItemById(audio.Id) as Audio.Audio; - audio.ExtraType = ExtraType.ThemeSong; + if (dbItem != null) + { + audio = dbItem; + } - return audio; + audio.ExtraType = ExtraType.ThemeSong; - // Sort them so that the list can be easily compared for changes - }).OrderBy(i => i.Path).ToList(); + return audio; + + // Sort them so that the list can be easily compared for changes + }).OrderBy(i => i.Path).ToList(); } /// <summary> @@ -751,21 +794,21 @@ namespace MediaBrowser.Controller.Entities return LibraryManager.ResolvePaths(files, directoryService, null) .OfType<Video>() .Select(item => - { - // Try to retrieve it from the db. If we don't find it, use the resolved version - var dbItem = LibraryManager.GetItemById(item.Id) as Video; - - if (dbItem != null) { - item = dbItem; - } + // Try to retrieve it from the db. If we don't find it, use the resolved version + var dbItem = LibraryManager.GetItemById(item.Id) as Video; + + if (dbItem != null) + { + item = dbItem; + } - item.ExtraType = ExtraType.ThemeVideo; + item.ExtraType = ExtraType.ThemeVideo; - return item; + return item; - // Sort them so that the list can be easily compared for changes - }).OrderBy(i => i.Path).ToList(); + // Sort them so that the list can be easily compared for changes + }).OrderBy(i => i.Path).ToList(); } public Task RefreshMetadata(CancellationToken cancellationToken) @@ -821,7 +864,7 @@ namespace MediaBrowser.Controller.Entities [IgnoreDataMember] protected virtual bool SupportsOwnedItems { - get { return IsFolder || Parent != null; } + get { return IsFolder || GetParent() != null; } } [IgnoreDataMember] @@ -846,7 +889,7 @@ namespace MediaBrowser.Controller.Entities var localTrailersChanged = false; - if (LocationType == LocationType.FileSystem && Parent != null) + if (LocationType == LocationType.FileSystem && GetParent() != null) { var hasThemeMedia = this as IHasThemeMedia; if (hasThemeMedia != null) @@ -1008,7 +1051,7 @@ namespace MediaBrowser.Controller.Entities if (string.IsNullOrWhiteSpace(lang)) { - lang = Parents + lang = GetParents() .Select(i => i.PreferredMetadataLanguage) .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i)); } @@ -1038,7 +1081,7 @@ namespace MediaBrowser.Controller.Entities if (string.IsNullOrWhiteSpace(lang)) { - lang = Parents + lang = GetParents() .Select(i => i.PreferredMetadataCountryCode) .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i)); } @@ -1120,6 +1163,23 @@ namespace MediaBrowser.Controller.Entities public int? GetParentalRatingValue() { + var rating = CustomRating; + + if (string.IsNullOrWhiteSpace(rating)) + { + rating = OfficialRating; + } + + if (string.IsNullOrWhiteSpace(rating)) + { + return null; + } + + return LocalizationManager.GetRatingLevel(rating); + } + + public int? GetInheritedParentalRatingValue() + { var rating = CustomRatingForComparison; if (string.IsNullOrWhiteSpace(rating)) @@ -1156,6 +1216,11 @@ namespace MediaBrowser.Controller.Entities return true; } + public virtual UnratedItem GetBlockUnratedType() + { + return UnratedItem.Other; + } + /// <summary> /// Gets the block unrated value. /// </summary> @@ -1174,7 +1239,7 @@ namespace MediaBrowser.Controller.Entities return false; } - return config.BlockUnratedItems.Contains(UnratedItem.Other); + return config.BlockUnratedItems.Contains(GetBlockUnratedType()); } /// <summary> @@ -1206,14 +1271,14 @@ namespace MediaBrowser.Controller.Entities return false; } - if (Parents.Any(i => !i.IsVisible(user))) + if (GetParents().Any(i => !i.IsVisible(user))) { return false; } if (checkFolders) { - var topParent = Parents.LastOrDefault() ?? this; + var topParent = GetParents().LastOrDefault() ?? this; if (string.IsNullOrWhiteSpace(topParent.Path)) { @@ -1308,15 +1373,6 @@ namespace MediaBrowser.Controller.Entities } /// <summary> - /// Adds a person to the item - /// </summary> - /// <param name="person">The person.</param> - /// <exception cref="System.ArgumentNullException"></exception> - public void AddPerson(PersonInfo person) - { - } - - /// <summary> /// Adds a studio to the item /// </summary> /// <param name="name">The name.</param> @@ -1779,7 +1835,8 @@ namespace MediaBrowser.Controller.Entities ProviderIds = ProviderIds, IndexNumber = IndexNumber, ParentIndexNumber = ParentIndexNumber, - Year = ProductionYear + Year = ProductionYear, + PremiereDate = PremiereDate }; } @@ -1874,5 +1931,54 @@ namespace MediaBrowser.Controller.Entities DateLastSaved.Ticks.ToString(CultureInfo.InvariantCulture) }; } + + public virtual IEnumerable<Guid> GetAncestorIds() + { + return GetParents().Select(i => i.Id).Concat(LibraryManager.GetCollectionFolders(this).Select(i => i.Id)); + } + + public BaseItem GetTopParent() + { + if (IsTopParent) + { + return this; + } + + return GetParents().FirstOrDefault(i => i.IsTopParent); + } + + [IgnoreDataMember] + public virtual bool IsTopParent + { + get + { + if (GetParent() is AggregateFolder || this is Channel || this is BasePluginFolder) + { + return true; + } + + var view = this as UserView; + if (view != null && string.Equals(view.ViewType, CollectionType.LiveTv, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + + return false; + } + } + + [IgnoreDataMember] + public virtual bool SupportsAncestors + { + get + { + return true; + } + } + + public virtual IEnumerable<Guid> GetIdsForAncestorQuery() + { + return new[] { Id }; + } } -} +}
\ No newline at end of file diff --git a/MediaBrowser.Controller/Entities/Book.cs b/MediaBrowser.Controller/Entities/Book.cs index d31675baf..f006fedd2 100644 --- a/MediaBrowser.Controller/Entities/Book.cs +++ b/MediaBrowser.Controller/Entities/Book.cs @@ -17,19 +17,8 @@ namespace MediaBrowser.Controller.Entities } } - /// <summary> - /// Gets or sets the tags. - /// </summary> - /// <value>The tags.</value> - public List<string> Tags { get; set; } - public string SeriesName { get; set; } - public Book() - { - Tags = new List<string>(); - } - public override bool CanDownload() { var locationType = LocationType; @@ -37,9 +26,9 @@ namespace MediaBrowser.Controller.Entities locationType != LocationType.Virtual; } - protected override bool GetBlockUnratedValue(UserPolicy config) + public override UnratedItem GetBlockUnratedType() { - return config.BlockUnratedItems.Contains(UnratedItem.Book); + return UnratedItem.Book; } public BookInfo GetLookupInfo() @@ -48,7 +37,7 @@ namespace MediaBrowser.Controller.Entities if (string.IsNullOrEmpty(SeriesName)) { - info.SeriesName = Parents.Select(i => i.Name).FirstOrDefault(); + info.SeriesName = GetParents().Select(i => i.Name).FirstOrDefault(); } else { diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index 0da253186..b2c7c2fa8 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -181,9 +181,7 @@ namespace MediaBrowser.Controller.Entities } private List<LinkedChild> GetLinkedChildrenInternal() { - return LibraryManager.RootFolder.Children - .OfType<Folder>() - .Where(i => i.Path != null && PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase)) + return GetPhysicalParents() .SelectMany(c => c.LinkedChildren) .ToList(); } @@ -199,11 +197,14 @@ namespace MediaBrowser.Controller.Entities private IEnumerable<BaseItem> GetActualChildren() { - return - LibraryManager.RootFolder.Children + return GetPhysicalParents().SelectMany(c => c.Children); + } + + public IEnumerable<Folder> GetPhysicalParents() + { + return LibraryManager.RootFolder.Children .OfType<Folder>() - .Where(i => i.Path != null && PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase)) - .SelectMany(c => c.Children); + .Where(i => i.Path != null && PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase)); } [IgnoreDataMember] diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 9ea1b64c0..824a067ad 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -28,7 +28,6 @@ namespace MediaBrowser.Controller.Entities public List<Guid> ThemeSongIds { get; set; } public List<Guid> ThemeVideoIds { get; set; } - public List<string> Tags { get; set; } public Folder() { @@ -36,7 +35,6 @@ namespace MediaBrowser.Controller.Entities ThemeSongIds = new List<Guid>(); ThemeVideoIds = new List<Guid>(); - Tags = new List<string>(); } [IgnoreDataMember] @@ -151,7 +149,15 @@ namespace MediaBrowser.Controller.Entities await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false); - await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false); + if (!EnableNewFolderQuerying()) + { + await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false); + } + } + + private static bool EnableNewFolderQuerying() + { + return ConfigurationManager.Configuration.MigrationVersion >= 1; } protected void AddChildrenInternal(IEnumerable<BaseItem> children) @@ -196,21 +202,6 @@ namespace MediaBrowser.Controller.Entities } } - [IgnoreDataMember] - public override string OfficialRatingForComparison - { - get - { - // Never want folders to be blocked by "BlockNotRated" - if (this is Series) - { - return base.OfficialRatingForComparison; - } - - return !string.IsNullOrWhiteSpace(base.OfficialRatingForComparison) ? base.OfficialRatingForComparison : "None"; - } - } - /// <summary> /// Removes the child. /// </summary> @@ -224,7 +215,12 @@ namespace MediaBrowser.Controller.Entities item.SetParent(null); - return ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken); + if (!EnableNewFolderQuerying()) + { + return ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken); + } + + return Task.FromResult(true); } /// <summary> @@ -457,32 +453,25 @@ namespace MediaBrowser.Controller.Entities { BaseItem currentChild; - if (currentChildren.TryGetValue(child.Id, out currentChild)) + if (currentChildren.TryGetValue(child.Id, out currentChild) && IsValidFromResolver(currentChild, child)) { - if (IsValidFromResolver(currentChild, child)) + var currentChildLocationType = currentChild.LocationType; + if (currentChildLocationType != LocationType.Remote && + currentChildLocationType != LocationType.Virtual) { - var currentChildLocationType = currentChild.LocationType; - if (currentChildLocationType != LocationType.Remote && - currentChildLocationType != LocationType.Virtual) - { - currentChild.DateModified = child.DateModified; - } - - await UpdateIsOffline(currentChild, false).ConfigureAwait(false); - validChildren.Add(currentChild); - } - else - { - newItems.Add(child); - validChildren.Add(child); + currentChild.DateModified = child.DateModified; } + + await UpdateIsOffline(currentChild, false).ConfigureAwait(false); + validChildren.Add(currentChild); + + continue; } - else - { - // Brand new item - needs to be added - newItems.Add(child); - validChildren.Add(child); - } + + // Brand new item - needs to be added + child.SetParent(this); + newItems.Add(child); + validChildren.Add(child); } // If any items were added or removed.... @@ -508,7 +497,6 @@ namespace MediaBrowser.Controller.Entities } else { - await UpdateIsOffline(item, false).ConfigureAwait(false); actualRemovals.Add(item); } } @@ -519,6 +507,11 @@ namespace MediaBrowser.Controller.Entities foreach (var item in actualRemovals) { + Logger.Debug("Removed item: " + item.Path); + + item.SetParent(null); + item.IsOffline = false; + await LibraryManager.DeleteItem(item, new DeleteOptions { DeleteFileLocation = false }).ConfigureAwait(false); LibraryManager.ReportItemRemoved(item); } } @@ -527,7 +520,10 @@ namespace MediaBrowser.Controller.Entities AddChildrenInternal(newItems); - await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false); + if (!EnableNewFolderQuerying()) + { + await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false); + } } } @@ -721,7 +717,7 @@ namespace MediaBrowser.Controller.Entities return true; } - return ContainsPath(LibraryManager.GetVirtualFolders(), originalPath); + return false; } /// <summary> @@ -757,19 +753,16 @@ namespace MediaBrowser.Controller.Entities /// <returns>IEnumerable{BaseItem}.</returns> protected IEnumerable<BaseItem> GetCachedChildren() { - if (ConfigurationManager.Configuration.DisableStartupScan) + if (EnableNewFolderQuerying()) { - return ItemRepository.GetChildrenItems(Id).Select(RetrieveChild).Where(i => i != null); - //return ItemRepository.GetItems(new InternalItemsQuery - //{ - // ParentId = Id + return ItemRepository.GetItemList(new InternalItemsQuery + { + ParentId = Id - //}).Items.Select(RetrieveChild).Where(i => i != null); - } - else - { - return ItemRepository.GetChildrenItems(Id).Select(RetrieveChild).Where(i => i != null); + }).Select(RetrieveChild).Where(i => i != null); } + + return ItemRepository.GetChildrenItems(Id).Select(RetrieveChild).Where(i => i != null); } private BaseItem RetrieveChild(BaseItem child) @@ -832,20 +825,8 @@ namespace MediaBrowser.Controller.Entities return UserViewBuilder.PostFilterAndSort(items, this, null, query, LibraryManager); } - /// <summary> - /// Gets allowed children of an item - /// </summary> - /// <param name="user">The user.</param> - /// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param> - /// <returns>IEnumerable{BaseItem}.</returns> - /// <exception cref="System.ArgumentNullException"></exception> public virtual IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren) { - return GetChildren(user, includeLinkedChildren, false); - } - - internal IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren, bool includeHidden) - { if (user == null) { throw new ArgumentNullException(); @@ -856,7 +837,7 @@ namespace MediaBrowser.Controller.Entities var result = new Dictionary<Guid, BaseItem>(); - AddChildren(user, includeLinkedChildren, result, includeHidden, false, null); + AddChildren(user, includeLinkedChildren, result, false, null); return result.Values; } @@ -872,29 +853,25 @@ namespace MediaBrowser.Controller.Entities /// <param name="user">The user.</param> /// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param> /// <param name="result">The result.</param> - /// <param name="includeHidden">if set to <c>true</c> [include hidden].</param> /// <param name="recursive">if set to <c>true</c> [recursive].</param> /// <param name="filter">The filter.</param> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> - private void AddChildren(User user, bool includeLinkedChildren, Dictionary<Guid, BaseItem> result, bool includeHidden, bool recursive, Func<BaseItem, bool> filter) + private void AddChildren(User user, bool includeLinkedChildren, Dictionary<Guid, BaseItem> result, bool recursive, Func<BaseItem, bool> filter) { foreach (var child in GetEligibleChildrenForRecursiveChildren(user)) { if (child.IsVisible(user)) { - if (includeHidden || !child.IsHiddenFromUser(user)) + if (filter == null || filter(child)) { - if (filter == null || filter(child)) - { - result[child.Id] = child; - } + result[child.Id] = child; } if (recursive && child.IsFolder) { var folder = (Folder)child; - folder.AddChildren(user, includeLinkedChildren, result, includeHidden, true, filter); + folder.AddChildren(user, includeLinkedChildren, result, true, filter); } } } @@ -935,7 +912,7 @@ namespace MediaBrowser.Controller.Entities var result = new Dictionary<Guid, BaseItem>(); - AddChildren(user, true, result, false, true, filter); + AddChildren(user, true, result, true, filter); return result.Values; } @@ -1184,6 +1161,7 @@ namespace MediaBrowser.Controller.Entities Recursive = true, IsFolder = false, IsUnaired = false + }; if (!user.Configuration.DisplayMissingEpisodes) @@ -1322,4 +1300,4 @@ namespace MediaBrowser.Controller.Entities } } } -} +}
\ No newline at end of file diff --git a/MediaBrowser.Controller/Entities/Game.cs b/MediaBrowser.Controller/Entities/Game.cs index ed3e85d58..e073d09f6 100644 --- a/MediaBrowser.Controller/Entities/Game.cs +++ b/MediaBrowser.Controller/Entities/Game.cs @@ -21,7 +21,6 @@ namespace MediaBrowser.Controller.Entities RemoteTrailerIds = new List<Guid>(); ThemeSongIds = new List<Guid>(); ThemeVideoIds = new List<Guid>(); - Tags = new List<string>(); } public List<Guid> LocalTrailerIds { get; set; } @@ -35,12 +34,6 @@ namespace MediaBrowser.Controller.Entities } /// <summary> - /// Gets or sets the tags. - /// </summary> - /// <value>The tags.</value> - public List<string> Tags { get; set; } - - /// <summary> /// Gets or sets the remote trailers. /// </summary> /// <value>The remote trailers.</value> @@ -105,9 +98,9 @@ namespace MediaBrowser.Controller.Entities return base.GetDeletePaths(); } - protected override bool GetBlockUnratedValue(UserPolicy config) + public override UnratedItem GetBlockUnratedType() { - return config.BlockUnratedItems.Contains(UnratedItem.Game); + return UnratedItem.Game; } public GameInfo GetLookupInfo() diff --git a/MediaBrowser.Controller/Entities/GameSystem.cs b/MediaBrowser.Controller/Entities/GameSystem.cs index 35f7e3350..bc35c4738 100644 --- a/MediaBrowser.Controller/Entities/GameSystem.cs +++ b/MediaBrowser.Controller/Entities/GameSystem.cs @@ -50,6 +50,11 @@ namespace MediaBrowser.Controller.Entities return false; } + public override UnratedItem GetBlockUnratedType() + { + return UnratedItem.Game; + } + public GameSystemInfo GetLookupInfo() { var id = GetItemLookupInfo<GameSystemInfo>(); diff --git a/MediaBrowser.Controller/Entities/ICollectionFolder.cs b/MediaBrowser.Controller/Entities/ICollectionFolder.cs index b55ca0a17..f4544f173 100644 --- a/MediaBrowser.Controller/Entities/ICollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/ICollectionFolder.cs @@ -16,6 +16,11 @@ namespace MediaBrowser.Controller.Entities IEnumerable<string> PhysicalLocations { get; } } + public interface ISupportsUserSpecificView + { + bool EnableUserSpecificView { get; } + } + public static class CollectionFolderExtensions { public static string GetViewType(this ICollectionFolder folder, User user) diff --git a/MediaBrowser.Controller/Entities/IHiddenFromDisplay.cs b/MediaBrowser.Controller/Entities/IHiddenFromDisplay.cs new file mode 100644 index 000000000..82d581fcf --- /dev/null +++ b/MediaBrowser.Controller/Entities/IHiddenFromDisplay.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MediaBrowser.Controller.Entities +{ + public interface IHiddenFromDisplay + { + /// <summary> + /// Determines whether the specified user is hidden. + /// </summary> + /// <param name="user">The user.</param> + /// <returns><c>true</c> if the specified user is hidden; otherwise, <c>false</c>.</returns> + bool IsHiddenFromUser(User user); + } +} diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index 785e2fd2b..96cd305a6 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -1,6 +1,7 @@ using MediaBrowser.Model.Entities; using System; using System.Collections.Generic; +using MediaBrowser.Model.Configuration; namespace MediaBrowser.Controller.Entities { @@ -30,6 +31,7 @@ namespace MediaBrowser.Controller.Entities public string[] MediaTypes { get; set; } public string[] IncludeItemTypes { get; set; } public string[] ExcludeItemTypes { get; set; } + public string[] ExcludeTags { get; set; } public string[] Genres { get; set; } public bool? IsMissing { get; set; } @@ -69,12 +71,15 @@ namespace MediaBrowser.Controller.Entities public string[] Studios { get; set; } public string[] StudioIds { get; set; } + public string[] GenreIds { get; set; } public ImageType[] ImageTypes { get; set; } public VideoType[] VideoTypes { get; set; } + public UnratedItem[] BlockUnratedItems { get; set; } public int[] Years { get; set; } public string[] Tags { get; set; } public string[] OfficialRatings { get; set; } + public DateTime? MinPremiereDate { get; set; } public DateTime? MinStartDate { get; set; } public DateTime? MaxStartDate { get; set; } public DateTime? MinEndDate { get; set; } @@ -87,6 +92,7 @@ namespace MediaBrowser.Controller.Entities public int? MinPlayers { get; set; } public int? MaxPlayers { get; set; } + public int? MinIndexNumber { get; set; } public double? MinCriticRating { get; set; } public double? MinCommunityRating { get; set; } @@ -101,9 +107,14 @@ namespace MediaBrowser.Controller.Entities public LocationType? LocationType { get; set; } public Guid? ParentId { get; set; } + public string[] AncestorIds { get; set; } + public string[] TopParentIds { get; set; } + + public LocationType[] ExcludeLocationTypes { get; set; } public InternalItemsQuery() { + BlockUnratedItems = new UnratedItem[] { }; Tags = new string[] { }; OfficialRatings = new string[] { }; SortBy = new string[] { }; @@ -113,6 +124,7 @@ namespace MediaBrowser.Controller.Entities Genres = new string[] { }; Studios = new string[] { }; StudioIds = new string[] { }; + GenreIds = new string[] { }; ImageTypes = new ImageType[] { }; VideoTypes = new VideoType[] { }; Years = new int[] { }; @@ -120,6 +132,29 @@ namespace MediaBrowser.Controller.Entities PersonIds = new string[] { }; ChannelIds = new string[] { }; ItemIds = new string[] { }; + AncestorIds = new string[] { }; + TopParentIds = new string[] { }; + ExcludeTags = new string[] { }; + ExcludeLocationTypes = new LocationType[] { }; + } + + public InternalItemsQuery(User user) + : this() + { + if (user != null) + { + var policy = user.Policy; + MaxParentalRating = policy.MaxParentalRating; + + if (policy.MaxParentalRating.HasValue) + { + BlockUnratedItems = policy.BlockUnratedItems; + } + + ExcludeTags = policy.BlockedTags; + + User = user; + } } } } diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs index 9317f688f..cd3e07ea3 100644 --- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs +++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs @@ -8,15 +8,13 @@ using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; -using System.Threading; -using System.Threading.Tasks; namespace MediaBrowser.Controller.Entities.Movies { /// <summary> /// Class BoxSet /// </summary> - public class BoxSet : Folder, IHasTrailers, IHasKeywords, IHasDisplayOrder, IHasLookupInfo<BoxSetInfo>, IMetadataContainer, IHasShares + public class BoxSet : Folder, IHasTrailers, IHasKeywords, IHasDisplayOrder, IHasLookupInfo<BoxSetInfo>, IHasShares { public List<Share> Shares { get; set; } @@ -65,6 +63,11 @@ namespace MediaBrowser.Controller.Entities.Movies return config.BlockUnratedItems.Contains(UnratedItem.Movie); } + public override UnratedItem GetBlockUnratedType() + { + return UnratedItem.Movie; + } + [IgnoreDataMember] public override bool IsPreSorted { @@ -154,34 +157,6 @@ namespace MediaBrowser.Controller.Entities.Movies return GetItemLookupInfo<BoxSetInfo>(); } - public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken) - { - // Refresh bottom up, children first, then the boxset - // By then hopefully the movies within will have Tmdb collection values - var items = GetRecursiveChildren().ToList(); - - var totalItems = items.Count; - var numComplete = 0; - - // Refresh songs - foreach (var item in items) - { - cancellationToken.ThrowIfCancellationRequested(); - - await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); - - numComplete++; - double percent = numComplete; - percent /= totalItems; - progress.Report(percent * 100); - } - - // Refresh current item - await RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); - - progress.Report(100); - } - public override bool IsVisible(User user) { var userId = user.Id.ToString("N"); diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs index 1a8148edf..749d562ac 100644 --- a/MediaBrowser.Controller/Entities/Movies/Movie.cs +++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs @@ -130,7 +130,7 @@ namespace MediaBrowser.Controller.Entities.Movies // Must have a parent to have special features // In other words, it must be part of the Parent/Child tree - if (LocationType == LocationType.FileSystem && Parent != null && !IsInMixedFolder) + if (LocationType == LocationType.FileSystem && GetParent() != null && !IsInMixedFolder) { var specialFeaturesChanged = await RefreshSpecialFeatures(options, fileSystemChildren, cancellationToken).ConfigureAwait(false); @@ -159,9 +159,9 @@ namespace MediaBrowser.Controller.Entities.Movies return itemsChanged; } - protected override bool GetBlockUnratedValue(UserPolicy config) + public override UnratedItem GetBlockUnratedType() { - return config.BlockUnratedItems.Contains(UnratedItem.Movie); + return UnratedItem.Movie; } public MovieInfo GetLookupInfo() diff --git a/MediaBrowser.Controller/Entities/MusicVideo.cs b/MediaBrowser.Controller/Entities/MusicVideo.cs index b2cad02de..8a820b5ff 100644 --- a/MediaBrowser.Controller/Entities/MusicVideo.cs +++ b/MediaBrowser.Controller/Entities/MusicVideo.cs @@ -56,9 +56,9 @@ namespace MediaBrowser.Controller.Entities return this.GetProviderId(MetadataProviders.Tmdb) ?? this.GetProviderId(MetadataProviders.Imdb) ?? base.CreateUserDataKey(); } - protected override bool GetBlockUnratedValue(UserPolicy config) + public override UnratedItem GetBlockUnratedType() { - return config.BlockUnratedItems.Contains(UnratedItem.Music); + return UnratedItem.Music; } public MusicVideoInfo GetLookupInfo() diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs index 6c277da56..120a376d4 100644 --- a/MediaBrowser.Controller/Entities/Person.cs +++ b/MediaBrowser.Controller/Entities/Person.cs @@ -101,6 +101,15 @@ namespace MediaBrowser.Controller.Entities return false; } } + + [IgnoreDataMember] + public override bool SupportsAncestors + { + get + { + return false; + } + } } /// <summary> diff --git a/MediaBrowser.Controller/Entities/Photo.cs b/MediaBrowser.Controller/Entities/Photo.cs index a3d892181..308e61590 100644 --- a/MediaBrowser.Controller/Entities/Photo.cs +++ b/MediaBrowser.Controller/Entities/Photo.cs @@ -9,12 +9,10 @@ namespace MediaBrowser.Controller.Entities { public class Photo : BaseItem, IHasTags, IHasTaglines { - public List<string> Tags { get; set; } public List<string> Taglines { get; set; } public Photo() { - Tags = new List<string>(); Taglines = new List<string>(); } @@ -51,7 +49,7 @@ namespace MediaBrowser.Controller.Entities { get { - return Parents.OfType<PhotoAlbum>().FirstOrDefault(); + return GetParents().OfType<PhotoAlbum>().FirstOrDefault(); } } @@ -70,10 +68,5 @@ namespace MediaBrowser.Controller.Entities public double? Longitude { get; set; } public double? Altitude { get; set; } public int? IsoSpeedRating { get; set; } - - protected override bool GetBlockUnratedValue(UserPolicy config) - { - return config.BlockUnratedItems.Contains(UnratedItem.Other); - } } } diff --git a/MediaBrowser.Controller/Entities/PhotoAlbum.cs b/MediaBrowser.Controller/Entities/PhotoAlbum.cs index 5b48a70e9..1f4faaf49 100644 --- a/MediaBrowser.Controller/Entities/PhotoAlbum.cs +++ b/MediaBrowser.Controller/Entities/PhotoAlbum.cs @@ -9,8 +9,9 @@ using System.Threading.Tasks; namespace MediaBrowser.Controller.Entities { - public class PhotoAlbum : Folder, IMetadataContainer + public class PhotoAlbum : Folder { + [IgnoreDataMember] public override bool SupportsLocalMetadata { get @@ -32,31 +33,5 @@ namespace MediaBrowser.Controller.Entities { return config.BlockUnratedItems.Contains(UnratedItem.Other); } - - public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken) - { - var items = GetRecursiveChildren().ToList(); - - var totalItems = items.Count; - var numComplete = 0; - - // Refresh songs - foreach (var item in items) - { - cancellationToken.ThrowIfCancellationRequested(); - - await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); - - numComplete++; - double percent = numComplete; - percent /= totalItems; - progress.Report(percent * 100); - } - - // Refresh current item - await RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); - - progress.Report(100); - } } } diff --git a/MediaBrowser.Controller/Entities/Studio.cs b/MediaBrowser.Controller/Entities/Studio.cs index 822f305ed..a55527f37 100644 --- a/MediaBrowser.Controller/Entities/Studio.cs +++ b/MediaBrowser.Controller/Entities/Studio.cs @@ -10,13 +10,6 @@ namespace MediaBrowser.Controller.Entities /// </summary> public class Studio : BaseItem, IItemByName, IHasTags { - public List<string> Tags { get; set; } - - public Studio() - { - Tags = new List<string>(); - } - /// <summary> /// Gets the user data key. /// </summary> diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index 92ca9e970..d4f829917 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -95,7 +95,7 @@ namespace MediaBrowser.Controller.Entities.TV { get { - return Season ?? Parent; + return Season ?? GetParent(); } } @@ -116,19 +116,6 @@ namespace MediaBrowser.Controller.Entities.TV } /// <summary> - /// Our rating comes from our series - /// </summary> - [IgnoreDataMember] - public override string OfficialRatingForComparison - { - get - { - var series = Series; - return series != null ? series.OfficialRatingForComparison : base.OfficialRatingForComparison; - } - } - - /// <summary> /// This Episode's Series Instance /// </summary> /// <value>The series.</value> @@ -265,14 +252,28 @@ namespace MediaBrowser.Controller.Entities.TV } } + public override IEnumerable<Guid> GetAncestorIds() + { + var list = base.GetAncestorIds().ToList(); + + var seasonId = SeasonId; + + if (seasonId.HasValue && !list.Contains(seasonId.Value)) + { + list.Add(seasonId.Value); + } + + return list; + } + public override IEnumerable<string> GetDeletePaths() { return new[] { Path }; } - protected override bool GetBlockUnratedValue(UserPolicy config) + public override UnratedItem GetBlockUnratedType() { - return config.BlockUnratedItems.Contains(UnratedItem.Series); + return UnratedItem.Series; } public EpisodeInfo GetLookupInfo() diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index 21b89d7a9..93eac058d 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -6,6 +6,7 @@ using MoreLinq; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; +using MediaBrowser.Model.Configuration; namespace MediaBrowser.Controller.Entities.TV { @@ -32,7 +33,7 @@ namespace MediaBrowser.Controller.Entities.TV [IgnoreDataMember] public override BaseItem DisplayParent { - get { return Series ?? Parent; } + get { return Series ?? GetParent(); } } // Genre, Rating and Stuido will all be the same @@ -88,19 +89,6 @@ namespace MediaBrowser.Controller.Entities.TV } /// <summary> - /// Our rating comes from our series - /// </summary> - [IgnoreDataMember] - public override string OfficialRatingForComparison - { - get - { - var series = Series; - return series != null ? series.OfficialRatingForComparison : base.OfficialRatingForComparison; - } - } - - /// <summary> /// Creates the name of the sort. /// </summary> /// <returns>System.String.</returns> @@ -234,6 +222,11 @@ namespace MediaBrowser.Controller.Entities.TV return false; } + public override UnratedItem GetBlockUnratedType() + { + return UnratedItem.Series; + } + [IgnoreDataMember] public string SeriesName { diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index b23833845..420b3c313 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -333,6 +333,11 @@ namespace MediaBrowser.Controller.Entities.TV return config.BlockUnratedItems.Contains(UnratedItem.Series); } + public override UnratedItem GetBlockUnratedType() + { + return UnratedItem.Series; + } + public SeriesInfo GetLookupInfo() { var info = GetItemLookupInfo<SeriesInfo>(); diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs index 6ec512783..3c7d39e0d 100644 --- a/MediaBrowser.Controller/Entities/Trailer.cs +++ b/MediaBrowser.Controller/Entities/Trailer.cs @@ -73,7 +73,7 @@ namespace MediaBrowser.Controller.Entities get { // Local trailers are not part of children - return Parent == null; + return GetParent() == null; } } @@ -97,9 +97,9 @@ namespace MediaBrowser.Controller.Entities return base.CreateUserDataKey(); } - protected override bool GetBlockUnratedValue(UserPolicy config) + public override UnratedItem GetBlockUnratedType() { - return config.BlockUnratedItems.Contains(UnratedItem.Trailer); + return UnratedItem.Trailer; } public TrailerInfo GetLookupInfo() diff --git a/MediaBrowser.Controller/Entities/User.cs b/MediaBrowser.Controller/Entities/User.cs index a9e314ede..976c6827f 100644 --- a/MediaBrowser.Controller/Entities/User.cs +++ b/MediaBrowser.Controller/Entities/User.cs @@ -20,7 +20,6 @@ namespace MediaBrowser.Controller.Entities { public static IUserManager UserManager { get; set; } public static IXmlSerializer XmlSerializer { get; set; } - public bool EnableUserViews { get; set; } /// <summary> /// From now on all user paths will be Id-based. @@ -58,6 +57,26 @@ namespace MediaBrowser.Controller.Entities } } + private string _name; + /// <summary> + /// Gets or sets the name. + /// </summary> + /// <value>The name.</value> + public override string Name + { + get + { + return _name; + } + set + { + _name = value; + + // lazy load this again + SortName = null; + } + } + /// <summary> /// Returns the folder containing the item. /// If the item is a folder, it returns the folder itself diff --git a/MediaBrowser.Controller/Entities/UserRootFolder.cs b/MediaBrowser.Controller/Entities/UserRootFolder.cs index a78beb645..b7946cb92 100644 --- a/MediaBrowser.Controller/Entities/UserRootFolder.cs +++ b/MediaBrowser.Controller/Entities/UserRootFolder.cs @@ -55,13 +55,21 @@ namespace MediaBrowser.Controller.Entities } } + protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user) + { + var list = base.GetEligibleChildrenForRecursiveChildren(user).ToList(); + list.AddRange(LibraryManager.RootFolder.VirtualChildren); + + return list; + } + /// <summary> /// Get the children of this folder from the actual file system /// </summary> /// <returns>IEnumerable{BaseItem}.</returns> protected override IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService) { - return base.GetNonCachedChildren(directoryService).Concat(LibraryManager.RootFolder.VirtualChildren); + return base.GetNonCachedChildren(directoryService); } public override bool BeforeMetadataRefresh() diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs index 5ee49ae5a..41c19f11d 100644 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ b/MediaBrowser.Controller/Entities/UserView.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Runtime.Serialization; using System.Threading.Tasks; +using System.Linq; namespace MediaBrowser.Controller.Entities { @@ -16,7 +17,7 @@ namespace MediaBrowser.Controller.Entities public Guid DisplayParentId { get; set; } public Guid? UserId { get; set; } - + public static ITVSeriesManager TVSeriesManager; public static IPlaylistManager PlaylistManager; @@ -24,7 +25,26 @@ namespace MediaBrowser.Controller.Entities { return true; } - + + public override IEnumerable<Guid> GetIdsForAncestorQuery() + { + var list = new List<Guid>(); + + if (DisplayParentId != Guid.Empty) + { + list.Add(DisplayParentId); + } + else if (ParentId != Guid.Empty) + { + list.Add(ParentId); + } + else + { + list.Add(Id); + } + return list; + } + public override Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query) { var parent = this as Folder; @@ -81,16 +101,11 @@ namespace MediaBrowser.Controller.Entities return GetChildren(user, false); } - public static bool IsExcludedFromGrouping(Folder folder) + public static bool IsUserSpecific(Folder folder) { var standaloneTypes = new List<string> { - CollectionType.Books, - CollectionType.HomeVideos, - CollectionType.Photos, - CollectionType.Playlists, - CollectionType.BoxSets, - CollectionType.MusicVideos + CollectionType.Playlists }; var collectionFolder = folder as ICollectionFolder; @@ -100,25 +115,63 @@ namespace MediaBrowser.Controller.Entities return false; } + var supportsUserSpecific = folder as ISupportsUserSpecificView; + if (supportsUserSpecific != null && supportsUserSpecific.EnableUserSpecificView) + { + return true; + } + return standaloneTypes.Contains(collectionFolder.CollectionType ?? string.Empty); } - public static bool IsUserSpecific(Folder folder) + public static bool IsEligibleForGrouping(Folder folder) { - var standaloneTypes = new List<string> - { - CollectionType.Playlists, - CollectionType.BoxSets + var collectionFolder = folder as ICollectionFolder; + return collectionFolder != null && IsEligibleForGrouping(collectionFolder.CollectionType); + } + + public static bool IsEligibleForGrouping(string viewType) + { + var types = new[] + { + CollectionType.Movies, + CollectionType.TvShows, + string.Empty }; - var collectionFolder = folder as ICollectionFolder; + return types.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase); + } - if (collectionFolder == null) - { - return false; - } + public static bool IsEligibleForEnhancedView(string viewType) + { + var types = new[] + { + CollectionType.Movies, + CollectionType.TvShows + }; - return standaloneTypes.Contains(collectionFolder.CollectionType ?? string.Empty); + return types.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase); + } + + public static bool EnableOriginalFolder(string viewType) + { + var types = new[] + { + CollectionType.Games, + CollectionType.Books, + CollectionType.MusicVideos, + CollectionType.HomeVideos, + CollectionType.Photos, + CollectionType.Music, + CollectionType.BoxSets + }; + + return types.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase); + } + + protected override Task ValidateChildrenInternal(IProgress<double> progress, System.Threading.CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, Providers.MetadataRefreshOptions refreshOptions, Providers.IDirectoryService directoryService) + { + return Task.FromResult(true); } [IgnoreDataMember] diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index f5800ce81..59ed67d9c 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -120,59 +120,34 @@ namespace MediaBrowser.Controller.Entities return await GetLiveTvView(queryParent, user, query).ConfigureAwait(false); } + case CollectionType.Photos: case CollectionType.Books: case CollectionType.HomeVideos: + case CollectionType.Games: case CollectionType.MusicVideos: + { + if (query.Recursive) + { + return GetResult(queryParent.GetRecursiveChildren(user, true), queryParent, query); + } return GetResult(queryParent.GetChildren(user, true), queryParent, query); + } case CollectionType.Folders: return GetResult(user.RootFolder.GetChildren(user, true), queryParent, query); - case CollectionType.Games: - return await GetGameView(user, queryParent, query).ConfigureAwait(false); - case CollectionType.Playlists: return await GetPlaylistsView(queryParent, user, query).ConfigureAwait(false); case CollectionType.BoxSets: return await GetBoxsetView(queryParent, user, query).ConfigureAwait(false); - case CollectionType.Photos: - return await GetPhotosView(queryParent, user, query).ConfigureAwait(false); - case CollectionType.TvShows: return await GetTvView(queryParent, user, query).ConfigureAwait(false); - case CollectionType.Music: - return await GetMusicFolders(queryParent, user, query).ConfigureAwait(false); - case CollectionType.Movies: return await GetMovieFolders(queryParent, user, query).ConfigureAwait(false); - case SpecialFolder.MusicGenres: - return await GetMusicGenres(queryParent, user, query).ConfigureAwait(false); - - case SpecialFolder.MusicGenre: - return await GetMusicGenreItems(queryParent, displayParent, user, query).ConfigureAwait(false); - - case SpecialFolder.GameGenres: - return await GetGameGenres(queryParent, user, query).ConfigureAwait(false); - - case SpecialFolder.GameGenre: - return await GetGameGenreItems(queryParent, displayParent, user, query).ConfigureAwait(false); - - case SpecialFolder.GameSystems: - return GetGameSystems(queryParent, user, query); - - case SpecialFolder.LatestGames: - return GetLatestGames(queryParent, user, query); - - case SpecialFolder.RecentlyPlayedGames: - return GetRecentlyPlayedGames(queryParent, user, query); - - case SpecialFolder.GameFavorites: - return GetFavoriteGames(queryParent, user, query); - case SpecialFolder.TvShowSeries: return GetTvSeries(queryParent, user, query); @@ -212,6 +187,21 @@ namespace MediaBrowser.Controller.Entities case SpecialFolder.MovieCollections: return GetMovieCollections(queryParent, user, query); + case SpecialFolder.TvFavoriteEpisodes: + return GetFavoriteEpisodes(queryParent, user, query); + + case SpecialFolder.TvFavoriteSeries: + return GetFavoriteSeries(queryParent, user, query); + + case CollectionType.Music: + return await GetMusicFolders(queryParent, user, query).ConfigureAwait(false); + + case SpecialFolder.MusicGenres: + return await GetMusicGenres(queryParent, user, query).ConfigureAwait(false); + + case SpecialFolder.MusicGenre: + return await GetMusicGenreItems(queryParent, displayParent, user, query).ConfigureAwait(false); + case SpecialFolder.MusicLatest: return GetMusicLatest(queryParent, user, query); @@ -230,12 +220,6 @@ namespace MediaBrowser.Controller.Entities case SpecialFolder.MusicSongs: return GetMusicSongs(queryParent, user, query); - case SpecialFolder.TvFavoriteEpisodes: - return GetFavoriteEpisodes(queryParent, user, query); - - case SpecialFolder.TvFavoriteSeries: - return GetFavoriteSeries(queryParent, user, query); - case SpecialFolder.MusicFavorites: return await GetMusicFavorites(queryParent, user, query).ConfigureAwait(false); @@ -262,18 +246,6 @@ namespace MediaBrowser.Controller.Entities } } - private async Task<QueryResult<BaseItem>> FindPlaylists(Folder parent, User user, InternalItemsQuery query) - { - var list = _playlistManager.GetPlaylists(user.Id.ToString("N")); - - return GetResult(list, parent, query); - } - - private int GetSpecialItemsLimit() - { - return 50; - } - private async Task<QueryResult<BaseItem>> GetMusicFolders(Folder parent, User user, InternalItemsQuery query) { if (query.Recursive) @@ -289,7 +261,7 @@ namespace MediaBrowser.Controller.Entities list.Add(await GetUserView(SpecialFolder.MusicPlaylists, "1", parent).ConfigureAwait(false)); list.Add(await GetUserView(SpecialFolder.MusicAlbums, "2", parent).ConfigureAwait(false)); list.Add(await GetUserView(SpecialFolder.MusicAlbumArtists, "3", parent).ConfigureAwait(false)); - //list.Add(await GetUserView(SpecialFolder.MusicArtists, user, "4", parent).ConfigureAwait(false)); + list.Add(await GetUserView(SpecialFolder.MusicArtists, "4", parent).ConfigureAwait(false)); list.Add(await GetUserView(SpecialFolder.MusicSongs, "5", parent).ConfigureAwait(false)); list.Add(await GetUserView(SpecialFolder.MusicGenres, "6", parent).ConfigureAwait(false)); list.Add(await GetUserView(SpecialFolder.MusicFavorites, "7", parent).ConfigureAwait(false)); @@ -422,6 +394,36 @@ namespace MediaBrowser.Controller.Entities return PostFilterAndSort(items, parent, null, query); } + private QueryResult<BaseItem> GetFavoriteSongs(Folder parent, User user, InternalItemsQuery query) + { + query.IsFavorite = true; + + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music }, i => (i is Audio.Audio) && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, null, query); + } + + private QueryResult<BaseItem> GetFavoriteAlbums(Folder parent, User user, InternalItemsQuery query) + { + query.IsFavorite = true; + + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music }, i => (i is MusicAlbum) && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, null, query); + } + + private async Task<QueryResult<BaseItem>> FindPlaylists(Folder parent, User user, InternalItemsQuery query) + { + var list = _playlistManager.GetPlaylists(user.Id.ToString("N")); + + return GetResult(list, parent, query); + } + + private int GetSpecialItemsLimit() + { + return 50; + } + private async Task<QueryResult<BaseItem>> GetMovieFolders(Folder parent, User user, InternalItemsQuery query) { if (query.Recursive) @@ -480,24 +482,6 @@ namespace MediaBrowser.Controller.Entities return PostFilterAndSort(items, parent, null, query); } - private QueryResult<BaseItem> GetFavoriteSongs(Folder parent, User user, InternalItemsQuery query) - { - query.IsFavorite = true; - - var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music }, i => (i is Audio.Audio) && FilterItem(i, query)); - - return PostFilterAndSort(items, parent, null, query); - } - - private QueryResult<BaseItem> GetFavoriteAlbums(Folder parent, User user, InternalItemsQuery query) - { - query.IsFavorite = true; - - var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music }, i => (i is MusicAlbum) && FilterItem(i, query)); - - return PostFilterAndSort(items, parent, null, query); - } - private QueryResult<BaseItem> GetMovieMovies(Folder parent, User user, InternalItemsQuery query) { var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }, i => (i is Movie) && FilterItem(i, query)); @@ -617,54 +601,6 @@ namespace MediaBrowser.Controller.Entities return GetResult(list, parent, query); } - private async Task<QueryResult<BaseItem>> GetGameView(User user, Folder parent, InternalItemsQuery query) - { - if (query.Recursive) - { - var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => FilterItem(i, query)); - return PostFilterAndSort(items, parent, null, query); - } - - var list = new List<BaseItem>(); - - list.Add(await GetUserView(SpecialFolder.LatestGames, "0", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.RecentlyPlayedGames, "1", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.GameFavorites, "2", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.GameSystems, "3", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.GameGenres, "4", parent).ConfigureAwait(false)); - - return GetResult(list, parent, query); - } - - private QueryResult<BaseItem> GetLatestGames(Folder parent, User user, InternalItemsQuery query) - { - query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName }; - query.SortOrder = SortOrder.Descending; - - var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => i is Game && FilterItem(i, query)); - - return PostFilterAndSort(items, parent, GetSpecialItemsLimit(), query); - } - - private QueryResult<BaseItem> GetRecentlyPlayedGames(Folder parent, User user, InternalItemsQuery query) - { - query.IsPlayed = true; - query.SortBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName }; - query.SortOrder = SortOrder.Descending; - - var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => i is Game && FilterItem(i, query)); - - return PostFilterAndSort(items, parent, GetSpecialItemsLimit(), query); - } - - private QueryResult<BaseItem> GetFavoriteGames(Folder parent, User user, InternalItemsQuery query) - { - query.IsFavorite = true; - - var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => i is Game && FilterItem(i, query)); - return PostFilterAndSort(items, parent, null, query); - } - private QueryResult<BaseItem> GetTvLatest(Folder parent, User user, InternalItemsQuery query) { query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName }; @@ -745,49 +681,6 @@ namespace MediaBrowser.Controller.Entities return GetResult(items, queryParent, query); } - private QueryResult<BaseItem> GetGameSystems(Folder parent, User user, InternalItemsQuery query) - { - var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => i is GameSystem && FilterItem(i, query)); - - return PostFilterAndSort(items, parent, null, query); - } - - private async Task<QueryResult<BaseItem>> GetGameGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query) - { - var items = GetRecursiveChildren(queryParent, user, new[] { CollectionType.Games }, - i => i is Game && i.Genres.Contains(displayParent.Name, StringComparer.OrdinalIgnoreCase)); - - return GetResult(items, queryParent, query); - } - - private async Task<QueryResult<BaseItem>> GetGameGenres(Folder parent, User user, InternalItemsQuery query) - { - var tasks = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }) - .OfType<Game>() - .SelectMany(i => i.Genres) - .DistinctNames() - .Select(i => - { - try - { - return _libraryManager.GetGameGenre(i); - } - catch - { - // Full exception logged at lower levels - _logger.Error("Error getting game genre"); - return null; - } - - }) - .Where(i => i != null) - .Select(i => GetUserView(i.Name, SpecialFolder.GameGenre, i.SortName, parent)); - - var genres = await Task.WhenAll(tasks).ConfigureAwait(false); - - return GetResult(genres, parent, query); - } - private QueryResult<BaseItem> GetResult<T>(QueryResult<T> result) where T : BaseItem { @@ -1061,6 +954,11 @@ namespace MediaBrowser.Controller.Entities return false; } + if (request.GenreIds.Length > 0) + { + return false; + } + if (request.VideoTypes.Length > 0) { return false; @@ -1101,10 +999,15 @@ namespace MediaBrowser.Controller.Entities return false; } + if (request.MinIndexNumber.HasValue) + { + return false; + } + return true; } - public static IEnumerable<BaseItem> FilterVirtualEpisodes( + private static IEnumerable<BaseItem> FilterVirtualEpisodes( IEnumerable<BaseItem> items, bool? isMissing, bool? isVirtualUnaired, @@ -1374,7 +1277,7 @@ namespace MediaBrowser.Controller.Entities if (query.IsInBoxSet.HasValue) { var val = query.IsInBoxSet.Value; - if (item.Parents.OfType<BoxSet>().Any() != val) + if (item.GetParents().OfType<BoxSet>().Any() != val) { return false; } @@ -1657,6 +1560,16 @@ namespace MediaBrowser.Controller.Entities return false; } + // Apply genre filter + if (query.GenreIds.Length > 0 && !query.GenreIds.Any(id => + { + var genreItem = libraryManager.GetItemById(id); + return genreItem != null && item.Genres.Contains(genreItem.Name, StringComparer.OrdinalIgnoreCase); + })) + { + return false; + } + // Apply year filter if (query.Years.Length > 0) { @@ -1779,6 +1692,16 @@ namespace MediaBrowser.Controller.Entities } } + if (query.MinIndexNumber.HasValue) + { + var val = query.MinIndexNumber.Value; + + if (!(item.IndexNumber.HasValue && item.IndexNumber.Value >= val)) + { + return false; + } + } + return true; } @@ -1789,12 +1712,12 @@ namespace MediaBrowser.Controller.Entities return _libraryManager.RootFolder .Children .OfType<Folder>() - .Where(i => !UserView.IsExcludedFromGrouping(i)); + .Where(UserView.IsEligibleForGrouping); } return user.RootFolder - .GetChildren(user, true, true) + .GetChildren(user, true) .OfType<Folder>() - .Where(i => user.IsFolderGrouped(i.Id) && !UserView.IsExcludedFromGrouping(i)); + .Where(i => user.IsFolderGrouped(i.Id) && UserView.IsEligibleForGrouping(i)); } private IEnumerable<Folder> GetMediaFolders(User user, IEnumerable<string> viewTypes) diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 10068eed7..197222669 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -186,12 +186,6 @@ namespace MediaBrowser.Controller.Entities public string ShortcutPath { get; set; } /// <summary> - /// Gets or sets the tags. - /// </summary> - /// <value>The tags.</value> - public List<string> Tags { get; set; } - - /// <summary> /// Gets or sets the video bit rate. /// </summary> /// <value>The video bit rate.</value> @@ -356,7 +350,7 @@ namespace MediaBrowser.Controller.Entities // Must have a parent to have additional parts or alternate versions // In other words, it must be part of the Parent/Child tree // The additional parts won't have additional parts themselves - if (LocationType == LocationType.FileSystem && Parent != null) + if (LocationType == LocationType.FileSystem && GetParent() != null) { if (!IsStacked) { |
