diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvService.cs b/MediaBrowser.Controller/LiveTv/ILiveTvService.cs index d39d98fa3c..3d68a4ec71 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvService.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvService.cs @@ -1,4 +1,5 @@ -using System.IO; +using System; +using System.IO; using MediaBrowser.Model.LiveTv; using System.Collections.Generic; using System.Threading; @@ -24,6 +25,24 @@ namespace MediaBrowser.Controller.LiveTv /// Task{IEnumerable{ChannelInfo}}. Task> GetChannelsAsync(CancellationToken cancellationToken); + /// + /// Cancels the recording asynchronous. + /// + /// The recording identifier. + /// The cancellation token. + /// Task. + Task CancelRecordingAsync(string recordingId, CancellationToken cancellationToken); + + /// + /// Schedules the recording asynchronous. + /// + /// The channel identifier. + /// The start time. + /// The duration. + /// The cancellation token. + /// Task. + Task ScheduleRecordingAsync(string channelId, DateTime startTime, TimeSpan duration, CancellationToken cancellationToken); + /// /// Gets the channel image asynchronous. /// diff --git a/MediaBrowser.Model/Querying/ItemSortBy.cs b/MediaBrowser.Model/Querying/ItemSortBy.cs index 12dfa96261..57e09d724c 100644 --- a/MediaBrowser.Model/Querying/ItemSortBy.cs +++ b/MediaBrowser.Model/Querying/ItemSortBy.cs @@ -6,6 +6,7 @@ namespace MediaBrowser.Model.Querying /// public static class ItemSortBy { + public const string AiredEpisodeOrder = "AiredEpisodeOrder"; /// /// The album /// diff --git a/MediaBrowser.Providers/TV/EpisodeIndexNumberProvider.cs b/MediaBrowser.Providers/TV/EpisodeIndexNumberProvider.cs index fc8f55ae14..592c5dcac3 100644 --- a/MediaBrowser.Providers/TV/EpisodeIndexNumberProvider.cs +++ b/MediaBrowser.Providers/TV/EpisodeIndexNumberProvider.cs @@ -27,6 +27,22 @@ namespace MediaBrowser.Providers.TV { } + protected override bool RefreshOnVersionChange + { + get + { + return true; + } + } + + protected override string ProviderVersion + { + get + { + return "2"; + } + } + /// /// Supportses the specified item. /// @@ -51,6 +67,16 @@ namespace MediaBrowser.Providers.TV episode.IndexNumber = TVUtils.GetEpisodeNumberFromFile(item.Path, item.Parent is Season); episode.IndexNumberEnd = TVUtils.GetEndingEpisodeNumberFromFile(item.Path); + if (!episode.ParentIndexNumber.HasValue) + { + var season = episode.Parent as Season; + + if (season != null) + { + episode.ParentIndexNumber = season.IndexNumber; + } + } + SetLastRefreshed(item, DateTime.UtcNow); return TrueTaskResult; diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index ac451e1ebd..282991cc1f 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -188,6 +188,7 @@ + diff --git a/MediaBrowser.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs b/MediaBrowser.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs new file mode 100644 index 0000000000..cec9743bae --- /dev/null +++ b/MediaBrowser.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs @@ -0,0 +1,134 @@ +using System; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Sorting; +using MediaBrowser.Model.Querying; + +namespace MediaBrowser.Server.Implementations.Sorting +{ + class AiredEpisodeOrderComparer : IBaseItemComparer + { + /// + /// Compares the specified x. + /// + /// The x. + /// The y. + /// System.Int32. + public int Compare(BaseItem x, BaseItem y) + { + var val = DateTime.Compare(x.PremiereDate ?? DateTime.MinValue, y.PremiereDate ?? DateTime.MinValue); + + if (val != 0) + { + return val; + } + + var episode1 = x as Episode; + var episode2 = y as Episode; + + if (episode1 == null) + { + if (episode2 == null) + { + return 0; + } + + return 1; + } + + if (episode2 == null) + { + return -1; + } + + return Compare(episode1, episode2); + } + + private int Compare(Episode x, Episode y) + { + var isXSpecial = (x.ParentIndexNumber ?? -1) == 0; + var isYSpecial = (y.ParentIndexNumber ?? -1) == 0; + + if (isXSpecial && isYSpecial) + { + return CompareSpecials(x, y); + } + + if (!isXSpecial && !isYSpecial) + { + return CompareEpisodes(x, y); + } + + if (!isXSpecial && isYSpecial) + { + return CompareEpisodeToSpecial(x, y); + } + + return CompareEpisodeToSpecial(x, y) * -1; + } + + private int CompareEpisodeToSpecial(Episode x, Episode y) + { + var xSeason = x.ParentIndexNumber ?? -1; + var ySeason = y.AirsAfterSeasonNumber ?? y.AirsBeforeSeasonNumber ?? -1; + + if (xSeason != ySeason) + { + return xSeason.CompareTo(ySeason); + } + + // Now we know they have the same season + + // Compare episode number + + // Add 1 to to non-specials to account for AirsBeforeEpisodeNumber + var xEpisode = (x.IndexNumber ?? 0) * 1000 + 1; + var yEpisode = (y.AirsBeforeEpisodeNumber ?? 0) * 1000; + + return xEpisode.CompareTo(yEpisode); + } + + private int CompareSpecials(Episode x, Episode y) + { + return GetSpecialCompareValue(x).CompareTo(GetSpecialCompareValue(y)); + } + + private int GetSpecialCompareValue(Episode item) + { + // First sort by season number + // Since there are three sort orders, pad with 9 digits (3 for each, figure 1000 episode buffer should be enough) + var val = (item.AirsBeforeSeasonNumber ?? item.AirsAfterSeasonNumber ?? 0) * 1000000000; + + // Second sort order is if it airs after the season + if (item.AirsAfterSeasonNumber.HasValue) + { + val += 1000000; + } + + // Third level is the episode number + val += (item.AirsBeforeEpisodeNumber ?? 0) * 1000; + + // Finally, if that's still the same, last resort is the special number itself + val += item.IndexNumber ?? 0; + + return val; + } + + private int CompareEpisodes(Episode x, Episode y) + { + var xValue = ((x.ParentIndexNumber ?? -1) * 1000) + (x.IndexNumber ?? -1); + var yValue = ((y.ParentIndexNumber ?? -1) * 1000) + (y.IndexNumber ?? -1); + + return xValue.CompareTo(yValue); + } + + /// + /// Gets the name. + /// + /// The name. + public string Name + { + get { return ItemSortBy.AiredEpisodeOrder; } + } + } +}