support metabrowser special episode attributes

This commit is contained in:
Luke Pulverenti 2013-11-17 10:27:48 -05:00
parent 50fc350c1b
commit 9f9ab1ac9f
11 changed files with 119 additions and 111 deletions

View File

@ -21,6 +21,9 @@ namespace MediaBrowser.Api.DefaultTheme
{ {
[ApiMember(Name = "UserId", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] [ApiMember(Name = "UserId", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
public Guid UserId { get; set; } 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")] [Route("/MBT/DefaultTheme/TV", "GET")]
@ -245,6 +248,19 @@ namespace MediaBrowser.Api.DefaultTheme
var fields = new List<ItemFields>(); 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 view.BackdropItems = gamesWithBackdrops
.OrderBy(i => Guid.NewGuid()) .OrderBy(i => Guid.NewGuid())
.Take(10) .Take(10)
@ -265,12 +281,6 @@ namespace MediaBrowser.Api.DefaultTheme
.Take(1) .Take(1)
.ToList(); .ToList();
view.MiniSpotlights = gamesWithBackdrops
.Randomize("minispotlight")
.Take(5)
.Select(i => _dtoService.GetBaseItemDto(i, fields, user))
.ToList();
return ToOptimizedResult(view); return ToOptimizedResult(view);
} }
@ -324,8 +334,6 @@ namespace MediaBrowser.Api.DefaultTheme
.Take(1) .Take(1)
.ToList(); .ToList();
view.ActorItems = GetActors(series, user.Id);
var spotlightSeries = seriesWithBestBackdrops var spotlightSeries = seriesWithBestBackdrops
.Where(i => i.CommunityRating.HasValue && i.CommunityRating >= 8.5) .Where(i => i.CommunityRating.HasValue && i.CommunityRating >= 8.5)
.ToList(); .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) var items = user.RootFolder.GetRecursiveChildren(user, i => i is Movie || i is Trailer || i is BoxSet)
.ToList(); .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 view = new MoviesView();
var movies = items.OfType<Movie>() var movies = items.OfType<Movie>()
@ -439,7 +443,7 @@ namespace MediaBrowser.Api.DefaultTheme
var fields = new List<ItemFields>(); var fields = new List<ItemFields>();
var itemsWithTopBackdrops = FilterItemsForBackdropDisplay(itemsWithBackdrops).ToList(); var itemsWithTopBackdrops = FilterItemsForBackdropDisplay(moviesWithBackdrops).ToList();
view.BackdropItems = itemsWithTopBackdrops view.BackdropItems = itemsWithTopBackdrops
.OrderBy(i => Guid.NewGuid()) .OrderBy(i => Guid.NewGuid())
@ -515,10 +519,10 @@ namespace MediaBrowser.Api.DefaultTheme
.Take(1) .Take(1)
.ToList(); .ToList();
view.PeopleItems = GetActors(items, user.Id); var currentUserId = user.Id;
var spotlightItems = itemsWithTopBackdrops var spotlightItems = itemsWithTopBackdrops
.Where(i => i.CommunityRating.HasValue && i.CommunityRating >= 8) .Where(i => i.CommunityRating.HasValue && i.CommunityRating >= 8)
.Where(i => !_userDataManager.GetUserData(currentUserId, i.GetUserDataKey()).Played)
.ToList(); .ToList();
if (spotlightItems.Count < 20) if (spotlightItems.Count < 20)
@ -551,14 +555,13 @@ namespace MediaBrowser.Api.DefaultTheme
.ToList(); .ToList();
// Avoid implicitly captured closure // Avoid implicitly captured closure
var currentUserId = user.Id; miniSpotlightItems.InsertRange(0, moviesWithBackdrops
miniSpotlightItems.InsertRange(2, moviesWithBackdrops
.Where(i => _userDataManager.GetUserData(currentUserId, i.GetUserDataKey()).PlaybackPositionTicks > 0) .Where(i => _userDataManager.GetUserData(currentUserId, i.GetUserDataKey()).PlaybackPositionTicks > 0)
.OrderByDescending(i => _userDataManager.GetUserData(currentUserId, i.GetUserDataKey()).LastPlayedDate ?? DateTime.MaxValue) .OrderByDescending(i => _userDataManager.GetUserData(currentUserId, i.GetUserDataKey()).LastPlayedDate ?? DateTime.MaxValue)
.Take(3)); .Take(3));
view.MiniSpotlights = miniSpotlightItems view.MiniSpotlights = miniSpotlightItems
.Take(5) .Take(3)
.Select(i => _dtoService.GetBaseItemDto(i, fields, user)) .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
.ToList(); .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) private ItemStub GetItemStub(BaseItem item, ImageType imageType)
{ {
var stub = new ItemStub var stub = new ItemStub

View File

@ -16,7 +16,6 @@ namespace MediaBrowser.Api.DefaultTheme
public class MoviesView : BaseView public class MoviesView : BaseView
{ {
public List<ItemStub> MovieItems { get; set; } public List<ItemStub> MovieItems { get; set; }
public List<ItemStub> PeopleItems { get; set; }
public List<ItemStub> BoxSetItems { get; set; } public List<ItemStub> BoxSetItems { get; set; }
public List<ItemStub> TrailerItems { get; set; } public List<ItemStub> TrailerItems { get; set; }
@ -39,7 +38,6 @@ namespace MediaBrowser.Api.DefaultTheme
public class TvView : BaseView public class TvView : BaseView
{ {
public List<ItemStub> ShowsItems { get; set; } public List<ItemStub> ShowsItems { get; set; }
public List<ItemStub> ActorItems { get; set; }
public List<ItemStub> RomanceItems { get; set; } public List<ItemStub> RomanceItems { get; set; }
public List<ItemStub> ComedyItems { get; set; } public List<ItemStub> ComedyItems { get; set; }
@ -60,7 +58,8 @@ namespace MediaBrowser.Api.DefaultTheme
public class GamesView : BaseView public class GamesView : BaseView
{ {
public List<ItemStub> MultiPlayerItems { get; set; } public List<ItemStub> MultiPlayerItems { get; set; }
public List<BaseItemDto> GameSystems { get; set; }
public List<BaseItemDto> RecentlyPlayedGames { get; set; }
} }
public class BaseView public class BaseView

View File

@ -1013,9 +1013,9 @@ namespace MediaBrowser.Api.UserLibrary
if (episode != null) 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; return false;

View File

@ -1728,11 +1728,9 @@ namespace MediaBrowser.Controller.Entities
// If we didn't the metafile entry, check the Season // If we didn't the metafile entry, check the Season
if (metaFileEntry == null) if (metaFileEntry == null)
{ {
var episode = this as Episode; if (Parent != null)
if (episode != null && episode.Season != null)
{ {
episode.Season.ResolveArgs.GetMetaFileByPath(imagePath); metaFileEntry = Parent.ResolveArgs.GetMetaFileByPath(imagePath);
} }
} }

View File

@ -1,7 +1,6 @@
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Progress; using MediaBrowser.Common.Progress;
using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Localization; using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Resolvers; using MediaBrowser.Controller.Resolvers;
@ -1315,7 +1314,7 @@ namespace MediaBrowser.Controller.Entities
public override async Task MarkPlayed(User user, DateTime? datePlayed, IUserDataManager userManager) public override async Task MarkPlayed(User user, DateTime? datePlayed, IUserDataManager userManager)
{ {
// Sweep through recursively and update status // 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); await Task.WhenAll(tasks).ConfigureAwait(false);
} }
@ -1329,7 +1328,7 @@ namespace MediaBrowser.Controller.Entities
public override async Task MarkUnplayed(User user, IUserDataManager userManager) public override async Task MarkUnplayed(User user, IUserDataManager userManager)
{ {
// Sweep through recursively and update status // 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); await Task.WhenAll(tasks).ConfigureAwait(false);
} }

View File

@ -36,7 +36,9 @@ namespace MediaBrowser.Controller.Entities.TV
/// Gets the season in which it aired. /// Gets the season in which it aired.
/// </summary> /// </summary>
/// <value>The aired season.</value> /// <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> /// <summary>
/// We want to group into series not show individually in an index /// We want to group into series not show individually in an index

View File

@ -76,11 +76,19 @@ namespace MediaBrowser.Providers.Savers
builder.Append("<EpisodeNumberEnd>" + SecurityElement.Escape(episode.IndexNumberEnd.Value.ToString(_usCulture)) + "</EpisodeNumberEnd>"); 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) if (episode.ParentIndexNumber.HasValue)
{ {
builder.Append("<SeasonNumber>" + SecurityElement.Escape(episode.ParentIndexNumber.Value.ToString(_usCulture)) + "</SeasonNumber>"); builder.Append("<SeasonNumber>" + SecurityElement.Escape(episode.ParentIndexNumber.Value.ToString(_usCulture)) + "</SeasonNumber>");
@ -105,7 +113,9 @@ namespace MediaBrowser.Providers.Savers
"EpisodeNumber", "EpisodeNumber",
"EpisodeName", "EpisodeName",
"EpisodeNumberEnd", "EpisodeNumberEnd",
"SpecialSeasonNumber" "airsafter_season",
"airsbefore_episode",
"airsbefore_season"
}); });
// Set last refreshed so that the provider doesn't trigger after the file save // Set last refreshed so that the provider doesn't trigger after the file save

View File

@ -2,6 +2,7 @@
using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using System.Globalization;
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -38,6 +39,8 @@ namespace MediaBrowser.Providers.TV
} }
} }
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
/// <summary> /// <summary>
/// Fetches the data from XML node. /// Fetches the data from XML node.
/// </summary> /// </summary>
@ -139,19 +142,57 @@ namespace MediaBrowser.Providers.TV
break; 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; break;
} }

View File

@ -113,7 +113,7 @@ namespace MediaBrowser.Providers.TV
{ {
get get
{ {
return "3"; return "5";
} }
} }
@ -404,6 +404,24 @@ namespace MediaBrowser.Providers.TV
break; 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": case "airsafter_season":
{ {
var val = reader.ReadElementContentAsString(); 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 // int.TryParse is local aware, so it can be probamatic, force us culture
if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval)) if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval))
{ {
item.SpecialSeasonNumber = rval; item.AirsAfterSeasonNumber = rval;
} }
} }
break; break;
} }
@ -432,9 +451,10 @@ namespace MediaBrowser.Providers.TV
// int.TryParse is local aware, so it can be probamatic, force us culture // int.TryParse is local aware, so it can be probamatic, force us culture
if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval)) if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval))
{ {
item.SpecialSeasonNumber = rval; item.AirsBeforeSeasonNumber = rval;
} }
} }
break; break;
} }

View File

@ -1029,7 +1029,7 @@ namespace MediaBrowser.Server.Implementations.Dto
if (episode != null) if (episode != null)
{ {
dto.IndexNumberEnd = episode.IndexNumberEnd; dto.IndexNumberEnd = episode.IndexNumberEnd;
dto.SpecialSeasonNumber = episode.SpecialSeasonNumber; dto.SpecialSeasonNumber = episode.AirsAfterSeasonNumber ?? episode.AirsBeforeSeasonNumber;
} }
// Add SeriesInfo // Add SeriesInfo

View File

@ -1,7 +1,6 @@
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.IO; using MediaBrowser.Common.IO;
using MediaBrowser.Common.MediaInfo; using MediaBrowser.Common.MediaInfo;
using MediaBrowser.Controller.IO;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Serialization;
@ -48,12 +47,12 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// <summary> /// <summary>
/// The audio image resource pool /// The audio image resource pool
/// </summary> /// </summary>
private readonly SemaphoreSlim _audioImageResourcePool = new SemaphoreSlim(1, 1); private readonly SemaphoreSlim _audioImageResourcePool = new SemaphoreSlim(2, 2);
/// <summary> /// <summary>
/// The FF probe resource pool /// The FF probe resource pool
/// </summary> /// </summary>
private readonly SemaphoreSlim _ffProbeResourcePool = new SemaphoreSlim(1, 1); private readonly SemaphoreSlim _ffProbeResourcePool = new SemaphoreSlim(2, 2);
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
public string FFMpegPath { get; private set; } public string FFMpegPath { get; private set; }