more support for episodes directly in a series folder
This commit is contained in:
parent
61a78e2be9
commit
40959a816f
|
@ -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<RecordingInfoDto>
|
||||
{
|
||||
[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<TimerInfoDto>
|
||||
{
|
||||
[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<QueryResult<TimerInfoDto>>
|
||||
|
@ -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
|
||||
|
|
|
@ -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; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -394,6 +401,13 @@ namespace MediaBrowser.Api
|
|||
seasons = _libraryManager.Sort(seasons, user, new[] { sortOrder }, SortOrder.Ascending)
|
||||
.Cast<Season>();
|
||||
|
||||
// This must be the last filter
|
||||
if (!string.IsNullOrEmpty(request.AdjacentTo))
|
||||
{
|
||||
seasons = ItemsService.FilterForAdjacency(seasons, request.AdjacentTo)
|
||||
.Cast<Season>();
|
||||
}
|
||||
|
||||
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<Episode>();
|
||||
|
||||
// This must be the last filter
|
||||
if (!string.IsNullOrEmpty(request.AdjacentTo))
|
||||
{
|
||||
episodes = ItemsService.FilterForAdjacency(episodes, request.AdjacentTo)
|
||||
.Cast<Episode>();
|
||||
}
|
||||
|
||||
var returnItems = episodes.Select(i => _dtoService.GetBaseItemDto(i, fields, user))
|
||||
.ToArray();
|
||||
|
||||
|
|
|
@ -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<BaseItem> FilterForAdjacency(IEnumerable<BaseItem> 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified item has image.
|
||||
/// </summary>
|
||||
|
|
|
@ -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<Season>()
|
||||
.FirstOrDefault(i => i.IndexNumber.HasValue && i.IndexNumber.Value == seasonNumber.Value);
|
||||
|
||||
if (season != null)
|
||||
{
|
||||
return season.Id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<string> GetDeletePaths()
|
||||
{
|
||||
return new[] { Path };
|
||||
|
|
|
@ -51,6 +51,22 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
/// <returns>IEnumerable{Channel}.</returns>
|
||||
QueryResult<ChannelInfoDto> GetChannels(ChannelQuery query);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the recording.
|
||||
/// </summary>
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{RecordingInfoDto}.</returns>
|
||||
Task<RecordingInfoDto> GetRecording(string id, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the timer.
|
||||
/// </summary>
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{TimerInfoDto}.</returns>
|
||||
Task<TimerInfoDto> GetTimer(string id, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the recordings.
|
||||
/// </summary>
|
||||
|
|
|
@ -20,7 +20,13 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
/// ChannelName of the recording.
|
||||
/// </summary>
|
||||
public string ChannelName { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the channel.
|
||||
/// </summary>
|
||||
/// <value>The type of the channel.</value>
|
||||
public ChannelType ChannelType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Name of the recording.
|
||||
/// </summary>
|
||||
|
@ -76,6 +82,18 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
/// <value>The episode title.</value>
|
||||
public string EpisodeTitle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the official rating.
|
||||
/// </summary>
|
||||
/// <value>The official rating.</value>
|
||||
public string OfficialRating { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the community rating.
|
||||
/// </summary>
|
||||
/// <value>The community rating.</value>
|
||||
public float? CommunityRating { get; set; }
|
||||
|
||||
public RecordingInfo()
|
||||
{
|
||||
Genres = new List<string>();
|
||||
|
|
|
@ -312,6 +312,12 @@ namespace MediaBrowser.Model.Dto
|
|||
/// <value>The series id.</value>
|
||||
public string SeriesId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the season identifier.
|
||||
/// </summary>
|
||||
/// <value>The season identifier.</value>
|
||||
public string SeasonId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the special feature count.
|
||||
/// </summary>
|
||||
|
|
|
@ -81,6 +81,36 @@ namespace MediaBrowser.Model.LiveTv
|
|||
/// <value>The episode title.</value>
|
||||
public string EpisodeTitle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the duration ms.
|
||||
/// </summary>
|
||||
/// <value>The duration ms.</value>
|
||||
public int DurationMs { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the media.
|
||||
/// </summary>
|
||||
/// <value>The type of the media.</value>
|
||||
public string MediaType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the channel.
|
||||
/// </summary>
|
||||
/// <value>The type of the channel.</value>
|
||||
public ChannelType ChannelType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the official rating.
|
||||
/// </summary>
|
||||
/// <value>The official rating.</value>
|
||||
public string OfficialRating { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the community rating.
|
||||
/// </summary>
|
||||
/// <value>The community rating.</value>
|
||||
public float? CommunityRating { get; set; }
|
||||
|
||||
public RecordingInfoDto()
|
||||
{
|
||||
Genres = new List<string>();
|
||||
|
|
|
@ -74,5 +74,11 @@ namespace MediaBrowser.Model.LiveTv
|
|||
/// </summary>
|
||||
/// <value>The post padding seconds.</value>
|
||||
public int PostPaddingSeconds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the duration ms.
|
||||
/// </summary>
|
||||
/// <value>The duration ms.</value>
|
||||
public int DurationMs { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<RecordingInfoDto> 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<TimerInfoDto> 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user