update season queries

pull/702/head
Luke Pulverenti 8 years ago
parent d6dc6ffe7e
commit cc62faa1c2

@ -423,23 +423,14 @@ namespace MediaBrowser.Api
throw new ResourceNotFoundException("No series exists with Id " + request.Id); throw new ResourceNotFoundException("No series exists with Id " + request.Id);
} }
var seasons = series.GetSeasons(user); var seasons = (await series.GetItems(new InternalItemsQuery(user)
if (request.IsSpecialSeason.HasValue)
{ {
var val = request.IsSpecialSeason.Value; IsMissing = request.IsMissing,
IsVirtualUnaired = request.IsVirtualUnaired,
seasons = seasons.Where(i => i.IsSpecialSeason == val); IsSpecialSeason = request.IsSpecialSeason,
} AdjacentTo = request.AdjacentTo
seasons = FilterVirtualSeasons(request, seasons); }).ConfigureAwait(false)).Items.OfType<Season>();
// This must be the last filter
if (!string.IsNullOrEmpty(request.AdjacentTo))
{
seasons = UserViewBuilder.FilterForAdjacency(seasons, request.AdjacentTo)
.Cast<Season>();
}
var dtoOptions = GetDtoOptions(request); var dtoOptions = GetDtoOptions(request);
@ -453,23 +444,6 @@ namespace MediaBrowser.Api
}; };
} }
private IEnumerable<Season> FilterVirtualSeasons(GetSeasons request, IEnumerable<Season> items)
{
if (request.IsMissing.HasValue)
{
var val = request.IsMissing.Value;
items = items.Where(i => (i.IsMissingSeason) == val);
}
if (request.IsVirtualUnaired.HasValue)
{
var val = request.IsVirtualUnaired.Value;
items = items.Where(i => i.IsVirtualUnaired == val);
}
return items;
}
public async Task<object> Get(GetEpisodes request) public async Task<object> Get(GetEpisodes request)
{ {
var user = _userManager.GetUserById(request.UserId); var user = _userManager.GetUserById(request.UserId);

@ -270,5 +270,54 @@ namespace MediaBrowser.Controller.Entities.Audio
return false; return false;
} }
} }
public static string GetPath(string name, bool normalizeName = true)
{
// Trim the period at the end because windows will have a hard time with that
var validName = normalizeName ?
FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
name;
return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.ArtistsPath, validName);
}
private string GetRebasedPath()
{
return GetPath(System.IO.Path.GetFileName(Path), false);
}
public override bool RequiresRefresh()
{
if (IsAccessedByName)
{
var newPath = GetRebasedPath();
if (!string.Equals(Path, newPath, StringComparison.Ordinal))
{
Logger.Debug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath);
return true;
}
}
return base.RequiresRefresh();
}
/// <summary>
/// This is called before any metadata refresh and returns true or false indicating if changes were made
/// </summary>
public override bool BeforeMetadataRefresh()
{
var hasChanges = base.BeforeMetadataRefresh();
if (IsAccessedByName)
{
var newPath = GetRebasedPath();
if (!string.Equals(Path, newPath, StringComparison.Ordinal))
{
Path = newPath;
hasChanges = true;
}
}
return hasChanges;
}
} }
} }

@ -92,5 +92,48 @@ namespace MediaBrowser.Controller.Entities.Audio
return LibraryManager.GetItemList(query); return LibraryManager.GetItemList(query);
} }
public static string GetPath(string name, bool normalizeName = true)
{
// Trim the period at the end because windows will have a hard time with that
var validName = normalizeName ?
FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
name;
return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.MusicGenrePath, validName);
}
private string GetRebasedPath()
{
return GetPath(System.IO.Path.GetFileName(Path), false);
}
public override bool RequiresRefresh()
{
var newPath = GetRebasedPath();
if (!string.Equals(Path, newPath, StringComparison.Ordinal))
{
Logger.Debug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath);
return true;
}
return base.RequiresRefresh();
}
/// <summary>
/// This is called before any metadata refresh and returns true or false indicating if changes were made
/// </summary>
public override bool BeforeMetadataRefresh()
{
var hasChanges = base.BeforeMetadataRefresh();
var newPath = GetRebasedPath();
if (!string.Equals(Path, newPath, StringComparison.Ordinal))
{
Path = newPath;
hasChanges = true;
}
return hasChanges;
}
} }
} }

@ -84,5 +84,48 @@ namespace MediaBrowser.Controller.Entities
return false; return false;
} }
} }
public static string GetPath(string name, bool normalizeName = true)
{
// Trim the period at the end because windows will have a hard time with that
var validName = normalizeName ?
FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
name;
return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.GameGenrePath, validName);
}
private string GetRebasedPath()
{
return GetPath(System.IO.Path.GetFileName(Path), false);
}
public override bool RequiresRefresh()
{
var newPath = GetRebasedPath();
if (!string.Equals(Path, newPath, StringComparison.Ordinal))
{
Logger.Debug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath);
return true;
}
return base.RequiresRefresh();
}
/// <summary>
/// This is called before any metadata refresh and returns true or false indicating if changes were made
/// </summary>
public override bool BeforeMetadataRefresh()
{
var hasChanges = base.BeforeMetadataRefresh();
var newPath = GetRebasedPath();
if (!string.Equals(Path, newPath, StringComparison.Ordinal))
{
Path = newPath;
hasChanges = true;
}
return hasChanges;
}
} }
} }

@ -87,5 +87,48 @@ namespace MediaBrowser.Controller.Entities
return false; return false;
} }
} }
public static string GetPath(string name, bool normalizeName = true)
{
// Trim the period at the end because windows will have a hard time with that
var validName = normalizeName ?
FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
name;
return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.GenrePath, validName);
}
private string GetRebasedPath()
{
return GetPath(System.IO.Path.GetFileName(Path), false);
}
public override bool RequiresRefresh()
{
var newPath = GetRebasedPath();
if (!string.Equals(Path, newPath, StringComparison.Ordinal))
{
Logger.Debug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath);
return true;
}
return base.RequiresRefresh();
}
/// <summary>
/// This is called before any metadata refresh and returns true or false indicating if changes were made
/// </summary>
public override bool BeforeMetadataRefresh()
{
var hasChanges = base.BeforeMetadataRefresh();
var newPath = GetRebasedPath();
if (!string.Equals(Path, newPath, StringComparison.Ordinal))
{
Path = newPath;
hasChanges = true;
}
return hasChanges;
}
} }
} }

@ -37,6 +37,7 @@ namespace MediaBrowser.Controller.Entities
public string[] Genres { get; set; } public string[] Genres { get; set; }
public string[] Keywords { get; set; } public string[] Keywords { get; set; }
public bool? IsSpecialSeason { get; set; }
public bool? IsMissing { get; set; } public bool? IsMissing { get; set; }
public bool? IsUnaired { get; set; } public bool? IsUnaired { get; set; }
public bool? IsVirtualUnaired { get; set; } public bool? IsVirtualUnaired { get; set; }
@ -50,6 +51,7 @@ namespace MediaBrowser.Controller.Entities
public string PresentationUniqueKey { get; set; } public string PresentationUniqueKey { get; set; }
public string Path { get; set; } public string Path { get; set; }
public string PathNotStartsWith { get; set; }
public string Name { get; set; } public string Name { get; set; }
public string SlugName { get; set; } public string SlugName { get; set; }

@ -122,6 +122,64 @@ namespace MediaBrowser.Controller.Entities
return false; return false;
} }
} }
public static string GetPath(string name, bool normalizeName = true)
{
// Trim the period at the end because windows will have a hard time with that
var validFilename = normalizeName ?
FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
name;
string subFolderPrefix = null;
foreach (char c in validFilename)
{
if (char.IsLetterOrDigit(c))
{
subFolderPrefix = c.ToString();
break;
}
}
var path = ConfigurationManager.ApplicationPaths.PeoplePath;
return string.IsNullOrEmpty(subFolderPrefix) ?
System.IO.Path.Combine(path, validFilename) :
System.IO.Path.Combine(path, subFolderPrefix, validFilename);
}
private string GetRebasedPath()
{
return GetPath(System.IO.Path.GetFileName(Path), false);
}
public override bool RequiresRefresh()
{
var newPath = GetRebasedPath();
if (!string.Equals(Path, newPath, StringComparison.Ordinal))
{
Logger.Debug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath);
return true;
}
return base.RequiresRefresh();
}
/// <summary>
/// This is called before any metadata refresh and returns true or false indicating if changes were made
/// </summary>
public override bool BeforeMetadataRefresh()
{
var hasChanges = base.BeforeMetadataRefresh();
var newPath = GetRebasedPath();
if (!string.Equals(Path, newPath, StringComparison.Ordinal))
{
Path = newPath;
hasChanges = true;
}
return hasChanges;
}
} }
/// <summary> /// <summary>

@ -85,5 +85,48 @@ namespace MediaBrowser.Controller.Entities
return false; return false;
} }
} }
public static string GetPath(string name, bool normalizeName = true)
{
// Trim the period at the end because windows will have a hard time with that
var validName = normalizeName ?
FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
name;
return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.StudioPath, validName);
}
private string GetRebasedPath()
{
return GetPath(System.IO.Path.GetFileName(Path), false);
}
public override bool RequiresRefresh()
{
var newPath = GetRebasedPath();
if (!string.Equals(Path, newPath, StringComparison.Ordinal))
{
Logger.Debug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath);
return true;
}
return base.RequiresRefresh();
}
/// <summary>
/// This is called before any metadata refresh and returns true or false indicating if changes were made
/// </summary>
public override bool BeforeMetadataRefresh()
{
var hasChanges = base.BeforeMetadataRefresh();
var newPath = GetRebasedPath();
if (!string.Equals(Path, newPath, StringComparison.Ordinal))
{
Path = newPath;
hasChanges = true;
}
return hasChanges;
}
} }
} }

@ -141,24 +141,6 @@ namespace MediaBrowser.Controller.Entities.TV
return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name; return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name;
} }
[IgnoreDataMember]
public bool IsMissingSeason
{
get { return (IsVirtualItem) && !IsUnaired; }
}
[IgnoreDataMember]
public bool IsVirtualUnaired
{
get { return (IsVirtualItem) && IsUnaired; }
}
[IgnoreDataMember]
public bool IsSpecialSeason
{
get { return (IndexNumber ?? -1) == 0; }
}
protected override Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery query) protected override Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery query)
{ {
if (query.User == null) if (query.User == null)
@ -189,19 +171,17 @@ namespace MediaBrowser.Controller.Entities.TV
/// <returns>IEnumerable{Episode}.</returns> /// <returns>IEnumerable{Episode}.</returns>
public IEnumerable<Episode> GetEpisodes(User user) public IEnumerable<Episode> GetEpisodes(User user)
{ {
var config = user.Configuration; return GetEpisodes(Series, user);
return GetEpisodes(Series, user, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
} }
public IEnumerable<Episode> GetEpisodes(Series series, User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes) public IEnumerable<Episode> GetEpisodes(Series series, User user)
{ {
return GetEpisodes(series, user, includeMissingEpisodes, includeVirtualUnairedEpisodes, null); return GetEpisodes(series, user, null);
} }
public IEnumerable<Episode> GetEpisodes(Series series, User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes, IEnumerable<Episode> allSeriesEpisodes) public IEnumerable<Episode> GetEpisodes(Series series, User user, IEnumerable<Episode> allSeriesEpisodes)
{ {
return series.GetSeasonEpisodes(user, this, includeMissingEpisodes, includeVirtualUnairedEpisodes, allSeriesEpisodes); return series.GetSeasonEpisodes(user, this, allSeriesEpisodes);
} }
public IEnumerable<Episode> GetEpisodes() public IEnumerable<Episode> GetEpisodes()

@ -207,7 +207,30 @@ namespace MediaBrowser.Controller.Entities.TV
{ {
var config = user.Configuration; var config = user.Configuration;
return GetSeasons(user, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes); var seriesKey = GetUniqueSeriesKey(this);
Logger.Debug("GetSeasons SeriesKey: {0}", seriesKey);
var query = new InternalItemsQuery(user)
{
AncestorWithPresentationUniqueKey = seriesKey,
IncludeItemTypes = new[] {typeof (Season).Name},
SortBy = new[] {ItemSortBy.SortName}
};
if (!config.DisplayMissingEpisodes && !config.DisplayUnairedEpisodes)
{
query.IsVirtualItem = false;
}
else if (!config.DisplayMissingEpisodes)
{
query.IsMissing = false;
}
else if (!config.DisplayUnairedEpisodes)
{
query.IsVirtualUnaired = false;
}
return LibraryManager.GetItemList(query).Cast<Season>();
} }
protected override Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery query) protected override Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery query)
@ -241,59 +264,39 @@ namespace MediaBrowser.Controller.Entities.TV
return Task.FromResult(result); return Task.FromResult(result);
} }
public IEnumerable<Season> GetSeasons(User user, bool includeMissingSeasons, bool includeVirtualUnaired) public IEnumerable<Episode> GetEpisodes(User user)
{ {
var seriesKey = GetUniqueSeriesKey(this); var seriesKey = GetUniqueSeriesKey(this);
Logger.Debug("GetEpisodes seriesKey: {0}", seriesKey);
Logger.Debug("GetSeasons SeriesKey: {0}", seriesKey); var query = new InternalItemsQuery(user)
var seasons = LibraryManager.GetItemList(new InternalItemsQuery(user)
{ {
AncestorWithPresentationUniqueKey = seriesKey, AncestorWithPresentationUniqueKey = seriesKey,
IncludeItemTypes = new[] { typeof(Season).Name }, IncludeItemTypes = new[] {typeof (Episode).Name, typeof (Season).Name},
SortBy = new[] {ItemSortBy.SortName} SortBy = new[] {ItemSortBy.SortName}
};
}).Cast<Season>().ToList(); var config = user.Configuration;
if (!config.DisplayMissingEpisodes && !config.DisplayUnairedEpisodes)
if (!includeMissingSeasons)
{ {
seasons = seasons.Where(i => !(i.IsMissingSeason)).ToList(); query.IsVirtualItem = false;
} }
else if (!config.DisplayMissingEpisodes)
if (!includeVirtualUnaired)
{ {
seasons = seasons.Where(i => !i.IsVirtualUnaired).ToList(); query.IsMissing = false;
} }
else if (!config.DisplayUnairedEpisodes)
return seasons;
}
public IEnumerable<Episode> GetEpisodes(User user)
{ {
var config = user.Configuration; query.IsVirtualUnaired = false;
return GetEpisodes(user, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
} }
public IEnumerable<Episode> GetEpisodes(User user, bool includeMissing, bool includeVirtualUnaired) var allItems = LibraryManager.GetItemList(query).ToList();
{
var seriesKey = GetUniqueSeriesKey(this);
Logger.Debug("GetEpisodes seriesKey: {0}", seriesKey);
var allItems = LibraryManager.GetItemList(new InternalItemsQuery(user)
{
AncestorWithPresentationUniqueKey = seriesKey,
IncludeItemTypes = new[] { typeof(Episode).Name, typeof(Season).Name },
SortBy = new[] { ItemSortBy.SortName }
}).ToList();
Logger.Debug("GetEpisodes return {0} items from database", allItems.Count); Logger.Debug("GetEpisodes return {0} items from database", allItems.Count);
var allSeriesEpisodes = allItems.OfType<Episode>().ToList(); var allSeriesEpisodes = allItems.OfType<Episode>().ToList();
var allEpisodes = allItems.OfType<Season>() var allEpisodes = allItems.OfType<Season>()
.SelectMany(i => i.GetEpisodes(this, user, includeMissing, includeVirtualUnaired, allSeriesEpisodes)) .SelectMany(i => i.GetEpisodes(this, user, allSeriesEpisodes))
.Reverse() .Reverse()
.ToList(); .ToList();
@ -370,13 +373,6 @@ namespace MediaBrowser.Controller.Entities.TV
progress.Report(100); progress.Report(100);
} }
public IEnumerable<Episode> GetSeasonEpisodes(User user, Season season)
{
var config = user.Configuration;
return GetSeasonEpisodes(user, season, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
}
private IEnumerable<Episode> GetAllEpisodes(User user) private IEnumerable<Episode> GetAllEpisodes(User user)
{ {
Logger.Debug("Series.GetAllEpisodes entering GetItemList"); Logger.Debug("Series.GetAllEpisodes entering GetItemList");
@ -394,62 +390,51 @@ namespace MediaBrowser.Controller.Entities.TV
return result; return result;
} }
public IEnumerable<Episode> GetSeasonEpisodes(User user, Season parentSeason, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes) public IEnumerable<Episode> GetSeasonEpisodes(User user, Season parentSeason)
{ {
IEnumerable<Episode> episodes = GetAllEpisodes(user); var seriesKey = GetUniqueSeriesKey(this);
Logger.Debug("GetSeasonEpisodes seriesKey: {0}", seriesKey);
return GetSeasonEpisodes(user, parentSeason, includeMissingEpisodes, includeVirtualUnairedEpisodes, episodes);
}
public IEnumerable<Episode> GetSeasonEpisodes(User user, Season parentSeason, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes, IEnumerable<Episode> allSeriesEpisodes) var query = new InternalItemsQuery(user)
{ {
if (allSeriesEpisodes == null) AncestorWithPresentationUniqueKey = seriesKey,
IncludeItemTypes = new[] { typeof(Episode).Name },
SortBy = new[] { ItemSortBy.SortName }
};
var config = user.Configuration;
if (!config.DisplayMissingEpisodes && !config.DisplayUnairedEpisodes)
{ {
Logger.Debug("GetSeasonEpisodes allSeriesEpisodes is null"); query.IsVirtualItem = false;
return GetSeasonEpisodes(user, parentSeason, includeMissingEpisodes, includeVirtualUnairedEpisodes);
} }
else if (!config.DisplayMissingEpisodes)
Logger.Debug("GetSeasonEpisodes FilterEpisodesBySeason");
var episodes = FilterEpisodesBySeason(allSeriesEpisodes, parentSeason, ConfigurationManager.Configuration.DisplaySpecialsWithinSeasons);
if (!includeMissingEpisodes)
{ {
episodes = episodes.Where(i => !i.IsMissingEpisode); query.IsMissing = false;
} }
if (!includeVirtualUnairedEpisodes) else if (!config.DisplayUnairedEpisodes)
{ {
episodes = episodes.Where(i => !i.IsVirtualUnaired); query.IsVirtualUnaired = false;
} }
var sortBy = (parentSeason.IndexNumber ?? -1) == 0 ? ItemSortBy.SortName : ItemSortBy.AiredEpisodeOrder; var allItems = LibraryManager.GetItemList(query).OfType<Episode>();
return LibraryManager.Sort(episodes, user, new[] { sortBy }, SortOrder.Ascending) return GetSeasonEpisodes(user, parentSeason, allItems);
.Cast<Episode>();
} }
/// <summary> public IEnumerable<Episode> GetSeasonEpisodes(User user, Season parentSeason, IEnumerable<Episode> allSeriesEpisodes)
/// Filters the episodes by season.
/// </summary>
public static IEnumerable<Episode> FilterEpisodesBySeason(IEnumerable<Episode> episodes, int seasonNumber, bool includeSpecials)
{ {
if (!includeSpecials || seasonNumber < 1) if (allSeriesEpisodes == null)
{ {
return episodes.Where(i => (i.ParentIndexNumber ?? -1) == seasonNumber); Logger.Debug("GetSeasonEpisodes allSeriesEpisodes is null");
return GetSeasonEpisodes(user, parentSeason);
} }
return episodes.Where(i => Logger.Debug("GetSeasonEpisodes FilterEpisodesBySeason");
{ var episodes = FilterEpisodesBySeason(allSeriesEpisodes, parentSeason, ConfigurationManager.Configuration.DisplaySpecialsWithinSeasons);
var episode = i;
if (episode != null)
{
var currentSeasonNumber = episode.AiredSeasonNumber;
return currentSeasonNumber.HasValue && currentSeasonNumber.Value == seasonNumber; var sortBy = (parentSeason.IndexNumber ?? -1) == 0 ? ItemSortBy.SortName : ItemSortBy.AiredEpisodeOrder;
}
return false; return LibraryManager.Sort(episodes, user, new[] { sortBy }, SortOrder.Ascending)
}); .Cast<Episode>();
} }
/// <summary> /// <summary>
@ -480,6 +465,32 @@ namespace MediaBrowser.Controller.Entities.TV
}); });
} }
/// <summary>
/// Filters the episodes by season.
/// </summary>
public static IEnumerable<Episode> FilterEpisodesBySeason(IEnumerable<Episode> episodes, int seasonNumber, bool includeSpecials)
{
if (!includeSpecials || seasonNumber < 1)
{
return episodes.Where(i => (i.ParentIndexNumber ?? -1) == seasonNumber);
}
return episodes.Where(i =>
{
var episode = i;
if (episode != null)
{
var currentSeasonNumber = episode.AiredSeasonNumber;
return currentSeasonNumber.HasValue && currentSeasonNumber.Value == seasonNumber;
}
return false;
});
}
protected override bool GetBlockUnratedValue(UserPolicy config) protected override bool GetBlockUnratedValue(UserPolicy config)
{ {
return config.BlockUnratedItems.Contains(UnratedItem.Series); return config.BlockUnratedItems.Contains(UnratedItem.Series);

@ -1100,8 +1100,6 @@ namespace MediaBrowser.Controller.Entities
bool? isVirtualUnaired, bool? isVirtualUnaired,
bool? isUnaired) bool? isUnaired)
{ {
items = FilterVirtualSeasons(items, isMissing, isVirtualUnaired, isUnaired);
if (isMissing.HasValue) if (isMissing.HasValue)
{ {
var val = isMissing.Value; var val = isMissing.Value;
@ -1147,57 +1145,6 @@ namespace MediaBrowser.Controller.Entities
return items; return items;
} }
private static IEnumerable<BaseItem> FilterVirtualSeasons(
IEnumerable<BaseItem> items,
bool? isMissing,
bool? isVirtualUnaired,
bool? isUnaired)
{
if (isMissing.HasValue)
{
var val = isMissing.Value;
items = items.Where(i =>
{
var e = i as Season;
if (e != null)
{
return (e.IsMissingSeason) == val;
}
return true;
});
}
if (isUnaired.HasValue)
{
var val = isUnaired.Value;
items = items.Where(i =>
{
var e = i as Season;
if (e != null)
{
return e.IsUnaired == val;
}
return true;
});
}
if (isVirtualUnaired.HasValue)
{
var val = isVirtualUnaired.Value;
items = items.Where(i =>
{
var e = i as Season;
if (e != null)
{
return e.IsVirtualUnaired == val;
}
return true;
});
}
return items;
}
public static QueryResult<BaseItem> SortAndPage(IEnumerable<BaseItem> items, public static QueryResult<BaseItem> SortAndPage(IEnumerable<BaseItem> items,
int? totalRecordLimit, int? totalRecordLimit,
InternalItemsQuery query, InternalItemsQuery query,

@ -112,5 +112,48 @@ namespace MediaBrowser.Controller.Entities
return false; return false;
} }
} }
public static string GetPath(string name, bool normalizeName = true)
{
// Trim the period at the end because windows will have a hard time with that
var validName = normalizeName ?
FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
name;
return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.YearPath, validName);
}
private string GetRebasedPath()
{
return GetPath(System.IO.Path.GetFileName(Path), false);
}
public override bool RequiresRefresh()
{
var newPath = GetRebasedPath();
if (!string.Equals(Path, newPath, StringComparison.Ordinal))
{
Logger.Debug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath);
return true;
}
return base.RequiresRefresh();
}
/// <summary>
/// This is called before any metadata refresh and returns true or false indicating if changes were made
/// </summary>
public override bool BeforeMetadataRefresh()
{
var hasChanges = base.BeforeMetadataRefresh();
var newPath = GetRebasedPath();
if (!string.Equals(Path, newPath, StringComparison.Ordinal))
{
Path = newPath;
hasChanges = true;
}
return hasChanges;
}
} }
} }

@ -106,5 +106,7 @@ namespace MediaBrowser.Controller
/// </summary> /// </summary>
/// <value>The internal metadata path.</value> /// <value>The internal metadata path.</value>
string InternalMetadataPath { get; } string InternalMetadataPath { get; }
string ArtistsPath { get; }
} }
} }

@ -343,14 +343,16 @@ namespace MediaBrowser.MediaEncoding.Encoder
// If that doesn't pan out, then do a recursive search // If that doesn't pan out, then do a recursive search
var files = Directory.GetFiles(path); var files = Directory.GetFiles(path);
var ffmpegPath = files.FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffmpeg", StringComparison.OrdinalIgnoreCase)); var excludeExtensions = new[] { ".c" };
var ffprobePath = files.FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffprobe", StringComparison.OrdinalIgnoreCase));
var ffmpegPath = files.FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffmpeg", StringComparison.OrdinalIgnoreCase) && !excludeExtensions.Contains(Path.GetExtension(i) ?? string.Empty));
var ffprobePath = files.FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffprobe", StringComparison.OrdinalIgnoreCase) && !excludeExtensions.Contains(Path.GetExtension(i) ?? string.Empty));
if (string.IsNullOrWhiteSpace(ffmpegPath) || !File.Exists(ffmpegPath)) if (string.IsNullOrWhiteSpace(ffmpegPath) || !File.Exists(ffmpegPath))
{ {
files = Directory.GetFiles(path, "*", SearchOption.AllDirectories); files = Directory.GetFiles(path, "*", SearchOption.AllDirectories);
ffmpegPath = files.FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffmpeg", StringComparison.OrdinalIgnoreCase)); ffmpegPath = files.FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffmpeg", StringComparison.OrdinalIgnoreCase) && !excludeExtensions.Contains(Path.GetExtension(i) ?? string.Empty));
if (!string.IsNullOrWhiteSpace(ffmpegPath)) if (!string.IsNullOrWhiteSpace(ffmpegPath))
{ {

@ -42,6 +42,13 @@ namespace MediaBrowser.Providers.Manager
var config = ProviderManager.GetMetadataOptions(item); var config = ProviderManager.GetMetadataOptions(item);
var updateType = ItemUpdateType.None; var updateType = ItemUpdateType.None;
var requiresRefresh = false;
if (refreshOptions.MetadataRefreshMode != MetadataRefreshMode.None)
{
// TODO: If this returns true, should we instead just change metadata refresh mode to Full?
requiresRefresh = item.RequiresRefresh();
}
var itemImageProvider = new ItemImageProvider(Logger, ProviderManager, ServerConfigurationManager, FileSystem); var itemImageProvider = new ItemImageProvider(Logger, ProviderManager, ServerConfigurationManager, FileSystem);
var localImagesFailed = false; var localImagesFailed = false;
@ -70,14 +77,10 @@ namespace MediaBrowser.Providers.Manager
bool hasRefreshedMetadata = true; bool hasRefreshedMetadata = true;
bool hasRefreshedImages = true; bool hasRefreshedImages = true;
var requiresRefresh = false;
// Next run metadata providers // Next run metadata providers
if (refreshOptions.MetadataRefreshMode != MetadataRefreshMode.None) if (refreshOptions.MetadataRefreshMode != MetadataRefreshMode.None)
{ {
// TODO: If this returns true, should we instead just change metadata refresh mode to Full?
requiresRefresh = item.RequiresRefresh();
var providers = GetProviders(item, refreshOptions, requiresRefresh) var providers = GetProviders(item, refreshOptions, requiresRefresh)
.ToList(); .ToList();

@ -955,6 +955,8 @@ namespace MediaBrowser.Server.Implementations.Dto
dto.Genres = item.Genres; dto.Genres = item.Genres;
} }
if (options.EnableImages)
{
dto.ImageTags = new Dictionary<ImageType, string>(); dto.ImageTags = new Dictionary<ImageType, string>();
// Prevent implicitly captured closure // Prevent implicitly captured closure
@ -972,6 +974,7 @@ namespace MediaBrowser.Server.Implementations.Dto
} }
} }
} }
}
dto.Id = GetDtoId(item); dto.Id = GetDtoId(item);
dto.IndexNumber = item.IndexNumber; dto.IndexNumber = item.IndexNumber;
@ -1527,97 +1530,6 @@ namespace MediaBrowser.Server.Implementations.Dto
} }
} }
/// <summary>
/// Since it can be slow to make all of these calculations independently, this method will provide a way to do them all at once
/// </summary>
/// <param name="folder">The folder.</param>
/// <param name="user">The user.</param>
/// <param name="dto">The dto.</param>
/// <param name="fields">The fields.</param>
/// <param name="syncProgress">The synchronize progress.</param>
/// <returns>Task.</returns>
private async Task SetSpecialCounts(Folder folder, User user, BaseItemDto dto, List<ItemFields> fields, Dictionary<string, SyncJobItemStatus> syncProgress)
{
var recursiveItemCount = 0;
var unplayed = 0;
double totalPercentPlayed = 0;
double totalSyncPercent = 0;
var children = await folder.GetItems(new InternalItemsQuery
{
IsFolder = false,
Recursive = true,
ExcludeLocationTypes = new[] { LocationType.Virtual },
User = user
}).ConfigureAwait(false);
// Loop through each recursive child
foreach (var child in children.Items)
{
var userdata = _userDataRepository.GetUserData(user, child);
recursiveItemCount++;
var isUnplayed = true;
// Incrememt totalPercentPlayed
if (userdata != null)
{
if (userdata.Played)
{
totalPercentPlayed += 100;
isUnplayed = false;
}
else if (userdata.PlaybackPositionTicks > 0 && child.RunTimeTicks.HasValue && child.RunTimeTicks.Value > 0)
{
double itemPercent = userdata.PlaybackPositionTicks;
itemPercent /= child.RunTimeTicks.Value;
totalPercentPlayed += itemPercent;
}
}
if (isUnplayed)
{
unplayed++;
}
double percent = 0;
SyncJobItemStatus syncItemProgress;
if (syncProgress.TryGetValue(child.Id.ToString("N"), out syncItemProgress))
{
switch (syncItemProgress)
{
case SyncJobItemStatus.Synced:
percent = 100;
break;
case SyncJobItemStatus.Converting:
case SyncJobItemStatus.ReadyToTransfer:
case SyncJobItemStatus.Transferring:
percent = 50;
break;
}
}
totalSyncPercent += percent;
}
dto.RecursiveItemCount = recursiveItemCount;
dto.UserData.UnplayedItemCount = unplayed;
if (recursiveItemCount > 0)
{
dto.UserData.PlayedPercentage = totalPercentPlayed / recursiveItemCount;
var pct = totalSyncPercent / recursiveItemCount;
if (pct > 0)
{
dto.SyncPercent = pct;
}
}
}
/// <summary> /// <summary>
/// Attaches the primary image aspect ratio. /// Attaches the primary image aspect ratio.
/// </summary> /// </summary>

@ -829,7 +829,7 @@ namespace MediaBrowser.Server.Implementations.Library
/// <returns>Task{Person}.</returns> /// <returns>Task{Person}.</returns>
public Person GetPerson(string name) public Person GetPerson(string name)
{ {
return GetItemByName<Person>(ConfigurationManager.ApplicationPaths.PeoplePath, name); return CreateItemByName<Person>(Person.GetPath(name), name);
} }
/// <summary> /// <summary>
@ -839,7 +839,7 @@ namespace MediaBrowser.Server.Implementations.Library
/// <returns>Task{Studio}.</returns> /// <returns>Task{Studio}.</returns>
public Studio GetStudio(string name) public Studio GetStudio(string name)
{ {
return GetItemByName<Studio>(ConfigurationManager.ApplicationPaths.StudioPath, name); return CreateItemByName<Studio>(Studio.GetPath(name), name);
} }
/// <summary> /// <summary>
@ -849,7 +849,7 @@ namespace MediaBrowser.Server.Implementations.Library
/// <returns>Task{Genre}.</returns> /// <returns>Task{Genre}.</returns>
public Genre GetGenre(string name) public Genre GetGenre(string name)
{ {
return GetItemByName<Genre>(ConfigurationManager.ApplicationPaths.GenrePath, name); return CreateItemByName<Genre>(Genre.GetPath(name), name);
} }
/// <summary> /// <summary>
@ -859,7 +859,7 @@ namespace MediaBrowser.Server.Implementations.Library
/// <returns>Task{MusicGenre}.</returns> /// <returns>Task{MusicGenre}.</returns>
public MusicGenre GetMusicGenre(string name) public MusicGenre GetMusicGenre(string name)
{ {
return GetItemByName<MusicGenre>(ConfigurationManager.ApplicationPaths.MusicGenrePath, name); return CreateItemByName<MusicGenre>(MusicGenre.GetPath(name), name);
} }
/// <summary> /// <summary>
@ -869,14 +869,9 @@ namespace MediaBrowser.Server.Implementations.Library
/// <returns>Task{GameGenre}.</returns> /// <returns>Task{GameGenre}.</returns>
public GameGenre GetGameGenre(string name) public GameGenre GetGameGenre(string name)
{ {
return GetItemByName<GameGenre>(ConfigurationManager.ApplicationPaths.GameGenrePath, name); return CreateItemByName<GameGenre>(GameGenre.GetPath(name), name);
} }
/// <summary>
/// The us culture
/// </summary>
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
/// <summary> /// <summary>
/// Gets a Year /// Gets a Year
/// </summary> /// </summary>
@ -890,19 +885,9 @@ namespace MediaBrowser.Server.Implementations.Library
throw new ArgumentOutOfRangeException("Years less than or equal to 0 are invalid."); throw new ArgumentOutOfRangeException("Years less than or equal to 0 are invalid.");
} }
return GetItemByName<Year>(ConfigurationManager.ApplicationPaths.YearPath, value.ToString(UsCulture)); var name = value.ToString(CultureInfo.InvariantCulture);
}
/// <summary> return CreateItemByName<Year>(Year.GetPath(name), name);
/// Gets the artists path.
/// </summary>
/// <value>The artists path.</value>
public string ArtistsPath
{
get
{
return Path.Combine(ConfigurationManager.ApplicationPaths.ItemsByNamePath, "artists");
}
} }
/// <summary> /// <summary>
@ -912,48 +897,7 @@ namespace MediaBrowser.Server.Implementations.Library
/// <returns>Task{Genre}.</returns> /// <returns>Task{Genre}.</returns>
public MusicArtist GetArtist(string name) public MusicArtist GetArtist(string name)
{ {
return GetItemByName<MusicArtist>(ArtistsPath, name); return CreateItemByName<MusicArtist>(MusicArtist.GetPath(name), name);
}
private T GetItemByName<T>(string path, string name)
where T : BaseItem, new()
{
if (string.IsNullOrWhiteSpace(path))
{
throw new ArgumentNullException("path");
}
if (string.IsNullOrWhiteSpace(name))
{
throw new ArgumentNullException("name");
}
// Trim the period at the end because windows will have a hard time with that
var validFilename = _fileSystem.GetValidFilename(name)
.Trim()
.TrimEnd('.');
string subFolderPrefix = null;
var type = typeof(T);
if (type == typeof(Person))
{
foreach (char c in validFilename)
{
if (char.IsLetterOrDigit(c))
{
subFolderPrefix = c.ToString();
break;
}
}
}
var fullPath = string.IsNullOrEmpty(subFolderPrefix) ?
Path.Combine(path, validFilename) :
Path.Combine(path, subFolderPrefix, validFilename);
return CreateItemByName<T>(fullPath, name);
} }
private T CreateItemByName<T>(string path, string name) private T CreateItemByName<T>(string path, string name)

@ -166,12 +166,12 @@ namespace MediaBrowser.Server.Implementations.Library
ExcludeItemTypes = excludeItemTypes.ToArray(), ExcludeItemTypes = excludeItemTypes.ToArray(),
IncludeItemTypes = includeItemTypes.ToArray(), IncludeItemTypes = includeItemTypes.ToArray(),
Limit = query.Limit, Limit = query.Limit,
IncludeItemsByName = true IncludeItemsByName = true,
IsVirtualItem = false
}); });
// Add search hints based on item name // Add search hints based on item name
hints.AddRange(mediaItems.Where(IncludeInSearch).Select(item => hints.AddRange(mediaItems.Select(item =>
{ {
var index = GetIndex(item.Name, searchTerm, terms); var index = GetIndex(item.Name, searchTerm, terms);
@ -187,20 +187,6 @@ namespace MediaBrowser.Server.Implementations.Library
return Task.FromResult(returnValue); return Task.FromResult(returnValue);
} }
private bool IncludeInSearch(BaseItem item)
{
var episode = item as Episode;
if (episode != null)
{
if (episode.IsMissingEpisode)
{
return false;
}
}
return true;
}
/// <summary> /// <summary>
/// Gets the index. /// Gets the index.
/// </summary> /// </summary>

@ -3095,6 +3095,17 @@ namespace MediaBrowser.Server.Implementations.Persistence
whereClauses.Add("LocationType<>'Virtual'"); whereClauses.Add("LocationType<>'Virtual'");
} }
} }
if (query.IsSpecialSeason.HasValue)
{
if (query.IsSpecialSeason.Value)
{
whereClauses.Add("IndexNumber = 0");
}
else
{
whereClauses.Add("IndexNumber <> 0");
}
}
if (query.IsUnaired.HasValue) if (query.IsUnaired.HasValue)
{ {
if (query.IsUnaired.Value) if (query.IsUnaired.Value)

@ -88,6 +88,14 @@ namespace MediaBrowser.Server.Implementations
} }
} }
public string ArtistsPath
{
get
{
return Path.Combine(ItemsByNamePath, "artists");
}
}
/// <summary> /// <summary>
/// Gets the path to the Genre directory /// Gets the path to the Genre directory
/// </summary> /// </summary>

@ -1001,7 +1001,8 @@ namespace MediaBrowser.Server.Implementations.Session
var series = episode.Series; var series = episode.Series;
if (series != null) if (series != null)
{ {
var episodes = series.GetEpisodes(user, false, false) var episodes = series.GetEpisodes(user)
.Where(i => !i.IsVirtualItem)
.SkipWhile(i => i.Id != episode.Id) .SkipWhile(i => i.Id != episode.Id)
.ToList(); .ToList();

Loading…
Cancel
Save