diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index e2280cdc8..b850efb72 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -52,6 +52,17 @@ namespace MediaBrowser.Api.LiveTv [ApiMember(Name = "UserId", Description = "Optional filter by user and attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] public string UserId { get; set; } + + [ApiMember(Name = "GroupId", Description = "Optional filter by recording group.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public string GroupId { get; set; } + } + + [Route("/LiveTv/Recordings/Groups", "GET")] + [Api(Description = "Gets live tv recording groups")] + public class GetRecordingGroups : IReturn> + { + [ApiMember(Name = "UserId", Description = "Optional filter by user and attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public string UserId { get; set; } } [Route("/LiveTv/Recordings/{Id}", "GET")] @@ -247,7 +258,8 @@ namespace MediaBrowser.Api.LiveTv var result = _liveTvManager.GetRecordings(new RecordingQuery { ChannelId = request.ChannelId, - UserId = request.UserId + UserId = request.UserId, + GroupId = request.GroupId }, CancellationToken.None).Result; @@ -378,5 +390,16 @@ namespace MediaBrowser.Api.LiveTv return ToStreamResult(stream.Stream, stream.MimeType); } + + public object Get(GetRecordingGroups request) + { + var result = _liveTvManager.GetRecordingGroups(new RecordingGroupQuery + { + UserId = request.UserId + + }, CancellationToken.None).Result; + + return ToOptimizedResult(result); + } } } \ No newline at end of file diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs index 1d98dc7cf..2458d4db4 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs @@ -211,5 +211,13 @@ namespace MediaBrowser.Controller.LiveTv /// The cancellation token. /// Task. Task CreateSeriesTimer(SeriesTimerInfoDto timer, CancellationToken cancellationToken); + + /// + /// Gets the recording groups. + /// + /// The query. + /// The cancellation token. + /// Task{QueryResult{RecordingGroupDto}}. + Task> GetRecordingGroups(RecordingGroupQuery query, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index afdabbf44..f8b12da9e 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -239,6 +239,9 @@ LiveTv\ProgramQuery.cs + + LiveTv\RecordingGroupDto.cs + LiveTv\RecordingInfoDto.cs diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index 7937bc403..d69cf56c6 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -226,6 +226,9 @@ LiveTv\ProgramQuery.cs + + LiveTv\RecordingGroupDto.cs + LiveTv\RecordingInfoDto.cs diff --git a/MediaBrowser.Model/LiveTv/RecordingGroupDto.cs b/MediaBrowser.Model/LiveTv/RecordingGroupDto.cs new file mode 100644 index 000000000..29f0824fb --- /dev/null +++ b/MediaBrowser.Model/LiveTv/RecordingGroupDto.cs @@ -0,0 +1,27 @@ + +namespace MediaBrowser.Model.LiveTv +{ + /// + /// Class RecordingGroupDto. + /// + public class RecordingGroupDto + { + /// + /// Gets or sets the name. + /// + /// The name. + public string Name { get; set; } + + /// + /// Gets or sets the identifier. + /// + /// The identifier. + public string Id { get; set; } + + /// + /// Gets or sets the recording count. + /// + /// The recording count. + public int RecordingCount { get; set; } + } +} diff --git a/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs b/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs index 3cf44f5c4..47accbec5 100644 --- a/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs +++ b/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs @@ -84,6 +84,12 @@ namespace MediaBrowser.Model.LiveTv /// The status. public RecordingStatus Status { get; set; } + /// + /// Gets or sets the name of the status. + /// + /// The name of the status. + public string StatusName { get; set; } + /// /// Genre of the program. /// diff --git a/MediaBrowser.Model/LiveTv/RecordingQuery.cs b/MediaBrowser.Model/LiveTv/RecordingQuery.cs index 20a7074a5..10161b99a 100644 --- a/MediaBrowser.Model/LiveTv/RecordingQuery.cs +++ b/MediaBrowser.Model/LiveTv/RecordingQuery.cs @@ -22,6 +22,21 @@ /// /// The identifier. public string Id { get; set; } + + /// + /// Gets or sets the group identifier. + /// + /// The group identifier. + public string GroupId { get; set; } + } + + public class RecordingGroupQuery + { + /// + /// Gets or sets the user identifier. + /// + /// The user identifier. + public string UserId { get; set; } } public class TimerQuery diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index bb6fedb9f..ab91416b7 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -75,6 +75,7 @@ + @@ -209,7 +210,6 @@ if '$(ConfigurationName)' == 'Release' ( xcopy "$(TargetPath)" "$(SolutionDir)\Nuget\dlls\net45\" /y /d /r /i ) - cp -fu "$(MSBuildProjectDirectory)\..\packages\PropertyChanged.Fody.1.41.0.0\PropertyChanged.Fody.dll" "$(MSBuildProjectDirectory)\..\Tools\Fody\" diff --git a/MediaBrowser.Mono.userprefs b/MediaBrowser.Mono.userprefs index 4a043b8b8..98959b10a 100644 --- a/MediaBrowser.Mono.userprefs +++ b/MediaBrowser.Mono.userprefs @@ -2,7 +2,7 @@ - + diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs index 6552c6892..ac9f07dcb 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs @@ -160,10 +160,30 @@ namespace MediaBrowser.Server.Implementations.LiveTv return val.Value * 2; } + public string GetStatusName(RecordingStatus status) + { + if (status == RecordingStatus.InProgress) + { + return "In Progress"; + } + + if (status == RecordingStatus.ConflictedNotOk) + { + return "Conflicted"; + } + + if (status == RecordingStatus.ConflictedOk) + { + return "Scheduled"; + } + + return status.ToString(); + } + public RecordingInfoDto GetRecordingInfoDto(LiveTvRecording recording, LiveTvChannel channel, ILiveTvService service, User user = null) { var info = recording.RecordingInfo; - + var dto = new RecordingInfoDto { Id = GetInternalRecordingId(service.Name, info.Id).ToString("N"), @@ -176,6 +196,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv ExternalId = info.Id, ChannelId = GetInternalChannelId(service.Name, info.ChannelId).ToString("N"), Status = info.Status, + StatusName = GetStatusName(info.Status), Path = info.Path, Genres = info.Genres, IsRepeat = info.IsRepeat, @@ -219,7 +240,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv { dto.ChannelName = channel.ChannelInfo.Name; } - + return dto; } @@ -263,7 +284,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv public ProgramInfoDto GetProgramInfoDto(LiveTvProgram item, string channelName, User user = null) { var program = item.ProgramInfo; - + var dto = new ProgramInfoDto { Id = GetInternalProgramId(item.ServiceName, program.Id).ToString("N"), @@ -291,9 +312,17 @@ namespace MediaBrowser.Server.Implementations.LiveTv IsNews = program.IsNews, IsKids = program.IsKids, IsPremiere = program.IsPremiere, - RunTimeTicks = (program.EndDate - program.StartDate).Ticks + RunTimeTicks = (program.EndDate - program.StartDate).Ticks, + Type = "Program" }; + var imageTag = GetImageTag(item); + + if (imageTag.HasValue) + { + dto.ImageTags[ImageType.Primary] = imageTag.Value; + } + if (user != null) { dto.UserData = _dtoService.GetUserItemDataDto(_userDataManager.GetUserData(user.Id, item.GetUserDataKey())); diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 1d12e2d45..04aad469a 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -448,15 +448,31 @@ namespace MediaBrowser.Server.Implementations.LiveTv if (!string.IsNullOrEmpty(query.ChannelId)) { + var guid = new Guid(query.ChannelId); + + var currentServiceName = service.Name; + list = list - .Where(i => _tvDtoService.GetInternalChannelId(service.Name, i.ChannelId) == new Guid(query.ChannelId)) + .Where(i => _tvDtoService.GetInternalChannelId(currentServiceName, i.ChannelId) == guid) .ToList(); } if (!string.IsNullOrEmpty(query.Id)) { + var guid = new Guid(query.Id); + + var currentServiceName = service.Name; + list = list - .Where(i => _tvDtoService.GetInternalRecordingId(service.Name, i.Id) == new Guid(query.Id)) + .Where(i => _tvDtoService.GetInternalRecordingId(currentServiceName, i.Id) == guid) + .ToList(); + } + + if (!string.IsNullOrEmpty(query.GroupId)) + { + var guid = new Guid(query.GroupId); + + list = list.Where(i => GetRecordingGroupIds(i).Contains(guid)) .ToList(); } @@ -734,5 +750,118 @@ namespace MediaBrowser.Server.Implementations.LiveTv await service.UpdateSeriesTimerAsync(info, cancellationToken).ConfigureAwait(false); } + + private List GetRecordingGroupNames(RecordingInfo recording) + { + var list = new List(); + + if (recording.IsSeries) + { + list.Add(recording.Name); + } + + if (recording.IsKids) + { + list.Add("Kids"); + } + + if (recording.IsMovie) + { + list.Add("Movies"); + } + + if (recording.IsNews) + { + list.Add("News"); + } + + if (recording.IsPremiere) + { + list.Add("Sports"); + } + + if (!recording.IsSports && !recording.IsNews && !recording.IsMovie && !recording.IsKids && !recording.IsSeries) + { + list.Add("Others"); + } + + return list; + } + + private List GetRecordingGroupIds(RecordingInfo recording) + { + return GetRecordingGroupNames(recording).Select(i => i.ToLower() + .GetMD5()) + .ToList(); + } + + public async Task> GetRecordingGroups(RecordingGroupQuery query, CancellationToken cancellationToken) + { + var recordingResult = await GetRecordings(new RecordingQuery + { + UserId = query.UserId + + }, cancellationToken).ConfigureAwait(false); + + var recordings = recordingResult.Items; + + var groups = new List(); + + var series = recordings + .Where(i => i.IsSeries) + .ToLookup(i => i.Name, StringComparer.OrdinalIgnoreCase) + .ToList(); + + groups.AddRange(series.OrderBy(i => i.Key).Select(i => new RecordingGroupDto + { + Name = i.Key, + RecordingCount = i.Count() + })); + + groups.Add(new RecordingGroupDto + { + Name = "Kids", + RecordingCount = recordings.Count(i => i.IsKids) + }); + + groups.Add(new RecordingGroupDto + { + Name = "Movies", + RecordingCount = recordings.Count(i => i.IsMovie) + }); + + groups.Add(new RecordingGroupDto + { + Name = "News", + RecordingCount = recordings.Count(i => i.IsNews) + }); + + groups.Add(new RecordingGroupDto + { + Name = "Sports", + RecordingCount = recordings.Count(i => i.IsSports) + }); + + groups.Add(new RecordingGroupDto + { + Name = "Others", + RecordingCount = recordings.Count(i => !i.IsSports && !i.IsNews && !i.IsMovie && !i.IsKids && !i.IsSeries) + }); + + groups = groups + .Where(i => i.RecordingCount > 0) + .ToList(); + + foreach (var group in groups) + { + group.Id = group.Name.ToLower().GetMD5().ToString("N"); + } + + return new QueryResult + { + Items = groups.ToArray(), + TotalRecordCount = groups.Count + }; + } } } diff --git a/MediaBrowser.WebDashboard/ApiClient.js b/MediaBrowser.WebDashboard/ApiClient.js index e260a0a05..18c007962 100644 --- a/MediaBrowser.WebDashboard/ApiClient.js +++ b/MediaBrowser.WebDashboard/ApiClient.js @@ -445,6 +445,17 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi }); }; + self.getLiveTvRecordingGroups = function (options) { + + var url = self.getUrl("LiveTv/Recordings/Groups", options || {}); + + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); + }; + self.getLiveTvRecording = function (id, userId) { if (!id) { diff --git a/MediaBrowser.WebDashboard/packages.config b/MediaBrowser.WebDashboard/packages.config index 659c5db1e..e36a72adf 100644 --- a/MediaBrowser.WebDashboard/packages.config +++ b/MediaBrowser.WebDashboard/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file