From 16203c52b4855b8474d5393ceebe1b7d85ce37fc Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 22 Nov 2013 10:33:14 -0500 Subject: Added specialized episodes endpoint, updated nuget. --- MediaBrowser.Api/TvShowsService.cs | 137 ++++++++++++++++++++++++++++++------- 1 file changed, 111 insertions(+), 26 deletions(-) (limited to 'MediaBrowser.Api/TvShowsService.cs') diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index 6cae379d2a..1774f1a8ed 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -17,7 +17,7 @@ namespace MediaBrowser.Api /// [Route("/Shows/NextUp", "GET")] [Api(("Gets a list of currently installed plugins"))] - public class GetNextUpEpisodes : IReturn + public class GetNextUpEpisodes : IReturn, IHasItemFields { /// /// Gets or sets the user id. @@ -49,38 +49,40 @@ namespace MediaBrowser.Api [ApiMember(Name = "SeriesId", Description = "Optional. Filter by series id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] public string SeriesId { get; set; } + } + + [Route("/Shows/{Id}/Similar", "GET")] + [Api(Description = "Finds tv shows similar to a given one.")] + public class GetSimilarShows : BaseGetSimilarItemsFromItem + { + } + [Route("/Shows/{Id}/Episodes", "GET")] + [Api(Description = "Finds tv shows similar to a given one.")] + public class GetEpisodes : IReturn, IHasItemFields + { /// - /// Gets the item fields. + /// Gets or sets the user id. /// - /// IEnumerable{ItemFields}. - public IEnumerable GetItemFields() - { - var val = Fields; - - if (string.IsNullOrEmpty(val)) - { - return new ItemFields[] { }; - } + /// The user id. + [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] + public Guid UserId { get; set; } - return val.Split(',').Select(v => - { - ItemFields value; + /// + /// Fields to return within the items, in addition to basic information + /// + /// The fields. + [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, OverviewHtml, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] + public string Fields { get; set; } - if (Enum.TryParse(v, true, out value)) - { - return (ItemFields?)value; - } - return null; + [ApiMember(Name = "Id", Description = "The series id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] + public Guid Id { get; set; } - }).Where(i => i.HasValue).Select(i => i.Value); - } - } + [ApiMember(Name = "Season", Description = "Optional filter by season number.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public int? Season { get; set; } - [Route("/Shows/{Id}/Similar", "GET")] - [Api(Description = "Finds tv shows similar to a given one.")] - public class GetSimilarShows : BaseGetSimilarItemsFromItem - { + [ApiMember(Name = "ExcludeLocationTypes", Description = "Optional. If specified, results will be filtered based on LocationType. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] + public string ExcludeLocationTypes { get; set; } } /// @@ -311,5 +313,88 @@ namespace MediaBrowser.Api return items; } + + public object Get(GetEpisodes request) + { + 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(); + + var sortOrder = ItemSortBy.SortName; + + if (request.Season.HasValue) + { + episodes = FilterEpisodesBySeason(episodes, request.Season.Value, true); + + sortOrder = ItemSortBy.AiredEpisodeOrder; + } + + var config = user.Configuration; + + if (!config.DisplayMissingEpisodes) + { + episodes = episodes.Where(i => !i.IsMissingEpisode); + } + if (!config.DisplayUnairedEpisodes) + { + episodes = episodes.Where(i => !i.IsVirtualUnaired); + } + + // ExcludeLocationTypes + if (!string.IsNullOrEmpty(request.ExcludeLocationTypes)) + { + var vals = request.ExcludeLocationTypes.Split(','); + episodes = episodes.Where(f => !vals.Contains(f.LocationType.ToString(), StringComparer.OrdinalIgnoreCase)); + } + + episodes = _libraryManager.Sort(episodes, user, new[] { sortOrder }, SortOrder.Ascending) + .Cast(); + + var returnItems = episodes.Select(i => _dtoService.GetBaseItemDto(i, fields, user)) + .ToArray(); + + return new ItemsResult + { + TotalRecordCount = returnItems.Length, + Items = returnItems + }; + } + + internal static IEnumerable FilterEpisodesBySeason(IEnumerable episodes, int seasonNumber, bool includeSpecials) + { + if (!includeSpecials || seasonNumber < 1) + { + return episodes.Where(i => (i.PhysicalSeasonNumber ?? -1) == seasonNumber); + } + + var episodeList = episodes.ToList(); + + // We can only enforce the air date requirement if the episodes have air dates + var enforceAirDate = episodeList.Any(i => i.PremiereDate.HasValue); + + return episodeList.Where(i => + { + var episode = i; + + if (episode != null) + { + if (enforceAirDate && !episode.PremiereDate.HasValue) + { + return false; + } + + var currentSeasonNumber = episode.AiredSeasonNumber; + + return currentSeasonNumber.HasValue && currentSeasonNumber.Value == seasonNumber; + } + + return false; + }); + } } } -- cgit v1.2.3 From 64818ebd223880d1ef7d7173b10968077d2378b0 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 26 Nov 2013 21:38:11 -0500 Subject: fix directory watchers not picking up changes --- .../Library/LibraryStructureService.cs | 33 ++++++++++++++++++---- MediaBrowser.Api/TvShowsService.cs | 12 +------- MediaBrowser.Controller/LiveTv/ILiveTvManager.cs | 4 +-- MediaBrowser.Model/LiveTv/ProgramInfoDto.cs | 12 ++++++++ .../TV/EpisodeProviderFromXml.cs | 1 - .../IO/DirectoryWatchers.cs | 2 +- .../Library/LibraryManager.cs | 14 +++++++++ .../LiveTv/RefreshChannelsScheduledTask.cs | 2 +- MediaBrowser.ServerApplication/ApplicationHost.cs | 2 -- 9 files changed, 59 insertions(+), 23 deletions(-) (limited to 'MediaBrowser.Api/TvShowsService.cs') diff --git a/MediaBrowser.Api/Library/LibraryStructureService.cs b/MediaBrowser.Api/Library/LibraryStructureService.cs index f3306bb63c..198bec1a0d 100644 --- a/MediaBrowser.Api/Library/LibraryStructureService.cs +++ b/MediaBrowser.Api/Library/LibraryStructureService.cs @@ -286,7 +286,12 @@ namespace MediaBrowser.Api.Library } finally { - _directoryWatchers.Start(); + // No need to start if scanning the library because it will handle it + if (!request.RefreshLibrary) + { + _directoryWatchers.Start(); + } + _directoryWatchers.RemoveTempIgnore(virtualFolderPath); } @@ -353,7 +358,12 @@ namespace MediaBrowser.Api.Library } finally { - _directoryWatchers.Start(); + // No need to start if scanning the library because it will handle it + if (!request.RefreshLibrary) + { + _directoryWatchers.Start(); + } + _directoryWatchers.RemoveTempIgnore(currentPath); _directoryWatchers.RemoveTempIgnore(newPath); } @@ -404,7 +414,12 @@ namespace MediaBrowser.Api.Library } finally { - _directoryWatchers.Start(); + // No need to start if scanning the library because it will handle it + if (!request.RefreshLibrary) + { + _directoryWatchers.Start(); + } + _directoryWatchers.RemoveTempIgnore(path); } @@ -442,7 +457,11 @@ namespace MediaBrowser.Api.Library } finally { - _directoryWatchers.Start(); + // No need to start if scanning the library because it will handle it + if (!request.RefreshLibrary) + { + _directoryWatchers.Start(); + } } if (request.RefreshLibrary) @@ -479,7 +498,11 @@ namespace MediaBrowser.Api.Library } finally { - _directoryWatchers.Start(); + // No need to start if scanning the library because it will handle it + if (!request.RefreshLibrary) + { + _directoryWatchers.Start(); + } } if (request.RefreshLibrary) diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index 1774f1a8ed..b36005c1aa 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -372,22 +372,12 @@ namespace MediaBrowser.Api return episodes.Where(i => (i.PhysicalSeasonNumber ?? -1) == seasonNumber); } - var episodeList = episodes.ToList(); - - // We can only enforce the air date requirement if the episodes have air dates - var enforceAirDate = episodeList.Any(i => i.PremiereDate.HasValue); - - return episodeList.Where(i => + return episodes.Where(i => { var episode = i; if (episode != null) { - if (enforceAirDate && !episode.PremiereDate.HasValue) - { - return false; - } - var currentSeasonNumber = episode.AiredSeasonNumber; return currentSeasonNumber.HasValue && currentSeasonNumber.Value == seasonNumber; diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs index a04072d28d..91634b4bfb 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs @@ -1,7 +1,7 @@ -using System.Threading; -using MediaBrowser.Model.LiveTv; +using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Querying; using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; namespace MediaBrowser.Controller.LiveTv diff --git a/MediaBrowser.Model/LiveTv/ProgramInfoDto.cs b/MediaBrowser.Model/LiveTv/ProgramInfoDto.cs index 2cafd288df..26cfd3cf00 100644 --- a/MediaBrowser.Model/LiveTv/ProgramInfoDto.cs +++ b/MediaBrowser.Model/LiveTv/ProgramInfoDto.cs @@ -100,6 +100,18 @@ namespace MediaBrowser.Model.LiveTv /// /// The recording status. public RecordingStatus? RecordingStatus { get; set; } + + /// + /// Gets or sets the timer identifier. + /// + /// The timer identifier. + public string TimerId { get; set; } + + /// + /// Gets or sets the timer status. + /// + /// The timer status. + public RecordingStatus? TimerStatus { get; set; } public ProgramInfoDto() { diff --git a/MediaBrowser.Providers/TV/EpisodeProviderFromXml.cs b/MediaBrowser.Providers/TV/EpisodeProviderFromXml.cs index b6fdaaa831..7ddf421b9b 100644 --- a/MediaBrowser.Providers/TV/EpisodeProviderFromXml.cs +++ b/MediaBrowser.Providers/TV/EpisodeProviderFromXml.cs @@ -2,7 +2,6 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; diff --git a/MediaBrowser.Server.Implementations/IO/DirectoryWatchers.cs b/MediaBrowser.Server.Implementations/IO/DirectoryWatchers.cs index b24cc20635..870a14bd80 100644 --- a/MediaBrowser.Server.Implementations/IO/DirectoryWatchers.cs +++ b/MediaBrowser.Server.Implementations/IO/DirectoryWatchers.cs @@ -69,7 +69,7 @@ namespace MediaBrowser.Server.Implementations.IO // This is an arbitraty amount of time, but delay it because file system writes often trigger events after RemoveTempIgnore has been called. // Seeing long delays in some situations, especially over the network. // Seeing delays up to 40 seconds, but not going to ignore changes for that long. - await Task.Delay(20000).ConfigureAwait(false); + await Task.Delay(1500).ConfigureAwait(false); string val; _tempIgnoredPaths.TryRemove(path, out val); diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 58a2fcd7ed..74c4f8b2a8 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -905,6 +905,20 @@ namespace MediaBrowser.Server.Implementations.Library /// The cancellation token. /// Task. public async Task ValidateMediaLibraryInternal(IProgress progress, CancellationToken cancellationToken) + { + _directoryWatchersFactory().Stop(); + + try + { + await PerformLibraryValidation(progress, cancellationToken).ConfigureAwait(false); + } + finally + { + _directoryWatchersFactory().Start(); + } + } + + private async Task PerformLibraryValidation(IProgress progress, CancellationToken cancellationToken) { _logger.Info("Validating media library"); diff --git a/MediaBrowser.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs b/MediaBrowser.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs index c3803d9bbc..3e7feeff79 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.LiveTv { - class RefreshChannelsScheduledTask : IScheduledTask + class RefreshChannelsScheduledTask { private readonly ILiveTvManager _liveTvManager; diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index c53277d778..fcd7d299cf 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -199,8 +199,6 @@ namespace MediaBrowser.ServerApplication { await base.RunStartupTasks().ConfigureAwait(false); - DirectoryWatchers.Start(); - Logger.Info("Core startup complete"); Parallel.ForEach(GetExports(), entryPoint => -- cgit v1.2.3 From 4892fb4e95f982527769620595e924c364204310 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 28 Nov 2013 13:27:29 -0500 Subject: add specialized get seasons method --- .../Progressive/BaseProgressiveStreamingService.cs | 82 ++++++++++---------- MediaBrowser.Api/TvShowsService.cs | 90 +++++++++++++++++++++- MediaBrowser.Controller/Entities/TV/Season.cs | 10 ++- MediaBrowser.Model/ApiClient/IApiClient.cs | 7 ++ MediaBrowser.Model/Querying/EpisodeQuery.cs | 19 +++++ .../MediaBrowser.Providers.csproj | 1 + .../UserRootFolderNameProvider.cs | 42 ++++++++++ MediaBrowser.WebDashboard/ApiClient.js | 11 +++ MediaBrowser.WebDashboard/packages.config | 2 +- 9 files changed, 218 insertions(+), 46 deletions(-) create mode 100644 MediaBrowser.Providers/UserRootFolderNameProvider.cs (limited to 'MediaBrowser.Api/TvShowsService.cs') diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs index 0b7b48f47e..1f0853e08b 100644 --- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs +++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs @@ -127,44 +127,44 @@ namespace MediaBrowser.Api.Playback.Progressive const string dlnaflags = ";DLNA.ORG_FLAGS=01500000000000000000000000000000"; - if (string.Equals(extension, ".mp3", StringComparison.OrdinalIgnoreCase)) - { - contentFeatures = "DLNA.ORG_PN=MP3"; - } - else if (string.Equals(extension, ".aac", StringComparison.OrdinalIgnoreCase)) - { - contentFeatures = "DLNA.ORG_PN=AAC_ISO"; - } - else if (string.Equals(extension, ".wma", StringComparison.OrdinalIgnoreCase)) - { - contentFeatures = "DLNA.ORG_PN=WMABASE"; - } - else if (string.Equals(extension, ".avi", StringComparison.OrdinalIgnoreCase)) - { - contentFeatures = "DLNA.ORG_PN=AVI"; - } - else if (string.Equals(extension, ".mp4", StringComparison.OrdinalIgnoreCase)) - { - contentFeatures = "DLNA.ORG_PN=MPEG4_P2_SP_AAC"; - } - else if (string.Equals(extension, ".mpeg", StringComparison.OrdinalIgnoreCase)) - { - contentFeatures = "DLNA.ORG_PN=MPEG_PS_PAL"; - } - else if (string.Equals(extension, ".wmv", StringComparison.OrdinalIgnoreCase)) - { - contentFeatures = "DLNA.ORG_PN=WMVHIGH_BASE"; - } - else if (string.Equals(extension, ".asf", StringComparison.OrdinalIgnoreCase)) - { - // ?? - contentFeatures = "DLNA.ORG_PN=WMVHIGH_BASE"; - } - else if (string.Equals(extension, ".mkv", StringComparison.OrdinalIgnoreCase)) - { - // ?? - contentFeatures = ""; - } + //if (string.Equals(extension, ".mp3", StringComparison.OrdinalIgnoreCase)) + //{ + // contentFeatures = "DLNA.ORG_PN=MP3"; + //} + //else if (string.Equals(extension, ".aac", StringComparison.OrdinalIgnoreCase)) + //{ + // contentFeatures = "DLNA.ORG_PN=AAC_ISO"; + //} + //else if (string.Equals(extension, ".wma", StringComparison.OrdinalIgnoreCase)) + //{ + // contentFeatures = "DLNA.ORG_PN=WMABASE"; + //} + //else if (string.Equals(extension, ".avi", StringComparison.OrdinalIgnoreCase)) + //{ + // contentFeatures = "DLNA.ORG_PN=AVI"; + //} + //else if (string.Equals(extension, ".mp4", StringComparison.OrdinalIgnoreCase)) + //{ + // contentFeatures = "DLNA.ORG_PN=MPEG4_P2_SP_AAC"; + //} + //else if (string.Equals(extension, ".mpeg", StringComparison.OrdinalIgnoreCase)) + //{ + // contentFeatures = "DLNA.ORG_PN=MPEG_PS_PAL"; + //} + //else if (string.Equals(extension, ".wmv", StringComparison.OrdinalIgnoreCase)) + //{ + // contentFeatures = "DLNA.ORG_PN=WMVHIGH_BASE"; + //} + //else if (string.Equals(extension, ".asf", StringComparison.OrdinalIgnoreCase)) + //{ + // // ?? + // contentFeatures = "DLNA.ORG_PN=WMVHIGH_BASE"; + //} + //else if (string.Equals(extension, ".mkv", StringComparison.OrdinalIgnoreCase)) + //{ + // // ?? + // contentFeatures = ""; + //} if (!string.IsNullOrEmpty(contentFeatures)) { @@ -206,10 +206,10 @@ namespace MediaBrowser.Api.Playback.Progressive var outputPath = GetOutputFilePath(state); var outputPathExists = File.Exists(outputPath); - //var isStatic = request.Static || - // (outputPathExists && !ApiEntryPoint.Instance.HasActiveTranscodingJob(outputPath, TranscodingJobType.Progressive)); + var isStatic = request.Static || + (outputPathExists && !ApiEntryPoint.Instance.HasActiveTranscodingJob(outputPath, TranscodingJobType.Progressive)); - //AddDlnaHeaders(state, responseHeaders, isStatic); + AddDlnaHeaders(state, responseHeaders, isStatic); if (request.Static) { diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index b36005c1aa..95bde2d283 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -58,7 +58,7 @@ namespace MediaBrowser.Api } [Route("/Shows/{Id}/Episodes", "GET")] - [Api(Description = "Finds tv shows similar to a given one.")] + [Api(Description = "Gets episodes for a tv season")] public class GetEpisodes : IReturn, IHasItemFields { /// @@ -85,6 +85,34 @@ namespace MediaBrowser.Api public string ExcludeLocationTypes { get; set; } } + [Route("/Shows/{Id}/Seasons", "GET")] + [Api(Description = "Gets seasons for a tv series")] + public class GetSeasons : IReturn, IHasItemFields + { + /// + /// Gets or sets the user id. + /// + /// The user id. + [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] + public Guid UserId { get; set; } + + /// + /// Fields to return within the items, in addition to basic information + /// + /// The fields. + [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, OverviewHtml, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] + public string Fields { get; set; } + + [ApiMember(Name = "Id", Description = "The series id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] + public Guid Id { get; set; } + + [ApiMember(Name = "ExcludeLocationTypes", Description = "Optional. If specified, results will be filtered based on LocationType. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] + public string ExcludeLocationTypes { get; set; } + + [ApiMember(Name = "IsSpecialSeason", Description = "Optional. Filter by special season.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] + public bool? IsSpecialSeason { get; set; } + } + /// /// Class TvShowsService /// @@ -314,6 +342,64 @@ namespace MediaBrowser.Api return items; } + public object Get(GetSeasons request) + { + var user = _userManager.GetUserById(request.UserId); + + var series = _libraryManager.GetItemById(request.Id) as Series; + + var fields = request.GetItemFields().ToList(); + + var seasons = series.GetChildren(user, true) + .OfType(); + + var sortOrder = ItemSortBy.SortName; + + if (request.IsSpecialSeason.HasValue) + { + var val = request.IsSpecialSeason.Value; + + 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); + } + } + + // ExcludeLocationTypes + if (!string.IsNullOrEmpty(request.ExcludeLocationTypes)) + { + var vals = request.ExcludeLocationTypes.Split(','); + seasons = seasons.Where(f => !vals.Contains(f.LocationType.ToString(), StringComparer.OrdinalIgnoreCase)); + } + + seasons = _libraryManager.Sort(seasons, user, new[] { sortOrder }, SortOrder.Ascending) + .Cast(); + + var returnItems = seasons.Select(i => _dtoService.GetBaseItemDto(i, fields, user)) + .ToArray(); + + return new ItemsResult + { + TotalRecordCount = returnItems.Length, + Items = returnItems + }; + } + public object Get(GetEpisodes request) { var user = _userManager.GetUserById(request.UserId); @@ -351,7 +437,7 @@ namespace MediaBrowser.Api var vals = request.ExcludeLocationTypes.Split(','); episodes = episodes.Where(f => !vals.Contains(f.LocationType.ToString(), StringComparer.OrdinalIgnoreCase)); } - + episodes = _libraryManager.Sort(episodes, user, new[] { sortOrder }, SortOrder.Ascending) .Cast(); diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index 97a09b7b55..218c9fa5b6 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -1,9 +1,9 @@ -using System.Linq; -using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Localization; using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Runtime.Serialization; namespace MediaBrowser.Controller.Entities.TV @@ -172,5 +172,11 @@ namespace MediaBrowser.Controller.Entities.TV { get { return LocationType == Model.Entities.LocationType.Virtual && Children.OfType().All(i => i.IsVirtualUnaired || i.IsMissingEpisode); } } + + [IgnoreDataMember] + public bool IsSpecialSeason + { + get { return (IndexNumber ?? -1) == 0; } + } } } diff --git a/MediaBrowser.Model/ApiClient/IApiClient.cs b/MediaBrowser.Model/ApiClient/IApiClient.cs index ad82966048..16b3543ebd 100644 --- a/MediaBrowser.Model/ApiClient/IApiClient.cs +++ b/MediaBrowser.Model/ApiClient/IApiClient.cs @@ -231,6 +231,13 @@ namespace MediaBrowser.Model.ApiClient /// The query. /// Task{ItemsResult}. Task GetEpisodesAsync(EpisodeQuery query); + + /// + /// Gets the seasons asynchronous. + /// + /// The query. + /// Task{ItemsResult}. + Task GetSeasonsAsync(SeasonQuery query); /// /// Queries for items diff --git a/MediaBrowser.Model/Querying/EpisodeQuery.cs b/MediaBrowser.Model/Querying/EpisodeQuery.cs index ab9b246c8c..406ac9844f 100644 --- a/MediaBrowser.Model/Querying/EpisodeQuery.cs +++ b/MediaBrowser.Model/Querying/EpisodeQuery.cs @@ -20,4 +20,23 @@ namespace MediaBrowser.Model.Querying ExcludeLocationTypes = new LocationType[] { }; } } + + public class SeasonQuery + { + public string UserId { get; set; } + + public string SeriesId { get; set; } + + public LocationType[] ExcludeLocationTypes { get; set; } + + public ItemFields[] Fields { get; set; } + + public bool? IsSpecialSeason { get; set; } + + public SeasonQuery() + { + Fields = new ItemFields[] { }; + ExcludeLocationTypes = new LocationType[] { }; + } + } } diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 83e0246c53..c7298b4622 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -135,6 +135,7 @@ + diff --git a/MediaBrowser.Providers/UserRootFolderNameProvider.cs b/MediaBrowser.Providers/UserRootFolderNameProvider.cs new file mode 100644 index 0000000000..5130202139 --- /dev/null +++ b/MediaBrowser.Providers/UserRootFolderNameProvider.cs @@ -0,0 +1,42 @@ +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Logging; +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Providers +{ + public class UserRootFolderNameProvider : BaseMetadataProvider + { + public UserRootFolderNameProvider(ILogManager logManager, IServerConfigurationManager configurationManager) + : base(logManager, configurationManager) + { + } + + public override bool Supports(BaseItem item) + { + return item is UserRootFolder; + } + + public override Task FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) + { + var parentName = Path.GetFileNameWithoutExtension(item.Path); + + if (string.Equals(parentName, "default", StringComparison.OrdinalIgnoreCase)) + { + item.Name = "Media Library"; + } + + SetLastRefreshed(item, DateTime.UtcNow); + return TrueTaskResult; + } + + public override MetadataProviderPriority Priority + { + get { return MetadataProviderPriority.First; } + } + } +} diff --git a/MediaBrowser.WebDashboard/ApiClient.js b/MediaBrowser.WebDashboard/ApiClient.js index 69f3f020cf..36476511ec 100644 --- a/MediaBrowser.WebDashboard/ApiClient.js +++ b/MediaBrowser.WebDashboard/ApiClient.js @@ -575,6 +575,17 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi }); }; + self.getSeasons = function (itemId, options) { + + var url = self.getUrl("Shows/" + itemId + "/Seasons", options); + + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); + }; + self.getSimilarMovies = function (itemId, options) { var url = self.getUrl("Movies/" + itemId + "/Similar", options); diff --git a/MediaBrowser.WebDashboard/packages.config b/MediaBrowser.WebDashboard/packages.config index 35511052f4..25938a358a 100644 --- a/MediaBrowser.WebDashboard/packages.config +++ b/MediaBrowser.WebDashboard/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file -- cgit v1.2.3 From 235b838fbe262f3f41cd64c8506d067c9ef9253e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 29 Nov 2013 11:58:24 -0500 Subject: support deleting and canceling live tv recordings and timers --- MediaBrowser.Api/LiveTv/LiveTvService.cs | 31 +++++++++++ .../ScheduledTasks/ScheduledTaskService.cs | 32 +++++++++-- .../ScheduledTasksWebSocketListener.cs | 6 +- MediaBrowser.Api/TvShowsService.cs | 64 +++++++++++++++++----- .../BaseApplicationHost.cs | 2 +- .../HttpClientManager/HttpClientManager.cs | 3 +- .../ScheduledTasks/Tasks/DeleteCacheFileTask.cs | 1 - .../ScheduledTasks/IScheduledTask.cs | 5 ++ .../ScheduledTasks/ScheduledTaskHelpers.cs | 12 +++- MediaBrowser.Controller/LiveTv/ILiveTvManager.cs | 14 +++++ MediaBrowser.Controller/LiveTv/ILiveTvService.cs | 8 --- MediaBrowser.Controller/LiveTv/RecordingInfo.cs | 6 ++ MediaBrowser.Controller/LiveTv/TimerInfo.cs | 18 ++---- MediaBrowser.Model/LiveTv/RecordingStatus.cs | 7 +++ MediaBrowser.Model/LiveTv/TimerInfoDto.cs | 24 +++----- MediaBrowser.Model/Querying/EpisodeQuery.cs | 13 +++-- MediaBrowser.Model/Tasks/TaskInfo.cs | 6 ++ .../LiveTv/LiveTvManager.cs | 57 ++++++++++++++++++- .../LiveTv/RefreshChannelsScheduledTask.cs | 9 ++- .../Native/HttpClientFactory.cs | 7 ++- MediaBrowser.WebDashboard/ApiClient.js | 20 ++++++- .../MediaBrowser.WebDashboard.csproj | 4 +- MediaBrowser.WebDashboard/packages.config | 2 +- Nuget/MediaBrowser.Common.Internal.nuspec | 4 +- Nuget/MediaBrowser.Common.nuspec | 2 +- Nuget/MediaBrowser.Server.Core.nuspec | 4 +- 26 files changed, 280 insertions(+), 81 deletions(-) (limited to 'MediaBrowser.Api/TvShowsService.cs') diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index 2961c920f8..4cd75afca5 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -1,4 +1,5 @@ using System.Threading; +using System.Threading.Tasks; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Querying; @@ -82,6 +83,22 @@ namespace MediaBrowser.Api.LiveTv public string UserId { get; set; } } + [Route("/LiveTv/Recordings/{Id}", "DELETE")] + [Api(Description = "Deletes a live tv recording")] + public class DeleteRecording : IReturnVoid + { + [ApiMember(Name = "Id", Description = "Recording Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string Id { get; set; } + } + + [Route("/LiveTv/Timers/{Id}", "DELETE")] + [Api(Description = "Cancels a live tv timer")] + public class CancelTimer : IReturnVoid + { + [ApiMember(Name = "Id", Description = "Timer Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string Id { get; set; } + } + public class LiveTvService : BaseApiService { private readonly ILiveTvManager _liveTvManager; @@ -176,5 +193,19 @@ namespace MediaBrowser.Api.LiveTv return ToOptimizedResult(result); } + + public void Delete(DeleteRecording request) + { + var task = _liveTvManager.DeleteRecording(request.Id); + + Task.WaitAll(task); + } + + public void Delete(CancelTimer request) + { + var task = _liveTvManager.CancelTimer(request.Id); + + Task.WaitAll(task); + } } } \ No newline at end of file diff --git a/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs b/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs index 2674529e51..d17a38e073 100644 --- a/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs +++ b/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs @@ -31,7 +31,8 @@ namespace MediaBrowser.Api.ScheduledTasks [Api(Description = "Gets scheduled tasks")] public class GetScheduledTasks : IReturn> { - + [ApiMember(Name = "IsHidden", Description = "Optional filter tasks that are hidden, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] + public bool? IsHidden { get; set; } } /// @@ -112,10 +113,33 @@ namespace MediaBrowser.Api.ScheduledTasks /// IEnumerable{TaskInfo}. public object Get(GetScheduledTasks request) { - var result = TaskManager.ScheduledTasks.OrderBy(i => i.Name) - .Select(ScheduledTaskHelpers.GetTaskInfo).ToList(); + IEnumerable result = TaskManager.ScheduledTasks + .OrderBy(i => i.Name); - return ToOptimizedResult(result); + if (request.IsHidden.HasValue) + { + var val = request.IsHidden.Value; + + result = result.Where(i => + { + var isHidden = false; + + var configurableTask = i.ScheduledTask as IConfigurableScheduledTask; + + if (configurableTask != null) + { + isHidden = configurableTask.IsHidden; + } + + return isHidden == val; + }); + } + + var infos = result + .Select(ScheduledTaskHelpers.GetTaskInfo) + .ToList(); + + return ToOptimizedResult(infos); } /// diff --git a/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs b/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs index 20634301a3..c143635bfa 100644 --- a/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs +++ b/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs @@ -46,8 +46,10 @@ namespace MediaBrowser.Api.ScheduledTasks /// Task{IEnumerable{TaskInfo}}. protected override Task> GetDataToSend(object state) { - return Task.FromResult(TaskManager.ScheduledTasks.OrderBy(i => i.Name) - .Select(ScheduledTaskHelpers.GetTaskInfo)); + return Task.FromResult(TaskManager.ScheduledTasks + .OrderBy(i => i.Name) + .Select(ScheduledTaskHelpers.GetTaskInfo) + .Where(i => !i.IsHidden)); } } } diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index 95bde2d283..23b8efa7bd 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -81,8 +81,11 @@ namespace MediaBrowser.Api [ApiMember(Name = "Season", Description = "Optional filter by season number.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] public int? Season { get; set; } - [ApiMember(Name = "ExcludeLocationTypes", Description = "Optional. If specified, results will be filtered based on LocationType. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] - public string ExcludeLocationTypes { get; set; } + [ApiMember(Name = "IsMissing", Description = "Optional filter by items that are missing episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] + public bool? IsMissing { get; set; } + + [ApiMember(Name = "IsVirtualUnaired", Description = "Optional filter by items that are virtual unaired episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] + public bool? IsVirtualUnaired { get; set; } } [Route("/Shows/{Id}/Seasons", "GET")] @@ -106,11 +109,14 @@ namespace MediaBrowser.Api [ApiMember(Name = "Id", Description = "The series id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] public Guid Id { get; set; } - [ApiMember(Name = "ExcludeLocationTypes", Description = "Optional. If specified, results will be filtered based on LocationType. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] - public string ExcludeLocationTypes { get; set; } - [ApiMember(Name = "IsSpecialSeason", Description = "Optional. Filter by special season.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] public bool? IsSpecialSeason { get; set; } + + [ApiMember(Name = "IsMissing", Description = "Optional filter by items that are missing episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] + public bool? IsMissing { get; set; } + + [ApiMember(Name = "IsVirtualUnaired", Description = "Optional filter by items that are virtual unaired episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] + public bool? IsVirtualUnaired { get; set; } } /// @@ -380,12 +386,7 @@ namespace MediaBrowser.Api } } - // ExcludeLocationTypes - if (!string.IsNullOrEmpty(request.ExcludeLocationTypes)) - { - var vals = request.ExcludeLocationTypes.Split(','); - seasons = seasons.Where(f => !vals.Contains(f.LocationType.ToString(), StringComparer.OrdinalIgnoreCase)); - } + seasons = FilterVirtualSeasons(request, seasons); seasons = _libraryManager.Sort(seasons, user, new[] { sortOrder }, SortOrder.Ascending) .Cast(); @@ -400,6 +401,34 @@ namespace MediaBrowser.Api }; } + private IEnumerable FilterVirtualSeasons(GetSeasons request, IEnumerable items) + { + if (request.IsMissing.HasValue && request.IsVirtualUnaired.HasValue) + { + var isMissing = request.IsMissing.Value; + var isVirtualUnaired = request.IsVirtualUnaired.Value; + + if (!isMissing && !isVirtualUnaired) + { + return items.Where(i => !i.IsMissingOrVirtualUnaired); + } + } + + if (request.IsMissing.HasValue) + { + var val = request.IsMissing.Value; + items = items.Where(i => i.IsMissingSeason == val); + } + + if (request.IsVirtualUnaired.HasValue) + { + var val = request.IsVirtualUnaired.Value; + items = items.Where(i => i.IsVirtualUnaired == val); + } + + return items; + } + public object Get(GetEpisodes request) { var user = _userManager.GetUserById(request.UserId); @@ -431,11 +460,16 @@ namespace MediaBrowser.Api episodes = episodes.Where(i => !i.IsVirtualUnaired); } - // ExcludeLocationTypes - if (!string.IsNullOrEmpty(request.ExcludeLocationTypes)) + if (request.IsMissing.HasValue) + { + var val = request.IsMissing.Value; + episodes = episodes.Where(i => i.IsMissingEpisode == val); + } + + if (request.IsVirtualUnaired.HasValue) { - var vals = request.ExcludeLocationTypes.Split(','); - episodes = episodes.Where(f => !vals.Contains(f.LocationType.ToString(), StringComparer.OrdinalIgnoreCase)); + var val = request.IsVirtualUnaired.Value; + episodes = episodes.Where(i => i.IsVirtualUnaired == val); } episodes = _libraryManager.Sort(episodes, user, new[] { sortOrder }, SortOrder.Ascending) diff --git a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs index ee22b7baa2..f1d8c94e55 100644 --- a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs +++ b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs @@ -218,7 +218,7 @@ namespace MediaBrowser.Common.Implementations try { // Increase the max http request limit - ServicePointManager.DefaultConnectionLimit = Math.Max(48, ServicePointManager.DefaultConnectionLimit); + ServicePointManager.DefaultConnectionLimit = Math.Max(96, ServicePointManager.DefaultConnectionLimit); } catch (Exception ex) { diff --git a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs index 0d6ba5c1da..181c83fd3a 100644 --- a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs +++ b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.Configuration; +using System.Reflection; +using MediaBrowser.Common.Configuration; using MediaBrowser.Common.IO; using MediaBrowser.Common.Net; using MediaBrowser.Model.Logging; diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs index e04cadfc5a..6d886bc696 100644 --- a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs +++ b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs @@ -29,7 +29,6 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks /// /// Initializes a new instance of the class. /// - /// The app paths. public DeleteCacheFileTask(IApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem) { ApplicationPaths = appPaths; diff --git a/MediaBrowser.Common/ScheduledTasks/IScheduledTask.cs b/MediaBrowser.Common/ScheduledTasks/IScheduledTask.cs index 351e96c7d5..2ee4fb4b50 100644 --- a/MediaBrowser.Common/ScheduledTasks/IScheduledTask.cs +++ b/MediaBrowser.Common/ScheduledTasks/IScheduledTask.cs @@ -42,4 +42,9 @@ namespace MediaBrowser.Common.ScheduledTasks /// IEnumerable{BaseTaskTrigger}. IEnumerable GetDefaultTriggers(); } + + public interface IConfigurableScheduledTask + { + bool IsHidden { get; } + } } diff --git a/MediaBrowser.Common/ScheduledTasks/ScheduledTaskHelpers.cs b/MediaBrowser.Common/ScheduledTasks/ScheduledTaskHelpers.cs index f316509869..39148166bc 100644 --- a/MediaBrowser.Common/ScheduledTasks/ScheduledTaskHelpers.cs +++ b/MediaBrowser.Common/ScheduledTasks/ScheduledTaskHelpers.cs @@ -16,6 +16,15 @@ namespace MediaBrowser.Common.ScheduledTasks /// TaskInfo. public static TaskInfo GetTaskInfo(IScheduledTaskWorker task) { + var isHidden = false; + + var configurableTask = task.ScheduledTask as IConfigurableScheduledTask; + + if (configurableTask != null) + { + isHidden = configurableTask.IsHidden; + } + return new TaskInfo { Name = task.Name, @@ -25,7 +34,8 @@ namespace MediaBrowser.Common.ScheduledTasks LastExecutionResult = task.LastExecutionResult, Triggers = task.Triggers.Select(GetTriggerInfo).ToList(), Description = task.Description, - Category = task.Category + Category = task.Category, + IsHidden = isHidden }; } diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs index 7938c38ec9..d5b9cea270 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs @@ -24,6 +24,20 @@ namespace MediaBrowser.Controller.LiveTv /// Task. Task ScheduleRecording(string programId); + /// + /// Deletes the recording. + /// + /// The identifier. + /// Task. + Task DeleteRecording(string id); + + /// + /// Cancels the timer. + /// + /// The identifier. + /// Task. + Task CancelTimer(string id); + /// /// Adds the parts. /// diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvService.cs b/MediaBrowser.Controller/LiveTv/ILiveTvService.cs index e903ad5ec6..9bc032af35 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvService.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvService.cs @@ -47,14 +47,6 @@ namespace MediaBrowser.Controller.LiveTv /// Task. Task CreateTimerAsync(TimerInfo info, CancellationToken cancellationToken); - /// - /// Updates the timer asynchronous. - /// - /// The information. - /// The cancellation token. - /// Task. - Task UpdateTimerAsync(TimerInfo info, CancellationToken cancellationToken); - /// /// Gets the channel image asynchronous. /// diff --git a/MediaBrowser.Controller/LiveTv/RecordingInfo.cs b/MediaBrowser.Controller/LiveTv/RecordingInfo.cs index f0daac5f91..88d093f645 100644 --- a/MediaBrowser.Controller/LiveTv/RecordingInfo.cs +++ b/MediaBrowser.Controller/LiveTv/RecordingInfo.cs @@ -40,6 +40,12 @@ namespace MediaBrowser.Controller.LiveTv /// public DateTime EndDate { get; set; } + /// + /// Gets or sets the program identifier. + /// + /// The program identifier. + public string ProgramId { get; set; } + /// /// Gets or sets the status. /// diff --git a/MediaBrowser.Controller/LiveTv/TimerInfo.cs b/MediaBrowser.Controller/LiveTv/TimerInfo.cs index f0f936b526..7401dafec9 100644 --- a/MediaBrowser.Controller/LiveTv/TimerInfo.cs +++ b/MediaBrowser.Controller/LiveTv/TimerInfo.cs @@ -1,6 +1,5 @@ using MediaBrowser.Model.LiveTv; using System; -using System.Collections.Generic; namespace MediaBrowser.Controller.LiveTv { @@ -21,6 +20,12 @@ namespace MediaBrowser.Controller.LiveTv /// public string ChannelName { get; set; } + /// + /// Gets or sets the program identifier. + /// + /// The program identifier. + public string ProgramId { get; set; } + /// /// Name of the recording. /// @@ -52,16 +57,5 @@ namespace MediaBrowser.Controller.LiveTv /// /// true if this instance is recurring; otherwise, false. public bool IsRecurring { get; set; } - - /// - /// Gets or sets the recurring days. - /// - /// The recurring days. - public List RecurringDays { get; set; } - - public TimerInfo() - { - RecurringDays = new List(); - } } } diff --git a/MediaBrowser.Model/LiveTv/RecordingStatus.cs b/MediaBrowser.Model/LiveTv/RecordingStatus.cs index b8af8f6e22..7789773407 100644 --- a/MediaBrowser.Model/LiveTv/RecordingStatus.cs +++ b/MediaBrowser.Model/LiveTv/RecordingStatus.cs @@ -10,4 +10,11 @@ namespace MediaBrowser.Model.LiveTv Conflicted, Deleted } + + public enum RecurrenceType + { + Manual, + NewProgramEvents, + AllProgramEvents + } } diff --git a/MediaBrowser.Model/LiveTv/TimerInfoDto.cs b/MediaBrowser.Model/LiveTv/TimerInfoDto.cs index 6a8339031a..ddefce59e2 100644 --- a/MediaBrowser.Model/LiveTv/TimerInfoDto.cs +++ b/MediaBrowser.Model/LiveTv/TimerInfoDto.cs @@ -1,11 +1,10 @@ using System; -using System.Collections.Generic; namespace MediaBrowser.Model.LiveTv { public class TimerInfoDto { - /// + /// /// Id of the recording. /// public string Id { get; set; } @@ -15,7 +14,7 @@ namespace MediaBrowser.Model.LiveTv /// /// The external identifier. public string ExternalId { get; set; } - + /// /// ChannelId of the recording. /// @@ -26,6 +25,12 @@ namespace MediaBrowser.Model.LiveTv /// public string ChannelName { get; set; } + /// + /// Gets or sets the program identifier. + /// + /// The program identifier. + public string ProgramId { get; set; } + /// /// Name of the recording. /// @@ -57,16 +62,5 @@ namespace MediaBrowser.Model.LiveTv /// /// true if this instance is recurring; otherwise, false. public bool IsRecurring { get; set; } - - /// - /// Gets or sets the recurring days. - /// - /// The recurring days. - public List RecurringDays { get; set; } - - public TimerInfoDto() - { - RecurringDays = new List(); - } - } + } } diff --git a/MediaBrowser.Model/Querying/EpisodeQuery.cs b/MediaBrowser.Model/Querying/EpisodeQuery.cs index 406ac9844f..56c50da7f7 100644 --- a/MediaBrowser.Model/Querying/EpisodeQuery.cs +++ b/MediaBrowser.Model/Querying/EpisodeQuery.cs @@ -1,5 +1,4 @@ -using MediaBrowser.Model.Entities; - + namespace MediaBrowser.Model.Querying { public class EpisodeQuery @@ -8,7 +7,9 @@ namespace MediaBrowser.Model.Querying public string SeriesId { get; set; } - public LocationType[] ExcludeLocationTypes { get; set; } + public bool? IsMissing { get; set; } + + public bool? IsVirtualUnaired { get; set; } public int? SeasonNumber { get; set; } @@ -17,7 +18,6 @@ namespace MediaBrowser.Model.Querying public EpisodeQuery() { Fields = new ItemFields[] { }; - ExcludeLocationTypes = new LocationType[] { }; } } @@ -27,7 +27,9 @@ namespace MediaBrowser.Model.Querying public string SeriesId { get; set; } - public LocationType[] ExcludeLocationTypes { get; set; } + public bool? IsMissing { get; set; } + + public bool? IsVirtualUnaired { get; set; } public ItemFields[] Fields { get; set; } @@ -36,7 +38,6 @@ namespace MediaBrowser.Model.Querying public SeasonQuery() { Fields = new ItemFields[] { }; - ExcludeLocationTypes = new LocationType[] { }; } } } diff --git a/MediaBrowser.Model/Tasks/TaskInfo.cs b/MediaBrowser.Model/Tasks/TaskInfo.cs index dee4fea7fc..a7d500303d 100644 --- a/MediaBrowser.Model/Tasks/TaskInfo.cs +++ b/MediaBrowser.Model/Tasks/TaskInfo.cs @@ -56,6 +56,12 @@ namespace MediaBrowser.Model.Tasks /// The category. public string Category { get; set; } + /// + /// Gets or sets a value indicating whether this instance is hidden. + /// + /// true if this instance is hidden; otherwise, false. + public bool IsHidden { get; set; } + /// /// Initializes a new instance of the class. /// diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 00ac83f15c..4d3d877889 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -397,6 +397,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv Status = info.Status }; + if (!string.IsNullOrEmpty(info.ProgramId)) + { + dto.ProgramId = GetInternalProgramIdId(service.Name, info.ProgramId).ToString("N"); + } + return dto; } @@ -503,13 +508,61 @@ namespace MediaBrowser.Server.Implementations.LiveTv ExternalId = info.Id, ChannelId = GetInternalChannelId(service.Name, info.ChannelId).ToString("N"), Status = info.Status, - IsRecurring = info.IsRecurring, - RecurringDays = info.RecurringDays + IsRecurring = info.IsRecurring }; + if (!string.IsNullOrEmpty(info.ProgramId)) + { + dto.ProgramId = GetInternalProgramIdId(service.Name, info.ProgramId).ToString("N"); + } + return dto; } + public async Task DeleteRecording(string recordingId) + { + var recordings = await GetRecordings(new RecordingQuery + { + + }, CancellationToken.None).ConfigureAwait(false); + + var recording = recordings.Items + .FirstOrDefault(i => string.Equals(recordingId, i.Id, StringComparison.OrdinalIgnoreCase)); + + if (recording == null) + { + throw new ResourceNotFoundException(string.Format("Recording with Id {0} not found", recordingId)); + } + + var channel = GetChannel(recording.ChannelId); + var service = GetServices(channel.ServiceName, null) + .First(); + + await service.DeleteRecordingAsync(recording.ExternalId, CancellationToken.None).ConfigureAwait(false); + } + + public async Task CancelTimer(string id) + { + var timers = await GetTimers(new TimerQuery + { + + }, CancellationToken.None).ConfigureAwait(false); + + var timer = timers.Items + .FirstOrDefault(i => string.Equals(id, i.Id, StringComparison.OrdinalIgnoreCase)); + + if (timer == null) + { + throw new ResourceNotFoundException(string.Format("Timer with Id {0} not found", id)); + } + + var channel = GetChannel(timer.ChannelId); + + var service = GetServices(channel.ServiceName, null) + .First(); + + await service.CancelTimerAsync(timer.ExternalId, CancellationToken.None).ConfigureAwait(false); + } } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs b/MediaBrowser.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs index c3803d9bbc..00bf9e55ba 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.LiveTv { - class RefreshChannelsScheduledTask : IScheduledTask + class RefreshChannelsScheduledTask : IScheduledTask, IConfigurableScheduledTask { private readonly ILiveTvManager _liveTvManager; @@ -33,7 +33,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv public Task Execute(System.Threading.CancellationToken cancellationToken, IProgress progress) { - var manager = (LiveTvManager) _liveTvManager; + var manager = (LiveTvManager)_liveTvManager; return manager.RefreshChannels(progress, cancellationToken); } @@ -50,5 +50,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv new IntervalTrigger{ Interval = TimeSpan.FromHours(2)} }; } + + public bool IsHidden + { + get { return _liveTvManager.Services.Count == 0; } + } } } diff --git a/MediaBrowser.ServerApplication/Native/HttpClientFactory.cs b/MediaBrowser.ServerApplication/Native/HttpClientFactory.cs index 57f00ba03b..368c60254b 100644 --- a/MediaBrowser.ServerApplication/Native/HttpClientFactory.cs +++ b/MediaBrowser.ServerApplication/Native/HttpClientFactory.cs @@ -17,14 +17,19 @@ namespace MediaBrowser.ServerApplication.Native /// HttpClient. public static HttpClient GetHttpClient(bool enableHttpCompression) { - return new HttpClient(new WebRequestHandler + var client = new HttpClient(new WebRequestHandler { CachePolicy = new RequestCachePolicy(RequestCacheLevel.Revalidate), AutomaticDecompression = enableHttpCompression ? DecompressionMethods.Deflate : DecompressionMethods.None + }) { Timeout = TimeSpan.FromSeconds(20) }; + + client.DefaultRequestHeaders.Add("Connection", "Keep-Alive"); + + return client; } } } diff --git a/MediaBrowser.WebDashboard/ApiClient.js b/MediaBrowser.WebDashboard/ApiClient.js index 36476511ec..de96c4de94 100644 --- a/MediaBrowser.WebDashboard/ApiClient.js +++ b/MediaBrowser.WebDashboard/ApiClient.js @@ -506,6 +506,20 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi }); }; + self.createLiveTvTimer = function (options) { + + if (!options) { + throw new Error("null options"); + } + + var url = self.getUrl("LiveTv/Timers", options); + + return self.ajax({ + type: "POST", + url: url + }); + }; + /** * Gets the current server status */ @@ -1019,9 +1033,11 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi /** * Gets the server's scheduled tasks */ - self.getScheduledTasks = function () { + self.getScheduledTasks = function (options) { - var url = self.getUrl("ScheduledTasks"); + options = options || {}; + + var url = self.getUrl("ScheduledTasks", options); return self.ajax({ type: "GET", diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 5585e0db5e..4aca619aa3 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -284,10 +284,10 @@ PreserveNewest - + PreserveNewest - + PreserveNewest diff --git a/MediaBrowser.WebDashboard/packages.config b/MediaBrowser.WebDashboard/packages.config index 25938a358a..a839ece186 100644 --- a/MediaBrowser.WebDashboard/packages.config +++ b/MediaBrowser.WebDashboard/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index 51bdf43d66..77765ddc62 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common.Internal - 3.0.252 + 3.0.253 MediaBrowser.Common.Internal Luke ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption. Copyright © Media Browser 2013 - + diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index 6ccfca542e..ac6b606cda 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.252 + 3.0.253 MediaBrowser.Common Media Browser Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index de9b90a461..a6c1bee112 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.252 + 3.0.253 Media Browser.Server.Core Media Browser Team ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains core components required to build plugins for Media Browser Server. Copyright © Media Browser 2013 - + -- cgit v1.2.3 From 58f1a314b5ef3d13c2bc034f8a8949d9e88d1c20 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Nov 2013 13:32:39 -0500 Subject: update to service stack 3.0.70.0 --- MediaBrowser.Api/MediaBrowser.Api.csproj | 21 ++-- MediaBrowser.Api/TvShowsService.cs | 23 ++++- MediaBrowser.Api/packages.config | 4 +- .../HttpClientManager/HttpClientManager.cs | 112 ++++----------------- .../MediaBrowser.Common.Implementations.csproj | 7 +- .../Serialization/JsonSerializer.cs | 2 + .../packages.config | 2 +- MediaBrowser.Common/MediaBrowser.Common.csproj | 21 ++-- MediaBrowser.Common/packages.config | 4 +- MediaBrowser.Model/Querying/EpisodeQuery.cs | 2 + MediaBrowser.Model/System/SystemInfo.cs | 12 +++ .../MediaBrowser.Server.Implementations.csproj | 60 +++++------ .../packages.config | 10 +- .../swagger-ui/index.html | 2 +- MediaBrowser.ServerApplication/ApplicationHost.cs | 2 + .../MediaBrowser.ServerApplication.csproj | 20 ++-- MediaBrowser.ServerApplication/packages.config | 6 +- .../MediaBrowser.WebDashboard.csproj | 21 ++-- MediaBrowser.WebDashboard/packages.config | 4 +- Nuget/MediaBrowser.Common.Internal.nuspec | 4 +- Nuget/MediaBrowser.Common.nuspec | 2 +- Nuget/MediaBrowser.Server.Core.nuspec | 4 +- 22 files changed, 155 insertions(+), 190 deletions(-) (limited to 'MediaBrowser.Api/TvShowsService.cs') diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index a5720dfad1..706117fc26 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -38,6 +38,18 @@ Always + + False + ..\packages\ServiceStack.Common.3.9.70\lib\net35\ServiceStack.Common.dll + + + False + ..\packages\ServiceStack.Common.3.9.70\lib\net35\ServiceStack.Interfaces.dll + + + False + ..\packages\ServiceStack.Text.3.9.70\lib\net35\ServiceStack.Text.dll + @@ -47,15 +59,6 @@ ..\packages\morelinq.1.0.16006\lib\net35\MoreLinq.dll - - ..\packages\ServiceStack.Common.3.9.62\lib\net35\ServiceStack.Common.dll - - - ..\packages\ServiceStack.Common.3.9.62\lib\net35\ServiceStack.Interfaces.dll - - - ..\packages\ServiceStack.Text.3.9.62\lib\net35\ServiceStack.Text.dll - diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index 23b8efa7bd..9191bfc0c7 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -81,6 +81,9 @@ namespace MediaBrowser.Api [ApiMember(Name = "Season", Description = "Optional filter by season number.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] public int? Season { get; set; } + [ApiMember(Name = "SeasonId", Description = "Optional. Filter by season id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public string SeasonId { get; set; } + [ApiMember(Name = "IsMissing", Description = "Optional filter by items that are missing episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] public bool? IsMissing { get; set; } @@ -442,7 +445,25 @@ namespace MediaBrowser.Api var sortOrder = ItemSortBy.SortName; - if (request.Season.HasValue) + if (!string.IsNullOrEmpty(request.SeasonId)) + { + var season = _libraryManager.GetItemById(request.Id) as Season; + + if (season.IndexNumber.HasValue) + { + episodes = FilterEpisodesBySeason(episodes, season.IndexNumber.Value, true); + + sortOrder = ItemSortBy.AiredEpisodeOrder; + } + else + { + episodes = season.RecursiveChildren.OfType(); + + sortOrder = ItemSortBy.SortName; + } + } + + else if (request.Season.HasValue) { episodes = FilterEpisodesBySeason(episodes, request.Season.Value, true); diff --git a/MediaBrowser.Api/packages.config b/MediaBrowser.Api/packages.config index c9fec81005..e9a27e8ad8 100644 --- a/MediaBrowser.Api/packages.config +++ b/MediaBrowser.Api/packages.config @@ -1,6 +1,6 @@  - - + + \ No newline at end of file diff --git a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs index 8d80185add..8fccb7c2a9 100644 --- a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs +++ b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs @@ -27,7 +27,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager /// /// When one request to a host times out, we'll ban all other requests for this period of time, to prevent scans from stalling /// - private int TimeoutSeconds = 30; + private const int TimeoutSeconds = 30; /// /// The _logger @@ -42,16 +42,14 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager private readonly IFileSystem _fileSystem; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The app paths. /// The logger. - /// The get HTTP client handler. - /// - /// appPaths + /// The file system. + /// appPaths /// or - /// logger - /// + /// logger public HttpClientManager(IApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem) { if (appPaths == null) @@ -143,7 +141,6 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager /// Gets the response internal. /// /// The options. - /// The HTTP method. /// Task{HttpResponseInfo}. /// /// @@ -490,27 +487,19 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager } catch (OperationCanceledException ex) { - var exception = GetCancellationException(options.Url, options.CancellationToken, ex); - - throw exception; + throw GetTempFileException(ex, options, tempFile); } catch (HttpRequestException ex) { - _logger.ErrorException("Error getting response from " + options.Url, ex); - - throw new HttpException(ex.Message, ex); + throw GetTempFileException(ex, options, tempFile); } catch (WebException ex) { - _logger.ErrorException("Error getting response from " + options.Url, ex); - - throw new HttpException(ex.Message, ex); + throw GetTempFileException(ex, options, tempFile); } catch (Exception ex) { - _logger.ErrorException("Error getting response from " + options.Url, ex); - - throw; + throw GetTempFileException(ex, options, tempFile); } finally { @@ -521,65 +510,6 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager } } - /// - /// Gets the message. - /// - /// The options. - /// HttpResponseMessage. - private HttpRequestMessage GetHttpRequestMessage(HttpRequestOptions options) - { - var message = new HttpRequestMessage(HttpMethod.Get, options.Url); - - foreach (var pair in options.RequestHeaders.ToList()) - { - if (!message.Headers.TryAddWithoutValidation(pair.Key, pair.Value)) - { - _logger.Error("Unable to add request header {0} with value {1}", pair.Key, pair.Value); - } - } - - return message; - } - - /// - /// Gets the length of the content. - /// - /// The response. - /// System.Nullable{System.Int64}. - private long? GetContentLength(HttpResponseMessage response) - { - IEnumerable lengthValues = null; - - // Seeing some InvalidOperationException here under mono - try - { - response.Headers.TryGetValues("content-length", out lengthValues); - } - catch (InvalidOperationException ex) - { - _logger.ErrorException("Error accessing response.Headers.TryGetValues Content-Length", ex); - } - - if (lengthValues == null) - { - try - { - response.Content.Headers.TryGetValues("content-length", out lengthValues); - } - catch (InvalidOperationException ex) - { - _logger.ErrorException("Error accessing response.Content.Headers.TryGetValues Content-Length", ex); - } - } - - if (lengthValues == null) - { - return null; - } - - return long.Parse(string.Join(string.Empty, lengthValues.ToArray()), UsCulture); - } - private long? GetContentLength(HttpWebResponse response) { var length = response.ContentLength; @@ -616,16 +546,23 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager _logger.ErrorException("Error getting response from " + options.Url, ex); - var httpRequestException = ex as HttpRequestException; - // Cleanup DeleteTempFile(tempFile); + var httpRequestException = ex as HttpRequestException; + if (httpRequestException != null) { return new HttpException(ex.Message, ex); } + var webException = ex as WebException; + + if (webException != null) + { + return new HttpException(ex.Message, ex); + } + return ex; } @@ -711,19 +648,6 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager return exception; } - /// - /// Ensures the success status code. - /// - /// The response. - /// - private void EnsureSuccessStatusCode(HttpResponseMessage response) - { - if (!response.IsSuccessStatusCode) - { - throw new HttpException(response.ReasonPhrase) { StatusCode = response.StatusCode }; - } - } - private void EnsureSuccessStatusCode(HttpWebResponse response) { var statusCode = response.StatusCode; diff --git a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj index 9e48f3b3e9..9487855756 100644 --- a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj +++ b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj @@ -41,6 +41,10 @@ False ..\packages\NLog.2.1.0\lib\net45\NLog.dll + + False + ..\packages\ServiceStack.Text.3.9.70\lib\net35\ServiceStack.Text.dll + ..\packages\sharpcompress.0.10.1.3\lib\net40\SharpCompress.dll @@ -55,9 +59,6 @@ - - ..\packages\ServiceStack.Text.3.9.62\lib\net35\ServiceStack.Text.dll - diff --git a/MediaBrowser.Common.Implementations/Serialization/JsonSerializer.cs b/MediaBrowser.Common.Implementations/Serialization/JsonSerializer.cs index 4a6b9255c1..3ff9560405 100644 --- a/MediaBrowser.Common.Implementations/Serialization/JsonSerializer.cs +++ b/MediaBrowser.Common.Implementations/Serialization/JsonSerializer.cs @@ -169,6 +169,8 @@ namespace MediaBrowser.Common.Implementations.Serialization ServiceStack.Text.JsConfig.DateHandler = ServiceStack.Text.JsonDateHandler.ISO8601; ServiceStack.Text.JsConfig.ExcludeTypeInfo = true; ServiceStack.Text.JsConfig.IncludeNullValues = false; + ServiceStack.Text.JsConfig.AlwaysUseUtc = true; + ServiceStack.Text.JsConfig.AssumeUtc = true; } /// diff --git a/MediaBrowser.Common.Implementations/packages.config b/MediaBrowser.Common.Implementations/packages.config index f2fe488309..269ac0e561 100644 --- a/MediaBrowser.Common.Implementations/packages.config +++ b/MediaBrowser.Common.Implementations/packages.config @@ -1,7 +1,7 @@  - + \ No newline at end of file diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index f4d759a4d1..a9499dedda 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -35,18 +35,21 @@ 4 - - - - - ..\packages\ServiceStack.Common.3.9.62\lib\net35\ServiceStack.Common.dll + + False + ..\packages\ServiceStack.Common.3.9.70\lib\net35\ServiceStack.Common.dll - - ..\packages\ServiceStack.Common.3.9.62\lib\net35\ServiceStack.Interfaces.dll + + False + ..\packages\ServiceStack.Common.3.9.70\lib\net35\ServiceStack.Interfaces.dll - - ..\packages\ServiceStack.Text.3.9.62\lib\net35\ServiceStack.Text.dll + + False + ..\packages\ServiceStack.Text.3.9.70\lib\net35\ServiceStack.Text.dll + + + diff --git a/MediaBrowser.Common/packages.config b/MediaBrowser.Common/packages.config index 6969b43c54..7411e313cd 100644 --- a/MediaBrowser.Common/packages.config +++ b/MediaBrowser.Common/packages.config @@ -1,5 +1,5 @@  - - + + \ No newline at end of file diff --git a/MediaBrowser.Model/Querying/EpisodeQuery.cs b/MediaBrowser.Model/Querying/EpisodeQuery.cs index 56c50da7f7..589b46433a 100644 --- a/MediaBrowser.Model/Querying/EpisodeQuery.cs +++ b/MediaBrowser.Model/Querying/EpisodeQuery.cs @@ -5,6 +5,8 @@ namespace MediaBrowser.Model.Querying { public string UserId { get; set; } + public string SeasonId { get; set; } + public string SeriesId { get; set; } public bool? IsMissing { get; set; } diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs index 9491139dbc..6a17ad133a 100644 --- a/MediaBrowser.Model/System/SystemInfo.cs +++ b/MediaBrowser.Model/System/SystemInfo.cs @@ -92,6 +92,18 @@ namespace MediaBrowser.Model.System /// The program data path. public string ProgramDataPath { get; set; } + /// + /// Gets or sets the items by name path. + /// + /// The items by name path. + public string ItemsByNamePath { get; set; } + + /// + /// Gets or sets the log path. + /// + /// The log path. + public string LogPath { get; set; } + /// /// Gets or sets the HTTP server port number. /// diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index f5ade2516c..2d32811d33 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -41,8 +41,29 @@ False ..\packages\MediaBrowser.BdInfo.1.0.0.5\lib\net20\BDInfo.dll - - ..\packages\ServiceStack.OrmLite.Sqlite32.3.9.63\lib\net40\ServiceStack.OrmLite.SqliteNET.dll + + False + ..\packages\ServiceStack.3.9.70\lib\net35\ServiceStack.dll + + + False + ..\packages\ServiceStack.Api.Swagger.3.9.70\lib\net35\ServiceStack.Api.Swagger.dll + + + False + ..\packages\ServiceStack.Common.3.9.70\lib\net35\ServiceStack.Common.dll + + + False + ..\packages\ServiceStack.Common.3.9.70\lib\net35\ServiceStack.Interfaces.dll + + + False + ..\packages\ServiceStack.3.9.70\lib\net35\ServiceStack.ServiceInterface.dll + + + False + ..\packages\ServiceStack.Text.3.9.70\lib\net35\ServiceStack.Text.dll @@ -72,39 +93,12 @@ ..\packages\morelinq.1.0.16006\lib\net35\MoreLinq.dll - - ..\packages\ServiceStack.3.9.62\lib\net35\ServiceStack.dll - - - ..\packages\ServiceStack.Api.Swagger.3.9.59\lib\net35\ServiceStack.Api.Swagger.dll - - - ..\packages\ServiceStack.Common.3.9.62\lib\net35\ServiceStack.Common.dll - - - ..\packages\ServiceStack.Common.3.9.62\lib\net35\ServiceStack.Interfaces.dll - ..\packages\ServiceStack.OrmLite.SqlServer.3.9.43\lib\ServiceStack.OrmLite.SqlServer.dll ..\packages\ServiceStack.Redis.3.9.43\lib\net35\ServiceStack.Redis.dll - - ..\packages\ServiceStack.3.9.62\lib\net35\ServiceStack.ServiceInterface.dll - - - ..\packages\ServiceStack.Text.3.9.62\lib\net35\ServiceStack.Text.dll - - - ..\packages\ServiceStack.OrmLite.Sqlite.Mono.3.9.64\lib\net35\Mono.Data.Sqlite.dll - - - ..\packages\ServiceStack.OrmLite.Sqlite.Mono.3.9.64\lib\net35\ServiceStack.OrmLite.dll - - - ..\packages\ServiceStack.OrmLite.Sqlite.Mono.3.9.64\lib\net35\ServiceStack.OrmLite.Sqlite.dll - @@ -268,7 +262,6 @@ - PreserveNewest @@ -287,9 +280,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest @@ -323,6 +313,10 @@ PreserveNewest + + + PreserveNewest + diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index eeeedfe362..d5abe58caf 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -6,13 +6,11 @@ - - - - - + + + - + \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/swagger-ui/index.html b/MediaBrowser.Server.Implementations/swagger-ui/index.html index 0fcc069596..49f983a723 100644 --- a/MediaBrowser.Server.Implementations/swagger-ui/index.html +++ b/MediaBrowser.Server.Implementations/swagger-ui/index.html @@ -20,7 +20,7 @@ $(function () { window.swaggerUi = new SwaggerUi({ discoveryUrl: "../resources", - apiKey:"special-key", + apiKey: "special-key", dom_id:"swagger-ui-container", supportHeaderParams: false, supportedSubmitMethods: ['get', 'post', 'put'], diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index be865881af..d2d700839e 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -609,6 +609,8 @@ namespace MediaBrowser.ServerApplication CompletedInstallations = InstallationManager.CompletedInstallations.ToList(), Id = _systemId, ProgramDataPath = ApplicationPaths.ProgramDataPath, + LogPath = ApplicationPaths.LogDirectoryPath, + ItemsByNamePath = ApplicationPaths.ItemsByNamePath, MacAddress = GetMacAddress(), HttpServerPortNumber = ServerConfigurationManager.Configuration.HttpServerPortNumber, OperatingSystem = Environment.OSVersion.ToString(), diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index 795799ca3e..5f05bc7875 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -131,17 +131,17 @@ False ..\packages\MediaBrowser.IsoMounting.3.0.65\lib\net45\pfmclrapi.dll - + False - ..\packages\ServiceStack.3.9.62\lib\net35\ServiceStack.dll + ..\packages\ServiceStack.3.9.70\lib\net35\ServiceStack.dll - + False - ..\packages\ServiceStack.Common.3.9.62\lib\net35\ServiceStack.Common.dll + ..\packages\ServiceStack.Common.3.9.70\lib\net35\ServiceStack.Common.dll - + False - ..\packages\ServiceStack.Common.3.9.62\lib\net35\ServiceStack.Interfaces.dll + ..\packages\ServiceStack.Common.3.9.70\lib\net35\ServiceStack.Interfaces.dll ..\packages\ServiceStack.OrmLite.SqlServer.3.9.44\lib\ServiceStack.OrmLite.SqlServer.dll @@ -149,13 +149,13 @@ ..\packages\ServiceStack.Redis.3.9.44\lib\net35\ServiceStack.Redis.dll - + False - ..\packages\ServiceStack.3.9.62\lib\net35\ServiceStack.ServiceInterface.dll + ..\packages\ServiceStack.3.9.70\lib\net35\ServiceStack.ServiceInterface.dll - + False - ..\packages\ServiceStack.Text.3.9.62\lib\net35\ServiceStack.Text.dll + ..\packages\ServiceStack.Text.3.9.70\lib\net35\ServiceStack.Text.dll False diff --git a/MediaBrowser.ServerApplication/packages.config b/MediaBrowser.ServerApplication/packages.config index e01ca1f672..5d7c3265f3 100644 --- a/MediaBrowser.ServerApplication/packages.config +++ b/MediaBrowser.ServerApplication/packages.config @@ -3,10 +3,10 @@ - - + + - + \ No newline at end of file diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 73b281d9a4..d36413fc2b 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -37,21 +37,24 @@ Always + + False + ..\packages\ServiceStack.Common.3.9.70\lib\net35\ServiceStack.Common.dll + + + False + ..\packages\ServiceStack.Common.3.9.70\lib\net35\ServiceStack.Interfaces.dll + + + False + ..\packages\ServiceStack.Text.3.9.70\lib\net35\ServiceStack.Text.dll + - - ..\packages\ServiceStack.Common.3.9.62\lib\net35\ServiceStack.Common.dll - - - ..\packages\ServiceStack.Common.3.9.62\lib\net35\ServiceStack.Interfaces.dll - - - ..\packages\ServiceStack.Text.3.9.62\lib\net35\ServiceStack.Text.dll - diff --git a/MediaBrowser.WebDashboard/packages.config b/MediaBrowser.WebDashboard/packages.config index a839ece186..4fa4e5a9ec 100644 --- a/MediaBrowser.WebDashboard/packages.config +++ b/MediaBrowser.WebDashboard/packages.config @@ -1,6 +1,6 @@  - - + + \ No newline at end of file diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index 17311530fa..150b081dc4 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common.Internal - 3.0.254 + 3.0.255 MediaBrowser.Common.Internal Luke ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption. Copyright © Media Browser 2013 - + diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index e95a638ab8..c28fa7922b 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.254 + 3.0.255 MediaBrowser.Common Media Browser Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index 38bb37530e..32f1da5365 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.254 + 3.0.255 Media Browser.Server.Core Media Browser Team ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains core components required to build plugins for Media Browser Server. Copyright © Media Browser 2013 - + -- cgit v1.2.3 From 40959a816f49d040e16e0178d0e11d51282d98cc Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 3 Dec 2013 23:18:50 -0500 Subject: more support for episodes directly in a series folder --- MediaBrowser.Api/LiveTv/LiveTvService.cs | 36 ++++++++++++-- MediaBrowser.Api/TvShowsService.cs | 25 +++++++++- MediaBrowser.Api/UserLibrary/ItemsService.cs | 55 ++++++++++++---------- MediaBrowser.Controller/Entities/TV/Episode.cs | 36 ++++++++++++++ MediaBrowser.Controller/LiveTv/ILiveTvManager.cs | 16 +++++++ MediaBrowser.Controller/LiveTv/RecordingInfo.cs | 20 +++++++- MediaBrowser.Model/Dto/BaseItemDto.cs | 6 +++ MediaBrowser.Model/LiveTv/RecordingInfoDto.cs | 30 ++++++++++++ MediaBrowser.Model/LiveTv/TimerInfoDto.cs | 6 +++ MediaBrowser.Providers/TV/SeriesPostScanTask.cs | 1 - .../Dto/DtoService.cs | 6 +++ .../LiveTv/LiveTvManager.cs | 26 +++++++++- 12 files changed, 231 insertions(+), 32 deletions(-) (limited to 'MediaBrowser.Api/TvShowsService.cs') diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index 4cd75afca5..0e40db58cd 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -1,12 +1,12 @@ -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Controller.LiveTv; using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Querying; using ServiceStack.ServiceHost; using System; using System.Collections.Generic; using System.Linq; +using System.Threading; +using System.Threading.Tasks; namespace MediaBrowser.Api.LiveTv { @@ -58,6 +58,22 @@ namespace MediaBrowser.Api.LiveTv public string ChannelId { get; set; } } + [Route("/LiveTv/Recordings/{Id}", "GET")] + [Api(Description = "Gets a live tv recording")] + public class GetRecording : IReturn + { + [ApiMember(Name = "Id", Description = "Recording Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string Id { get; set; } + } + + [Route("/LiveTv/Timers/{Id}", "GET")] + [Api(Description = "Gets a live tv timer")] + public class GetTimer : IReturn + { + [ApiMember(Name = "Id", Description = "Timer Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string Id { get; set; } + } + [Route("/LiveTv/Timers", "GET")] [Api(Description = "Gets live tv timers")] public class GetTimers : IReturn> @@ -182,6 +198,20 @@ namespace MediaBrowser.Api.LiveTv return ToOptimizedResult(result); } + public object Get(GetRecording request) + { + var result = _liveTvManager.GetRecording(request.Id, CancellationToken.None).Result; + + return ToOptimizedResult(result); + } + + public object Get(GetTimer request) + { + var result = _liveTvManager.GetTimer(request.Id, CancellationToken.None).Result; + + return ToOptimizedResult(result); + } + public object Get(GetTimers request) { var result = _liveTvManager.GetTimers(new TimerQuery diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index 9191bfc0c7..68ebd60c54 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller.Dto; +using MediaBrowser.Api.UserLibrary; +using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; @@ -89,6 +90,9 @@ namespace MediaBrowser.Api [ApiMember(Name = "IsVirtualUnaired", Description = "Optional filter by items that are virtual unaired episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] public bool? IsVirtualUnaired { get; set; } + + [ApiMember(Name = "AdjacentTo", Description = "Optional. Return items that are siblings of a supplied item.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public string AdjacentTo { get; set; } } [Route("/Shows/{Id}/Seasons", "GET")] @@ -120,6 +124,9 @@ namespace MediaBrowser.Api [ApiMember(Name = "IsVirtualUnaired", Description = "Optional filter by items that are virtual unaired episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] public bool? IsVirtualUnaired { get; set; } + + [ApiMember(Name = "AdjacentTo", Description = "Optional. Return items that are siblings of a supplied item.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public string AdjacentTo { get; set; } } /// @@ -394,6 +401,13 @@ namespace MediaBrowser.Api seasons = _libraryManager.Sort(seasons, user, new[] { sortOrder }, SortOrder.Ascending) .Cast(); + // This must be the last filter + if (!string.IsNullOrEmpty(request.AdjacentTo)) + { + seasons = ItemsService.FilterForAdjacency(seasons, request.AdjacentTo) + .Cast(); + } + var returnItems = seasons.Select(i => _dtoService.GetBaseItemDto(i, fields, user)) .ToArray(); @@ -447,7 +461,7 @@ namespace MediaBrowser.Api if (!string.IsNullOrEmpty(request.SeasonId)) { - var season = _libraryManager.GetItemById(request.Id) as Season; + var season = _libraryManager.GetItemById(new Guid(request.SeasonId)) as Season; if (season.IndexNumber.HasValue) { @@ -496,6 +510,13 @@ namespace MediaBrowser.Api episodes = _libraryManager.Sort(episodes, user, new[] { sortOrder }, SortOrder.Ascending) .Cast(); + // This must be the last filter + if (!string.IsNullOrEmpty(request.AdjacentTo)) + { + episodes = ItemsService.FilterForAdjacency(episodes, request.AdjacentTo) + .Cast(); + } + var returnItems = episodes.Select(i => _dtoService.GetBaseItemDto(i, fields, user)) .ToArray(); diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index 0e40ef3957..3a7ea5ddd6 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -310,6 +310,12 @@ namespace MediaBrowser.Api.UserLibrary items = ApplySortOrder(request, items, user, _libraryManager); + // This must be the last filter + if (!string.IsNullOrEmpty(request.AdjacentTo)) + { + items = FilterForAdjacency(items, request.AdjacentTo); + } + var itemsArray = items.ToList(); var pagedItems = ApplyPaging(request, itemsArray); @@ -666,30 +672,6 @@ namespace MediaBrowser.Api.UserLibrary }); } - if (!string.IsNullOrEmpty(request.AdjacentTo)) - { - var item = _dtoService.GetItemByDtoId(request.AdjacentTo); - - var allSiblings = item.Parent.GetChildren(user, true).OrderBy(i => i.SortName).ToList(); - - var index = allSiblings.IndexOf(item); - - var previousId = Guid.Empty; - var nextId = Guid.Empty; - - if (index > 0) - { - previousId = allSiblings[index - 1].Id; - } - - if (index < allSiblings.Count - 1) - { - nextId = allSiblings[index + 1].Id; - } - - items = items.Where(i => i.Id == previousId || i.Id == nextId); - } - // Min index number if (request.MinIndexNumber.HasValue) { @@ -1144,6 +1126,31 @@ namespace MediaBrowser.Api.UserLibrary return false; } + internal static IEnumerable FilterForAdjacency(IEnumerable items, string adjacentToId) + { + var list = items.ToList(); + + var adjacentToIdGuid = new Guid(adjacentToId); + var adjacentToItem = list.FirstOrDefault(i => i.Id == adjacentToIdGuid); + + var index = list.IndexOf(adjacentToItem); + + var previousId = Guid.Empty; + var nextId = Guid.Empty; + + if (index > 0) + { + previousId = list[index - 1].Id; + } + + if (index < list.Count - 1) + { + nextId = list[index + 1].Id; + } + + return list.Where(i => i.Id == previousId || i.Id == nextId); + } + /// /// Determines whether the specified item has image. /// diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index 40b999b02a..e9f250d2a4 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -235,6 +235,42 @@ namespace MediaBrowser.Controller.Entities.TV get { return LocationType == Model.Entities.LocationType.Virtual && IsUnaired; } } + [IgnoreDataMember] + public Guid? SeasonId + { + get + { + // First see if the parent is a Season + var season = Parent as Season; + + if (season != null) + { + return season.Id; + } + + var seasonNumber = ParentIndexNumber; + + // Parent is a Series + if (seasonNumber.HasValue) + { + var series = Parent as Series; + + if (series != null) + { + season = series.Children.OfType() + .FirstOrDefault(i => i.IndexNumber.HasValue && i.IndexNumber.Value == seasonNumber.Value); + + if (season != null) + { + return season.Id; + } + } + } + + return null; + } + } + public override IEnumerable GetDeletePaths() { return new[] { Path }; diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs index d5b9cea270..4e73fc109f 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs @@ -51,6 +51,22 @@ namespace MediaBrowser.Controller.LiveTv /// IEnumerable{Channel}. QueryResult GetChannels(ChannelQuery query); + /// + /// Gets the recording. + /// + /// The identifier. + /// The cancellation token. + /// Task{RecordingInfoDto}. + Task GetRecording(string id, CancellationToken cancellationToken); + + /// + /// Gets the timer. + /// + /// The identifier. + /// The cancellation token. + /// Task{TimerInfoDto}. + Task GetTimer(string id, CancellationToken cancellationToken); + /// /// Gets the recordings. /// diff --git a/MediaBrowser.Controller/LiveTv/RecordingInfo.cs b/MediaBrowser.Controller/LiveTv/RecordingInfo.cs index 65e977d75e..2c8e8cb464 100644 --- a/MediaBrowser.Controller/LiveTv/RecordingInfo.cs +++ b/MediaBrowser.Controller/LiveTv/RecordingInfo.cs @@ -20,7 +20,13 @@ namespace MediaBrowser.Controller.LiveTv /// ChannelName of the recording. /// public string ChannelName { get; set; } - + + /// + /// Gets or sets the type of the channel. + /// + /// The type of the channel. + public ChannelType ChannelType { get; set; } + /// /// Name of the recording. /// @@ -76,6 +82,18 @@ namespace MediaBrowser.Controller.LiveTv /// The episode title. public string EpisodeTitle { get; set; } + /// + /// Gets or sets the official rating. + /// + /// The official rating. + public string OfficialRating { get; set; } + + /// + /// Gets or sets the community rating. + /// + /// The community rating. + public float? CommunityRating { get; set; } + public RecordingInfo() { Genres = new List(); diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index bfa7517561..20f60586c1 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -312,6 +312,12 @@ namespace MediaBrowser.Model.Dto /// The series id. public string SeriesId { get; set; } + /// + /// Gets or sets the season identifier. + /// + /// The season identifier. + public string SeasonId { get; set; } + /// /// Gets or sets the special feature count. /// diff --git a/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs b/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs index 9ad6233a67..86e82b562d 100644 --- a/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs +++ b/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs @@ -81,6 +81,36 @@ namespace MediaBrowser.Model.LiveTv /// The episode title. public string EpisodeTitle { get; set; } + /// + /// Gets or sets the duration ms. + /// + /// The duration ms. + public int DurationMs { get; set; } + + /// + /// Gets or sets the type of the media. + /// + /// The type of the media. + public string MediaType { get; set; } + + /// + /// Gets or sets the type of the channel. + /// + /// The type of the channel. + public ChannelType ChannelType { get; set; } + + /// + /// Gets or sets the official rating. + /// + /// The official rating. + public string OfficialRating { get; set; } + + /// + /// Gets or sets the community rating. + /// + /// The community rating. + public float? CommunityRating { get; set; } + public RecordingInfoDto() { Genres = new List(); diff --git a/MediaBrowser.Model/LiveTv/TimerInfoDto.cs b/MediaBrowser.Model/LiveTv/TimerInfoDto.cs index 59a320bfda..9ebc2314d4 100644 --- a/MediaBrowser.Model/LiveTv/TimerInfoDto.cs +++ b/MediaBrowser.Model/LiveTv/TimerInfoDto.cs @@ -74,5 +74,11 @@ namespace MediaBrowser.Model.LiveTv /// /// The post padding seconds. public int PostPaddingSeconds { get; set; } + + /// + /// Gets or sets the duration ms. + /// + /// The duration ms. + public int DurationMs { get; set; } } } diff --git a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs index 055a6c101c..56b06f4906 100644 --- a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs +++ b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs @@ -1,6 +1,5 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Entities; diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index f6291cf36b..f298c2d4d1 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -1029,6 +1029,12 @@ namespace MediaBrowser.Server.Implementations.Dto { dto.IndexNumberEnd = episode.IndexNumberEnd; dto.SpecialSeasonNumber = episode.AirsAfterSeasonNumber ?? episode.AirsBeforeSeasonNumber; + + var seasonId = episode.SeasonId; + if (seasonId.HasValue) + { + dto.SeasonId = seasonId.Value.ToString("N"); + } } // Add SeriesInfo diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 704d1ea59c..4fd1f0e43b 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -391,9 +391,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv Path = info.Path, Genres = info.Genres, IsRepeat = info.IsRepeat, - EpisodeTitle = info.EpisodeTitle + EpisodeTitle = info.EpisodeTitle, + ChannelType = info.ChannelType, + MediaType = info.ChannelType == ChannelType.Radio ? MediaType.Audio : MediaType.Video, + CommunityRating = info.CommunityRating, + OfficialRating = info.OfficialRating }; + var duration = info.EndDate - info.StartDate; + dto.DurationMs = Convert.ToInt32(duration.TotalMilliseconds); + if (!string.IsNullOrEmpty(info.ProgramId)) { dto.ProgramId = GetInternalProgramIdId(service.Name, info.ProgramId).ToString("N"); @@ -510,6 +517,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv PostPaddingSeconds = info.PostPaddingSeconds }; + var duration = info.EndDate - info.StartDate; + dto.DurationMs = Convert.ToInt32(duration.TotalMilliseconds); + if (!string.IsNullOrEmpty(info.ProgramId)) { dto.ProgramId = GetInternalProgramIdId(service.Name, info.ProgramId).ToString("N"); @@ -563,5 +573,19 @@ namespace MediaBrowser.Server.Implementations.LiveTv await service.CancelTimerAsync(timer.ExternalId, CancellationToken.None).ConfigureAwait(false); } + + public async Task GetRecording(string id, CancellationToken cancellationToken) + { + var results = await GetRecordings(new RecordingQuery(), cancellationToken).ConfigureAwait(false); + + return results.Items.FirstOrDefault(i => string.Equals(i.Id, id, StringComparison.CurrentCulture)); + } + + public async Task GetTimer(string id, CancellationToken cancellationToken) + { + var results = await GetTimers(new TimerQuery(), cancellationToken).ConfigureAwait(false); + + return results.Items.FirstOrDefault(i => string.Equals(i.Id, id, StringComparison.CurrentCulture)); + } } } -- cgit v1.2.3