diff options
| -rw-r--r-- | MediaBrowser.Api/ItemUpdateService.cs | 1 | ||||
| -rw-r--r-- | MediaBrowser.Api/TvShowsService.cs | 112 | ||||
| -rw-r--r-- | MediaBrowser.Api/UserLibrary/ItemsService.cs | 2 | ||||
| -rw-r--r-- | MediaBrowser.Controller/Entities/TV/Episode.cs | 6 | ||||
| -rw-r--r-- | MediaBrowser.Controller/Entities/TV/Season.cs | 38 | ||||
| -rw-r--r-- | MediaBrowser.Controller/Entities/TV/Series.cs | 85 | ||||
| -rw-r--r-- | MediaBrowser.Model/Dto/BaseItemDto.cs | 1 | ||||
| -rw-r--r-- | MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs | 8 | ||||
| -rw-r--r-- | MediaBrowser.Providers/Savers/XmlSaverHelpers.cs | 20 | ||||
| -rw-r--r-- | MediaBrowser.Providers/TV/EpisodeXmlParser.cs | 17 | ||||
| -rw-r--r-- | MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs | 18 | ||||
| -rw-r--r-- | MediaBrowser.Server.Implementations/Dto/DtoService.cs | 25 |
12 files changed, 225 insertions, 108 deletions
diff --git a/MediaBrowser.Api/ItemUpdateService.cs b/MediaBrowser.Api/ItemUpdateService.cs index a244b71df..3e79fb91c 100644 --- a/MediaBrowser.Api/ItemUpdateService.cs +++ b/MediaBrowser.Api/ItemUpdateService.cs @@ -279,6 +279,7 @@ namespace MediaBrowser.Api episode.AirsAfterSeasonNumber = request.AirsAfterSeasonNumber; episode.AirsBeforeEpisodeNumber = request.AirsBeforeEpisodeNumber; episode.AirsBeforeSeasonNumber = request.AirsBeforeSeasonNumber; + episode.AbsoluteEpisodeNumber = request.AbsoluteEpisodeNumber; } var hasTags = item as IHasTags; diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index b45d4dfb0..11cd72cf4 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -1,4 +1,5 @@ using MediaBrowser.Api.UserLibrary; +using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; @@ -364,12 +365,11 @@ namespace MediaBrowser.Api var series = _libraryManager.GetItemById(request.Id) as Series; - var fields = request.GetItemFields().ToList(); - - var seasons = series.GetChildren(user, true) - .OfType<Season>(); - - var sortOrder = ItemSortBy.SortName; + if (series == null) + { + throw new ResourceNotFoundException("No series exists with Id " + request.Id); + } + var seasons = series.GetSeasons(user); if (request.IsSpecialSeason.HasValue) { @@ -378,29 +378,8 @@ namespace MediaBrowser.Api seasons = seasons.Where(i => i.IsSpecialSeason == val); } - var config = user.Configuration; - - if (!config.DisplayMissingEpisodes && !config.DisplayUnairedEpisodes) - { - seasons = seasons.Where(i => !i.IsMissingOrVirtualUnaired); - } - else - { - if (!config.DisplayMissingEpisodes) - { - seasons = seasons.Where(i => !i.IsMissingSeason); - } - if (!config.DisplayUnairedEpisodes) - { - seasons = seasons.Where(i => !i.IsVirtualUnaired); - } - } - seasons = FilterVirtualSeasons(request, seasons); - seasons = _libraryManager.Sort(seasons, user, new[] { sortOrder }, SortOrder.Ascending) - .Cast<Season>(); - // This must be the last filter if (!string.IsNullOrEmpty(request.AdjacentTo)) { @@ -408,6 +387,8 @@ namespace MediaBrowser.Api .Cast<Season>(); } + var fields = request.GetItemFields().ToList(); + var returnItems = seasons.Select(i => _dtoService.GetBaseItemDto(i, fields, user)) .ToArray(); @@ -450,66 +431,45 @@ namespace MediaBrowser.Api { var user = _userManager.GetUserById(request.UserId); - var series = _libraryManager.GetItemById(request.Id) as Series; - - var fields = request.GetItemFields().ToList(); - - var episodes = series.GetRecursiveChildren(user) - .OfType<Episode>(); + IEnumerable<Episode> episodes; - var sortOrder = ItemSortBy.SortName; - - if (!string.IsNullOrEmpty(request.SeasonId)) + if (string.IsNullOrEmpty(request.SeasonId)) { - var season = _libraryManager.GetItemById(new Guid(request.SeasonId)) as Season; + var series = _libraryManager.GetItemById(request.Id) as Series; - if (season.IndexNumber.HasValue) + if (series == null) { - episodes = FilterEpisodesBySeason(episodes, season.IndexNumber.Value, true); - - sortOrder = ItemSortBy.AiredEpisodeOrder; + throw new ResourceNotFoundException("No series exists with Id " + request.Id); } - else - { - episodes = season.RecursiveChildren.OfType<Episode>(); - sortOrder = ItemSortBy.SortName; - } + episodes = series.GetEpisodes(user, request.Season.Value); } - - else if (request.Season.HasValue) + else { - episodes = FilterEpisodesBySeason(episodes, request.Season.Value, true); - - sortOrder = ItemSortBy.AiredEpisodeOrder; - } - - var config = user.Configuration; + var season = _libraryManager.GetItemById(new Guid(request.SeasonId)) as Season; - if (!config.DisplayMissingEpisodes) - { - episodes = episodes.Where(i => !i.IsMissingEpisode); - } - if (!config.DisplayUnairedEpisodes) - { - episodes = episodes.Where(i => !i.IsVirtualUnaired); + if (season == null) + { + throw new ResourceNotFoundException("No season exists with Id " + request.SeasonId); + } + + episodes = season.GetEpisodes(user); } + // Filter after the fact in case the ui doesn't want them if (request.IsMissing.HasValue) { var val = request.IsMissing.Value; episodes = episodes.Where(i => i.IsMissingEpisode == val); } + // Filter after the fact in case the ui doesn't want them if (request.IsVirtualUnaired.HasValue) { var val = request.IsVirtualUnaired.Value; episodes = episodes.Where(i => i.IsVirtualUnaired == val); } - episodes = _libraryManager.Sort(episodes, user, new[] { sortOrder }, SortOrder.Ascending) - .Cast<Episode>(); - // This must be the last filter if (!string.IsNullOrEmpty(request.AdjacentTo)) { @@ -517,6 +477,8 @@ namespace MediaBrowser.Api .Cast<Episode>(); } + var fields = request.GetItemFields().ToList(); + var returnItems = episodes.Select(i => _dtoService.GetBaseItemDto(i, fields, user)) .ToArray(); @@ -526,27 +488,5 @@ namespace MediaBrowser.Api Items = returnItems }; } - - internal static IEnumerable<Episode> FilterEpisodesBySeason(IEnumerable<Episode> episodes, int seasonNumber, bool includeSpecials) - { - if (!includeSpecials || seasonNumber < 1) - { - return episodes.Where(i => (i.PhysicalSeasonNumber ?? -1) == seasonNumber); - } - - return episodes.Where(i => - { - var episode = i; - - if (episode != null) - { - var currentSeasonNumber = episode.AiredSeasonNumber; - - return currentSeasonNumber.HasValue && currentSeasonNumber.Value == seasonNumber; - } - - return false; - }); - } } } diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index 6fcff545f..dc4a833b0 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -1041,7 +1041,7 @@ namespace MediaBrowser.Api.UserLibrary if (request.AiredDuringSeason.HasValue) { - items = TvShowsService.FilterEpisodesBySeason(items.OfType<Episode>(), request.AiredDuringSeason.Value, true); + items = Series.FilterEpisodesBySeason(items.OfType<Episode>(), request.AiredDuringSeason.Value, true); } if (!string.IsNullOrEmpty(request.MinPremiereDate)) diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index f24d86408..7f94ab8e8 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -52,6 +52,12 @@ namespace MediaBrowser.Controller.Entities.TV public float? DvdEpisodeNumber { get; set; } /// <summary> + /// Gets or sets the absolute episode number. + /// </summary> + /// <value>The absolute episode number.</value> + public int? AbsoluteEpisodeNumber { get; set; } + + /// <summary> /// We want to group into series not show individually in an index /// </summary> /// <value><c>true</c> if [group in index]; otherwise, <c>false</c>.</value> diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index 78e0b8bc4..3a767421a 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -1,5 +1,7 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Localization; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Querying; using System; using System.Collections.Generic; using System.IO; @@ -186,7 +188,7 @@ namespace MediaBrowser.Controller.Entities.TV [IgnoreDataMember] public bool IsMissingSeason { - get { return LocationType == Model.Entities.LocationType.Virtual && GetEpisodes().All(i => i.IsMissingEpisode); } + get { return LocationType == LocationType.Virtual && GetEpisodes().All(i => i.IsMissingEpisode); } } [IgnoreDataMember] @@ -198,13 +200,13 @@ namespace MediaBrowser.Controller.Entities.TV [IgnoreDataMember] public bool IsVirtualUnaired { - get { return LocationType == Model.Entities.LocationType.Virtual && IsUnaired; } + get { return LocationType == LocationType.Virtual && IsUnaired; } } [IgnoreDataMember] public bool IsMissingOrVirtualUnaired { - get { return LocationType == Model.Entities.LocationType.Virtual && GetEpisodes().All(i => i.IsVirtualUnaired || i.IsMissingEpisode); } + get { return LocationType == LocationType.Virtual && GetEpisodes().All(i => i.IsVirtualUnaired || i.IsMissingEpisode); } } [IgnoreDataMember] @@ -212,5 +214,35 @@ namespace MediaBrowser.Controller.Entities.TV { get { return (IndexNumber ?? -1) == 0; } } + + /// <summary> + /// Gets the episodes. + /// </summary> + /// <param name="user">The user.</param> + /// <returns>IEnumerable{Episode}.</returns> + public IEnumerable<Episode> GetEpisodes(User user) + { + if (IndexNumber.HasValue) + { + var series = Series; + + if (series != null) + { + return series.GetEpisodes(user, IndexNumber.Value); + } + } + + var episodes = GetRecursiveChildren(user) + .OfType<Episode>(); + + return LibraryManager + .Sort(episodes, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending) + .Cast<Episode>(); + } + + public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren, string indexBy = null) + { + return GetEpisodes(user); + } } } diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 2312df2a1..1c4bef942 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -1,6 +1,7 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Localization; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Querying; using System; using System.Collections.Generic; using System.IO; @@ -117,5 +118,89 @@ namespace MediaBrowser.Controller.Entities.TV return Children.OfType<Video>().Any(); } } + + public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren, string indexBy = null) + { + return GetSeasons(user); + } + + public IEnumerable<Season> GetSeasons(User user) + { + var seasons = base.GetChildren(user, true) + .OfType<Season>(); + + var config = user.Configuration; + + if (!config.DisplayMissingEpisodes && !config.DisplayUnairedEpisodes) + { + seasons = seasons.Where(i => !i.IsMissingOrVirtualUnaired); + } + else + { + if (!config.DisplayMissingEpisodes) + { + seasons = seasons.Where(i => !i.IsMissingSeason); + } + if (!config.DisplayUnairedEpisodes) + { + seasons = seasons.Where(i => !i.IsVirtualUnaired); + } + } + + return LibraryManager + .Sort(seasons, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending) + .Cast<Season>(); + } + + public IEnumerable<Episode> GetEpisodes(User user, int seasonNumber) + { + var episodes = GetRecursiveChildren(user) + .OfType<Episode>(); + + episodes = FilterEpisodesBySeason(episodes, seasonNumber, true); + + var config = user.Configuration; + + if (!config.DisplayMissingEpisodes) + { + episodes = episodes.Where(i => !i.IsMissingEpisode); + } + if (!config.DisplayUnairedEpisodes) + { + episodes = episodes.Where(i => !i.IsVirtualUnaired); + } + + return LibraryManager.Sort(episodes, user, new[] { ItemSortBy.AiredEpisodeOrder }, SortOrder.Ascending) + .Cast<Episode>(); + } + + /// <summary> + /// Filters the episodes by season. + /// </summary> + /// <param name="episodes">The episodes.</param> + /// <param name="seasonNumber">The season number.</param> + /// <param name="includeSpecials">if set to <c>true</c> [include specials].</param> + /// <returns>IEnumerable{Episode}.</returns> + public static IEnumerable<Episode> FilterEpisodesBySeason(IEnumerable<Episode> episodes, int seasonNumber, bool includeSpecials) + { + if (!includeSpecials || seasonNumber < 1) + { + return episodes.Where(i => (i.PhysicalSeasonNumber ?? -1) == seasonNumber); + } + + return episodes.Where(i => + { + var episode = i; + + if (episode != null) + { + var currentSeasonNumber = episode.AiredSeasonNumber; + + return currentSeasonNumber.HasValue && currentSeasonNumber.Value == seasonNumber; + } + + return false; + }); + } } } diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index 3bdbf2ae6..7b067dd1f 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -33,6 +33,7 @@ namespace MediaBrowser.Model.Dto public int? AirsBeforeSeasonNumber { get; set; } public int? AirsAfterSeasonNumber { get; set; } public int? AirsBeforeEpisodeNumber { get; set; } + public int? AbsoluteEpisodeNumber { get; set; } /// <summary> /// Gets or sets the DVD season number. diff --git a/MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs b/MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs index 88b3af5be..91e769994 100644 --- a/MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs @@ -92,6 +92,11 @@ namespace MediaBrowser.Providers.Savers builder.Append("<SeasonNumber>" + SecurityElement.Escape(episode.ParentIndexNumber.Value.ToString(_usCulture)) + "</SeasonNumber>"); } + if (episode.AbsoluteEpisodeNumber.HasValue) + { + builder.Append("<absolute_number>" + SecurityElement.Escape(episode.AbsoluteEpisodeNumber.Value.ToString(_usCulture)) + "</absolute_number>"); + } + if (episode.DvdEpisodeNumber.HasValue) { builder.Append("<DVD_episodenumber>" + SecurityElement.Escape(episode.DvdEpisodeNumber.Value.ToString(_usCulture)) + "</DVD_episodenumber>"); @@ -125,7 +130,8 @@ namespace MediaBrowser.Providers.Savers "airsbefore_episode", "airsbefore_season", "DVD_episodenumber", - "DVD_season" + "DVD_season", + "absolute_number" }); } diff --git a/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs b/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs index 522b2c90b..551da20b0 100644 --- a/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs +++ b/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs @@ -534,20 +534,12 @@ namespace MediaBrowser.Providers.Savers { var video = item as Video; - builder.Append("<MediaInfo>"); - - builder.Append("<Video>"); - - if (item.RunTimeTicks.HasValue) + if (video != null && video.Video3DFormat.HasValue) { - var timespan = TimeSpan.FromTicks(item.RunTimeTicks.Value); + builder.Append("<MediaInfo>"); - builder.Append("<Duration>" + Convert.ToInt64(timespan.TotalMinutes).ToString(UsCulture) + "</Duration>"); - builder.Append("<DurationSeconds>" + Convert.ToInt64(timespan.TotalSeconds).ToString(UsCulture) + "</DurationSeconds>"); - } + builder.Append("<Video>"); - if (video != null && video.Video3DFormat.HasValue) - { switch (video.Video3DFormat.Value) { case Video3DFormat.FullSideBySide: @@ -563,11 +555,11 @@ namespace MediaBrowser.Providers.Savers builder.Append("<Format3D>HTAB</Format3D>"); break; } - } - builder.Append("</Video>"); + builder.Append("</Video>"); - builder.Append("</MediaInfo>"); + builder.Append("</MediaInfo>"); + } } } } diff --git a/MediaBrowser.Providers/TV/EpisodeXmlParser.cs b/MediaBrowser.Providers/TV/EpisodeXmlParser.cs index a06a3bf23..446c34f74 100644 --- a/MediaBrowser.Providers/TV/EpisodeXmlParser.cs +++ b/MediaBrowser.Providers/TV/EpisodeXmlParser.cs @@ -143,6 +143,23 @@ namespace MediaBrowser.Providers.TV break; } + case "absolute_number": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + int rval; + + // int.TryParse is local aware, so it can be probamatic, force us culture + if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval)) + { + item.AbsoluteEpisodeNumber = rval; + } + } + + break; + } case "DVD_episodenumber": { var number = reader.ReadElementContentAsString(); diff --git a/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs index b7709b5d3..f5e21bf69 100644 --- a/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs @@ -438,6 +438,24 @@ namespace MediaBrowser.Providers.TV break; } + case "absolute_number": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + int rval; + + // int.TryParse is local aware, so it can be probamatic, force us culture + if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval)) + { + item.AbsoluteEpisodeNumber = rval; + } + } + + break; + } + case "airsbefore_episode": { var val = reader.ReadElementContentAsString(); diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 6e8c9d3eb..936239657 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -163,8 +163,7 @@ namespace MediaBrowser.Server.Implementations.Dto { var folder = (Folder)item; - dto.ChildCount = folder.GetChildren(user, true) - .Count(); + dto.ChildCount = GetChildCount(folder, user); if (!(folder is UserRootFolder)) { @@ -182,6 +181,12 @@ namespace MediaBrowser.Server.Implementations.Dto } } + private int GetChildCount(Folder folder, User user) + { + return folder.GetChildren(user, true) + .Count(); + } + public UserDto GetUserDto(User user) { if (user == null) @@ -1067,6 +1072,7 @@ namespace MediaBrowser.Server.Implementations.Dto dto.AirsAfterSeasonNumber = episode.AirsAfterSeasonNumber; dto.AirsBeforeEpisodeNumber = episode.AirsBeforeEpisodeNumber; dto.AirsBeforeSeasonNumber = episode.AirsBeforeSeasonNumber; + dto.AbsoluteEpisodeNumber = episode.AbsoluteEpisodeNumber; var seasonId = episode.SeasonId; if (seasonId.HasValue) @@ -1202,8 +1208,21 @@ namespace MediaBrowser.Server.Implementations.Dto double totalPercentPlayed = 0; + IEnumerable<BaseItem> children; + + var season = folder as Season; + + if (season != null) + { + children = season.GetEpisodes(user).Where(i => i.LocationType != LocationType.Virtual); + } + else + { + children = folder.GetRecursiveChildren(user, i => !i.IsFolder && i.LocationType != LocationType.Virtual); + } + // Loop through each recursive child - foreach (var child in folder.GetRecursiveChildren(user, i => !i.IsFolder && i.LocationType != LocationType.Virtual)) + foreach (var child in children) { var userdata = _userDataRepository.GetUserData(user.Id, child.GetUserDataKey()); |
