diff --git a/MediaBrowser.Plugins.NextPvr/LiveTvService.cs b/MediaBrowser.Plugins.NextPvr/LiveTvService.cs
index fbc1751..a36919e 100644
--- a/MediaBrowser.Plugins.NextPvr/LiveTvService.cs
+++ b/MediaBrowser.Plugins.NextPvr/LiveTvService.cs
@@ -39,6 +39,8 @@ namespace MediaBrowser.Plugins.NextPvr
private ICryptoProvider _cryptoProvider;
private IFileSystem _fileSystem;
+ public DateTime LastRecordingChange = DateTime.MinValue;
+
public LiveTvService(IHttpClient httpClient, IJsonSerializer jsonSerializer, ILogger logger, ICryptoProvider cryptoProvider, IFileSystem fileSystem)
{
_httpClient = httpClient;
@@ -246,6 +248,8 @@ namespace MediaBrowser.Plugins.NextPvr
using (var stream = await _httpClient.Get(options).ConfigureAwait(false))
{
+ LastRecordingChange = DateTime.UtcNow;
+
bool? error = new CancelDeleteRecordingResponse().RecordingError(stream, _jsonSerializer, _logger);
if (error == null || error == true)
@@ -287,6 +291,7 @@ namespace MediaBrowser.Plugins.NextPvr
using (var stream = await _httpClient.Get(options).ConfigureAwait(false))
{
+ LastRecordingChange = DateTime.UtcNow;
bool? error = new CancelDeleteRecordingResponse().RecordingError(stream, _jsonSerializer, _logger);
if (error == null || error == true)
@@ -606,9 +611,11 @@ namespace MediaBrowser.Plugins.NextPvr
try
{
await _httpClient.Post(options).ConfigureAwait((false));
+ LastRecordingChange = DateTime.UtcNow;
}
catch (HttpException ex)
{
+ LastRecordingChange = DateTime.UtcNow;
_logger.Error(string.Format("[NextPvr] UpdateTimer Async with exception: {0}", ex.Message));
throw new LiveTvConflictException();
}
@@ -728,7 +735,8 @@ namespace MediaBrowser.Plugins.NextPvr
}
},
- Container = "mpegts"
+ Container = "mpegts",
+ SupportsProbing = false
};
}
}
@@ -757,7 +765,8 @@ namespace MediaBrowser.Plugins.NextPvr
}
},
- Container = "mpegts"
+ Container = "mpegts",
+ SupportsProbing = false
};
}
diff --git a/MediaBrowser.Plugins.NextPvr/MediaBrowser.Plugins.NextPvr.csproj b/MediaBrowser.Plugins.NextPvr/MediaBrowser.Plugins.NextPvr.csproj
index f8b8d23..4eb2fd0 100644
--- a/MediaBrowser.Plugins.NextPvr/MediaBrowser.Plugins.NextPvr.csproj
+++ b/MediaBrowser.Plugins.NextPvr/MediaBrowser.Plugins.NextPvr.csproj
@@ -2,8 +2,8 @@
netstandard1.3;
- 3.1.8.0
- 3.1.8.0
+ 3.1.9.0
+ 3.1.9.0
@@ -15,7 +15,7 @@
-
+
diff --git a/MediaBrowser.Plugins.NextPvr/RecordingsChannel.cs b/MediaBrowser.Plugins.NextPvr/RecordingsChannel.cs
new file mode 100644
index 0000000..9f28e69
--- /dev/null
+++ b/MediaBrowser.Plugins.NextPvr/RecordingsChannel.cs
@@ -0,0 +1,342 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Controller.Channels;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Channels;
+using MediaBrowser.Model.MediaInfo;
+using MediaBrowser.Controller.LiveTv;
+using System.Linq;
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Model.Dto;
+using System.Globalization;
+using MediaBrowser.Controller.Entities;
+
+namespace MediaBrowser.Plugins.NextPvr
+{
+ public class RecordingsChannel : IChannel, IIndexableChannel, IHasCacheKey, ISupportsDelete
+ {
+ public ILiveTvManager _liveTvManager;
+
+ public RecordingsChannel(ILiveTvManager liveTvManager)
+ {
+ _liveTvManager = liveTvManager;
+ }
+
+ public string Name
+ {
+ get
+ {
+ return "Next Pvr Recordings";
+ }
+ }
+
+ public string Description
+ {
+ get
+ {
+ return "Next Pvr Recordings";
+ }
+ }
+
+ public string DataVersion
+ {
+ get
+ {
+ return "1";
+ }
+ }
+
+ public string HomePageUrl
+ {
+ get { return "http://www.nextpvr.com/"; }
+ }
+
+ public ChannelParentalRating ParentalRating
+ {
+ get { return ChannelParentalRating.GeneralAudience; }
+ }
+
+ public string GetCacheKey(string userId)
+ {
+ var now = DateTime.UtcNow;
+
+ var values = new List();
+
+ values.Add(now.DayOfYear.ToString(CultureInfo.InvariantCulture));
+ values.Add(now.Hour.ToString(CultureInfo.InvariantCulture));
+
+ double minute = now.Minute;
+ minute /= 5;
+
+ values.Add(Math.Floor(minute).ToString(CultureInfo.InvariantCulture));
+
+ values.Add(GetService().LastRecordingChange.Ticks.ToString(CultureInfo.InvariantCulture));
+
+ return string.Join("-", values.ToArray());
+ }
+
+ public InternalChannelFeatures GetChannelFeatures()
+ {
+ return new InternalChannelFeatures
+ {
+ ContentTypes = new List
+ {
+ ChannelMediaContentType.Movie,
+ ChannelMediaContentType.Episode,
+ ChannelMediaContentType.Clip
+ },
+ MediaTypes = new List
+ {
+ ChannelMediaType.Audio,
+ ChannelMediaType.Video
+ },
+ SupportsContentDownloading = true
+ };
+ }
+
+ public Task GetChannelImage(ImageType type, CancellationToken cancellationToken)
+ {
+ if (type == ImageType.Primary)
+ {
+ return Task.FromResult(new DynamicImageResponse
+ {
+ Path = "https://raw.githubusercontent.com/MediaBrowser/MediaBrowser.Resources/master/images/catalog/nextpvr.png",
+ Protocol = MediaProtocol.Http,
+ HasImage = true
+ });
+ }
+
+ return Task.FromResult(new DynamicImageResponse
+ {
+ HasImage = false
+ });
+ }
+
+ public IEnumerable GetSupportedChannelImages()
+ {
+ return new List
+ {
+ ImageType.Primary
+ };
+ }
+
+ public bool IsEnabledFor(string userId)
+ {
+ return true;
+ }
+
+ private LiveTvService GetService()
+ {
+ return _liveTvManager.Services.OfType().First();
+ }
+
+ public bool CanDelete(BaseItem item)
+ {
+ return !item.IsFolder;
+ }
+
+ public Task DeleteItem(string id, CancellationToken cancellationToken)
+ {
+ return GetService().DeleteRecordingAsync(id, cancellationToken);
+ }
+
+ public Task GetAllMedia(InternalAllChannelMediaQuery query, CancellationToken cancellationToken)
+ {
+ return GetChannelItems(new InternalChannelItemQuery(), i => true, cancellationToken);
+ }
+
+ public Task GetChannelItems(InternalChannelItemQuery query, CancellationToken cancellationToken)
+ {
+ if (string.IsNullOrWhiteSpace(query.FolderId))
+ {
+ return GetRecordingGroups(query, cancellationToken);
+ }
+
+ if (query.FolderId.StartsWith("series_", StringComparison.OrdinalIgnoreCase))
+ {
+ var hash = query.FolderId.Split('_')[1];
+ return GetChannelItems(query, i => i.IsSeries && string.Equals(i.Name.GetMD5().ToString("N"), hash, StringComparison.Ordinal), cancellationToken);
+ }
+
+ if (string.Equals(query.FolderId, "kids", StringComparison.OrdinalIgnoreCase))
+ {
+ return GetChannelItems(query, i => i.IsKids, cancellationToken);
+ }
+
+ if (string.Equals(query.FolderId, "movies", StringComparison.OrdinalIgnoreCase))
+ {
+ return GetChannelItems(query, i => i.IsMovie, cancellationToken);
+ }
+
+ if (string.Equals(query.FolderId, "news", StringComparison.OrdinalIgnoreCase))
+ {
+ return GetChannelItems(query, i => i.IsNews, cancellationToken);
+ }
+
+ if (string.Equals(query.FolderId, "sports", StringComparison.OrdinalIgnoreCase))
+ {
+ return GetChannelItems(query, i => i.IsSports, cancellationToken);
+ }
+
+ if (string.Equals(query.FolderId, "others", StringComparison.OrdinalIgnoreCase))
+ {
+ return GetChannelItems(query, i => !i.IsSports && !i.IsNews && !i.IsMovie && !i.IsKids && !i.IsSeries, cancellationToken);
+ }
+
+ var result = new ChannelItemResult()
+ {
+ Items = new List()
+ };
+
+ return Task.FromResult(result);
+ }
+
+ public async Task GetChannelItems(InternalChannelItemQuery query, Func filter, CancellationToken cancellationToken)
+ {
+ var service = GetService();
+ var allRecordings = await service.GetRecordingsAsync(cancellationToken).ConfigureAwait(false);
+
+ var result = new ChannelItemResult()
+ {
+ Items = new List()
+ };
+
+ result.Items.AddRange(allRecordings.Where(filter).Select(ConvertToChannelItem));
+
+ return result;
+ }
+
+ private ChannelItemInfo ConvertToChannelItem(RecordingInfo item)
+ {
+ var channelItem = new ChannelItemInfo
+ {
+ Name = string.IsNullOrEmpty(item.EpisodeTitle) ? item.Name : item.EpisodeTitle,
+ SeriesName = !string.IsNullOrEmpty(item.EpisodeTitle) || item.IsSeries ? item.Name : null,
+ OfficialRating = item.OfficialRating,
+ CommunityRating = item.CommunityRating,
+ ContentType = item.IsMovie ? ChannelMediaContentType.Movie : (item.IsSeries ? ChannelMediaContentType.Episode : ChannelMediaContentType.Clip),
+ Genres = item.Genres,
+ ImageUrl = item.ImageUrl,
+ //HomePageUrl = item.HomePageUrl
+ Id = item.Id,
+ //IndexNumber = item.IndexNumber,
+ MediaType = item.ChannelType == Model.LiveTv.ChannelType.TV ? ChannelMediaType.Video : ChannelMediaType.Audio,
+ MediaSources = new List
+ {
+ new MediaSourceInfo
+ {
+ Path = item.Path,
+ Protocol = item.Path.StartsWith("http", StringComparison.OrdinalIgnoreCase) ? MediaProtocol.Http : MediaProtocol.File,
+ Id = item.Id
+ }
+ },
+ //ParentIndexNumber = item.ParentIndexNumber,
+ PremiereDate = item.OriginalAirDate,
+ //ProductionYear = item.ProductionYear,
+ //Studios = item.Studios,
+ Type = ChannelItemType.Media,
+ DateModified = item.DateLastUpdated,
+ Overview = item.Overview,
+ //People = item.People
+ };
+
+ return channelItem;
+ }
+
+ private async Task GetRecordingGroups(InternalChannelItemQuery query, CancellationToken cancellationToken)
+ {
+ var service = GetService();
+
+ var allRecordings = await service.GetRecordingsAsync(cancellationToken).ConfigureAwait(false);
+ var result = new ChannelItemResult()
+ {
+ Items = new List()
+ };
+
+ var series = allRecordings
+ .Where(i => i.IsSeries)
+ .ToLookup(i => i.Name, StringComparer.OrdinalIgnoreCase);
+
+ result.Items.AddRange(series.OrderBy(i => i.Key).Select(i => new ChannelItemInfo
+ {
+ Name = i.Key,
+ FolderType = ChannelFolderType.Container,
+ Id = "series_" + i.Key.GetMD5().ToString("N"),
+ Type = ChannelItemType.Folder,
+ ImageUrl = i.First().ImageUrl
+ }));
+
+ var kids = allRecordings.FirstOrDefault(i => i.IsKids);
+
+ if (kids != null)
+ {
+ result.Items.Add(new ChannelItemInfo
+ {
+ Name = "Kids",
+ FolderType = ChannelFolderType.Container,
+ Id = "kids",
+ Type = ChannelItemType.Folder,
+ ImageUrl = kids.ImageUrl
+ });
+ }
+
+ var movies = allRecordings.FirstOrDefault(i => i.IsMovie);
+ if (movies != null)
+ {
+ result.Items.Add(new ChannelItemInfo
+ {
+ Name = "Movies",
+ FolderType = ChannelFolderType.Container,
+ Id = "movies",
+ Type = ChannelItemType.Folder,
+ ImageUrl = movies.ImageUrl
+ });
+ }
+
+ var news = allRecordings.FirstOrDefault(i => i.IsNews);
+ if (news != null)
+ {
+ result.Items.Add(new ChannelItemInfo
+ {
+ Name = "News",
+ FolderType = ChannelFolderType.Container,
+ Id = "news",
+ Type = ChannelItemType.Folder,
+ ImageUrl = news.ImageUrl
+ });
+ }
+
+ var sports = allRecordings.FirstOrDefault(i => i.IsSports);
+ if (sports != null)
+ {
+ result.Items.Add(new ChannelItemInfo
+ {
+ Name = "Sports",
+ FolderType = ChannelFolderType.Container,
+ Id = "sports",
+ Type = ChannelItemType.Folder,
+ ImageUrl = sports.ImageUrl
+ });
+ }
+
+ var other = allRecordings.FirstOrDefault(i => !i.IsSports && !i.IsNews && !i.IsMovie && !i.IsKids && !i.IsSeries);
+ if (other != null)
+ {
+ result.Items.Add(new ChannelItemInfo
+ {
+ Name = "Others",
+ FolderType = ChannelFolderType.Container,
+ Id = "others",
+ Type = ChannelItemType.Folder,
+ ImageUrl = other.ImageUrl
+ });
+ }
+
+ return result;
+ }
+ }
+}