support metabrowser special episode attributes
This commit is contained in:
parent
50fc350c1b
commit
9f9ab1ac9f
|
@ -21,6 +21,9 @@ namespace MediaBrowser.Api.DefaultTheme
|
|||
{
|
||||
[ApiMember(Name = "UserId", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||
public Guid UserId { get; set; }
|
||||
|
||||
[ApiMember(Name = "RecentlyPlayedGamesLimit", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
||||
public int RecentlyPlayedGamesLimit { get; set; }
|
||||
}
|
||||
|
||||
[Route("/MBT/DefaultTheme/TV", "GET")]
|
||||
|
@ -245,6 +248,19 @@ namespace MediaBrowser.Api.DefaultTheme
|
|||
|
||||
var fields = new List<ItemFields>();
|
||||
|
||||
view.GameSystems = items
|
||||
.OfType<GameSystem>()
|
||||
.OrderBy(i => i.SortName)
|
||||
.Select(i => _dtoService.GetBaseItemDto(i, fields, user))
|
||||
.ToList();
|
||||
|
||||
var currentUserId = user.Id;
|
||||
view.RecentlyPlayedGames = gamesWithImages
|
||||
.OrderByDescending(i => _userDataManager.GetUserData(currentUserId, i.GetUserDataKey()).LastPlayedDate ?? DateTime.MinValue)
|
||||
.Take(request.RecentlyPlayedGamesLimit)
|
||||
.Select(i => _dtoService.GetBaseItemDto(i, fields, user))
|
||||
.ToList();
|
||||
|
||||
view.BackdropItems = gamesWithBackdrops
|
||||
.OrderBy(i => Guid.NewGuid())
|
||||
.Take(10)
|
||||
|
@ -265,12 +281,6 @@ namespace MediaBrowser.Api.DefaultTheme
|
|||
.Take(1)
|
||||
.ToList();
|
||||
|
||||
view.MiniSpotlights = gamesWithBackdrops
|
||||
.Randomize("minispotlight")
|
||||
.Take(5)
|
||||
.Select(i => _dtoService.GetBaseItemDto(i, fields, user))
|
||||
.ToList();
|
||||
|
||||
return ToOptimizedResult(view);
|
||||
}
|
||||
|
||||
|
@ -324,8 +334,6 @@ namespace MediaBrowser.Api.DefaultTheme
|
|||
.Take(1)
|
||||
.ToList();
|
||||
|
||||
view.ActorItems = GetActors(series, user.Id);
|
||||
|
||||
var spotlightSeries = seriesWithBestBackdrops
|
||||
.Where(i => i.CommunityRating.HasValue && i.CommunityRating >= 8.5)
|
||||
.ToList();
|
||||
|
@ -409,10 +417,6 @@ namespace MediaBrowser.Api.DefaultTheme
|
|||
var items = user.RootFolder.GetRecursiveChildren(user, i => i is Movie || i is Trailer || i is BoxSet)
|
||||
.ToList();
|
||||
|
||||
// Exclude trailers from backdrops because they're not always 1080p
|
||||
var itemsWithBackdrops = items.Where(i => i.BackdropImagePaths.Count > 0)
|
||||
.ToList();
|
||||
|
||||
var view = new MoviesView();
|
||||
|
||||
var movies = items.OfType<Movie>()
|
||||
|
@ -439,7 +443,7 @@ namespace MediaBrowser.Api.DefaultTheme
|
|||
|
||||
var fields = new List<ItemFields>();
|
||||
|
||||
var itemsWithTopBackdrops = FilterItemsForBackdropDisplay(itemsWithBackdrops).ToList();
|
||||
var itemsWithTopBackdrops = FilterItemsForBackdropDisplay(moviesWithBackdrops).ToList();
|
||||
|
||||
view.BackdropItems = itemsWithTopBackdrops
|
||||
.OrderBy(i => Guid.NewGuid())
|
||||
|
@ -515,10 +519,10 @@ namespace MediaBrowser.Api.DefaultTheme
|
|||
.Take(1)
|
||||
.ToList();
|
||||
|
||||
view.PeopleItems = GetActors(items, user.Id);
|
||||
|
||||
var currentUserId = user.Id;
|
||||
var spotlightItems = itemsWithTopBackdrops
|
||||
.Where(i => i.CommunityRating.HasValue && i.CommunityRating >= 8)
|
||||
.Where(i => !_userDataManager.GetUserData(currentUserId, i.GetUserDataKey()).Played)
|
||||
.ToList();
|
||||
|
||||
if (spotlightItems.Count < 20)
|
||||
|
@ -551,14 +555,13 @@ namespace MediaBrowser.Api.DefaultTheme
|
|||
.ToList();
|
||||
|
||||
// Avoid implicitly captured closure
|
||||
var currentUserId = user.Id;
|
||||
miniSpotlightItems.InsertRange(2, moviesWithBackdrops
|
||||
miniSpotlightItems.InsertRange(0, moviesWithBackdrops
|
||||
.Where(i => _userDataManager.GetUserData(currentUserId, i.GetUserDataKey()).PlaybackPositionTicks > 0)
|
||||
.OrderByDescending(i => _userDataManager.GetUserData(currentUserId, i.GetUserDataKey()).LastPlayedDate ?? DateTime.MaxValue)
|
||||
.Take(3));
|
||||
|
||||
view.MiniSpotlights = miniSpotlightItems
|
||||
.Take(5)
|
||||
.Take(3)
|
||||
.Select(i => _dtoService.GetBaseItemDto(i, fields, user))
|
||||
.ToList();
|
||||
|
||||
|
@ -617,69 +620,6 @@ namespace MediaBrowser.Api.DefaultTheme
|
|||
}
|
||||
}
|
||||
|
||||
private List<ItemStub> GetActors(IEnumerable<BaseItem> mediaItems, Guid userId)
|
||||
{
|
||||
var actors = mediaItems.SelectMany(i => i.People)
|
||||
.Select(i => i.Name)
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.Randomize()
|
||||
.ToList();
|
||||
|
||||
var result = actors.Select(actor =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var person = _libraryManager.GetPerson(actor);
|
||||
|
||||
if (!string.IsNullOrEmpty(person.PrimaryImagePath))
|
||||
{
|
||||
var userdata = _userDataManager.GetUserData(userId, person.GetUserDataKey());
|
||||
|
||||
if (userdata.IsFavorite || (userdata.Likes ?? false))
|
||||
{
|
||||
return GetItemStub(person, ImageType.Primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorException("Error getting person {0}", ex, actor);
|
||||
}
|
||||
|
||||
return null;
|
||||
})
|
||||
.Where(i => i != null)
|
||||
.Take(1)
|
||||
.ToList();
|
||||
|
||||
if (result.Count == 0)
|
||||
{
|
||||
result = actors.Select(actor =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var person = _libraryManager.GetPerson(actor);
|
||||
|
||||
if (!string.IsNullOrEmpty(person.PrimaryImagePath))
|
||||
{
|
||||
return GetItemStub(person, ImageType.Primary);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorException("Error getting person {0}", ex, actor);
|
||||
}
|
||||
|
||||
return null;
|
||||
})
|
||||
.Where(i => i != null)
|
||||
.Take(1)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private ItemStub GetItemStub(BaseItem item, ImageType imageType)
|
||||
{
|
||||
var stub = new ItemStub
|
||||
|
|
|
@ -16,7 +16,6 @@ namespace MediaBrowser.Api.DefaultTheme
|
|||
public class MoviesView : BaseView
|
||||
{
|
||||
public List<ItemStub> MovieItems { get; set; }
|
||||
public List<ItemStub> PeopleItems { get; set; }
|
||||
|
||||
public List<ItemStub> BoxSetItems { get; set; }
|
||||
public List<ItemStub> TrailerItems { get; set; }
|
||||
|
@ -39,7 +38,6 @@ namespace MediaBrowser.Api.DefaultTheme
|
|||
public class TvView : BaseView
|
||||
{
|
||||
public List<ItemStub> ShowsItems { get; set; }
|
||||
public List<ItemStub> ActorItems { get; set; }
|
||||
|
||||
public List<ItemStub> RomanceItems { get; set; }
|
||||
public List<ItemStub> ComedyItems { get; set; }
|
||||
|
@ -60,7 +58,8 @@ namespace MediaBrowser.Api.DefaultTheme
|
|||
public class GamesView : BaseView
|
||||
{
|
||||
public List<ItemStub> MultiPlayerItems { get; set; }
|
||||
|
||||
public List<BaseItemDto> GameSystems { get; set; }
|
||||
public List<BaseItemDto> RecentlyPlayedGames { get; set; }
|
||||
}
|
||||
|
||||
public class BaseView
|
||||
|
|
|
@ -1013,9 +1013,9 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
|
||||
if (episode != null)
|
||||
{
|
||||
var seasonNumber = episode.SpecialSeasonNumber ?? episode.ParentIndexNumber;
|
||||
var seasonNumber = episode.AirsAfterSeasonNumber ?? episode.AirsBeforeEpisodeNumber ?? episode.ParentIndexNumber;
|
||||
|
||||
return seasonNumber.HasValue && seasonNumber.Value == val;
|
||||
return episode.PremiereDate.HasValue && seasonNumber.HasValue && seasonNumber.Value == val;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -1728,11 +1728,9 @@ namespace MediaBrowser.Controller.Entities
|
|||
// If we didn't the metafile entry, check the Season
|
||||
if (metaFileEntry == null)
|
||||
{
|
||||
var episode = this as Episode;
|
||||
|
||||
if (episode != null && episode.Season != null)
|
||||
if (Parent != null)
|
||||
{
|
||||
episode.Season.ResolveArgs.GetMetaFileByPath(imagePath);
|
||||
metaFileEntry = Parent.ResolveArgs.GetMetaFileByPath(imagePath);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Common.Progress;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Localization;
|
||||
using MediaBrowser.Controller.Resolvers;
|
||||
|
@ -1315,7 +1314,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
public override async Task MarkPlayed(User user, DateTime? datePlayed, IUserDataManager userManager)
|
||||
{
|
||||
// Sweep through recursively and update status
|
||||
var tasks = GetRecursiveChildren(user, true).Where(i => !i.IsFolder).Select(c => c.MarkPlayed(user, datePlayed, userManager));
|
||||
var tasks = GetRecursiveChildren(user, true).Where(i => !i.IsFolder && i.LocationType != LocationType.Virtual).Select(c => c.MarkPlayed(user, datePlayed, userManager));
|
||||
|
||||
await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
}
|
||||
|
@ -1329,7 +1328,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
public override async Task MarkUnplayed(User user, IUserDataManager userManager)
|
||||
{
|
||||
// Sweep through recursively and update status
|
||||
var tasks = GetRecursiveChildren(user, true).Where(i => !i.IsFolder).Select(c => c.MarkUnplayed(user, userManager));
|
||||
var tasks = GetRecursiveChildren(user, true).Where(i => !i.IsFolder && i.LocationType != LocationType.Virtual).Select(c => c.MarkUnplayed(user, userManager));
|
||||
|
||||
await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
}
|
||||
|
|
|
@ -36,7 +36,9 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
/// Gets the season in which it aired.
|
||||
/// </summary>
|
||||
/// <value>The aired season.</value>
|
||||
public int? SpecialSeasonNumber { get; set; }
|
||||
public int? AirsBeforeSeasonNumber { get; set; }
|
||||
public int? AirsAfterSeasonNumber { get; set; }
|
||||
public int? AirsBeforeEpisodeNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// We want to group into series not show individually in an index
|
||||
|
|
|
@ -76,9 +76,17 @@ namespace MediaBrowser.Providers.Savers
|
|||
builder.Append("<EpisodeNumberEnd>" + SecurityElement.Escape(episode.IndexNumberEnd.Value.ToString(_usCulture)) + "</EpisodeNumberEnd>");
|
||||
}
|
||||
|
||||
if (episode.SpecialSeasonNumber.HasValue)
|
||||
if (episode.AirsAfterSeasonNumber.HasValue)
|
||||
{
|
||||
builder.Append("<SpecialSeasonNumber>" + SecurityElement.Escape(episode.SpecialSeasonNumber.Value.ToString(_usCulture)) + "</SpecialSeasonNumber>");
|
||||
builder.Append("<airsafter_season>" + SecurityElement.Escape(episode.AirsAfterSeasonNumber.Value.ToString(_usCulture)) + "</airsafter_season>");
|
||||
}
|
||||
if (episode.AirsBeforeEpisodeNumber.HasValue)
|
||||
{
|
||||
builder.Append("<airsbefore_episode>" + SecurityElement.Escape(episode.AirsBeforeEpisodeNumber.Value.ToString(_usCulture)) + "</airsbefore_episode>");
|
||||
}
|
||||
if (episode.AirsBeforeSeasonNumber.HasValue)
|
||||
{
|
||||
builder.Append("<airsbefore_season>" + SecurityElement.Escape(episode.AirsBeforeSeasonNumber.Value.ToString(_usCulture)) + "</airsbefore_season>");
|
||||
}
|
||||
|
||||
if (episode.ParentIndexNumber.HasValue)
|
||||
|
@ -105,7 +113,9 @@ namespace MediaBrowser.Providers.Savers
|
|||
"EpisodeNumber",
|
||||
"EpisodeName",
|
||||
"EpisodeNumberEnd",
|
||||
"SpecialSeasonNumber"
|
||||
"airsafter_season",
|
||||
"airsbefore_episode",
|
||||
"airsbefore_season"
|
||||
});
|
||||
|
||||
// Set last refreshed so that the provider doesn't trigger after the file save
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using MediaBrowser.Controller.Persistence;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -38,6 +39,8 @@ namespace MediaBrowser.Providers.TV
|
|||
}
|
||||
}
|
||||
|
||||
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
||||
|
||||
/// <summary>
|
||||
/// Fetches the data from XML node.
|
||||
/// </summary>
|
||||
|
@ -139,19 +142,57 @@ namespace MediaBrowser.Providers.TV
|
|||
break;
|
||||
}
|
||||
|
||||
case "SpecialSeasonNumber":
|
||||
case "airsbefore_episode":
|
||||
{
|
||||
var number = reader.ReadElementContentAsString();
|
||||
var val = reader.ReadElementContentAsString();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(number))
|
||||
if (!string.IsNullOrWhiteSpace(val))
|
||||
{
|
||||
int num;
|
||||
int rval;
|
||||
|
||||
if (int.TryParse(number, out num))
|
||||
// int.TryParse is local aware, so it can be probamatic, force us culture
|
||||
if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval))
|
||||
{
|
||||
item.SpecialSeasonNumber = num;
|
||||
item.AirsBeforeEpisodeNumber = rval;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "airsafter_season":
|
||||
{
|
||||
var val = reader.ReadElementContentAsString();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(val))
|
||||
{
|
||||
int rval;
|
||||
|
||||
// int.TryParse is local aware, so it can be probamatic, force us culture
|
||||
if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval))
|
||||
{
|
||||
item.AirsAfterSeasonNumber = rval;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "airsbefore_season":
|
||||
{
|
||||
var val = reader.ReadElementContentAsString();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(val))
|
||||
{
|
||||
int rval;
|
||||
|
||||
// int.TryParse is local aware, so it can be probamatic, force us culture
|
||||
if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval))
|
||||
{
|
||||
item.AirsBeforeSeasonNumber = rval;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ namespace MediaBrowser.Providers.TV
|
|||
{
|
||||
get
|
||||
{
|
||||
return "3";
|
||||
return "5";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -404,6 +404,24 @@ namespace MediaBrowser.Providers.TV
|
|||
break;
|
||||
}
|
||||
|
||||
case "airsbefore_episode":
|
||||
{
|
||||
var val = reader.ReadElementContentAsString();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(val))
|
||||
{
|
||||
int rval;
|
||||
|
||||
// int.TryParse is local aware, so it can be probamatic, force us culture
|
||||
if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval))
|
||||
{
|
||||
item.AirsBeforeEpisodeNumber = rval;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "airsafter_season":
|
||||
{
|
||||
var val = reader.ReadElementContentAsString();
|
||||
|
@ -415,9 +433,10 @@ namespace MediaBrowser.Providers.TV
|
|||
// int.TryParse is local aware, so it can be probamatic, force us culture
|
||||
if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval))
|
||||
{
|
||||
item.SpecialSeasonNumber = rval;
|
||||
item.AirsAfterSeasonNumber = rval;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -432,9 +451,10 @@ namespace MediaBrowser.Providers.TV
|
|||
// int.TryParse is local aware, so it can be probamatic, force us culture
|
||||
if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval))
|
||||
{
|
||||
item.SpecialSeasonNumber = rval;
|
||||
item.AirsBeforeSeasonNumber = rval;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -1029,7 +1029,7 @@ namespace MediaBrowser.Server.Implementations.Dto
|
|||
if (episode != null)
|
||||
{
|
||||
dto.IndexNumberEnd = episode.IndexNumberEnd;
|
||||
dto.SpecialSeasonNumber = episode.SpecialSeasonNumber;
|
||||
dto.SpecialSeasonNumber = episode.AirsAfterSeasonNumber ?? episode.AirsBeforeSeasonNumber;
|
||||
}
|
||||
|
||||
// Add SeriesInfo
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Common.MediaInfo;
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
|
@ -48,12 +47,12 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
|
|||
/// <summary>
|
||||
/// The audio image resource pool
|
||||
/// </summary>
|
||||
private readonly SemaphoreSlim _audioImageResourcePool = new SemaphoreSlim(1, 1);
|
||||
private readonly SemaphoreSlim _audioImageResourcePool = new SemaphoreSlim(2, 2);
|
||||
|
||||
/// <summary>
|
||||
/// The FF probe resource pool
|
||||
/// </summary>
|
||||
private readonly SemaphoreSlim _ffProbeResourcePool = new SemaphoreSlim(1, 1);
|
||||
private readonly SemaphoreSlim _ffProbeResourcePool = new SemaphoreSlim(2, 2);
|
||||
private readonly IFileSystem _fileSystem;
|
||||
|
||||
public string FFMpegPath { get; private set; }
|
||||
|
|
Loading…
Reference in New Issue
Block a user