diff options
| author | Luke <luke.pulverenti@gmail.com> | 2016-06-30 15:27:06 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-06-30 15:27:06 -0400 |
| commit | 2708df6cc28c48a89416bdfbdde7e78fc4227c62 (patch) | |
| tree | 9f892d6350a4d694c96985d679f622c0f7005278 /MediaBrowser.Controller | |
| parent | d9406d48ca0231bc096aeadc595c30f0596c8dda (diff) | |
| parent | 5bdc96bb6a9b863980661e2d11c1ad00a02eb601 (diff) | |
Merge pull request #1899 from MediaBrowser/beta
Beta
Diffstat (limited to 'MediaBrowser.Controller')
59 files changed, 588 insertions, 883 deletions
diff --git a/MediaBrowser.Controller/Channels/ChannelItemInfo.cs b/MediaBrowser.Controller/Channels/ChannelItemInfo.cs index 587023ab4..57c2f1f7f 100644 --- a/MediaBrowser.Controller/Channels/ChannelItemInfo.cs +++ b/MediaBrowser.Controller/Channels/ChannelItemInfo.cs @@ -53,6 +53,12 @@ namespace MediaBrowser.Controller.Channels public bool IsInfiniteStream { get; set; } + public string HomePageUrl { get; set; } + + public List<string> Artists { get; set; } + + public List<string> AlbumArtists { get; set; } + public ChannelItemInfo() { MediaSources = new List<ChannelMediaInfo>(); @@ -62,6 +68,8 @@ namespace MediaBrowser.Controller.Channels People = new List<PersonInfo>(); Tags = new List<string>(); ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); + Artists = new List<string>(); + AlbumArtists = new List<string>(); } } } diff --git a/MediaBrowser.Controller/Chapters/IChapterManager.cs b/MediaBrowser.Controller/Chapters/IChapterManager.cs index 676ef9c56..27e06fb8d 100644 --- a/MediaBrowser.Controller/Chapters/IChapterManager.cs +++ b/MediaBrowser.Controller/Chapters/IChapterManager.cs @@ -33,7 +33,7 @@ namespace MediaBrowser.Controller.Chapters /// <param name="chapters">The chapters.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - Task SaveChapters(string itemId, IEnumerable<ChapterInfo> chapters, CancellationToken cancellationToken); + Task SaveChapters(string itemId, List<ChapterInfo> chapters, CancellationToken cancellationToken); /// <summary> /// Searches the specified video. diff --git a/MediaBrowser.Controller/Drawing/ImageCollageOptions.cs b/MediaBrowser.Controller/Drawing/ImageCollageOptions.cs index edc4f8558..92a7f5ac9 100644 --- a/MediaBrowser.Controller/Drawing/ImageCollageOptions.cs +++ b/MediaBrowser.Controller/Drawing/ImageCollageOptions.cs @@ -23,10 +23,5 @@ namespace MediaBrowser.Controller.Drawing /// </summary> /// <value>The height.</value> public int Height { get; set; } - /// <summary> - /// Gets or sets the text. - /// </summary> - /// <value>The text.</value> - public string Text { get; set; } } } diff --git a/MediaBrowser.Controller/Dto/IDtoService.cs b/MediaBrowser.Controller/Dto/IDtoService.cs index 5f0442f93..e4aa466df 100644 --- a/MediaBrowser.Controller/Dto/IDtoService.cs +++ b/MediaBrowser.Controller/Dto/IDtoService.cs @@ -3,6 +3,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Querying; using System.Collections.Generic; +using System.Threading.Tasks; namespace MediaBrowser.Controller.Dto { @@ -68,7 +69,7 @@ namespace MediaBrowser.Controller.Dto /// <param name="user">The user.</param> /// <param name="owner">The owner.</param> /// <returns>IEnumerable<BaseItemDto>.</returns> - IEnumerable<BaseItemDto> GetBaseItemDtos(IEnumerable<BaseItem> items, DtoOptions options, User user = null, + Task<List<BaseItemDto>> GetBaseItemDtos(IEnumerable<BaseItem> items, DtoOptions options, User user = null, BaseItem owner = null); /// <summary> diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index c34a884ff..b3df34c4d 100644 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs @@ -20,15 +20,12 @@ namespace MediaBrowser.Controller.Entities.Audio IHasArtist, IHasMusicGenres, IHasLookupInfo<SongInfo>, - IHasTags, IHasMediaSources, IThemeMedia, IArchivable { public List<ChannelMediaInfo> ChannelMediaSources { get; set; } - public long? Size { get; set; } - public string Container { get; set; } public int? TotalBitrate { get; set; } public ExtraType? ExtraType { get; set; } diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs index 615276e83..1f3b0c92a 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs @@ -179,17 +179,13 @@ namespace MediaBrowser.Controller.Entities.Audio { var items = GetRecursiveChildren().ToList(); - var songs = items.OfType<Audio>().ToList(); - - var others = items.Except(songs).ToList(); - - var totalItems = songs.Count + others.Count; + var totalItems = items.Count; var numComplete = 0; var childUpdateType = ItemUpdateType.None; // Refresh songs - foreach (var item in songs) + foreach (var item in items) { cancellationToken.ThrowIfCancellationRequested(); @@ -199,7 +195,7 @@ namespace MediaBrowser.Controller.Entities.Audio numComplete++; double percent = numComplete; percent /= totalItems; - progress.Report(percent * 100); + progress.Report(percent * 95); } var parentRefreshOptions = refreshOptions; @@ -212,19 +208,6 @@ namespace MediaBrowser.Controller.Entities.Audio // Refresh current item await RefreshMetadata(parentRefreshOptions, cancellationToken).ConfigureAwait(false); - // Refresh all non-songs - foreach (var item in others) - { - cancellationToken.ThrowIfCancellationRequested(); - - var updateType = await item.RefreshMetadata(parentRefreshOptions, cancellationToken).ConfigureAwait(false); - - numComplete++; - double percent = numComplete; - percent /= totalItems; - progress.Report(percent * 100); - } - progress.Report(100); } } diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs index 02dad93cb..6790a1bcf 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs @@ -9,6 +9,7 @@ using System.Linq; using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Extensions; namespace MediaBrowser.Controller.Entities.Audio { @@ -62,13 +63,6 @@ namespace MediaBrowser.Controller.Entities.Audio query.ArtistNames = new[] { Name }; } - // Need this for now since the artist filter isn't yet supported by the db - if (ConfigurationManager.Configuration.SchemaVersion < 79) - { - var filter = GetItemFilter(); - return LibraryManager.GetItemList(query).Where(filter); - } - return LibraryManager.GetItemList(query); } @@ -86,6 +80,15 @@ namespace MediaBrowser.Controller.Entities.Audio } } + public override int GetChildCount(User user) + { + if (IsAccessedByName) + { + return 0; + } + return base.GetChildCount(user); + } + public override bool IsSaveLocalMetadataEnabled() { if (IsAccessedByName) @@ -163,10 +166,17 @@ namespace MediaBrowser.Controller.Entities.Audio list.Add("Artist-Musicbrainz-" + id); } - list.Add("Artist-" + item.Name); + list.Add("Artist-" + (item.Name ?? string.Empty).RemoveDiacritics()); return list; } + public override string PresentationUniqueKey + { + get + { + return "Artist-" + (Name ?? string.Empty).RemoveDiacritics(); + } + } protected override bool GetBlockUnratedValue(UserPolicy config) { return config.BlockUnratedItems.Contains(UnratedItem.Music); diff --git a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs index 77cf0cc49..798bc79fb 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; +using MediaBrowser.Common.Extensions; namespace MediaBrowser.Controller.Entities.Audio { @@ -14,10 +15,18 @@ namespace MediaBrowser.Controller.Entities.Audio { var list = base.GetUserDataKeys(); - list.Insert(0, "MusicGenre-" + Name); + list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics()); return list; } + public override string PresentationUniqueKey + { + get + { + return GetUserDataKeys()[0]; + } + } + [IgnoreDataMember] public override bool SupportsAddingToPlaylist { diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 61060766f..0dd7b3c83 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -26,6 +26,7 @@ using System.Threading.Tasks; using CommonIO; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.LiveTv; +using MediaBrowser.Model.Providers; namespace MediaBrowser.Controller.Entities { @@ -36,6 +37,7 @@ namespace MediaBrowser.Controller.Entities { protected BaseItem() { + Keywords = new List<string>(); Tags = new List<string>(); Genres = new List<string>(); Studios = new List<string>(); @@ -67,12 +69,20 @@ namespace MediaBrowser.Controller.Entities [IgnoreDataMember] public string PreferredMetadataLanguage { get; set; } + public long? Size { get; set; } + public string Container { get; set; } + public string ShortOverview { get; set; } + public List<ItemImageInfo> ImageInfos { get; set; } + [IgnoreDataMember] + public bool IsVirtualItem { get; set; } + /// <summary> /// Gets or sets the album. /// </summary> /// <value>The album.</value> + [IgnoreDataMember] public string Album { get; set; } /// <summary> @@ -810,6 +820,8 @@ namespace MediaBrowser.Controller.Entities [IgnoreDataMember] public List<string> Tags { get; set; } + public List<string> Keywords { get; set; } + /// <summary> /// Gets or sets the home page URL. /// </summary> @@ -1031,9 +1043,7 @@ namespace MediaBrowser.Controller.Entities } : options; - var result = await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false); - - return result; + return await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false); } [IgnoreDataMember] @@ -1394,15 +1404,10 @@ namespace MediaBrowser.Controller.Entities private bool IsVisibleViaTags(User user) { - var hasTags = this as IHasTags; - - if (hasTags != null) + var policy = user.Policy; + if (policy.BlockedTags.Any(i => Tags.Contains(i, StringComparer.OrdinalIgnoreCase))) { - var policy = user.Policy; - if (policy.BlockedTags.Any(i => hasTags.Tags.Contains(i, StringComparer.OrdinalIgnoreCase))) - { - return false; - } + return false; } return true; @@ -2088,7 +2093,7 @@ namespace MediaBrowser.Controller.Entities return path; } - public virtual void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user) + public virtual Task FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user) { if (RunTimeTicks.HasValue) { @@ -2104,6 +2109,8 @@ namespace MediaBrowser.Controller.Entities } } } + + return Task.FromResult(true); } protected Task RefreshMetadataForOwnedVideo(MetadataRefreshOptions options, string path, CancellationToken cancellationToken) @@ -2168,7 +2175,7 @@ namespace MediaBrowser.Controller.Entities { get { - if (GetParent() is AggregateFolder || this is BasePluginFolder) + if (GetParent() is AggregateFolder || this is BasePluginFolder || this is Channel) { return true; } @@ -2214,5 +2221,10 @@ namespace MediaBrowser.Controller.Entities DeleteFileLocation = false }); } + + public virtual List<ExternalUrl> GetRelatedUrls() + { + return new List<ExternalUrl>(); + } } }
\ No newline at end of file diff --git a/MediaBrowser.Controller/Entities/Book.cs b/MediaBrowser.Controller/Entities/Book.cs index 1c86a53f0..96fad670e 100644 --- a/MediaBrowser.Controller/Entities/Book.cs +++ b/MediaBrowser.Controller/Entities/Book.cs @@ -6,7 +6,7 @@ using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Entities { - public class Book : BaseItem, IHasTags, IHasLookupInfo<BookInfo>, IHasSeries + public class Book : BaseItem, IHasLookupInfo<BookInfo>, IHasSeries { [IgnoreDataMember] public override string MediaType diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index e7b1df55a..210c11564 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -13,6 +13,7 @@ using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; using CommonIO; +using MediaBrowser.Controller.Channels; using MediaBrowser.Model.Channels; namespace MediaBrowser.Controller.Entities @@ -20,7 +21,7 @@ namespace MediaBrowser.Controller.Entities /// <summary> /// Class Folder /// </summary> - public class Folder : BaseItem, IHasThemeMedia, IHasTags + public class Folder : BaseItem, IHasThemeMedia { public static IUserManager UserManager { get; set; } public static IUserViewManager UserViewManager { get; set; } @@ -164,49 +165,15 @@ namespace MediaBrowser.Controller.Entities item.DateModified = DateTime.UtcNow; } - AddChildInternal(item.Id); - await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false); } - protected void AddChildrenInternal(List<Guid> children) - { - lock (_childrenSyncLock) - { - var newChildren = ChildIds.ToList(); - newChildren.AddRange(children); - _children = newChildren.ToList(); - } - } - protected void AddChildInternal(Guid child) - { - lock (_childrenSyncLock) - { - var childIds = ChildIds.ToList(); - if (!childIds.Contains(child)) - { - childIds.Add(child); - _children = childIds.ToList(); - } - } - } - - protected void RemoveChildrenInternal(List<Guid> children) - { - lock (_childrenSyncLock) - { - _children = ChildIds.Except(children).ToList(); - } - } - /// <summary> /// Removes the child. /// </summary> /// <param name="item">The item.</param> public void RemoveChild(BaseItem item) { - RemoveChildrenInternal(new[] { item.Id }.ToList()); - item.SetParent(null); } @@ -242,33 +209,6 @@ namespace MediaBrowser.Controller.Entities #endregion /// <summary> - /// The children - /// </summary> - private IReadOnlyList<Guid> _children; - /// <summary> - /// The _children sync lock - /// </summary> - private readonly object _childrenSyncLock = new object(); - /// <summary> - /// Gets or sets the actual children. - /// </summary> - /// <value>The actual children.</value> - protected virtual IEnumerable<Guid> ChildIds - { - get - { - lock (_childrenSyncLock) - { - if (_children == null) - { - _children = LoadChildren().ToList(); - } - return _children.ToList(); - } - } - } - - /// <summary> /// Gets the actual children. /// </summary> /// <value>The actual children.</value> @@ -277,7 +217,7 @@ namespace MediaBrowser.Controller.Entities { get { - return ChildIds.Select(LibraryManager.GetItemById).Where(i => i != null); + return LoadChildren(); } } @@ -331,7 +271,7 @@ namespace MediaBrowser.Controller.Entities /// Loads our children. Validation will occur externally. /// We want this sychronous. /// </summary> - protected virtual IEnumerable<Guid> LoadChildren() + protected virtual IEnumerable<BaseItem> LoadChildren() { //just load our children from the repo - the library will be validated and maintained in other processes return GetCachedChildren(); @@ -461,17 +401,15 @@ namespace MediaBrowser.Controller.Entities foreach (var item in itemsRemoved) { - if (item.LocationType == LocationType.Virtual || - item.LocationType == LocationType.Remote) + var itemLocationType = item.LocationType; + if (itemLocationType == LocationType.Virtual || + itemLocationType == LocationType.Remote) { - // Don't remove these because there's no way to accurately validate them. - validChildren.Add(item); } else if (!string.IsNullOrEmpty(item.Path) && IsPathOffline(item.Path)) { await UpdateIsOffline(item, true).ConfigureAwait(false); - validChildren.Add(item); } else { @@ -481,8 +419,6 @@ namespace MediaBrowser.Controller.Entities if (actualRemovals.Count > 0) { - RemoveChildrenInternal(actualRemovals.Select(i => i.Id).ToList()); - foreach (var item in actualRemovals) { Logger.Debug("Removed item: " + item.Path); @@ -495,8 +431,6 @@ namespace MediaBrowser.Controller.Entities } await LibraryManager.CreateItems(newItems, cancellationToken).ConfigureAwait(false); - - AddChildrenInternal(newItems.Select(i => i.Id).ToList()); } } @@ -724,15 +658,36 @@ namespace MediaBrowser.Controller.Entities /// Get our children from the repo - stubbed for now /// </summary> /// <returns>IEnumerable{BaseItem}.</returns> - protected IEnumerable<Guid> GetCachedChildren() + protected IEnumerable<BaseItem> GetCachedChildren() { - return ItemRepository.GetItemIdsList(new InternalItemsQuery + return ItemRepository.GetItemList(new InternalItemsQuery { ParentId = Id, GroupByPresentationUniqueKey = false }); } + public virtual int GetChildCount(User user) + { + if (LinkedChildren.Count > 0) + { + if (!(this is ICollectionFolder)) + { + return GetChildren(user, true).Count(); + } + } + + var result = GetItems(new InternalItemsQuery(user) + { + Recursive = false, + Limit = 0, + ParentId = Id + + }).Result; + + return result.TotalRecordCount; + } + public QueryResult<BaseItem> QueryRecursive(InternalItemsQuery query) { var user = query.User; @@ -768,58 +723,13 @@ namespace MediaBrowser.Controller.Entities { if (!(this is ICollectionFolder)) { - Logger.Debug("Query requires post-filtering due to LinkedChildren"); + Logger.Debug("Query requires post-filtering due to LinkedChildren. Type: " + GetType().Name); return true; } } - var supportsUserDataQueries = ConfigurationManager.Configuration.SchemaVersion >= 76; - if (query.SortBy != null && query.SortBy.Length > 0) { - if (!supportsUserDataQueries) - { - if (query.SortBy.Contains(ItemSortBy.DatePlayed, StringComparer.OrdinalIgnoreCase)) - { - Logger.Debug("Query requires post-filtering due to ItemSortBy.IsFavoriteOrLiked"); - return true; - } - if (query.SortBy.Contains(ItemSortBy.PlayCount, StringComparer.OrdinalIgnoreCase)) - { - Logger.Debug("Query requires post-filtering due to ItemSortBy.PlayCount"); - return true; - } - if (query.SortBy.Contains(ItemSortBy.IsFavoriteOrLiked, StringComparer.OrdinalIgnoreCase)) - { - Logger.Debug("Query requires post-filtering due to ItemSortBy.IsFavoriteOrLiked"); - return true; - } - if (query.SortBy.Contains(ItemSortBy.IsPlayed, StringComparer.OrdinalIgnoreCase)) - { - Logger.Debug("Query requires post-filtering due to ItemSortBy.IsPlayed"); - return true; - } - if (query.SortBy.Contains(ItemSortBy.IsUnplayed, StringComparer.OrdinalIgnoreCase)) - { - Logger.Debug("Query requires post-filtering due to ItemSortBy.IsUnplayed"); - return true; - } - } - - if (ConfigurationManager.Configuration.SchemaVersion < 79) - { - if (query.SortBy.Contains(ItemSortBy.AlbumArtist, StringComparer.OrdinalIgnoreCase)) - { - Logger.Debug("Query requires post-filtering due to ItemSortBy.AlbumArtist"); - return true; - } - if (query.SortBy.Contains(ItemSortBy.Artist, StringComparer.OrdinalIgnoreCase)) - { - Logger.Debug("Query requires post-filtering due to ItemSortBy.Artist"); - return true; - } - } - if (query.SortBy.Contains(ItemSortBy.AiredEpisodeOrder, StringComparer.OrdinalIgnoreCase)) { Logger.Debug("Query requires post-filtering due to ItemSortBy.AiredEpisodeOrder"); @@ -840,11 +750,6 @@ namespace MediaBrowser.Controller.Entities Logger.Debug("Query requires post-filtering due to ItemSortBy.Metascore"); return true; } - if (query.SortBy.Contains(ItemSortBy.OfficialRating, StringComparer.OrdinalIgnoreCase)) - { - Logger.Debug("Query requires post-filtering due to ItemSortBy.OfficialRating"); - return true; - } if (query.SortBy.Contains(ItemSortBy.Players, StringComparer.OrdinalIgnoreCase)) { Logger.Debug("Query requires post-filtering due to ItemSortBy.Players"); @@ -860,11 +765,6 @@ namespace MediaBrowser.Controller.Entities Logger.Debug("Query requires post-filtering due to ItemSortBy.SeriesSortName"); return true; } - if (query.SortBy.Contains(ItemSortBy.Studio, StringComparer.OrdinalIgnoreCase)) - { - Logger.Debug("Query requires post-filtering due to ItemSortBy.Studio"); - return true; - } if (query.SortBy.Contains(ItemSortBy.VideoBitRate, StringComparer.OrdinalIgnoreCase)) { Logger.Debug("Query requires post-filtering due to ItemSortBy.VideoBitRate"); @@ -878,45 +778,6 @@ namespace MediaBrowser.Controller.Entities return true; } - if (query.PersonIds.Length > 0) - { - Logger.Debug("Query requires post-filtering due to PersonIds"); - return true; - } - - if (!supportsUserDataQueries) - { - if (query.IsLiked.HasValue) - { - Logger.Debug("Query requires post-filtering due to IsLiked"); - return true; - } - - if (query.IsFavoriteOrLiked.HasValue) - { - Logger.Debug("Query requires post-filtering due to IsFavoriteOrLiked"); - return true; - } - - if (query.IsFavorite.HasValue) - { - Logger.Debug("Query requires post-filtering due to IsFavorite"); - return true; - } - - if (query.IsResumable.HasValue) - { - Logger.Debug("Query requires post-filtering due to IsResumable"); - return true; - } - - if (query.IsPlayed.HasValue) - { - Logger.Debug("Query requires post-filtering due to IsPlayed"); - return true; - } - } - if (query.IsInBoxSet.HasValue) { Logger.Debug("Query requires post-filtering due to IsInBoxSet"); @@ -930,30 +791,6 @@ namespace MediaBrowser.Controller.Entities return true; } - if (query.HasImdbId.HasValue) - { - Logger.Debug("Query requires post-filtering due to HasImdbId"); - return true; - } - - if (query.HasTmdbId.HasValue) - { - Logger.Debug("Query requires post-filtering due to HasTmdbId"); - return true; - } - - if (query.HasTvdbId.HasValue) - { - Logger.Debug("Query requires post-filtering due to HasTvdbId"); - return true; - } - - if (query.IsYearMismatched.HasValue) - { - Logger.Debug("Query requires post-filtering due to IsYearMismatched"); - return true; - } - if (query.HasOfficialRating.HasValue) { Logger.Debug("Query requires post-filtering due to HasOfficialRating"); @@ -1003,26 +840,6 @@ namespace MediaBrowser.Controller.Entities return true; } - if (query.ImageTypes.Length > 0) - { - Logger.Debug("Query requires post-filtering due to ImageTypes"); - return true; - } - - // Apply studio filter - if (query.StudioIds.Length > 0) - { - Logger.Debug("Query requires post-filtering due to StudioIds"); - return true; - } - - // Apply genre filter - if (query.GenreIds.Length > 0) - { - Logger.Debug("Query requires post-filtering due to GenreIds"); - return true; - } - // Apply person filter if (query.ItemIdsFromPersonFilters != null) { @@ -1042,12 +859,6 @@ namespace MediaBrowser.Controller.Entities return true; } - if (query.OfficialRatings.Length > 0) - { - Logger.Debug("Query requires post-filtering due to OfficialRatings"); - return true; - } - if (query.IsMissing.HasValue) { Logger.Debug("Query requires post-filtering due to IsMissing"); @@ -1066,7 +877,7 @@ namespace MediaBrowser.Controller.Entities return true; } - if (UserViewBuilder.CollapseBoxSetItems(query, this, query.User)) + if (UserViewBuilder.CollapseBoxSetItems(query, this, query.User, ConfigurationManager)) { Logger.Debug("Query requires post-filtering due to CollapseBoxSetItems"); return true; @@ -1102,15 +913,6 @@ namespace MediaBrowser.Controller.Entities return true; } - if (ConfigurationManager.Configuration.SchemaVersion < 79) - { - if (query.ArtistNames.Length > 0) - { - Logger.Debug("Query requires post-filtering due to ArtistNames"); - return true; - } - } - return false; } @@ -1183,7 +985,7 @@ namespace MediaBrowser.Controller.Entities protected QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, InternalItemsQuery query) { - return UserViewBuilder.PostFilterAndSort(items, this, null, query, LibraryManager); + return UserViewBuilder.PostFilterAndSort(items, this, null, query, LibraryManager, ConfigurationManager); } public virtual IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren) @@ -1601,72 +1403,61 @@ namespace MediaBrowser.Controller.Entities { return false; } + if (this is Channel) + { + return false; + } + if (SourceType != SourceType.Library) + { + return false; + } return true; } } - public override void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user) + public override async Task FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user) { if (!SupportsUserDataFromChildren) { return; } - var recursiveItemCount = 0; - var unplayed = 0; - - double totalPercentPlayed = 0; - - var itemsResult = GetItems(new InternalItemsQuery(user) + var unplayedQueryResult = await GetItems(new InternalItemsQuery(user) { Recursive = true, IsFolder = false, - ExcludeLocationTypes = new[] { LocationType.Virtual }, - EnableTotalRecordCount = false - - }).Result; + IsVirtualItem = false, + EnableTotalRecordCount = true, + Limit = 0, + IsPlayed = false - var children = itemsResult.Items; + }).ConfigureAwait(false); - // Loop through each recursive child - foreach (var child in children) + var allItemsQueryResult = await GetItems(new InternalItemsQuery(user) { - recursiveItemCount++; - - var isUnplayed = true; - - var itemUserData = UserDataManager.GetUserData(user, child); - - // Incrememt totalPercentPlayed - if (itemUserData != null) - { - if (itemUserData.Played) - { - totalPercentPlayed += 100; + Recursive = true, + IsFolder = false, + IsVirtualItem = false, + EnableTotalRecordCount = true, + Limit = 0 - isUnplayed = false; - } - else if (itemUserData.PlaybackPositionTicks > 0 && child.RunTimeTicks.HasValue && child.RunTimeTicks.Value > 0) - { - double itemPercent = itemUserData.PlaybackPositionTicks; - itemPercent /= child.RunTimeTicks.Value; - totalPercentPlayed += itemPercent; - } - } + }).ConfigureAwait(false); - if (isUnplayed) - { - unplayed++; - } + if (itemDto != null) + { + itemDto.RecursiveItemCount = allItemsQueryResult.TotalRecordCount; } - dto.UnplayedItemCount = unplayed; + double recursiveItemCount = allItemsQueryResult.TotalRecordCount; + double unplayedCount = unplayedQueryResult.TotalRecordCount; if (recursiveItemCount > 0) { - dto.PlayedPercentage = totalPercentPlayed / recursiveItemCount; + var unplayedPercentage = (unplayedCount / recursiveItemCount) * 100; + dto.PlayedPercentage = 100 - unplayedPercentage; dto.Played = dto.PlayedPercentage.Value >= 100; + dto.UnplayedItemCount = unplayedQueryResult.TotalRecordCount; } } } diff --git a/MediaBrowser.Controller/Entities/Game.cs b/MediaBrowser.Controller/Entities/Game.cs index 9ed240046..317c71529 100644 --- a/MediaBrowser.Controller/Entities/Game.cs +++ b/MediaBrowser.Controller/Entities/Game.cs @@ -7,7 +7,7 @@ using System.Linq; namespace MediaBrowser.Controller.Entities { - public class Game : BaseItem, IHasTrailers, IHasThemeMedia, IHasTags, IHasScreenshots, ISupportsPlaceHolders, IHasLookupInfo<GameInfo> + public class Game : BaseItem, IHasTrailers, IHasThemeMedia, IHasScreenshots, ISupportsPlaceHolders, IHasLookupInfo<GameInfo> { public List<Guid> ThemeSongIds { get; set; } public List<Guid> ThemeVideoIds { get; set; } diff --git a/MediaBrowser.Controller/Entities/GameGenre.cs b/MediaBrowser.Controller/Entities/GameGenre.cs index 7c1e88cb1..45e766c0f 100644 --- a/MediaBrowser.Controller/Entities/GameGenre.cs +++ b/MediaBrowser.Controller/Entities/GameGenre.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; +using MediaBrowser.Common.Extensions; namespace MediaBrowser.Controller.Entities { @@ -11,10 +12,18 @@ namespace MediaBrowser.Controller.Entities { var list = base.GetUserDataKeys(); - list.Insert(0, "GameGenre-" + Name); + list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics()); return list; } + public override string PresentationUniqueKey + { + get + { + return GetUserDataKeys()[0]; + } + } + /// <summary> /// Returns the folder containing the item. /// If the item is a folder, it returns the folder itself diff --git a/MediaBrowser.Controller/Entities/Genre.cs b/MediaBrowser.Controller/Entities/Genre.cs index c87d4daaf..cc5aebb2a 100644 --- a/MediaBrowser.Controller/Entities/Genre.cs +++ b/MediaBrowser.Controller/Entities/Genre.cs @@ -3,6 +3,7 @@ using MediaBrowser.Controller.Entities.Audio; using System; using System.Collections.Generic; using System.Linq; +using MediaBrowser.Common.Extensions; namespace MediaBrowser.Controller.Entities { @@ -15,10 +16,18 @@ namespace MediaBrowser.Controller.Entities { var list = base.GetUserDataKeys(); - list.Insert(0, "Genre-" + Name); + list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics()); return list; } + public override string PresentationUniqueKey + { + get + { + return GetUserDataKeys()[0]; + } + } + /// <summary> /// Returns the folder containing the item. /// If the item is a folder, it returns the folder itself diff --git a/MediaBrowser.Controller/Entities/IHasUserData.cs b/MediaBrowser.Controller/Entities/IHasUserData.cs index 244b319bd..2495b0ccd 100644 --- a/MediaBrowser.Controller/Entities/IHasUserData.cs +++ b/MediaBrowser.Controller/Entities/IHasUserData.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Threading.Tasks; using MediaBrowser.Model.Dto; namespace MediaBrowser.Controller.Entities @@ -16,7 +17,7 @@ namespace MediaBrowser.Controller.Entities /// <param name="dto">The dto.</param> /// <param name="userData">The user data.</param> /// <param name="user">The user.</param> - void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user); + Task FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user); bool EnableRememberingTrackSelections { get; } } diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index 823f4066c..5faf85b2a 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -19,6 +19,8 @@ namespace MediaBrowser.Controller.Entities public User User { get; set; } + public BaseItem SimilarTo { get; set; } + public bool? IsFolder { get; set; } public bool? IsFavorite { get; set; } public bool? IsFavoriteOrLiked { get; set; } @@ -33,6 +35,7 @@ namespace MediaBrowser.Controller.Entities public string[] ExcludeTags { get; set; } public string[] ExcludeInheritedTags { get; set; } public string[] Genres { get; set; } + public string[] Keywords { get; set; } public bool? IsMissing { get; set; } public bool? IsUnaired { get; set; } @@ -43,6 +46,7 @@ namespace MediaBrowser.Controller.Entities public string NameStartsWith { get; set; } public string NameLessThan { get; set; } public string NameContains { get; set; } + public string MinSortName { get; set; } public string PresentationUniqueKey { get; set; } public string Path { get; set; } @@ -52,6 +56,7 @@ namespace MediaBrowser.Controller.Entities public string Person { get; set; } public string[] PersonIds { get; set; } public string[] ItemIds { get; set; } + public string[] ExcludeItemIds { get; set; } public string AdjacentTo { get; set; } public string[] PersonTypes { get; set; } @@ -60,7 +65,6 @@ namespace MediaBrowser.Controller.Entities public bool? IsInBoxSet { get; set; } public bool? IsLocked { get; set; } public bool? IsPlaceHolder { get; set; } - public bool? IsYearMismatched { get; set; } public bool? HasImdbId { get; set; } public bool? HasOverview { get; set; } @@ -107,6 +111,7 @@ namespace MediaBrowser.Controller.Entities internal List<Guid> ItemIdsFromPersonFilters { get; set; } public int? ParentIndexNumber { get; set; } + public int? ParentIndexNumberNotEquals { get; set; } public int? IndexNumber { get; set; } public int? MinParentalRating { get; set; } public int? MaxParentalRating { get; set; } @@ -114,6 +119,7 @@ namespace MediaBrowser.Controller.Entities public bool? IsCurrentSchema { get; set; } public bool? HasDeadParentId { get; set; } public bool? IsOffline { get; set; } + public bool? IsVirtualItem { get; set; } public Guid? ParentId { get; set; } public string[] AncestorIds { get; set; } @@ -137,6 +143,8 @@ namespace MediaBrowser.Controller.Entities public bool GroupByPresentationUniqueKey { get; set; } public bool EnableTotalRecordCount { get; set; } public bool ForceDirect { get; set; } + public Dictionary<string, string> ExcludeProviderIds { get; set; } + public bool EnableGroupByMetadataKey { get; set; } public InternalItemsQuery() { @@ -145,12 +153,14 @@ namespace MediaBrowser.Controller.Entities AlbumNames = new string[] { }; ArtistNames = new string[] { }; - + ExcludeProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); + BlockUnratedItems = new UnratedItem[] { }; Tags = new string[] { }; OfficialRatings = new string[] { }; SortBy = new string[] { }; MediaTypes = new string[] { }; + Keywords = new string[] { }; IncludeItemTypes = new string[] { }; ExcludeItemTypes = new string[] { }; Genres = new string[] { }; @@ -164,6 +174,7 @@ namespace MediaBrowser.Controller.Entities PersonIds = new string[] { }; ChannelIds = new string[] { }; ItemIds = new string[] { }; + ExcludeItemIds = new string[] { }; AncestorIds = new string[] { }; TopParentIds = new string[] { }; ExcludeTags = new string[] { }; diff --git a/MediaBrowser.Controller/Entities/IHasKeywords.cs b/MediaBrowser.Controller/Entities/KeywordExtensions.cs index ab9eb4aee..5c9afdf3d 100644 --- a/MediaBrowser.Controller/Entities/IHasKeywords.cs +++ b/MediaBrowser.Controller/Entities/KeywordExtensions.cs @@ -1,21 +1,11 @@ using System; -using System.Collections.Generic; using System.Linq; namespace MediaBrowser.Controller.Entities { - public interface IHasKeywords - { - /// <summary> - /// Gets or sets the keywords. - /// </summary> - /// <value>The keywords.</value> - List<string> Keywords { get; set; } - } - public static class KeywordExtensions { - public static void AddKeyword(this IHasKeywords item, string name) + public static void AddKeyword(this BaseItem item, string name) { if (string.IsNullOrWhiteSpace(name)) { diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs index 09a9d97bc..4effc162e 100644 --- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs +++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs @@ -15,7 +15,7 @@ namespace MediaBrowser.Controller.Entities.Movies /// <summary> /// Class BoxSet /// </summary> - public class BoxSet : Folder, IHasTrailers, IHasKeywords, IHasDisplayOrder, IHasLookupInfo<BoxSetInfo>, IHasShares + public class BoxSet : Folder, IHasTrailers, IHasDisplayOrder, IHasLookupInfo<BoxSetInfo>, IHasShares { public List<Share> Shares { get; set; } @@ -26,7 +26,6 @@ namespace MediaBrowser.Controller.Entities.Movies RemoteTrailerIds = new List<Guid>(); DisplayOrder = ItemSortBy.PremiereDate; - Keywords = new List<string>(); Shares = new List<Share>(); } @@ -48,12 +47,6 @@ namespace MediaBrowser.Controller.Entities.Movies public List<MediaUrl> RemoteTrailers { get; set; } /// <summary> - /// Gets or sets the tags. - /// </summary> - /// <value>The tags.</value> - public List<string> Keywords { get; set; } - - /// <summary> /// Gets or sets the display order. /// </summary> /// <value>The display order.</value> diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs index 5882b5f4d..c7a833c58 100644 --- a/MediaBrowser.Controller/Entities/Movies/Movie.cs +++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs @@ -8,13 +8,14 @@ using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; using CommonIO; +using MediaBrowser.Model.Providers; namespace MediaBrowser.Controller.Entities.Movies { /// <summary> /// Class Movie /// </summary> - public class Movie : Video, IHasCriticRating, IHasSpecialFeatures, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTrailers, IHasThemeMedia, IHasTaglines, IHasAwards, IHasMetascore, IHasLookupInfo<MovieInfo>, ISupportsBoxSetGrouping, IHasOriginalTitle + public class Movie : Video, IHasCriticRating, IHasSpecialFeatures, IHasProductionLocations, IHasBudget, IHasTrailers, IHasThemeMedia, IHasTaglines, IHasAwards, IHasMetascore, IHasLookupInfo<MovieInfo>, ISupportsBoxSetGrouping, IHasOriginalTitle { public List<Guid> SpecialFeatureIds { get; set; } @@ -31,7 +32,6 @@ namespace MediaBrowser.Controller.Entities.Movies ThemeSongIds = new List<Guid>(); ThemeVideoIds = new List<Guid>(); Taglines = new List<string>(); - Keywords = new List<string>(); ProductionLocations = new List<string>(); } @@ -41,7 +41,6 @@ namespace MediaBrowser.Controller.Entities.Movies public List<Guid> LocalTrailerIds { get; set; } public List<Guid> RemoteTrailerIds { get; set; } - public List<string> Keywords { get; set; } public List<MediaUrl> RemoteTrailers { get; set; } @@ -163,5 +162,22 @@ namespace MediaBrowser.Controller.Entities.Movies return hasChanges; } + + public override List<ExternalUrl> GetRelatedUrls() + { + var list = base.GetRelatedUrls(); + + var imdbId = this.GetProviderId(MetadataProviders.Imdb); + if (!string.IsNullOrWhiteSpace(imdbId)) + { + list.Add(new ExternalUrl + { + Name = "Trakt", + Url = string.Format("https://trakt.tv/movies/{0}", imdbId) + }); + } + + return list; + } } } diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs index 2b099e3d5..8ef0d70bf 100644 --- a/MediaBrowser.Controller/Entities/Person.cs +++ b/MediaBrowser.Controller/Entities/Person.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; +using MediaBrowser.Common.Extensions; using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Entities @@ -22,10 +23,18 @@ namespace MediaBrowser.Controller.Entities { var list = base.GetUserDataKeys(); - list.Insert(0, "Person-" + Name); + list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics()); return list; } + public override string PresentationUniqueKey + { + get + { + return GetUserDataKeys()[0]; + } + } + public PersonLookupInfo GetLookupInfo() { return GetItemLookupInfo<PersonLookupInfo>(); diff --git a/MediaBrowser.Controller/Entities/Photo.cs b/MediaBrowser.Controller/Entities/Photo.cs index 3358ccc6f..de756563d 100644 --- a/MediaBrowser.Controller/Entities/Photo.cs +++ b/MediaBrowser.Controller/Entities/Photo.cs @@ -5,7 +5,7 @@ using System.Runtime.Serialization; namespace MediaBrowser.Controller.Entities { - public class Photo : BaseItem, IHasTags, IHasTaglines + public class Photo : BaseItem, IHasTaglines { public List<string> Taglines { get; set; } diff --git a/MediaBrowser.Controller/Entities/Studio.cs b/MediaBrowser.Controller/Entities/Studio.cs index 48ca7bbcc..762798b55 100644 --- a/MediaBrowser.Controller/Entities/Studio.cs +++ b/MediaBrowser.Controller/Entities/Studio.cs @@ -2,22 +2,31 @@ using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; +using MediaBrowser.Common.Extensions; namespace MediaBrowser.Controller.Entities { /// <summary> /// Class Studio /// </summary> - public class Studio : BaseItem, IItemByName, IHasTags + public class Studio : BaseItem, IItemByName { public override List<string> GetUserDataKeys() { var list = base.GetUserDataKeys(); - list.Insert(0, "Studio-" + Name); + list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics()); return list; } + public override string PresentationUniqueKey + { + get + { + return GetUserDataKeys()[0]; + } + } + /// <summary> /// Returns the folder containing the item. /// If the item is a folder, it returns the folder itself diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index a4b0b3082..2dc459239 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -11,13 +11,25 @@ namespace MediaBrowser.Controller.Entities.TV /// <summary> /// Class Episode /// </summary> - public class Episode : Video, IHasLookupInfo<EpisodeInfo>, IHasSeries - { - /// <summary> - /// Gets the season in which it aired. - /// </summary> - /// <value>The aired season.</value> - public int? AirsBeforeSeasonNumber { get; set; } + public class Episode : Video, IHasTrailers, IHasLookupInfo<EpisodeInfo>, IHasSeries + {
+
+ public Episode()
+ {
+ RemoteTrailers = new List<MediaUrl>();
+ LocalTrailerIds = new List<Guid>();
+ RemoteTrailerIds = new List<Guid>();
+ }
+
+ public List<Guid> LocalTrailerIds { get; set; }
+ public List<Guid> RemoteTrailerIds { get; set; }
+ public List<MediaUrl> RemoteTrailers { get; set; }
+
+ /// <summary> + /// Gets the season in which it aired. + /// </summary> + /// <value>The aired season.</value> + public int? AirsBeforeSeasonNumber { get; set; } public int? AirsAfterSeasonNumber { get; set; } public int? AirsBeforeEpisodeNumber { get; set; } @@ -96,7 +108,13 @@ namespace MediaBrowser.Controller.Entities.TV var series = Series; if (series != null && ParentIndexNumber.HasValue && IndexNumber.HasValue) { - list.InsertRange(0, series.GetUserDataKeys().Select(i => i + ParentIndexNumber.Value.ToString("000") + IndexNumber.Value.ToString("000"))); + var seriesUserDataKeys = series.GetUserDataKeys(); + var take = seriesUserDataKeys.Count; + if (seriesUserDataKeys.Count > 1) + { + take--; + } + list.InsertRange(0, seriesUserDataKeys.Take(take).Select(i => i + ParentIndexNumber.Value.ToString("000") + IndexNumber.Value.ToString("000"))); } return list; diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index 7fa1b55de..9a9014844 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -75,6 +75,11 @@ namespace MediaBrowser.Controller.Entities.TV return list; } + public override int GetChildCount(User user) + { + return GetChildren(user, true).Count(); + } + /// <summary> /// This Episode's Series Instance /// </summary> @@ -128,39 +133,16 @@ namespace MediaBrowser.Controller.Entities.TV return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name; } - public override bool RequiresRefresh() - { - var result = base.RequiresRefresh(); - - if (!result) - { - if (!IsVirtualItem.HasValue) - { - return true; - } - } - - return result; - } - - [IgnoreDataMember] - public bool? IsVirtualItem { get; set; } - [IgnoreDataMember] public bool IsMissingSeason { - get { return (IsVirtualItem ?? DetectIsVirtualItem()) && !IsUnaired; } + get { return (IsVirtualItem) && !IsUnaired; } } [IgnoreDataMember] public bool IsVirtualUnaired { - get { return (IsVirtualItem ?? DetectIsVirtualItem()) && IsUnaired; } - } - - private bool DetectIsVirtualItem() - { - return LocationType == LocationType.Virtual && GetEpisodes().All(i => i.LocationType == LocationType.Virtual); + get { return (IsVirtualItem) && IsUnaired; } } [IgnoreDataMember] @@ -196,52 +178,17 @@ namespace MediaBrowser.Controller.Entities.TV { var config = user.Configuration; - return GetEpisodes(user, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes); + return GetEpisodes(Series, user, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes); } - public IEnumerable<Episode> GetEpisodes(User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes) + public IEnumerable<Episode> GetEpisodes(Series series, User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes) { - var series = Series; - - if (IndexNumber.HasValue && series != null) - { - return series.GetEpisodes(user, this, includeMissingEpisodes, includeVirtualUnairedEpisodes); - } - - var episodes = GetRecursiveChildren(user) - .OfType<Episode>(); - - if (series != null && series.ContainsEpisodesWithoutSeasonFolders) - { - var seasonNumber = IndexNumber; - var list = episodes.ToList(); - - if (seasonNumber.HasValue) - { - list.AddRange(series.GetRecursiveChildren(user).OfType<Episode>() - .Where(i => i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == seasonNumber.Value)); - } - else - { - list.AddRange(series.GetRecursiveChildren(user).OfType<Episode>() - .Where(i => !i.ParentIndexNumber.HasValue)); - } - - episodes = list.DistinctBy(i => i.Id); - } - - if (!includeMissingEpisodes) - { - episodes = episodes.Where(i => !i.IsMissingEpisode); - } - if (!includeVirtualUnairedEpisodes) - { - episodes = episodes.Where(i => !i.IsVirtualUnaired); - } + return GetEpisodes(series, user, includeMissingEpisodes, includeVirtualUnairedEpisodes, null); + } - return LibraryManager - .Sort(episodes, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending) - .Cast<Episode>(); + public IEnumerable<Episode> GetEpisodes(Series series, User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes, IEnumerable<Episode> allSeriesEpisodes) + { + return series.GetEpisodes(user, this, includeMissingEpisodes, includeVirtualUnairedEpisodes, allSeriesEpisodes); } public IEnumerable<Episode> GetEpisodes() diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 6c499f618..1cc496b35 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -9,6 +9,7 @@ using System.Linq; using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Model.Providers; using MoreLinq; namespace MediaBrowser.Controller.Entities.TV @@ -30,7 +31,6 @@ namespace MediaBrowser.Controller.Entities.TV RemoteTrailers = new List<MediaUrl>(); LocalTrailerIds = new List<Guid>(); RemoteTrailerIds = new List<Guid>(); - DisplaySpecialsWithSeasons = true; } [IgnoreDataMember] @@ -57,8 +57,6 @@ namespace MediaBrowser.Controller.Entities.TV } } - public bool DisplaySpecialsWithSeasons { get; set; } - public List<Guid> LocalTrailerIds { get; set; } public List<Guid> RemoteTrailerIds { get; set; } @@ -94,10 +92,7 @@ namespace MediaBrowser.Controller.Entities.TV { get { - return GetRecursiveChildren(i => i is Episode) - .Select(i => i.DateCreated) - .OrderByDescending(i => i) - .FirstOrDefault(); + return DateLastMediaAdded ?? DateTime.MinValue; } } @@ -106,14 +101,30 @@ namespace MediaBrowser.Controller.Entities.TV { get { - if (EnablePooling()) + var userdatakeys = GetUserDataKeys(); + + if (userdatakeys.Count > 1) { - return GetUserDataKeys().First(); + return userdatakeys[0]; } return base.PresentationUniqueKey; } } + public override int GetChildCount(User user) + { + var result = LibraryManager.GetItemsResult(new InternalItemsQuery(user) + { + AncestorWithPresentationUniqueKey = PresentationUniqueKey, + IncludeItemTypes = new[] { typeof(Season).Name }, + SortBy = new[] { ItemSortBy.SortName }, + IsVirtualItem = false, + Limit = 0 + }); + + return result.TotalRecordCount; + } + /// <summary> /// Gets the user data key. /// </summary> @@ -182,27 +193,32 @@ namespace MediaBrowser.Controller.Entities.TV protected override Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery query) { - var user = query.User; - - Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager); - - IEnumerable<BaseItem> items; - if (query.User == null) { - items = query.Recursive - ? GetRecursiveChildren(filter) - : Children.Where(filter); + return base.GetItemsInternal(query); } - else + + var user = query.User; + + if (query.Recursive) { - items = query.Recursive - ? GetSeasons(user).Cast<BaseItem>().Concat(GetEpisodes(user)).Where(filter) - : GetSeasons(user).Where(filter); + query.AncestorWithPresentationUniqueKey = PresentationUniqueKey; + if (query.SortBy.Length == 0) + { + query.SortBy = new[] { ItemSortBy.SortName }; + } + if (query.IncludeItemTypes.Length == 0) + { + query.IncludeItemTypes = new[] { typeof(Episode).Name, typeof(Season).Name }; + } + query.IsVirtualItem = false; + return Task.FromResult(LibraryManager.GetItemsResult(query)); } - var result = PostFilterAndSort(items, query); + Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager); + var items = GetSeasons(user).Where(filter); + var result = PostFilterAndSort(items, query); return Task.FromResult(result); } @@ -210,33 +226,13 @@ namespace MediaBrowser.Controller.Entities.TV { IEnumerable<Season> seasons; - if (EnablePooling()) + seasons = LibraryManager.GetItemList(new InternalItemsQuery(user) { - var seriesIds = LibraryManager.GetItemIds(new InternalItemsQuery(user) - { - PresentationUniqueKey = PresentationUniqueKey, - IncludeItemTypes = new[] { typeof(Series).Name } - }); + AncestorWithPresentationUniqueKey = PresentationUniqueKey, + IncludeItemTypes = new[] { typeof(Season).Name }, + SortBy = new[] { ItemSortBy.SortName } - if (seriesIds.Count > 1) - { - seasons = LibraryManager.GetItemList(new InternalItemsQuery(user) - { - AncestorIds = seriesIds.Select(i => i.ToString("N")).ToArray(), - IncludeItemTypes = new[] { typeof(Season).Name }, - SortBy = new[] { ItemSortBy.SortName } - - }).Cast<Season>(); - } - else - { - seasons = LibraryManager.Sort(base.GetChildren(user, true), user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).OfType<Season>(); - } - } - else - { - seasons = LibraryManager.Sort(base.GetChildren(user, true), user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).OfType<Season>(); - } + }).Cast<Season>(); if (!includeMissingSeasons) { @@ -259,8 +255,18 @@ namespace MediaBrowser.Controller.Entities.TV public IEnumerable<Episode> GetEpisodes(User user, bool includeMissing, bool includeVirtualUnaired) { - var allEpisodes = GetSeasons(user, true, true) - .SelectMany(i => i.GetEpisodes(user, includeMissing, includeVirtualUnaired)) + var allItems = LibraryManager.GetItemList(new InternalItemsQuery(user) + { + AncestorWithPresentationUniqueKey = PresentationUniqueKey, + IncludeItemTypes = new[] { typeof(Episode).Name, typeof(Season).Name }, + SortBy = new[] { ItemSortBy.SortName } + + }).ToList(); + + var allSeriesEpisodes = allItems.OfType<Episode>().ToList(); + + var allEpisodes = allItems.OfType<Season>() + .SelectMany(i => i.GetEpisodes(this, user, includeMissing, includeVirtualUnaired, allSeriesEpisodes)) .Reverse() .ToList(); @@ -283,9 +289,6 @@ namespace MediaBrowser.Controller.Entities.TV var totalItems = seasons.Count + otherItems.Count; var numComplete = 0; - refreshOptions = new MetadataRefreshOptions(refreshOptions); - refreshOptions.IsPostRecursiveRefresh = true; - // Refresh current item await RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); @@ -315,7 +318,7 @@ namespace MediaBrowser.Controller.Entities.TV && refreshOptions.MetadataRefreshMode != MetadataRefreshMode.FullRefresh && !refreshOptions.ReplaceAllMetadata && episode.IsMissingEpisode - && episode.LocationType == Model.Entities.LocationType.Virtual + && episode.LocationType == LocationType.Virtual && episode.PremiereDate.HasValue && (DateTime.UtcNow - episode.PremiereDate.Value).TotalDays > 30) { @@ -333,6 +336,8 @@ namespace MediaBrowser.Controller.Entities.TV progress.Report(percent * 100); } + refreshOptions = new MetadataRefreshOptions(refreshOptions); + refreshOptions.IsPostRecursiveRefresh = true; await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false); progress.Report(100); @@ -345,50 +350,32 @@ namespace MediaBrowser.Controller.Entities.TV return GetEpisodes(user, season, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes); } - private bool EnablePooling() + private IEnumerable<Episode> GetAllEpisodes(User user) { - return false; + return LibraryManager.GetItemList(new InternalItemsQuery(user) + { + AncestorWithPresentationUniqueKey = PresentationUniqueKey, + IncludeItemTypes = new[] { typeof(Episode).Name }, + SortBy = new[] { ItemSortBy.SortName } + + }).Cast<Episode>(); } public IEnumerable<Episode> GetEpisodes(User user, Season parentSeason, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes) { - IEnumerable<Episode> episodes; - - if (EnablePooling()) - { - var seriesIds = LibraryManager.GetItemIds(new InternalItemsQuery(user) - { - PresentationUniqueKey = PresentationUniqueKey, - IncludeItemTypes = new[] { typeof(Series).Name } - }); + IEnumerable<Episode> episodes = GetAllEpisodes(user); - if (seriesIds.Count > 1) - { - episodes = LibraryManager.GetItemList(new InternalItemsQuery(user) - { - AncestorIds = seriesIds.Select(i => i.ToString("N")).ToArray(), - IncludeItemTypes = new[] { typeof(Episode).Name }, - SortBy = new[] { ItemSortBy.SortName } + return GetEpisodes(user, parentSeason, includeMissingEpisodes, includeVirtualUnairedEpisodes, episodes); + } - }).Cast<Episode>(); - } - else - { - episodes = GetRecursiveChildren(user, new InternalItemsQuery(user) - { - IncludeItemTypes = new[] { typeof(Episode).Name } - }).Cast<Episode>(); - } - } - else + public IEnumerable<Episode> GetEpisodes(User user, Season parentSeason, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes, IEnumerable<Episode> allSeriesEpisodes) + { + if (allSeriesEpisodes == null) { - episodes = GetRecursiveChildren(user, new InternalItemsQuery(user) - { - IncludeItemTypes = new[] { typeof(Episode).Name } - }).Cast<Episode>(); + return GetEpisodes(user, parentSeason, includeMissingEpisodes, includeVirtualUnairedEpisodes); } - episodes = FilterEpisodesBySeason(episodes, parentSeason, DisplaySpecialsWithSeasons); + var episodes = FilterEpisodesBySeason(allSeriesEpisodes, parentSeason, ConfigurationManager.Configuration.DisplaySpecialsWithinSeasons); if (!includeMissingEpisodes) { @@ -436,38 +423,31 @@ namespace MediaBrowser.Controller.Entities.TV public static IEnumerable<Episode> FilterEpisodesBySeason(IEnumerable<Episode> episodes, Season parentSeason, bool includeSpecials) { var seasonNumber = parentSeason.IndexNumber; - if (!includeSpecials || (seasonNumber.HasValue && seasonNumber.Value == 0)) - { - var seasonPresentationKey = parentSeason.PresentationUniqueKey; + var seasonPresentationKey = parentSeason.PresentationUniqueKey; - return episodes.Where(i => - { - if ((i.ParentIndexNumber ?? -1) == seasonNumber) - { - return true; - } + var supportSpecialsInSeason = includeSpecials && seasonNumber.HasValue && seasonNumber.Value != 0; - var season = i.Season; - return season != null && string.Equals(season.PresentationUniqueKey, seasonPresentationKey, StringComparison.OrdinalIgnoreCase); - }); - } - else + return episodes.Where(episode => { - var seasonPresentationKey = parentSeason.PresentationUniqueKey; - - return episodes.Where(episode => + var currentSeasonNumber = supportSpecialsInSeason ? episode.AiredSeasonNumber : episode.ParentIndexNumber; + if (currentSeasonNumber.HasValue && seasonNumber.HasValue && currentSeasonNumber.Value == seasonNumber.Value) { - var currentSeasonNumber = episode.AiredSeasonNumber; + return true; + } - if (currentSeasonNumber.HasValue && seasonNumber.HasValue && currentSeasonNumber.Value == seasonNumber.Value) - { - return true; - } + if (!currentSeasonNumber.HasValue && !seasonNumber.HasValue && parentSeason.LocationType == LocationType.Virtual) + { + return true; + } + if (!episode.ParentIndexNumber.HasValue) + { var season = episode.Season; return season != null && string.Equals(season.PresentationUniqueKey, seasonPresentationKey, StringComparison.OrdinalIgnoreCase); - }); - } + } + + return false; + }); } protected override bool GetBlockUnratedValue(UserPolicy config) @@ -508,5 +488,22 @@ namespace MediaBrowser.Controller.Entities.TV return hasChanges; } + + public override List<ExternalUrl> GetRelatedUrls() + { + var list = base.GetRelatedUrls(); + + var imdbId = this.GetProviderId(MetadataProviders.Imdb); + if (!string.IsNullOrWhiteSpace(imdbId)) + { + list.Add(new ExternalUrl + { + Name = "Trakt", + Url = string.Format("https://trakt.tv/shows/{0}", imdbId) + }); + } + + return list; + } } } diff --git a/MediaBrowser.Controller/Entities/IHasTags.cs b/MediaBrowser.Controller/Entities/TagExtensions.cs index 45a56009d..0e1df72cd 100644 --- a/MediaBrowser.Controller/Entities/IHasTags.cs +++ b/MediaBrowser.Controller/Entities/TagExtensions.cs @@ -1,24 +1,11 @@ using System; -using System.Collections.Generic; using System.Linq; namespace MediaBrowser.Controller.Entities { - /// <summary> - /// Interface IHasTags - /// </summary> - public interface IHasTags - { - /// <summary> - /// Gets or sets the tags. - /// </summary> - /// <value>The tags.</value> - List<string> Tags { get; set; } - } - public static class TagExtensions { - public static void AddTag(this IHasTags item, string name) + public static void AddTag(this BaseItem item, string name) { if (string.IsNullOrWhiteSpace(name)) { diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs index 3be2fc624..eab5ab679 100644 --- a/MediaBrowser.Controller/Entities/Trailer.cs +++ b/MediaBrowser.Controller/Entities/Trailer.cs @@ -5,13 +5,14 @@ using System.Collections.Generic; using System.Globalization; using System.Runtime.Serialization; using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Model.Providers; namespace MediaBrowser.Controller.Entities { /// <summary> /// Class Trailer /// </summary> - public class Trailer : Video, IHasCriticRating, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTaglines, IHasMetascore, IHasOriginalTitle, IHasLookupInfo<TrailerInfo> + public class Trailer : Video, IHasCriticRating, IHasProductionLocations, IHasBudget, IHasTaglines, IHasMetascore, IHasOriginalTitle, IHasLookupInfo<TrailerInfo> { public List<string> ProductionLocations { get; set; } @@ -30,8 +31,6 @@ namespace MediaBrowser.Controller.Entities public List<MediaUrl> RemoteTrailers { get; set; } - public List<string> Keywords { get; set; } - [IgnoreDataMember] public bool IsLocalTrailer { @@ -110,5 +109,22 @@ namespace MediaBrowser.Controller.Entities return hasChanges; } + + public override List<ExternalUrl> GetRelatedUrls() + { + var list = base.GetRelatedUrls(); + + var imdbId = this.GetProviderId(MetadataProviders.Imdb); + if (!string.IsNullOrWhiteSpace(imdbId)) + { + list.Add(new ExternalUrl + { + Name = "Trakt", + Url = string.Format("https://trakt.tv/movies/{0}", imdbId) + }); + } + + return list; + } } } diff --git a/MediaBrowser.Controller/Entities/UserRootFolder.cs b/MediaBrowser.Controller/Entities/UserRootFolder.cs index 37c4c91b1..8e6f11c2c 100644 --- a/MediaBrowser.Controller/Entities/UserRootFolder.cs +++ b/MediaBrowser.Controller/Entities/UserRootFolder.cs @@ -38,6 +38,11 @@ namespace MediaBrowser.Controller.Entities return PostFilterAndSort(result.Where(filter), query); } + public override int GetChildCount(User user) + { + return GetChildren(user, true).Count(); + } + [IgnoreDataMember] protected override bool SupportsShortcutChildren { diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs index e40d9ca38..35375e7e6 100644 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ b/MediaBrowser.Controller/Entities/UserView.cs @@ -45,6 +45,11 @@ namespace MediaBrowser.Controller.Entities return list; } + public override int GetChildCount(User user) + { + return GetChildren(user, true).Count(); + } + protected override Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery query) { var parent = this as Folder; @@ -58,7 +63,7 @@ namespace MediaBrowser.Controller.Entities parent = LibraryManager.GetItemById(ParentId) as Folder ?? parent; } - return new UserViewBuilder(UserViewManager, LiveTvManager, ChannelManager, LibraryManager, Logger, UserDataManager, TVSeriesManager, CollectionManager, PlaylistManager) + return new UserViewBuilder(UserViewManager, LiveTvManager, ChannelManager, LibraryManager, Logger, UserDataManager, TVSeriesManager, ConfigurationManager, PlaylistManager) .GetUserItems(parent, this, ViewType, query); } diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index d4a8b0730..175a7240c 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -18,6 +18,8 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Model.Configuration; namespace MediaBrowser.Controller.Entities { @@ -30,10 +32,10 @@ namespace MediaBrowser.Controller.Entities private readonly ILogger _logger; private readonly IUserDataManager _userDataManager; private readonly ITVSeriesManager _tvSeriesManager; - private readonly ICollectionManager _collectionManager; + private readonly IServerConfigurationManager _config; private readonly IPlaylistManager _playlistManager; - public UserViewBuilder(IUserViewManager userViewManager, ILiveTvManager liveTvManager, IChannelManager channelManager, ILibraryManager libraryManager, ILogger logger, IUserDataManager userDataManager, ITVSeriesManager tvSeriesManager, ICollectionManager collectionManager, IPlaylistManager playlistManager) + public UserViewBuilder(IUserViewManager userViewManager, ILiveTvManager liveTvManager, IChannelManager channelManager, ILibraryManager libraryManager, ILogger logger, IUserDataManager userDataManager, ITVSeriesManager tvSeriesManager, IServerConfigurationManager config, IPlaylistManager playlistManager) { _userViewManager = userViewManager; _liveTvManager = liveTvManager; @@ -42,7 +44,7 @@ namespace MediaBrowser.Controller.Entities _logger = logger; _userDataManager = userDataManager; _tvSeriesManager = tvSeriesManager; - _collectionManager = collectionManager; + _config = config; _playlistManager = playlistManager; } @@ -159,7 +161,7 @@ namespace MediaBrowser.Controller.Entities return await GetTvGenres(queryParent, user, query).ConfigureAwait(false); case SpecialFolder.TvGenre: - return await GetTvGenreItems(queryParent, displayParent, user, query).ConfigureAwait(false); + return GetTvGenreItems(queryParent, displayParent, user, query); case SpecialFolder.TvResume: return GetTvResume(queryParent, user, query); @@ -332,13 +334,14 @@ namespace MediaBrowser.Controller.Entities private QueryResult<BaseItem> GetMusicAlbumArtists(Folder parent, User user, InternalItemsQuery query) { - var items = _libraryManager.GetItemList(new InternalItemsQuery(user) + var items = parent.QueryRecursive(new InternalItemsQuery(user) { Recursive = true, ParentId = parent.Id, - IncludeItemTypes = new[] { typeof(Audio.Audio).Name } + IncludeItemTypes = new[] { typeof(Audio.Audio).Name }, + EnableTotalRecordCount = false - }).Cast<IHasAlbumArtist>(); + }).Items.Cast<IHasAlbumArtist>(); var artists = _libraryManager.GetAlbumArtists(items); @@ -347,13 +350,14 @@ namespace MediaBrowser.Controller.Entities private QueryResult<BaseItem> GetMusicArtists(Folder parent, User user, InternalItemsQuery query) { - var items = _libraryManager.GetItemList(new InternalItemsQuery(user) + var items = parent.QueryRecursive(new InternalItemsQuery(user) { Recursive = true, ParentId = parent.Id, - IncludeItemTypes = new[] { typeof(Audio.Audio).Name, typeof(MusicVideo).Name } + IncludeItemTypes = new[] { typeof(Audio.Audio).Name, typeof(MusicVideo).Name }, + EnableTotalRecordCount = false - }).Cast<IHasArtist>(); + }).Items.Cast<IHasArtist>(); var artists = _libraryManager.GetArtists(items); @@ -362,13 +366,14 @@ namespace MediaBrowser.Controller.Entities private QueryResult<BaseItem> GetFavoriteArtists(Folder parent, User user, InternalItemsQuery query) { - var items = _libraryManager.GetItemList(new InternalItemsQuery(user) + var items = parent.QueryRecursive(new InternalItemsQuery(user) { Recursive = true, ParentId = parent.Id, - IncludeItemTypes = new[] { typeof(Audio.Audio).Name } + IncludeItemTypes = new[] { typeof(Audio.Audio).Name }, + EnableTotalRecordCount = false - }).Cast<IHasAlbumArtist>(); + }).Items.Cast<IHasAlbumArtist>(); var artists = _libraryManager.GetAlbumArtists(items).Where(i => _userDataManager.GetUserData(user, i).IsFavorite); @@ -545,7 +550,7 @@ namespace MediaBrowser.Controller.Entities query.Limit = GetSpecialItemsLimit(); query.IncludeItemTypes = new[] { typeof(Movie).Name }; - return _libraryManager.GetItemsResult(query); + return ConvertToResult(_libraryManager.GetItemList(query)); } private QueryResult<BaseItem> GetMovieResume(Folder parent, User user, InternalItemsQuery query) @@ -559,7 +564,17 @@ namespace MediaBrowser.Controller.Entities query.Limit = GetSpecialItemsLimit(); query.IncludeItemTypes = new[] { typeof(Movie).Name }; - return _libraryManager.GetItemsResult(query); + return ConvertToResult(_libraryManager.GetItemList(query)); + } + + private QueryResult<BaseItem> ConvertToResult(IEnumerable<BaseItem> items) + { + var arr = items.ToArray(); + return new QueryResult<BaseItem> + { + Items = arr, + TotalRecordCount = arr.Length + }; } private async Task<QueryResult<BaseItem>> GetMovieGenres(Folder parent, User user, InternalItemsQuery query) @@ -660,8 +675,9 @@ namespace MediaBrowser.Controller.Entities query.SetUser(user); query.Limit = GetSpecialItemsLimit(); query.IncludeItemTypes = new[] { typeof(Episode).Name }; + query.ExcludeLocationTypes = new[] { LocationType.Virtual }; - return _libraryManager.GetItemsResult(query); + return ConvertToResult(_libraryManager.GetItemList(query)); } private QueryResult<BaseItem> GetTvNextUp(Folder parent, InternalItemsQuery query) @@ -690,7 +706,7 @@ namespace MediaBrowser.Controller.Entities query.Limit = GetSpecialItemsLimit(); query.IncludeItemTypes = new[] { typeof(Episode).Name }; - return _libraryManager.GetItemsResult(query); + return ConvertToResult(_libraryManager.GetItemList(query)); } private QueryResult<BaseItem> GetTvSeries(Folder parent, User user, InternalItemsQuery query) @@ -737,7 +753,7 @@ namespace MediaBrowser.Controller.Entities return GetResult(genres, parent, query); } - private async Task<QueryResult<BaseItem>> GetTvGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query) + private QueryResult<BaseItem> GetTvGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query) { query.Recursive = true; query.ParentId = queryParent.Id; @@ -766,7 +782,7 @@ namespace MediaBrowser.Controller.Entities { items = items.Where(i => Filter(i, query.User, query, _userDataManager, _libraryManager)); - return PostFilterAndSort(items, queryParent, null, query, _libraryManager); + return PostFilterAndSort(items, queryParent, null, query, _libraryManager, _config); } public static bool FilterItem(BaseItem item, InternalItemsQuery query) @@ -779,14 +795,15 @@ namespace MediaBrowser.Controller.Entities int? totalRecordLimit, InternalItemsQuery query) { - return PostFilterAndSort(items, queryParent, totalRecordLimit, query, _libraryManager); + return PostFilterAndSort(items, queryParent, totalRecordLimit, query, _libraryManager, _config); } public static QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, BaseItem queryParent, int? totalRecordLimit, InternalItemsQuery query, - ILibraryManager libraryManager) + ILibraryManager libraryManager, + IServerConfigurationManager configurationManager) { var user = query.User; @@ -795,7 +812,7 @@ namespace MediaBrowser.Controller.Entities query.IsVirtualUnaired, query.IsUnaired); - items = CollapseBoxSetItemsIfNeeded(items, query, queryParent, user); + items = CollapseBoxSetItemsIfNeeded(items, query, queryParent, user, configurationManager); // This must be the last filter if (!string.IsNullOrEmpty(query.AdjacentTo)) @@ -809,14 +826,15 @@ namespace MediaBrowser.Controller.Entities public static IEnumerable<BaseItem> CollapseBoxSetItemsIfNeeded(IEnumerable<BaseItem> items, InternalItemsQuery query, BaseItem queryParent, - User user) + User user, + IServerConfigurationManager configurationManager) { if (items == null) { throw new ArgumentNullException("items"); } - if (CollapseBoxSetItems(query, queryParent, user)) + if (CollapseBoxSetItems(query, queryParent, user, configurationManager)) { items = BaseItem.CollectionManager.CollapseItemsWithinBoxSets(items, user); } @@ -849,7 +867,8 @@ namespace MediaBrowser.Controller.Entities public static bool CollapseBoxSetItems(InternalItemsQuery query, BaseItem queryParent, - User user) + User user, + IServerConfigurationManager configurationManager) { // Could end up stuck in a loop like this if (queryParent is BoxSet) @@ -861,7 +880,7 @@ namespace MediaBrowser.Controller.Entities if (!param.HasValue) { - if (user != null && !user.Configuration.GroupMoviesIntoBoxSets) + if (user != null && !configurationManager.Configuration.EnableGroupingIntoCollections) { return false; } @@ -992,11 +1011,6 @@ namespace MediaBrowser.Controller.Entities return false; } - if (request.IsYearMismatched.HasValue) - { - return false; - } - if (!string.IsNullOrWhiteSpace(request.Person)) { return false; @@ -1415,16 +1429,6 @@ namespace MediaBrowser.Controller.Entities } } - if (query.IsYearMismatched.HasValue) - { - var filterValue = query.IsYearMismatched.Value; - - if (IsYearMismatched(item, libraryManager) != filterValue) - { - return false; - } - } - if (query.HasOfficialRating.HasValue) { var filterValue = query.HasOfficialRating.Value; @@ -1658,12 +1662,7 @@ namespace MediaBrowser.Controller.Entities var tags = query.Tags; if (tags.Length > 0) { - var hasTags = item as IHasTags; - if (hasTags == null) - { - return false; - } - if (!tags.Any(v => hasTags.Tags.Contains(v, StringComparer.OrdinalIgnoreCase))) + if (!tags.Any(v => item.Tags.Contains(v, StringComparer.OrdinalIgnoreCase))) { return false; } @@ -1976,34 +1975,6 @@ namespace MediaBrowser.Controller.Entities return _userViewManager.GetUserSubView(parent.Id.ToString("N"), type, sortName, CancellationToken.None); } - public static bool IsYearMismatched(BaseItem item, ILibraryManager libraryManager) - { - if (item.ProductionYear.HasValue) - { - var path = item.Path; - - if (!string.IsNullOrEmpty(path)) - { - var info = libraryManager.ParseName(Path.GetFileName(path)); - var yearInName = info.Year; - - // Go up a level if we didn't get a year - if (!yearInName.HasValue) - { - info = libraryManager.ParseName(Path.GetFileName(Path.GetDirectoryName(path))); - yearInName = info.Year; - } - - if (yearInName.HasValue) - { - return yearInName.Value != item.ProductionYear.Value; - } - } - } - - return false; - } - public static IEnumerable<BaseItem> FilterForAdjacency(IEnumerable<BaseItem> items, string adjacentToId) { var list = items.ToList(); diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 6a9d7cb51..73c893dd6 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -21,7 +21,6 @@ namespace MediaBrowser.Controller.Entities /// </summary> public class Video : BaseItem, IHasAspectRatio, - IHasTags, ISupportsPlaceHolders, IHasMediaSources, IHasShortOverview, @@ -59,10 +58,7 @@ namespace MediaBrowser.Controller.Entities } } - public long? Size { get; set; } - public string Container { get; set; } public int? TotalBitrate { get; set; } - public string ShortOverview { get; set; } public ExtraType? ExtraType { get; set; } /// <summary> diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index 65eed1a23..f4c0e7658 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -3,6 +3,7 @@ using MediaBrowser.Model.System; using System; using System.Collections.Generic; using System.Net; +using System.Threading.Tasks; namespace MediaBrowser.Controller { @@ -17,7 +18,7 @@ namespace MediaBrowser.Controller /// Gets the system info. /// </summary> /// <returns>SystemInfo.</returns> - SystemInfo GetSystemInfo(); + Task<SystemInfo> GetSystemInfo(); /// <summary> /// Gets a value indicating whether [supports automatic run at startup]. @@ -65,13 +66,13 @@ namespace MediaBrowser.Controller /// Gets the local ip address. /// </summary> /// <value>The local ip address.</value> - List<IPAddress> LocalIpAddresses { get; } + Task<List<IPAddress>> GetLocalIpAddresses(); /// <summary> /// Gets the local API URL. /// </summary> /// <value>The local API URL.</value> - string LocalApiUrl { get; } + Task<string> GetLocalApiUrl(); /// <summary> /// Gets the local API URL. diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 936b97c6e..4e641b005 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -11,6 +11,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using CommonIO; +using MediaBrowser.Model.Dto; namespace MediaBrowser.Controller.Library { @@ -151,13 +152,6 @@ namespace MediaBrowser.Controller.Library BaseItem GetItemById(Guid id); /// <summary> - /// Gets the memory item by identifier. - /// </summary> - /// <param name="id">The identifier.</param> - /// <returns>BaseItem.</returns> - BaseItem GetMemoryItemById(Guid id); - - /// <summary> /// Gets the intros. /// </summary> /// <param name="item">The item.</param> @@ -574,5 +568,12 @@ namespace MediaBrowser.Controller.Library void RemoveVirtualFolder(string name, bool refreshLibrary); void AddMediaPath(string virtualFolderName, string path); void RemoveMediaPath(string virtualFolderName, string path); + + QueryResult<Tuple<BaseItem, ItemCounts>> GetGenres(InternalItemsQuery query); + QueryResult<Tuple<BaseItem, ItemCounts>> GetMusicGenres(InternalItemsQuery query); + QueryResult<Tuple<BaseItem, ItemCounts>> GetGameGenres(InternalItemsQuery query); + QueryResult<Tuple<BaseItem, ItemCounts>> GetStudios(InternalItemsQuery query); + QueryResult<Tuple<BaseItem, ItemCounts>> GetArtists(InternalItemsQuery query); + QueryResult<Tuple<BaseItem, ItemCounts>> GetAlbumArtists(InternalItemsQuery query); } }
\ No newline at end of file diff --git a/MediaBrowser.Controller/Library/IUserDataManager.cs b/MediaBrowser.Controller/Library/IUserDataManager.cs index e2358650b..86c52c4c3 100644 --- a/MediaBrowser.Controller/Library/IUserDataManager.cs +++ b/MediaBrowser.Controller/Library/IUserDataManager.cs @@ -40,7 +40,9 @@ namespace MediaBrowser.Controller.Library /// <param name="item">The item.</param> /// <param name="user">The user.</param> /// <returns>UserItemDataDto.</returns> - UserItemDataDto GetUserDataDto(IHasUserData item, User user); + Task<UserItemDataDto> GetUserDataDto(IHasUserData item, User user); + + Task<UserItemDataDto> GetUserDataDto(IHasUserData item, BaseItemDto itemDto, User user); /// <summary> /// Get all user data for the given user diff --git a/MediaBrowser.Controller/LiveTv/IListingsProvider.cs b/MediaBrowser.Controller/LiveTv/IListingsProvider.cs index f5048bdda..5ecd70cc5 100644 --- a/MediaBrowser.Controller/LiveTv/IListingsProvider.cs +++ b/MediaBrowser.Controller/LiveTv/IListingsProvider.cs @@ -15,5 +15,6 @@ namespace MediaBrowser.Controller.LiveTv Task AddMetadata(ListingsProviderInfo info, List<ChannelInfo> channels, CancellationToken cancellationToken); Task Validate(ListingsProviderInfo info, bool validateLogin, bool validateListings); Task<List<NameIdPair>> GetLineups(ListingsProviderInfo info, string country, string location); + Task<List<ChannelInfo>> GetChannels(ListingsProviderInfo info, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs index a4bd32fff..fe69b38cb 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs @@ -8,6 +8,7 @@ using MediaBrowser.Model.Querying; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Model.Events; namespace MediaBrowser.Controller.LiveTv { @@ -344,6 +345,13 @@ namespace MediaBrowser.Controller.LiveTv /// <param name="validateListings">if set to <c>true</c> [validate listings].</param> /// <returns>Task.</returns> Task<ListingsProviderInfo> SaveListingProvider(ListingsProviderInfo info, bool validateLogin, bool validateListings); + + void DeleteListingsProvider(string id); + + Task<TunerChannelMapping> SetChannelMapping(string providerId, string tunerChannelNumber, string providerChannelNumber); + + TunerChannelMapping GetTunerChannelMapping(ChannelInfo channel, List<NameValuePair> mappings, List<ChannelInfo> providerChannels); + /// <summary> /// Gets the lineups. /// </summary> @@ -385,5 +393,15 @@ namespace MediaBrowser.Controller.LiveTv List<NameValuePair> GetSatIniMappings(); Task<List<ChannelInfo>> GetSatChannelScanResult(TunerHostInfo info, CancellationToken cancellationToken); + + Task<List<ChannelInfo>> GetChannelsForListingsProvider(string id, CancellationToken cancellationToken); + Task<List<ChannelInfo>> GetChannelsFromListingsProviderData(string id, CancellationToken cancellationToken); + + List<IListingsProvider> ListingProviders { get;} + + event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCancelled; + event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCancelled; + event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCreated; + event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCreated; } } diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvService.cs b/MediaBrowser.Controller/LiveTv/ILiveTvService.cs index 4ef4847a3..d7d8336d0 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvService.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvService.cs @@ -226,4 +226,23 @@ namespace MediaBrowser.Controller.LiveTv /// <returns>Task.</returns> Task ResetTuner(string id, CancellationToken cancellationToken); } + + public interface ISupportsNewTimerIds + { + /// <summary> + /// Creates the timer asynchronous. + /// </summary> + /// <param name="info">The information.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns>Task.</returns> + Task<string> CreateTimer(TimerInfo info, CancellationToken cancellationToken); + + /// <summary> + /// Creates the series timer asynchronous. + /// </summary> + /// <param name="info">The information.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns>Task.</returns> + Task<string> CreateSeriesTimer(SeriesTimerInfo info, CancellationToken cancellationToken); + } } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs index cc30709db..74c993248 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; using System.Runtime.Serialization; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Providers; namespace MediaBrowser.Controller.LiveTv { @@ -235,5 +236,25 @@ namespace MediaBrowser.Controller.LiveTv return false; } } + + public override List<ExternalUrl> GetRelatedUrls() + { + var list = base.GetRelatedUrls(); + + var imdbId = this.GetProviderId(MetadataProviders.Imdb); + if (!string.IsNullOrWhiteSpace(imdbId)) + { + if (IsMovie) + { + list.Add(new ExternalUrl + { + Name = "Trakt", + Url = string.Format("https://trakt.tv/movies/{0}", imdbId) + }); + } + } + + return list; + } } } diff --git a/MediaBrowser.Controller/LiveTv/TimerEventInfo.cs b/MediaBrowser.Controller/LiveTv/TimerEventInfo.cs new file mode 100644 index 000000000..0e1a05475 --- /dev/null +++ b/MediaBrowser.Controller/LiveTv/TimerEventInfo.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MediaBrowser.Controller.LiveTv +{ + public class TimerEventInfo + { + public string Id { get; set; } + public string ProgramId { get; set; } + } +} diff --git a/MediaBrowser.Controller/LiveTv/TunerChannelMapping.cs b/MediaBrowser.Controller/LiveTv/TunerChannelMapping.cs new file mode 100644 index 000000000..da0527eea --- /dev/null +++ b/MediaBrowser.Controller/LiveTv/TunerChannelMapping.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MediaBrowser.Controller.LiveTv +{ + public class TunerChannelMapping + { + public string Name { get; set; } + public string Number { get; set; } + public string ProviderChannelNumber { get; set; } + public string ProviderChannelName { get; set; } + } +} diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index bc28ec015..0462117cb 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -142,7 +142,7 @@ <Compile Include="Entities\IHasDisplayOrder.cs" /> <Compile Include="Entities\IHasId.cs" /> <Compile Include="Entities\IHasImages.cs" /> - <Compile Include="Entities\IHasKeywords.cs" /> + <Compile Include="Entities\KeywordExtensions.cs" /> <Compile Include="Entities\IHasMediaSources.cs" /> <Compile Include="Entities\IHasMetascore.cs" /> <Compile Include="Entities\IHasOriginalTitle.cs" /> @@ -154,7 +154,6 @@ <Compile Include="Entities\IHasSpecialFeatures.cs" /> <Compile Include="Entities\IHasStartDate.cs" /> <Compile Include="Entities\IHasTaglines.cs" /> - <Compile Include="Entities\IHasTags.cs" /> <Compile Include="Entities\IHasThemeMedia.cs" /> <Compile Include="Entities\IHasTrailers.cs" /> <Compile Include="Entities\IHasUserData.cs" /> @@ -177,6 +176,7 @@ <Compile Include="Entities\PhotoAlbum.cs" /> <Compile Include="Entities\Share.cs" /> <Compile Include="Entities\SourceType.cs" /> + <Compile Include="Entities\TagExtensions.cs" /> <Compile Include="Entities\UserView.cs" /> <Compile Include="Entities\UserViewBuilder.cs" /> <Compile Include="FileOrganization\IFileOrganizationService.cs" /> @@ -218,7 +218,9 @@ <Compile Include="LiveTv\ProgramInfo.cs" /> <Compile Include="LiveTv\RecordingInfo.cs" /> <Compile Include="LiveTv\SeriesTimerInfo.cs" /> + <Compile Include="LiveTv\TimerEventInfo.cs" /> <Compile Include="LiveTv\TimerInfo.cs" /> + <Compile Include="LiveTv\TunerChannelMapping.cs" /> <Compile Include="Localization\ILocalizationManager.cs" /> <Compile Include="MediaEncoding\ChapterImageRefreshOptions.cs" /> <Compile Include="MediaEncoding\EncodingJobOptions.cs" /> @@ -290,21 +292,17 @@ <Compile Include="Providers\IImageFileSaver.cs" /> <Compile Include="Providers\IImageProvider.cs" /> <Compile Include="Providers\IImageSaver.cs" /> - <Compile Include="Providers\IItemIdentityConverter.cs" /> - <Compile Include="Providers\IItemIdentityProvider.cs" /> <Compile Include="Providers\ILocalImageFileProvider.cs" /> <Compile Include="Providers\ILocalMetadataProvider.cs" /> <Compile Include="Providers\ImageRefreshMode.cs" /> <Compile Include="Providers\ImageRefreshOptions.cs" /> <Compile Include="Providers\IPreRefreshProvider.cs" /> - <Compile Include="Providers\IProviderRepository.cs" /> <Compile Include="Providers\IRemoteImageProvider.cs" /> <Compile Include="Providers\ILocalImageProvider.cs" /> <Compile Include="Providers\IMetadataProvider.cs" /> <Compile Include="Providers\IMetadataService.cs" /> <Compile Include="Providers\IRemoteMetadataProvider.cs" /> <Compile Include="Providers\IRemoteSearchProvider.cs" /> - <Compile Include="Providers\ISeriesOrderProvider.cs" /> <Compile Include="Providers\ItemInfo.cs" /> <Compile Include="Providers\LiveTvProgramLookupInfo.cs" /> <Compile Include="Providers\LocalImageInfo.cs" /> @@ -330,12 +328,8 @@ <Compile Include="Sorting\SortHelper.cs" /> <Compile Include="Subtitles\ISubtitleManager.cs" /> <Compile Include="Subtitles\ISubtitleProvider.cs" /> - <Compile Include="Providers\ItemIdentifier.cs" /> - <Compile Include="Providers\ItemIdentities.cs" /> <Compile Include="Providers\ItemLookupInfo.cs" /> <Compile Include="Providers\MetadataRefreshOptions.cs" /> - <Compile Include="Providers\MetadataStatus.cs" /> - <Compile Include="Providers\ISeriesOrderManager.cs" /> <Compile Include="Session\ISessionManager.cs" /> <Compile Include="Entities\AggregateFolder.cs" /> <Compile Include="Entities\Audio\Audio.cs" /> diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs index c87ac4e73..44b741755 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Model.Dlna; +using System.Linq; +using MediaBrowser.Model.Dlna; namespace MediaBrowser.Controller.MediaEncoding { @@ -74,7 +75,7 @@ namespace MediaBrowser.Controller.MediaEncoding Level = info.VideoLevel; ItemId = info.ItemId; MediaSourceId = info.MediaSourceId; - AudioCodec = info.AudioCodec; + AudioCodec = info.TargetAudioCodec; MaxAudioChannels = info.MaxAudioChannels; AudioBitRate = info.AudioBitrate; AudioSampleRate = info.TargetAudioSampleRate; diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index 7c3959f6e..62377b19e 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -13,6 +13,8 @@ namespace MediaBrowser.Controller.MediaEncoding /// </summary> public interface IMediaEncoder : ITranscoderSupport { + string EncoderLocationType { get; } + /// <summary> /// Gets the encoder path. /// </summary> @@ -20,12 +22,6 @@ namespace MediaBrowser.Controller.MediaEncoding string EncoderPath { get; } /// <summary> - /// Gets the version. - /// </summary> - /// <value>The version.</value> - string Version { get; } - - /// <summary> /// Supportses the decoder. /// </summary> /// <param name="decoder">The decoder.</param> @@ -66,12 +62,12 @@ namespace MediaBrowser.Controller.MediaEncoding /// <param name="maxWidth">The maximum width.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - Task ExtractVideoImagesOnInterval(string[] inputFiles, - MediaProtocol protocol, - Video3DFormat? threedFormat, - TimeSpan interval, - string targetDirectory, - string filenamePrefix, + Task ExtractVideoImagesOnInterval(string[] inputFiles, + MediaProtocol protocol, + Video3DFormat? threedFormat, + TimeSpan interval, + string targetDirectory, + string filenamePrefix, int? maxWidth, CancellationToken cancellationToken); @@ -134,5 +130,9 @@ namespace MediaBrowser.Controller.MediaEncoding /// <param name="path">The path.</param> /// <returns>System.String.</returns> string EscapeSubtitleFilterPath(string path); + + Task Init(); + + Task UpdateEncoderPath(string path, string pathType); } } diff --git a/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs b/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs index e538b84d8..44489cbf5 100644 --- a/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs @@ -10,13 +10,6 @@ namespace MediaBrowser.Controller.MediaEncoding /// <summary> /// Gets the subtitles. /// </summary> - /// <param name="itemId">The item identifier.</param> - /// <param name="mediaSourceId">The media source identifier.</param> - /// <param name="subtitleStreamIndex">Index of the subtitle stream.</param> - /// <param name="outputFormat">The output format.</param> - /// <param name="startTimeTicks">The start time ticks.</param> - /// <param name="endTimeTicks">The end time ticks.</param> - /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task{Stream}.</returns> Task<Stream> GetSubtitles(string itemId, string mediaSourceId, @@ -24,6 +17,7 @@ namespace MediaBrowser.Controller.MediaEncoding string outputFormat, long startTimeTicks, long? endTimeTicks, + bool preserveOriginalTimestamps, CancellationToken cancellationToken); /// <summary> diff --git a/MediaBrowser.Controller/Net/IHttpResultFactory.cs b/MediaBrowser.Controller/Net/IHttpResultFactory.cs index 526bf4be2..cd7ee603e 100644 --- a/MediaBrowser.Controller/Net/IHttpResultFactory.cs +++ b/MediaBrowser.Controller/Net/IHttpResultFactory.cs @@ -80,7 +80,7 @@ namespace MediaBrowser.Controller.Net /// <param name="responseHeaders">The response headers.</param> /// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param> /// <returns>System.Object.</returns> - object GetStaticResult(IRequest requestContext, + Task<object> GetStaticResult(IRequest requestContext, Guid cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration, @@ -94,7 +94,7 @@ namespace MediaBrowser.Controller.Net /// <param name="requestContext">The request context.</param> /// <param name="options">The options.</param> /// <returns>System.Object.</returns> - object GetStaticResult(IRequest requestContext, StaticResultOptions options); + Task<object> GetStaticResult(IRequest requestContext, StaticResultOptions options); /// <summary> /// Gets the static file result. @@ -103,7 +103,7 @@ namespace MediaBrowser.Controller.Net /// <param name="path">The path.</param> /// <param name="fileShare">The file share.</param> /// <returns>System.Object.</returns> - object GetStaticFileResult(IRequest requestContext, string path, FileShare fileShare = FileShare.Read); + Task<object> GetStaticFileResult(IRequest requestContext, string path, FileShare fileShare = FileShare.Read); /// <summary> /// Gets the static file result. @@ -111,7 +111,7 @@ namespace MediaBrowser.Controller.Net /// <param name="requestContext">The request context.</param> /// <param name="options">The options.</param> /// <returns>System.Object.</returns> - object GetStaticFileResult(IRequest requestContext, + Task<object> GetStaticFileResult(IRequest requestContext, StaticFileResultOptions options); } } diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs index 7bcc36958..78138999c 100644 --- a/MediaBrowser.Controller/Persistence/IItemRepository.cs +++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Model.Dto; using MediaBrowser.Model.Querying; namespace MediaBrowser.Controller.Persistence @@ -81,7 +82,7 @@ namespace MediaBrowser.Controller.Persistence /// <param name="chapters">The chapters.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - Task SaveChapters(Guid id, IEnumerable<ChapterInfo> chapters, CancellationToken cancellationToken); + Task SaveChapters(Guid id, List<ChapterInfo> chapters, CancellationToken cancellationToken); /// <summary> /// Gets the media streams. @@ -97,7 +98,7 @@ namespace MediaBrowser.Controller.Persistence /// <param name="streams">The streams.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - Task SaveMediaStreams(Guid id, IEnumerable<MediaStream> streams, CancellationToken cancellationToken); + Task SaveMediaStreams(Guid id, List<MediaStream> streams, CancellationToken cancellationToken); /// <summary> /// Gets the item ids. @@ -153,7 +154,7 @@ namespace MediaBrowser.Controller.Persistence /// </summary> /// <param name="query">The query.</param> /// <returns>List<BaseItem>.</returns> - IEnumerable<BaseItem> GetItemList(InternalItemsQuery query); + List<BaseItem> GetItemList(InternalItemsQuery query); /// <summary> /// Updates the inherited values. @@ -161,6 +162,13 @@ namespace MediaBrowser.Controller.Persistence /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> Task UpdateInheritedValues(CancellationToken cancellationToken); + + QueryResult<Tuple<BaseItem, ItemCounts>> GetGenres(InternalItemsQuery query); + QueryResult<Tuple<BaseItem, ItemCounts>> GetMusicGenres(InternalItemsQuery query); + QueryResult<Tuple<BaseItem, ItemCounts>> GetGameGenres(InternalItemsQuery query); + QueryResult<Tuple<BaseItem, ItemCounts>> GetStudios(InternalItemsQuery query); + QueryResult<Tuple<BaseItem, ItemCounts>> GetArtists(InternalItemsQuery query); + QueryResult<Tuple<BaseItem, ItemCounts>> GetAlbumArtists(InternalItemsQuery query); } } diff --git a/MediaBrowser.Controller/Persistence/IUserDataRepository.cs b/MediaBrowser.Controller/Persistence/IUserDataRepository.cs index 2e165f416..ca4dc9751 100644 --- a/MediaBrowser.Controller/Persistence/IUserDataRepository.cs +++ b/MediaBrowser.Controller/Persistence/IUserDataRepository.cs @@ -29,6 +29,8 @@ namespace MediaBrowser.Controller.Persistence /// <returns>Task{UserItemData}.</returns> UserItemData GetUserData(Guid userId, string key); + UserItemData GetUserData(Guid userId, List<string> keys); + /// <summary> /// Return all user data associated with the given user /// </summary> diff --git a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs index 1014fc2ee..a783910e3 100644 --- a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs +++ b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs @@ -803,11 +803,7 @@ namespace MediaBrowser.Controller.Providers { using (var subtree = reader.ReadSubtree()) { - var hasTags = item as IHasTags; - if (hasTags != null) - { - FetchFromTagsNode(subtree, hasTags); - } + FetchFromTagsNode(subtree, item); } break; } @@ -816,11 +812,7 @@ namespace MediaBrowser.Controller.Providers { using (var subtree = reader.ReadSubtree()) { - var hasTags = item as IHasKeywords; - if (hasTags != null) - { - FetchFromKeywordsNode(subtree, hasTags); - } + FetchFromKeywordsNode(subtree, item); } break; } @@ -1070,7 +1062,7 @@ namespace MediaBrowser.Controller.Providers } } - private void FetchFromTagsNode(XmlReader reader, IHasTags item) + private void FetchFromTagsNode(XmlReader reader, BaseItem item) { reader.MoveToContent(); @@ -1099,7 +1091,7 @@ namespace MediaBrowser.Controller.Providers } } - private void FetchFromKeywordsNode(XmlReader reader, IHasKeywords item) + private void FetchFromKeywordsNode(XmlReader reader, BaseItem item) { reader.MoveToContent(); diff --git a/MediaBrowser.Controller/Providers/IItemIdentityConverter.cs b/MediaBrowser.Controller/Providers/IItemIdentityConverter.cs deleted file mode 100644 index bfdd1dbf3..000000000 --- a/MediaBrowser.Controller/Providers/IItemIdentityConverter.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace MediaBrowser.Controller.Providers -{ - public interface IItemIdentityConverter { } -}
\ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/IItemIdentityProvider.cs b/MediaBrowser.Controller/Providers/IItemIdentityProvider.cs deleted file mode 100644 index 6b403bb55..000000000 --- a/MediaBrowser.Controller/Providers/IItemIdentityProvider.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace MediaBrowser.Controller.Providers -{ - public interface IItemIdentityProvider { } -}
\ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs index 57e4ff320..3eefa9647 100644 --- a/MediaBrowser.Controller/Providers/IProviderManager.cs +++ b/MediaBrowser.Controller/Providers/IProviderManager.cs @@ -97,13 +97,11 @@ namespace MediaBrowser.Controller.Providers /// </summary> /// <param name="imageProviders">The image providers.</param> /// <param name="metadataServices">The metadata services.</param> - /// <param name="identityProviders">The identity providers.</param> - /// <param name="identityConverters">The identity converters.</param> /// <param name="metadataProviders">The metadata providers.</param> /// <param name="savers">The savers.</param> /// <param name="imageSavers">The image savers.</param> /// <param name="externalIds">The external ids.</param> - void AddParts(IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices, IEnumerable<IItemIdentityProvider> identityProviders, IEnumerable<IItemIdentityConverter> identityConverters, IEnumerable<IMetadataProvider> metadataProviders, + void AddParts(IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices, IEnumerable<IMetadataProvider> metadataProviders, IEnumerable<IMetadataSaver> savers, IEnumerable<IImageSaver> imageSavers, IEnumerable<IExternalId> externalIds); @@ -135,7 +133,7 @@ namespace MediaBrowser.Controller.Providers /// </summary> /// <param name="item">The item.</param> /// <returns>IEnumerable{ExternalUrl}.</returns> - IEnumerable<ExternalUrl> GetExternalUrls(IHasProviderIds item); + IEnumerable<ExternalUrl> GetExternalUrls(BaseItem item); /// <summary> /// Gets the external identifier infos. @@ -190,21 +188,5 @@ namespace MediaBrowser.Controller.Providers /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task{HttpResponseInfo}.</returns> Task<HttpResponseInfo> GetSearchImage(string providerName, string url, CancellationToken cancellationToken); - - /// <summary> - /// Gets the item identity providers. - /// </summary> - /// <typeparam name="TLookupInfo">The type of the t lookup information.</typeparam> - /// <returns>IEnumerable<IItemIdentityProvider<TLookupInfo, TIdentity>>.</returns> - IEnumerable<IItemIdentityProvider<TLookupInfo>> GetItemIdentityProviders<TLookupInfo>() - where TLookupInfo : ItemLookupInfo; - - /// <summary> - /// Gets the item identity converters. - /// </summary> - /// <typeparam name="TLookupInfo">The type of the t lookup information.</typeparam> - /// <returns>IEnumerable<IItemIdentityConverter<TIdentity>>.</returns> - IEnumerable<IItemIdentityConverter<TLookupInfo>> GetItemIdentityConverters<TLookupInfo>() - where TLookupInfo : ItemLookupInfo; } }
\ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/IProviderRepository.cs b/MediaBrowser.Controller/Providers/IProviderRepository.cs deleted file mode 100644 index 891275d77..000000000 --- a/MediaBrowser.Controller/Providers/IProviderRepository.cs +++ /dev/null @@ -1,25 +0,0 @@ -using MediaBrowser.Controller.Persistence; -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Controller.Providers -{ - public interface IProviderRepository : IRepository - { - /// <summary> - /// Gets the metadata status. - /// </summary> - /// <param name="itemId">The item identifier.</param> - /// <returns>MetadataStatus.</returns> - MetadataStatus GetMetadataStatus(Guid itemId); - - /// <summary> - /// Saves the metadata status. - /// </summary> - /// <param name="status">The status.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - Task SaveMetadataStatus(MetadataStatus status, CancellationToken cancellationToken); - } -} diff --git a/MediaBrowser.Controller/Providers/ISeriesOrderManager.cs b/MediaBrowser.Controller/Providers/ISeriesOrderManager.cs deleted file mode 100644 index 970f7a7be..000000000 --- a/MediaBrowser.Controller/Providers/ISeriesOrderManager.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace MediaBrowser.Controller.Providers -{ - public interface ISeriesOrderManager - { - Task<int?> FindSeriesIndex(string orderType, string seriesName); - void AddParts(IEnumerable<ISeriesOrderProvider> orderProviders); - } -} diff --git a/MediaBrowser.Controller/Providers/ISeriesOrderProvider.cs b/MediaBrowser.Controller/Providers/ISeriesOrderProvider.cs deleted file mode 100644 index ee0f3c197..000000000 --- a/MediaBrowser.Controller/Providers/ISeriesOrderProvider.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Threading.Tasks; - -namespace MediaBrowser.Controller.Providers -{ - public interface ISeriesOrderProvider - { - string OrderType { get; } - Task<int?> FindSeriesIndex(string seriesName); - } -}
\ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/ItemIdentifier.cs b/MediaBrowser.Controller/Providers/ItemIdentifier.cs deleted file mode 100644 index bbc6dd76c..000000000 --- a/MediaBrowser.Controller/Providers/ItemIdentifier.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Controller.Providers -{ - public static class ItemIdentifier<TLookupInfo> - where TLookupInfo : ItemLookupInfo - { - public static async Task FindIdentities(TLookupInfo item, IProviderManager providerManager, CancellationToken cancellationToken) - { - var providers = providerManager.GetItemIdentityProviders<TLookupInfo>(); - var converters = providerManager.GetItemIdentityConverters<TLookupInfo>().ToList(); - - foreach (var provider in providers) - { - await provider.Identify(item); - } - - bool changesMade = true; - - while (changesMade) - { - changesMade = false; - - foreach (var converter in converters) - { - if (await converter.Convert(item)) - { - changesMade = true; - } - } - } - } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/ItemIdentities.cs b/MediaBrowser.Controller/Providers/ItemIdentities.cs deleted file mode 100644 index 48316d0f4..000000000 --- a/MediaBrowser.Controller/Providers/ItemIdentities.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Threading.Tasks; - -namespace MediaBrowser.Controller.Providers -{ - public interface IItemIdentityProvider<in TLookupInfo> : IItemIdentityProvider - where TLookupInfo : ItemLookupInfo - { - Task Identify(TLookupInfo info); - } - - public interface IItemIdentityConverter<in TLookupInfo> : IItemIdentityConverter - where TLookupInfo : ItemLookupInfo - { - Task<bool> Convert(TLookupInfo info); - } -}
\ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/ItemInfo.cs b/MediaBrowser.Controller/Providers/ItemInfo.cs index d16a73028..63cc48058 100644 --- a/MediaBrowser.Controller/Providers/ItemInfo.cs +++ b/MediaBrowser.Controller/Providers/ItemInfo.cs @@ -1,3 +1,4 @@ +using System; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Entities; @@ -5,10 +6,6 @@ namespace MediaBrowser.Controller.Providers { public class ItemInfo { - public ItemInfo() - { - } - public ItemInfo(IHasMetadata item) { Path = item.Path; @@ -21,8 +18,11 @@ namespace MediaBrowser.Controller.Providers VideoType = video.VideoType; IsPlaceHolder = video.IsPlaceHolder; } + + ItemType = item.GetType(); } + public Type ItemType { get; set; } public string Path { get; set; } public string ContainingFolderPath { get; set; } public VideoType VideoType { get; set; } diff --git a/MediaBrowser.Controller/Providers/MetadataStatus.cs b/MediaBrowser.Controller/Providers/MetadataStatus.cs deleted file mode 100644 index b19377a68..000000000 --- a/MediaBrowser.Controller/Providers/MetadataStatus.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; - -namespace MediaBrowser.Controller.Providers -{ - public class MetadataStatus - { - /// <summary> - /// Gets or sets the item identifier. - /// </summary> - /// <value>The item identifier.</value> - public Guid ItemId { get; set; } - - /// <summary> - /// Gets or sets the date last metadata refresh. - /// </summary> - /// <value>The date last metadata refresh.</value> - public DateTime? DateLastMetadataRefresh { get; set; } - - /// <summary> - /// Gets or sets the date last images refresh. - /// </summary> - /// <value>The date last images refresh.</value> - public DateTime? DateLastImagesRefresh { get; set; } - - public DateTime? ItemDateModified { get; set; } - - public bool IsDirty { get; private set; } - - public void SetDateLastMetadataRefresh(DateTime? date) - { - if (date != DateLastMetadataRefresh) - { - IsDirty = true; - } - - DateLastMetadataRefresh = date; - } - - public void SetDateLastImagesRefresh(DateTime? date) - { - if (date != DateLastImagesRefresh) - { - IsDirty = true; - } - - DateLastImagesRefresh = date; - } - } -} diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs index fa74c5749..6659d1553 100644 --- a/MediaBrowser.Controller/Session/ISessionManager.cs +++ b/MediaBrowser.Controller/Session/ISessionManager.cs @@ -315,9 +315,8 @@ namespace MediaBrowser.Controller.Session /// <summary> /// Revokes the user tokens. /// </summary> - /// <param name="userId">The user identifier.</param> /// <returns>Task.</returns> - Task RevokeUserTokens(string userId); + Task RevokeUserTokens(string userId, string currentAccessToken); /// <summary> /// Revokes the token. |
