aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MediaBrowser.Api/TvShowsService.cs38
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicArtist.cs49
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicGenre.cs43
-rw-r--r--MediaBrowser.Controller/Entities/GameGenre.cs43
-rw-r--r--MediaBrowser.Controller/Entities/Genre.cs43
-rw-r--r--MediaBrowser.Controller/Entities/InternalItemsQuery.cs2
-rw-r--r--MediaBrowser.Controller/Entities/Person.cs58
-rw-r--r--MediaBrowser.Controller/Entities/Studio.cs43
-rw-r--r--MediaBrowser.Controller/Entities/TV/Season.cs30
-rw-r--r--MediaBrowser.Controller/Entities/TV/Series.cs175
-rw-r--r--MediaBrowser.Controller/Entities/UserViewBuilder.cs53
-rw-r--r--MediaBrowser.Controller/Entities/Year.cs43
-rw-r--r--MediaBrowser.Controller/IServerApplicationPaths.cs2
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs8
-rw-r--r--MediaBrowser.Providers/Manager/MetadataService.cs11
-rw-r--r--MediaBrowser.Server.Implementations/Dto/DtoService.cs116
-rw-r--r--MediaBrowser.Server.Implementations/Library/LibraryManager.cs72
-rw-r--r--MediaBrowser.Server.Implementations/Library/SearchEngine.cs20
-rw-r--r--MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs11
-rw-r--r--MediaBrowser.Server.Implementations/ServerApplicationPaths.cs8
-rw-r--r--MediaBrowser.Server.Implementations/Session/SessionManager.cs3
21 files changed, 488 insertions, 383 deletions
diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs
index e295f3b3a..daaa6343d 100644
--- a/MediaBrowser.Api/TvShowsService.cs
+++ b/MediaBrowser.Api/TvShowsService.cs
@@ -423,23 +423,14 @@ namespace MediaBrowser.Api
throw new ResourceNotFoundException("No series exists with Id " + request.Id);
}
- var seasons = series.GetSeasons(user);
-
- if (request.IsSpecialSeason.HasValue)
+ var seasons = (await series.GetItems(new InternalItemsQuery(user)
{
- var val = request.IsSpecialSeason.Value;
-
- seasons = seasons.Where(i => i.IsSpecialSeason == val);
- }
+ IsMissing = request.IsMissing,
+ IsVirtualUnaired = request.IsVirtualUnaired,
+ IsSpecialSeason = request.IsSpecialSeason,
+ AdjacentTo = request.AdjacentTo
- seasons = FilterVirtualSeasons(request, seasons);
-
- // This must be the last filter
- if (!string.IsNullOrEmpty(request.AdjacentTo))
- {
- seasons = UserViewBuilder.FilterForAdjacency(seasons, request.AdjacentTo)
- .Cast<Season>();
- }
+ }).ConfigureAwait(false)).Items.OfType<Season>();
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)
{
var user = _userManager.GetUserById(request.UserId);
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
index 56f9a5b88..81d1deaa2 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
@@ -270,5 +270,54 @@ namespace MediaBrowser.Controller.Entities.Audio
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;
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
index 9aa5625fa..bd991d9f4 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
@@ -92,5 +92,48 @@ namespace MediaBrowser.Controller.Entities.Audio
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;
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/GameGenre.cs b/MediaBrowser.Controller/Entities/GameGenre.cs
index 5d66bf3ab..6448828fb 100644
--- a/MediaBrowser.Controller/Entities/GameGenre.cs
+++ b/MediaBrowser.Controller/Entities/GameGenre.cs
@@ -84,5 +84,48 @@ namespace MediaBrowser.Controller.Entities
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;
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/Genre.cs b/MediaBrowser.Controller/Entities/Genre.cs
index c7fe25a96..1736ba8c7 100644
--- a/MediaBrowser.Controller/Entities/Genre.cs
+++ b/MediaBrowser.Controller/Entities/Genre.cs
@@ -87,5 +87,48 @@ namespace MediaBrowser.Controller.Entities
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;
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
index 69cab5ec5..deea63112 100644
--- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
+++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
@@ -37,6 +37,7 @@ namespace MediaBrowser.Controller.Entities
public string[] Genres { get; set; }
public string[] Keywords { get; set; }
+ public bool? IsSpecialSeason { get; set; }
public bool? IsMissing { get; set; }
public bool? IsUnaired { get; set; }
public bool? IsVirtualUnaired { get; set; }
@@ -50,6 +51,7 @@ namespace MediaBrowser.Controller.Entities
public string PresentationUniqueKey { get; set; }
public string Path { get; set; }
+ public string PathNotStartsWith { get; set; }
public string Name { get; set; }
public string SlugName { get; set; }
diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs
index 4ee140b2b..f21bc0a71 100644
--- a/MediaBrowser.Controller/Entities/Person.cs
+++ b/MediaBrowser.Controller/Entities/Person.cs
@@ -122,6 +122,64 @@ namespace MediaBrowser.Controller.Entities
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>
diff --git a/MediaBrowser.Controller/Entities/Studio.cs b/MediaBrowser.Controller/Entities/Studio.cs
index 7e3d6fe8e..04b09b744 100644
--- a/MediaBrowser.Controller/Entities/Studio.cs
+++ b/MediaBrowser.Controller/Entities/Studio.cs
@@ -85,5 +85,48 @@ namespace MediaBrowser.Controller.Entities
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;
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs
index 628e27c02..842b2fd60 100644
--- a/MediaBrowser.Controller/Entities/TV/Season.cs
+++ b/MediaBrowser.Controller/Entities/TV/Season.cs
@@ -141,24 +141,6 @@ namespace MediaBrowser.Controller.Entities.TV
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)
{
if (query.User == null)
@@ -189,19 +171,17 @@ namespace MediaBrowser.Controller.Entities.TV
/// <returns>IEnumerable{Episode}.</returns>
public IEnumerable<Episode> GetEpisodes(User user)
{
- var config = user.Configuration;
-
- return GetEpisodes(Series, user, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
+ return GetEpisodes(Series, user);
}
- 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()
diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs
index e48c32a25..4915cfedc 100644
--- a/MediaBrowser.Controller/Entities/TV/Series.cs
+++ b/MediaBrowser.Controller/Entities/TV/Series.cs
@@ -207,7 +207,30 @@ namespace MediaBrowser.Controller.Entities.TV
{
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)
@@ -241,59 +264,39 @@ namespace MediaBrowser.Controller.Entities.TV
return Task.FromResult(result);
}
- public IEnumerable<Season> GetSeasons(User user, bool includeMissingSeasons, bool includeVirtualUnaired)
+ public IEnumerable<Episode> GetEpisodes(User user)
{
var seriesKey = GetUniqueSeriesKey(this);
+ Logger.Debug("GetEpisodes seriesKey: {0}", seriesKey);
- Logger.Debug("GetSeasons SeriesKey: {0}", seriesKey);
- var seasons = LibraryManager.GetItemList(new InternalItemsQuery(user)
+ var query = new InternalItemsQuery(user)
{
AncestorWithPresentationUniqueKey = seriesKey,
- IncludeItemTypes = new[] { typeof(Season).Name },
- SortBy = new[] { ItemSortBy.SortName }
-
- }).Cast<Season>().ToList();
-
-
- if (!includeMissingSeasons)
+ IncludeItemTypes = new[] {typeof (Episode).Name, typeof (Season).Name},
+ SortBy = new[] {ItemSortBy.SortName}
+ };
+ var config = user.Configuration;
+ if (!config.DisplayMissingEpisodes && !config.DisplayUnairedEpisodes)
{
- seasons = seasons.Where(i => !(i.IsMissingSeason)).ToList();
+ query.IsVirtualItem = false;
}
-
- if (!includeVirtualUnaired)
+ else if (!config.DisplayMissingEpisodes)
{
- seasons = seasons.Where(i => !i.IsVirtualUnaired).ToList();
+ query.IsMissing = false;
}
-
- return seasons;
- }
-
- public IEnumerable<Episode> GetEpisodes(User user)
- {
- var config = user.Configuration;
-
- return GetEpisodes(user, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
- }
-
- public IEnumerable<Episode> GetEpisodes(User user, bool includeMissing, bool includeVirtualUnaired)
- {
- var seriesKey = GetUniqueSeriesKey(this);
- Logger.Debug("GetEpisodes seriesKey: {0}", seriesKey);
-
- var allItems = LibraryManager.GetItemList(new InternalItemsQuery(user)
+ else if (!config.DisplayUnairedEpisodes)
{
- AncestorWithPresentationUniqueKey = seriesKey,
- IncludeItemTypes = new[] { typeof(Episode).Name, typeof(Season).Name },
- SortBy = new[] { ItemSortBy.SortName }
+ query.IsVirtualUnaired = false;
+ }
- }).ToList();
+ var allItems = LibraryManager.GetItemList(query).ToList();
Logger.Debug("GetEpisodes return {0} items from database", allItems.Count);
var allSeriesEpisodes = allItems.OfType<Episode>().ToList();
var allEpisodes = allItems.OfType<Season>()
- .SelectMany(i => i.GetEpisodes(this, user, includeMissing, includeVirtualUnaired, allSeriesEpisodes))
+ .SelectMany(i => i.GetEpisodes(this, user, allSeriesEpisodes))
.Reverse()
.ToList();
@@ -370,13 +373,6 @@ namespace MediaBrowser.Controller.Entities.TV
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)
{
Logger.Debug("Series.GetAllEpisodes entering GetItemList");
@@ -394,62 +390,51 @@ namespace MediaBrowser.Controller.Entities.TV
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);
-
- return GetSeasonEpisodes(user, parentSeason, includeMissingEpisodes, includeVirtualUnairedEpisodes, episodes);
- }
+ var seriesKey = GetUniqueSeriesKey(this);
+ Logger.Debug("GetSeasonEpisodes seriesKey: {0}", seriesKey);
- public IEnumerable<Episode> GetSeasonEpisodes(User user, Season parentSeason, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes, IEnumerable<Episode> allSeriesEpisodes)
- {
- if (allSeriesEpisodes == null)
+ var query = new InternalItemsQuery(user)
{
- Logger.Debug("GetSeasonEpisodes allSeriesEpisodes is null");
- return GetSeasonEpisodes(user, parentSeason, includeMissingEpisodes, includeVirtualUnairedEpisodes);
+ AncestorWithPresentationUniqueKey = seriesKey,
+ IncludeItemTypes = new[] { typeof(Episode).Name },
+ SortBy = new[] { ItemSortBy.SortName }
+ };
+ var config = user.Configuration;
+ if (!config.DisplayMissingEpisodes && !config.DisplayUnairedEpisodes)
+ {
+ query.IsVirtualItem = false;
}
-
- Logger.Debug("GetSeasonEpisodes FilterEpisodesBySeason");
- var episodes = FilterEpisodesBySeason(allSeriesEpisodes, parentSeason, ConfigurationManager.Configuration.DisplaySpecialsWithinSeasons);
-
- if (!includeMissingEpisodes)
+ else if (!config.DisplayMissingEpisodes)
{
- 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)
- .Cast<Episode>();
+ return GetSeasonEpisodes(user, parentSeason, allItems);
}
- /// <summary>
- /// Filters the episodes by season.
- /// </summary>
- public static IEnumerable<Episode> FilterEpisodesBySeason(IEnumerable<Episode> episodes, int seasonNumber, bool includeSpecials)
+ public IEnumerable<Episode> GetSeasonEpisodes(User user, Season parentSeason, IEnumerable<Episode> allSeriesEpisodes)
{
- 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 =>
- {
- var episode = i;
-
- if (episode != null)
- {
- var currentSeasonNumber = episode.AiredSeasonNumber;
+ Logger.Debug("GetSeasonEpisodes FilterEpisodesBySeason");
+ var episodes = FilterEpisodesBySeason(allSeriesEpisodes, parentSeason, ConfigurationManager.Configuration.DisplaySpecialsWithinSeasons);
- 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>
@@ -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)
{
return config.BlockUnratedItems.Contains(UnratedItem.Series);
diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
index 6128192ea..9f3acc3fc 100644
--- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs
+++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
@@ -1100,8 +1100,6 @@ namespace MediaBrowser.Controller.Entities
bool? isVirtualUnaired,
bool? isUnaired)
{
- items = FilterVirtualSeasons(items, isMissing, isVirtualUnaired, isUnaired);
-
if (isMissing.HasValue)
{
var val = isMissing.Value;
@@ -1147,57 +1145,6 @@ namespace MediaBrowser.Controller.Entities
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,
int? totalRecordLimit,
InternalItemsQuery query,
diff --git a/MediaBrowser.Controller/Entities/Year.cs b/MediaBrowser.Controller/Entities/Year.cs
index db896f1fc..4197ea93e 100644
--- a/MediaBrowser.Controller/Entities/Year.cs
+++ b/MediaBrowser.Controller/Entities/Year.cs
@@ -112,5 +112,48 @@ namespace MediaBrowser.Controller.Entities
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;
+ }
}
}
diff --git a/MediaBrowser.Controller/IServerApplicationPaths.cs b/MediaBrowser.Controller/IServerApplicationPaths.cs
index c07934d0b..c89a60a6f 100644
--- a/MediaBrowser.Controller/IServerApplicationPaths.cs
+++ b/MediaBrowser.Controller/IServerApplicationPaths.cs
@@ -106,5 +106,7 @@ namespace MediaBrowser.Controller
/// </summary>
/// <value>The internal metadata path.</value>
string InternalMetadataPath { get; }
+
+ string ArtistsPath { get; }
}
} \ No newline at end of file
diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
index c8a28e832..e90f6bdc3 100644
--- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
@@ -343,14 +343,16 @@ namespace MediaBrowser.MediaEncoding.Encoder
// If that doesn't pan out, then do a recursive search
var files = Directory.GetFiles(path);
- var ffmpegPath = files.FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffmpeg", StringComparison.OrdinalIgnoreCase));
- var ffprobePath = files.FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffprobe", StringComparison.OrdinalIgnoreCase));
+ var excludeExtensions = new[] { ".c" };
+
+ 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))
{
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))
{
diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs
index 04437cff7..2a69948b1 100644
--- a/MediaBrowser.Providers/Manager/MetadataService.cs
+++ b/MediaBrowser.Providers/Manager/MetadataService.cs
@@ -42,6 +42,13 @@ namespace MediaBrowser.Providers.Manager
var config = ProviderManager.GetMetadataOptions(item);
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 localImagesFailed = false;
@@ -70,14 +77,10 @@ namespace MediaBrowser.Providers.Manager
bool hasRefreshedMetadata = true;
bool hasRefreshedImages = true;
- var requiresRefresh = false;
// Next run metadata providers
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)
.ToList();
diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
index 3d257d194..be68162ca 100644
--- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs
+++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
@@ -955,20 +955,23 @@ namespace MediaBrowser.Server.Implementations.Dto
dto.Genres = item.Genres;
}
- dto.ImageTags = new Dictionary<ImageType, string>();
-
- // Prevent implicitly captured closure
- var currentItem = item;
- foreach (var image in currentItem.ImageInfos.Where(i => !currentItem.AllowsMultipleImages(i.Type))
- .ToList())
+ if (options.EnableImages)
{
- if (options.GetImageLimit(image.Type) > 0)
- {
- var tag = GetImageCacheTag(item, image);
+ dto.ImageTags = new Dictionary<ImageType, string>();
- if (tag != null)
+ // Prevent implicitly captured closure
+ var currentItem = item;
+ foreach (var image in currentItem.ImageInfos.Where(i => !currentItem.AllowsMultipleImages(i.Type))
+ .ToList())
+ {
+ if (options.GetImageLimit(image.Type) > 0)
{
- dto.ImageTags[image.Type] = tag;
+ var tag = GetImageCacheTag(item, image);
+
+ if (tag != null)
+ {
+ dto.ImageTags[image.Type] = tag;
+ }
}
}
}
@@ -1528,97 +1531,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>
/// Attaches the primary image aspect ratio.
/// </summary>
/// <param name="dto">The dto.</param>
diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
index a19f70e68..a5e6c1b92 100644
--- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
@@ -829,7 +829,7 @@ namespace MediaBrowser.Server.Implementations.Library
/// <returns>Task{Person}.</returns>
public Person GetPerson(string name)
{
- return GetItemByName<Person>(ConfigurationManager.ApplicationPaths.PeoplePath, name);
+ return CreateItemByName<Person>(Person.GetPath(name), name);
}
/// <summary>
@@ -839,7 +839,7 @@ namespace MediaBrowser.Server.Implementations.Library
/// <returns>Task{Studio}.</returns>
public Studio GetStudio(string name)
{
- return GetItemByName<Studio>(ConfigurationManager.ApplicationPaths.StudioPath, name);
+ return CreateItemByName<Studio>(Studio.GetPath(name), name);
}
/// <summary>
@@ -849,7 +849,7 @@ namespace MediaBrowser.Server.Implementations.Library
/// <returns>Task{Genre}.</returns>
public Genre GetGenre(string name)
{
- return GetItemByName<Genre>(ConfigurationManager.ApplicationPaths.GenrePath, name);
+ return CreateItemByName<Genre>(Genre.GetPath(name), name);
}
/// <summary>
@@ -859,7 +859,7 @@ namespace MediaBrowser.Server.Implementations.Library
/// <returns>Task{MusicGenre}.</returns>
public MusicGenre GetMusicGenre(string name)
{
- return GetItemByName<MusicGenre>(ConfigurationManager.ApplicationPaths.MusicGenrePath, name);
+ return CreateItemByName<MusicGenre>(MusicGenre.GetPath(name), name);
}
/// <summary>
@@ -869,15 +869,10 @@ namespace MediaBrowser.Server.Implementations.Library
/// <returns>Task{GameGenre}.</returns>
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>
/// Gets a Year
/// </summary>
/// <param name="value">The value.</param>
@@ -890,19 +885,9 @@ namespace MediaBrowser.Server.Implementations.Library
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>
- /// Gets the artists path.
- /// </summary>
- /// <value>The artists path.</value>
- public string ArtistsPath
- {
- get
- {
- return Path.Combine(ConfigurationManager.ApplicationPaths.ItemsByNamePath, "artists");
- }
+ return CreateItemByName<Year>(Year.GetPath(name), name);
}
/// <summary>
@@ -912,48 +897,7 @@ namespace MediaBrowser.Server.Implementations.Library
/// <returns>Task{Genre}.</returns>
public MusicArtist GetArtist(string name)
{
- return GetItemByName<MusicArtist>(ArtistsPath, 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);
+ return CreateItemByName<MusicArtist>(MusicArtist.GetPath(name), name);
}
private T CreateItemByName<T>(string path, string name)
diff --git a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs
index cf6f070d0..a6d6b5cb8 100644
--- a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs
+++ b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs
@@ -166,12 +166,12 @@ namespace MediaBrowser.Server.Implementations.Library
ExcludeItemTypes = excludeItemTypes.ToArray(),
IncludeItemTypes = includeItemTypes.ToArray(),
Limit = query.Limit,
- IncludeItemsByName = true
-
+ IncludeItemsByName = true,
+ IsVirtualItem = false
});
// 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);
@@ -187,20 +187,6 @@ namespace MediaBrowser.Server.Implementations.Library
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>
/// Gets the index.
/// </summary>
diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
index cf8e2fe36..8006e2b08 100644
--- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
+++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
@@ -3095,6 +3095,17 @@ namespace MediaBrowser.Server.Implementations.Persistence
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.Value)
diff --git a/MediaBrowser.Server.Implementations/ServerApplicationPaths.cs b/MediaBrowser.Server.Implementations/ServerApplicationPaths.cs
index 8a04f29a2..237d49fda 100644
--- a/MediaBrowser.Server.Implementations/ServerApplicationPaths.cs
+++ b/MediaBrowser.Server.Implementations/ServerApplicationPaths.cs
@@ -88,6 +88,14 @@ namespace MediaBrowser.Server.Implementations
}
}
+ public string ArtistsPath
+ {
+ get
+ {
+ return Path.Combine(ItemsByNamePath, "artists");
+ }
+ }
+
/// <summary>
/// Gets the path to the Genre directory
/// </summary>
diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
index 84aab5e1f..f495e557a 100644
--- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs
+++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
@@ -1001,7 +1001,8 @@ namespace MediaBrowser.Server.Implementations.Session
var series = episode.Series;
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)
.ToList();