aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs2
-rw-r--r--MediaBrowser.Api/TvShowsService.cs4
-rw-r--r--MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs2
-rw-r--r--MediaBrowser.Api/UserLibrary/ItemsService.cs1101
-rw-r--r--MediaBrowser.Controller/Channels/ChannelAudioItem.cs19
-rw-r--r--MediaBrowser.Controller/Channels/ChannelVideoItem.cs11
-rw-r--r--MediaBrowser.Controller/Channels/IChannelManager.cs10
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs2
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs2
-rw-r--r--MediaBrowser.Controller/Entities/InternalItemsQuery.cs47
-rw-r--r--MediaBrowser.Controller/Entities/UserView.cs2
-rw-r--r--MediaBrowser.Controller/Entities/UserViewBuilder.cs829
-rw-r--r--MediaBrowser.Model/Dlna/StreamInfo.cs7
-rw-r--r--MediaBrowser.Providers/Movies/MovieDbProvider.cs8
-rw-r--r--MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs13
-rw-r--r--MediaBrowser.Server.Implementations/Channels/ChannelManager.cs18
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/de.json2
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json2
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/fr.json2
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/hr.json62
-rw-r--r--MediaBrowser.ServerApplication/ApplicationHost.cs6
21 files changed, 1339 insertions, 812 deletions
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 734b6a939..ba1f73ff2 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -1718,7 +1718,7 @@ namespace MediaBrowser.Api.Playback
string mediaSourceId,
CancellationToken cancellationToken)
{
- var channelMediaSources = await ChannelManager.GetChannelItemMediaSources(id, cancellationToken)
+ var channelMediaSources = await ChannelManager.GetChannelItemMediaSources(id, true, cancellationToken)
.ConfigureAwait(false);
var list = channelMediaSources.ToList();
diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs
index f3df6c7b0..f4ea7ef94 100644
--- a/MediaBrowser.Api/TvShowsService.cs
+++ b/MediaBrowser.Api/TvShowsService.cs
@@ -344,7 +344,7 @@ namespace MediaBrowser.Api
// This must be the last filter
if (!string.IsNullOrEmpty(request.AdjacentTo))
{
- seasons = ItemsService.FilterForAdjacency(seasons, request.AdjacentTo)
+ seasons = UserViewBuilder.FilterForAdjacency(seasons, request.AdjacentTo)
.Cast<Season>();
}
@@ -434,7 +434,7 @@ namespace MediaBrowser.Api
// This must be the last filter
if (!string.IsNullOrEmpty(request.AdjacentTo))
{
- episodes = ItemsService.FilterForAdjacency(episodes, request.AdjacentTo)
+ episodes = UserViewBuilder.FilterForAdjacency(episodes, request.AdjacentTo)
.Cast<Episode>();
}
diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs
index 15a2d5c33..458cf8bae 100644
--- a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs
+++ b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs
@@ -188,7 +188,7 @@ namespace MediaBrowser.Api.UserLibrary
var imageTypes = request.GetImageTypes().ToList();
if (imageTypes.Count > 0)
{
- items = items.Where(item => imageTypes.Any(imageType => ItemsService.HasImage(item, imageType)));
+ items = items.Where(item => imageTypes.Any(item.HasImage));
}
var filters = request.GetFilters().ToList();
diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs
index 011864d35..897a68a65 100644
--- a/MediaBrowser.Api/UserLibrary/ItemsService.cs
+++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs
@@ -243,6 +243,43 @@ namespace MediaBrowser.Api.UserLibrary
[ApiMember(Name = "CollapseBoxSetItems", Description = "Whether or not to hide items behind their boxsets.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
public bool? CollapseBoxSetItems { get; set; }
+
+ public string[] GetAllGenres()
+ {
+ return (AllGenres ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
+ }
+
+ public string[] GetGenres()
+ {
+ return (Genres ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
+ }
+
+ public string[] GetStudios()
+ {
+ return (Studios ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
+ }
+
+ public string[] GetPersonTypes()
+ {
+ return (PersonTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
+ }
+
+ public int[] GetYears()
+ {
+ return (Years ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();
+ }
+
+ public IEnumerable<VideoType> GetVideoTypes()
+ {
+ var val = VideoTypes;
+
+ if (string.IsNullOrEmpty(val))
+ {
+ return new VideoType[] { };
+ }
+
+ return val.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(v => (VideoType)Enum.Parse(typeof(VideoType), v, true));
+ }
}
/// <summary>
@@ -331,21 +368,21 @@ namespace MediaBrowser.Api.UserLibrary
items = ApplyFilter(items, filter, user, _userDataRepository);
}
- items = FilterVirtualEpisodes(request, items, user);
+ items = UserViewBuilder.FilterVirtualEpisodes(items,
+ request.IsMissing,
+ request.IsVirtualUnaired,
+ request.IsUnaired);
- if (CollapseBoxSetItems(request, parentItem, user))
- {
- items = _collectionManager.CollapseItemsWithinBoxSets(items, user);
- }
+ var internalQuery = GetItemsQuery(request, user);
- items = ApplyPostCollectionCollapseFilters(request, items, user);
+ items = UserViewBuilder.CollapseBoxSetItemsIfNeeded(items, internalQuery, parentItem, user);
items = _libraryManager.Sort(items, user, request.GetOrderBy(), request.SortOrder ?? SortOrder.Ascending);
// This must be the last filter
if (!string.IsNullOrEmpty(request.AdjacentTo))
{
- items = FilterForAdjacency(items, request.AdjacentTo);
+ items = UserViewBuilder.FilterForAdjacency(items, request.AdjacentTo);
}
var itemsArray = items.ToList();
@@ -363,33 +400,6 @@ namespace MediaBrowser.Api.UserLibrary
};
}
- private bool CollapseBoxSetItems(GetItems request, BaseItem parentItem, User user)
- {
- // Could end up stuck in a loop like this
- if (parentItem is BoxSet)
- {
- return false;
- }
-
- var param = request.CollapseBoxSetItems;
-
- if (!param.HasValue)
- {
- if (user != null && !user.Configuration.GroupMoviesIntoBoxSets)
- {
- return false;
- }
-
- if (!string.IsNullOrWhiteSpace(request.IncludeItemTypes) &&
- request.IncludeItemTypes.Split(',').Contains("Movie", StringComparer.OrdinalIgnoreCase))
- {
- param = true;
- }
- }
-
- return param.HasValue && param.Value && AllowBoxSetCollapsing(request);
- }
-
/// <summary>
/// Gets the items to serialize.
/// </summary>
@@ -486,9 +496,48 @@ namespace MediaBrowser.Api.UserLibrary
Filter = (i, u) => ApplyAdditionalFilters(request, i, u, true),
Limit = request.Limit,
- StartIndex = request.StartIndex
+ StartIndex = request.StartIndex,
+ IsMissing = request.IsMissing,
+ IsVirtualUnaired = request.IsVirtualUnaired,
+ IsUnaired = request.IsUnaired,
+ CollapseBoxSetItems = request.CollapseBoxSetItems,
+ NameLessThan = request.NameLessThan,
+ NameStartsWith = request.NameStartsWith,
+ NameStartsWithOrGreater = request.NameStartsWithOrGreater,
+ HasImdbId = request.HasImdbId,
+ IsYearMismatched = request.IsYearMismatched,
+ IsUnidentified = request.IsUnidentified,
+ IsPlaceHolder = request.IsPlaceHolder,
+ IsLocked = request.IsLocked,
+ IsInBoxSet = request.IsInBoxSet,
+ IsHD = request.IsHD,
+ Is3D = request.Is3D,
+ HasTvdbId = request.HasTvdbId,
+ HasTmdbId = request.HasTmdbId,
+ HasOverview = request.HasOverview,
+ HasOfficialRating = request.HasOfficialRating,
+ HasParentalRating = request.HasParentalRating,
+ HasSpecialFeature = request.HasSpecialFeature,
+ HasSubtitles = request.HasSubtitles,
+ HasThemeSong = request.HasThemeSong,
+ HasThemeVideo = request.HasThemeVideo,
+ HasTrailer = request.HasTrailer,
+ Genres = request.GetGenres(),
+ AllGenres = request.GetAllGenres(),
+ Studios = request.GetStudios(),
+ Person = request.Person,
+ PersonTypes = request.GetPersonTypes(),
+ Years = request.GetYears(),
+ ImageTypes = request.GetImageTypes().ToArray(),
+ VideoTypes = request.GetVideoTypes().ToArray(),
+ AdjacentTo = request.AdjacentTo
};
+ if (!string.IsNullOrWhiteSpace(request.Ids))
+ {
+ query.CollapseBoxSetItems = false;
+ }
+
foreach (var filter in request.GetFilters())
{
switch (filter)
@@ -610,156 +659,376 @@ namespace MediaBrowser.Api.UserLibrary
return items;
}
- private IEnumerable<BaseItem> FilterVirtualEpisodes(GetItems request, IEnumerable<BaseItem> items, User user)
+ private bool ApplyAdditionalFilters(GetItems request, BaseItem i, User user, bool isPreFiltered)
{
- items = FilterVirtualSeasons(request, items, user);
-
- if (request.IsMissing.HasValue)
+ if (!isPreFiltered)
{
- var val = request.IsMissing.Value;
- items = items.Where(i =>
+ var mediaTypes = request.GetMediaTypes();
+ if (mediaTypes.Length > 0)
{
- var e = i as Episode;
- if (e != null)
+ if (!(!string.IsNullOrEmpty(i.MediaType) && mediaTypes.Contains(i.MediaType, StringComparer.OrdinalIgnoreCase)))
{
- return e.IsMissingEpisode == val;
+ return false;
}
- return true;
- });
- }
+ }
- if (request.IsUnaired.HasValue)
- {
- var val = request.IsUnaired.Value;
- items = items.Where(i =>
+ if (request.IsPlayed.HasValue)
{
- var e = i as Episode;
- if (e != null)
+ var val = request.IsPlayed.Value;
+ if (i.IsPlayed(user) != val)
{
- return e.IsUnaired == val;
+ return false;
}
- return true;
- });
- }
+ }
- if (request.IsVirtualUnaired.HasValue)
- {
- var val = request.IsVirtualUnaired.Value;
- items = items.Where(i =>
+ // Exclude item types
+ var excluteItemTypes = request.GetExcludeItemTypes();
+ if (excluteItemTypes.Length > 0 && excluteItemTypes.Contains(i.GetType().Name, StringComparer.OrdinalIgnoreCase))
+ {
+ return false;
+ }
+
+ // Include item types
+ var includeItemTypes = request.GetIncludeItemTypes();
+ if (includeItemTypes.Length > 0 && !includeItemTypes.Contains(i.GetType().Name, StringComparer.OrdinalIgnoreCase))
+ {
+ return false;
+ }
+
+ if (request.IsInBoxSet.HasValue)
{
- var e = i as Episode;
- if (e != null)
+ var val = request.IsInBoxSet.Value;
+ if (i.Parents.OfType<BoxSet>().Any() != val)
{
- return e.IsVirtualUnaired == val;
+ return false;
}
- return true;
- });
- }
+ }
- return items;
- }
+ // Filter by Video3DFormat
+ if (request.Is3D.HasValue)
+ {
+ var val = request.Is3D.Value;
+ var video = i as Video;
- private IEnumerable<BaseItem> FilterVirtualSeasons(GetItems request, IEnumerable<BaseItem> items, User user)
- {
- if (request.IsMissing.HasValue && request.IsVirtualUnaired.HasValue)
- {
- var isMissing = request.IsMissing.Value;
- var isVirtualUnaired = request.IsVirtualUnaired.Value;
+ if (video == null || val != video.Video3DFormat.HasValue)
+ {
+ return false;
+ }
+ }
+
+ if (request.IsHD.HasValue)
+ {
+ var val = request.IsHD.Value;
+ var video = i as Video;
+
+ if (video == null || val != video.IsHD)
+ {
+ return false;
+ }
+ }
+
+ if (request.IsUnidentified.HasValue)
+ {
+ var val = request.IsUnidentified.Value;
+ if (i.IsUnidentified != val)
+ {
+ return false;
+ }
+ }
+
+ if (request.IsLocked.HasValue)
+ {
+ var val = request.IsLocked.Value;
+ if (i.IsLocked != val)
+ {
+ return false;
+ }
+ }
+
+ if (request.HasOverview.HasValue)
+ {
+ var filterValue = request.HasOverview.Value;
+
+ var hasValue = !string.IsNullOrEmpty(i.Overview);
+
+ if (hasValue != filterValue)
+ {
+ return false;
+ }
+ }
- if (!isMissing && !isVirtualUnaired)
+ if (request.HasImdbId.HasValue)
{
- return items.Where(i =>
+ var filterValue = request.HasImdbId.Value;
+
+ var hasValue = !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Imdb));
+
+ if (hasValue != filterValue)
+ {
+ return false;
+ }
+ }
+
+ if (request.HasTmdbId.HasValue)
+ {
+ var filterValue = request.HasTmdbId.Value;
+
+ var hasValue = !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Tmdb));
+
+ if (hasValue != filterValue)
{
- var e = i as Season;
- if (e != null)
+ return false;
+ }
+ }
+
+ if (request.HasTvdbId.HasValue)
+ {
+ var filterValue = request.HasTvdbId.Value;
+
+ var hasValue = !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Tvdb));
+
+ if (hasValue != filterValue)
+ {
+ return false;
+ }
+ }
+
+ if (request.IsYearMismatched.HasValue)
+ {
+ var filterValue = request.IsYearMismatched.Value;
+
+ if (UserViewBuilder.IsYearMismatched(i) != filterValue)
+ {
+ return false;
+ }
+ }
+
+ if (request.HasOfficialRating.HasValue)
+ {
+ var filterValue = request.HasOfficialRating.Value;
+
+ var hasValue = !string.IsNullOrEmpty(i.OfficialRating);
+
+ if (hasValue != filterValue)
+ {
+ return false;
+ }
+ }
+
+ if (request.IsPlaceHolder.HasValue)
+ {
+ var filterValue = request.IsPlaceHolder.Value;
+
+ var isPlaceHolder = false;
+
+ var hasPlaceHolder = i as ISupportsPlaceHolders;
+
+ if (hasPlaceHolder != null)
+ {
+ isPlaceHolder = hasPlaceHolder.IsPlaceHolder;
+ }
+
+ if (isPlaceHolder != filterValue)
+ {
+ return false;
+ }
+ }
+
+ if (request.HasSpecialFeature.HasValue)
+ {
+ var filterValue = request.HasSpecialFeature.Value;
+
+ var movie = i as IHasSpecialFeatures;
+
+ if (movie != null)
+ {
+ var ok = filterValue
+ ? movie.SpecialFeatureIds.Count > 0
+ : movie.SpecialFeatureIds.Count == 0;
+
+ if (!ok)
{
- return !e.IsMissingOrVirtualUnaired;
+ return false;
}
- return true;
- });
+ }
+ else
+ {
+ return false;
+ }
}
- }
- if (request.IsMissing.HasValue)
- {
- var val = request.IsMissing.Value;
- items = items.Where(i =>
+ if (request.HasSubtitles.HasValue)
{
- var e = i as Season;
- if (e != null)
+ var val = request.HasSubtitles.Value;
+
+ var video = i as Video;
+
+ if (video == null || val != video.HasSubtitles)
{
- return e.IsMissingSeason == val;
+ return false;
}
- return true;
- });
- }
+ }
- if (request.IsUnaired.HasValue)
- {
- var val = request.IsUnaired.Value;
- items = items.Where(i =>
+ if (request.HasParentalRating.HasValue)
{
- var e = i as Season;
- if (e != null)
+ var val = request.HasParentalRating.Value;
+
+ var rating = i.CustomRating;
+
+ if (string.IsNullOrEmpty(rating))
{
- return e.IsUnaired == val;
+ rating = i.OfficialRating;
}
- return true;
- });
- }
- if (request.IsVirtualUnaired.HasValue)
- {
- var val = request.IsVirtualUnaired.Value;
- items = items.Where(i =>
+ if (val)
+ {
+ if (string.IsNullOrEmpty(rating))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (!string.IsNullOrEmpty(rating))
+ {
+ return false;
+ }
+ }
+ }
+
+ if (request.HasTrailer.HasValue)
{
- var e = i as Season;
- if (e != null)
+ var val = request.HasTrailer.Value;
+ var trailerCount = 0;
+
+ var hasTrailers = i as IHasTrailers;
+ if (hasTrailers != null)
{
- return e.IsVirtualUnaired == val;
+ trailerCount = hasTrailers.LocalTrailerIds.Count;
}
- return true;
- });
- }
- return items;
- }
+ var ok = val ? trailerCount > 0 : trailerCount == 0;
- private bool ApplyAdditionalFilters(GetItems request, BaseItem i, User user, bool isPreFiltered)
- {
- if (!isPreFiltered)
- {
- var mediaTypes = request.GetMediaTypes();
- if (mediaTypes.Length > 0)
+ if (!ok)
+ {
+ return false;
+ }
+ }
+
+ if (request.HasThemeSong.HasValue)
{
- if (!(!string.IsNullOrEmpty(i.MediaType) && mediaTypes.Contains(i.MediaType, StringComparer.OrdinalIgnoreCase)))
+ var filterValue = request.HasThemeSong.Value;
+
+ var themeCount = 0;
+ var iHasThemeMedia = i as IHasThemeMedia;
+
+ if (iHasThemeMedia != null)
+ {
+ themeCount = iHasThemeMedia.ThemeSongIds.Count;
+ }
+ var ok = filterValue ? themeCount > 0 : themeCount == 0;
+
+ if (!ok)
{
return false;
}
}
- if (request.IsPlayed.HasValue)
+ if (request.HasThemeVideo.HasValue)
{
- var val = request.IsPlayed.Value;
- if (i.IsPlayed(user) != val)
+ var filterValue = request.HasThemeVideo.Value;
+
+ var themeCount = 0;
+ var iHasThemeMedia = i as IHasThemeMedia;
+
+ if (iHasThemeMedia != null)
+ {
+ themeCount = iHasThemeMedia.ThemeVideoIds.Count;
+ }
+ var ok = filterValue ? themeCount > 0 : themeCount == 0;
+
+ if (!ok)
{
return false;
}
}
- // Exclude item types
- var excluteItemTypes = request.GetExcludeItemTypes();
- if (excluteItemTypes.Length > 0 && excluteItemTypes.Contains(i.GetType().Name, StringComparer.OrdinalIgnoreCase))
+ // Apply genre filter
+ var genres = request.GetGenres();
+ if (genres.Length > 0 && !(genres.Any(v => i.Genres.Contains(v, StringComparer.OrdinalIgnoreCase))))
{
return false;
}
- // Include item types
- var includeItemTypes = request.GetIncludeItemTypes();
- if (includeItemTypes.Length > 0 && !includeItemTypes.Contains(i.GetType().Name, StringComparer.OrdinalIgnoreCase))
+ // Apply genre filter
+ var allGenres = request.GetAllGenres();
+ if (allGenres.Length > 0 && !allGenres.All(v => i.Genres.Contains(v, StringComparer.OrdinalIgnoreCase)))
{
return false;
}
+
+ // Filter by VideoType
+ if (!string.IsNullOrEmpty(request.VideoTypes))
+ {
+ var types = request.VideoTypes.Split(',');
+
+ var video = i as Video;
+ if (video == null || !types.Contains(video.VideoType.ToString(), StringComparer.OrdinalIgnoreCase))
+ {
+ return false;
+ }
+ }
+
+ var imageTypes = request.GetImageTypes().ToList();
+ if (imageTypes.Count > 0)
+ {
+ if (!(imageTypes.Any(i.HasImage)))
+ {
+ return false;
+ }
+ }
+
+ // Apply studio filter
+ var studios = request.GetStudios();
+ if (studios.Length > 0 && !studios.Any(v => i.Studios.Contains(v, StringComparer.OrdinalIgnoreCase)))
+ {
+ return false;
+ }
+
+ // Apply year filter
+ var years = request.GetYears();
+ if (years.Length > 0 && !(i.ProductionYear.HasValue && years.Contains(i.ProductionYear.Value)))
+ {
+ return false;
+ }
+
+ // Apply person filter
+ if (!string.IsNullOrEmpty(request.Person))
+ {
+ var personTypes = request.GetPersonTypes();
+
+ if (personTypes.Length == 0)
+ {
+ if (!(i.People.Any(p => string.Equals(p.Name, request.Person, StringComparison.OrdinalIgnoreCase))))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ var types = personTypes;
+
+ var ok = new[] { i }.Any(item =>
+ item.People != null &&
+ item.People.Any(p =>
+ p.Name.Equals(request.Person, StringComparison.OrdinalIgnoreCase) && (types.Contains(p.Type, StringComparer.OrdinalIgnoreCase) || types.Contains(p.Role, StringComparer.OrdinalIgnoreCase))));
+
+ if (!ok)
+ {
+ return false;
+ }
+ }
+ }
}
if (request.MinCommunityRating.HasValue)
@@ -960,164 +1229,6 @@ namespace MediaBrowser.Api.UserLibrary
}
}
- // Filter by Video3DFormat
- if (request.Is3D.HasValue)
- {
- var val = request.Is3D.Value;
- var video = i as Video;
-
- if (video == null || val != video.Video3DFormat.HasValue)
- {
- return false;
- }
- }
-
- // Filter by VideoType
- if (!string.IsNullOrEmpty(request.VideoTypes))
- {
- var types = request.VideoTypes.Split(',');
-
- var video = i as Video;
- if (video == null || !types.Contains(video.VideoType.ToString(), StringComparer.OrdinalIgnoreCase))
- {
- return false;
- }
- }
-
- var imageTypes = request.GetImageTypes().ToList();
- if (imageTypes.Count > 0)
- {
- if (!(imageTypes.Any(imageType => HasImage(i, imageType))))
- {
- return false;
- }
- }
-
- // Apply genre filter
- if (!string.IsNullOrEmpty(request.Genres))
- {
- var vals = request.Genres.Split('|');
- if (!(vals.Any(v => i.Genres.Contains(v, StringComparer.OrdinalIgnoreCase))))
- {
- return false;
- }
- }
-
- // Apply genre filter
- if (!string.IsNullOrEmpty(request.AllGenres))
- {
- var vals = request.AllGenres.Split('|');
- if (!vals.All(v => i.Genres.Contains(v, StringComparer.OrdinalIgnoreCase)))
- {
- return false;
- }
- }
-
- // Apply studio filter
- if (!string.IsNullOrEmpty(request.Studios))
- {
- var vals = request.Studios.Split('|');
- if (!vals.Any(v => i.Studios.Contains(v, StringComparer.OrdinalIgnoreCase)))
- {
- return false;
- }
- }
-
- // Apply year filter
- if (!string.IsNullOrEmpty(request.Years))
- {
- var vals = request.Years.Split(',').Select(int.Parse).ToList();
- if (!(i.ProductionYear.HasValue && vals.Contains(i.ProductionYear.Value)))
- {
- return false;
- }
- }
-
- // Apply person filter
- if (!string.IsNullOrEmpty(request.Person))
- {
- var personTypes = request.PersonTypes;
-
- if (string.IsNullOrEmpty(personTypes))
- {
- if (!(i.People.Any(p => string.Equals(p.Name, request.Person, StringComparison.OrdinalIgnoreCase))))
- {
- return false;
- }
- }
- else
- {
- var types = personTypes.Split(',');
-
- var ok = new[] { i }.Any(item =>
- item.People != null &&
- item.People.Any(p =>
- p.Name.Equals(request.Person, StringComparison.OrdinalIgnoreCase) && (types.Contains(p.Type, StringComparer.OrdinalIgnoreCase) || types.Contains(p.Role, StringComparer.OrdinalIgnoreCase))));
-
- if (!ok)
- {
- return false;
- }
- }
- }
-
- if (request.HasTrailer.HasValue)
- {
- var val = request.HasTrailer.Value;
- var trailerCount = 0;
-
- var hasTrailers = i as IHasTrailers;
- if (hasTrailers != null)
- {
- trailerCount = hasTrailers.LocalTrailerIds.Count;
- }
-
- var ok = val ? trailerCount > 0 : trailerCount == 0;
-
- if (!ok)
- {
- return false;
- }
- }
-
- if (request.HasThemeSong.HasValue)
- {
- var filterValue = request.HasThemeSong.Value;
-
- var themeCount = 0;
- var iHasThemeMedia = i as IHasThemeMedia;
-
- if (iHasThemeMedia != null)
- {
- themeCount = iHasThemeMedia.ThemeSongIds.Count;
- }
- var ok = filterValue ? themeCount > 0 : themeCount == 0;
-
- if (!ok)
- {
- return false;
- }
- }
-
- if (request.HasThemeVideo.HasValue)
- {
- var filterValue = request.HasThemeVideo.Value;
-
- var themeCount = 0;
- var iHasThemeMedia = i as IHasThemeMedia;
-
- if (iHasThemeMedia != null)
- {
- themeCount = iHasThemeMedia.ThemeVideoIds.Count;
- }
- var ok = filterValue ? themeCount > 0 : themeCount == 0;
-
- if (!ok)
- {
- return false;
- }
- }
-
if (request.MinPlayers.HasValue)
{
var filterValue = request.MinPlayers.Value;
@@ -1164,106 +1275,6 @@ namespace MediaBrowser.Api.UserLibrary
}
}
- if (request.HasSpecialFeature.HasValue)
- {
- var filterValue = request.HasSpecialFeature.Value;
-
- var movie = i as IHasSpecialFeatures;
-
- if (movie != null)
- {
- var ok = filterValue
- ? movie.SpecialFeatureIds.Count > 0
- : movie.SpecialFeatureIds.Count == 0;
-
- if (!ok)
- {
- return false;
- }
- }
- else
- {
- return false;
- }
- }
-
- if (request.HasSubtitles.HasValue)
- {
- var val = request.HasSubtitles.Value;
-
- var video = i as Video;
-
- if (video == null || val != video.HasSubtitles)
- {
- return false;
- }
- }
-
- if (request.HasParentalRating.HasValue)
- {
- var val = request.HasParentalRating.Value;
-
- var rating = i.CustomRating;
-
- if (string.IsNullOrEmpty(rating))
- {
- rating = i.OfficialRating;
- }
-
- if (val)
- {
- if (string.IsNullOrEmpty(rating))
- {
- return false;
- }
- }
- else
- {
- if (!string.IsNullOrEmpty(rating))
- {
- return false;
- }
- }
- }
-
- if (request.IsHD.HasValue)
- {
- var val = request.IsHD.Value;
- var video = i as Video;
-
- if (video == null || val != video.IsHD)
- {
- return false;
- }
- }
-
- if (request.IsInBoxSet.HasValue)
- {
- var val = request.IsHD.Value;
- if (i.Parents.OfType<BoxSet>().Any() != val)
- {
- return false;
- }
- }
-
- if (request.IsUnidentified.HasValue)
- {
- var val = request.IsUnidentified.Value;
- if (i.IsUnidentified != val)
- {
- return false;
- }
- }
-
- if (request.IsLocked.HasValue)
- {
- var val = request.IsLocked.Value;
- if (i.IsLocked != val)
- {
- return false;
- }
- }
-
if (request.ParentIndexNumber.HasValue)
{
var filterValue = request.ParentIndexNumber.Value;
@@ -1324,321 +1335,9 @@ namespace MediaBrowser.Api.UserLibrary
}
}
- if (request.HasOverview.HasValue)
- {
- var filterValue = request.HasOverview.Value;
-
- var hasValue = !string.IsNullOrEmpty(i.Overview);
-
- if (hasValue != filterValue)
- {
- return false;
- }
- }
-
- if (request.HasImdbId.HasValue)
- {
- var filterValue = request.HasImdbId.Value;
-
- var hasValue = !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Imdb));
-
- if (hasValue != filterValue)
- {
- return false;
- }
- }
-
- if (request.HasTmdbId.HasValue)
- {
- var filterValue = request.HasTmdbId.Value;
-
- var hasValue = !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Tmdb));
-
- if (hasValue != filterValue)
- {
- return false;
- }
- }
-
- if (request.HasTvdbId.HasValue)
- {
- var filterValue = request.HasTvdbId.Value;
-
- var hasValue = !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Tvdb));
-
- if (hasValue != filterValue)
- {
- return false;
- }
- }
-
- if (request.IsYearMismatched.HasValue)
- {
- var filterValue = request.IsYearMismatched.Value;
-
- if (IsYearMismatched(i) != filterValue)
- {
- return false;
- }
- }
-
- if (request.HasOfficialRating.HasValue)
- {
- var filterValue = request.HasOfficialRating.Value;
-
- var hasValue = !string.IsNullOrEmpty(i.OfficialRating);
-
- if (hasValue != filterValue)
- {
- return false;
- }
- }
-
- if (request.IsPlaceHolder.HasValue)
- {
- var filterValue = request.IsPlaceHolder.Value;
-
- var isPlaceHolder = false;
-
- var hasPlaceHolder = i as ISupportsPlaceHolders;
-
- if (hasPlaceHolder != null)
- {
- isPlaceHolder = hasPlaceHolder.IsPlaceHolder;
- }
-
- if (isPlaceHolder != filterValue)
- {
- return false;
- }
- }
-
return true;
}
- private IEnumerable<BaseItem> ApplyPostCollectionCollapseFilters(GetItems request, IEnumerable<BaseItem> items, User user)
- {
- if (!string.IsNullOrEmpty(request.NameStartsWithOrGreater))
- {
- items = items.Where(i => string.Compare(request.NameStartsWithOrGreater, i.SortName, StringComparison.CurrentCultureIgnoreCase) < 1);
- }
- if (!string.IsNullOrEmpty(request.NameStartsWith))
- {
- items = items.Where(i => string.Compare(request.NameStartsWith, i.SortName.Substring(0, 1), StringComparison.CurrentCultureIgnoreCase) == 0);
- }
-
- if (!string.IsNullOrEmpty(request.NameLessThan))
- {
- items = items.Where(i => string.Compare(request.NameLessThan, i.SortName, StringComparison.CurrentCultureIgnoreCase) == 1);
- }
-
- return items;
- }
-
- private bool IsYearMismatched(BaseItem item)
- {
- if (item.ProductionYear.HasValue)
- {
- var path = item.Path;
-
- if (!string.IsNullOrEmpty(path))
- {
- int? yearInName;
- string name;
- NameParser.ParseName(Path.GetFileName(path), out name, out yearInName);
-
- // Go up a level if we didn't get a year
- if (!yearInName.HasValue)
- {
- NameParser.ParseName(Path.GetFileName(Path.GetDirectoryName(path)), out name, out yearInName);
- }
-
- if (yearInName.HasValue)
- {
- return yearInName.Value != item.ProductionYear.Value;
- }
- }
- }
-
- return false;
- }
-
- private bool AllowBoxSetCollapsing(GetItems request)
- {
- if (!string.IsNullOrWhiteSpace(request.Filters))
- {
- return false;
- }
-
- if (!string.IsNullOrWhiteSpace(request.AllGenres))
- {
- return false;
- }
-
- if (!string.IsNullOrWhiteSpace(request.Genres))
- {
- return false;
- }
-
- if (request.HasImdbId.HasValue)
- {
- return false;
- }
-
- if (request.HasOfficialRating.HasValue)
- {
- return false;
- }
-
- if (request.HasOverview.HasValue)
- {
- return false;
- }
-
- if (request.HasParentalRating.HasValue)
- {
- return false;
- }
-
- if (request.HasSpecialFeature.HasValue)
- {
- return false;
- }
-
- if (request.HasSubtitles.HasValue)
- {
- return false;
- }
-
- if (request.HasThemeSong.HasValue)
- {
- return false;
- }
-
- if (request.HasThemeVideo.HasValue)
- {
- return false;
- }
-
- if (request.HasTmdbId.HasValue)
- {
- return false;
- }
-
- if (request.HasTrailer.HasValue)
- {
- return false;
- }
-
- if (!string.IsNullOrWhiteSpace(request.Ids))
- {
- return false;
- }
-
- if (!string.IsNullOrWhiteSpace(request.ImageTypes))
- {
- return false;
- }
-
- if (request.Is3D.HasValue)
- {
- return false;
- }
-
- if (request.IsHD.HasValue)
- {
- return false;
- }
-
- if (request.IsInBoxSet.HasValue)
- {
- return false;
- }
-
- if (request.IsLocked.HasValue)
- {
- return false;
- }
-
- if (request.IsPlaceHolder.HasValue)
- {
- return false;
- }
-
- if (request.IsPlayed.HasValue)
- {
- return false;
- }
-
- if (request.IsUnidentified.HasValue)
- {
- return false;
- }
-
- if (request.IsYearMismatched.HasValue)
- {
- return false;
- }
-
- if (!string.IsNullOrWhiteSpace(request.Person))
- {
- return false;
- }
-
- if (!string.IsNullOrWhiteSpace(request.Studios))
- {
- return false;
- }
-
- if (!string.IsNullOrWhiteSpace(request.VideoTypes))
- {
- return false;
- }
-
- if (!string.IsNullOrWhiteSpace(request.Years))
- {
- return false;
- }
-
- return true;
- }
-
- internal static IEnumerable<BaseItem> FilterForAdjacency(IEnumerable<BaseItem> items, string adjacentToId)
- {
- var list = items.ToList();
-
- var adjacentToIdGuid = new Guid(adjacentToId);
- var adjacentToItem = list.FirstOrDefault(i => i.Id == adjacentToIdGuid);
-
- var index = list.IndexOf(adjacentToItem);
-
- var previousId = Guid.Empty;
- var nextId = Guid.Empty;
-
- if (index > 0)
- {
- previousId = list[index - 1].Id;
- }
-
- if (index < list.Count - 1)
- {
- nextId = list[index + 1].Id;
- }
-
- return list.Where(i => i.Id == previousId || i.Id == nextId || i.Id == adjacentToIdGuid);
- }
-
- /// <summary>
- /// Determines whether the specified item has image.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <param name="imageType">Type of the image.</param>
- /// <returns><c>true</c> if the specified item has image; otherwise, <c>false</c>.</returns>
- internal static bool HasImage(BaseItem item, ImageType imageType)
- {
- return item.HasImage(imageType);
- }
-
/// <summary>
/// Applies the paging.
/// </summary>
diff --git a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs b/MediaBrowser.Controller/Channels/ChannelAudioItem.cs
index 6d505aecb..ede366dab 100644
--- a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs
+++ b/MediaBrowser.Controller/Channels/ChannelAudioItem.cs
@@ -1,9 +1,11 @@
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Model.Channels;
using MediaBrowser.Model.Configuration;
+using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using System.Collections.Generic;
using System.Linq;
+using System.Threading;
namespace MediaBrowser.Controller.Channels
{
@@ -69,5 +71,22 @@ namespace MediaBrowser.Controller.Channels
{
return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N"));
}
+
+ public override IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
+ {
+ var list = base.GetMediaSources(enablePathSubstitution).ToList();
+
+ var sources = ChannelManager.GetChannelItemMediaSources(Id.ToString("N"), false, CancellationToken.None)
+ .Result.ToList();
+
+ if (sources.Count > 0)
+ {
+ return sources;
+ }
+
+ list.InsertRange(0, sources);
+
+ return list;
+ }
}
}
diff --git a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
index e6fa45972..72e2b110a 100644
--- a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
+++ b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
@@ -7,6 +7,7 @@ using MediaBrowser.Model.Entities;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
+using System.Threading;
namespace MediaBrowser.Controller.Channels
{
@@ -90,7 +91,15 @@ namespace MediaBrowser.Controller.Channels
{
var list = base.GetMediaSources(enablePathSubstitution).ToList();
- list.InsertRange(0, ChannelManager.GetCachedChannelItemMediaSources(Id.ToString("N")));
+ var sources = ChannelManager.GetChannelItemMediaSources(Id.ToString("N"), false, CancellationToken.None)
+ .Result.ToList();
+
+ if (sources.Count > 0)
+ {
+ return sources;
+ }
+
+ list.InsertRange(0, sources);
return list;
}
diff --git a/MediaBrowser.Controller/Channels/IChannelManager.cs b/MediaBrowser.Controller/Channels/IChannelManager.cs
index f4e985c7a..05015da37 100644
--- a/MediaBrowser.Controller/Channels/IChannelManager.cs
+++ b/MediaBrowser.Controller/Channels/IChannelManager.cs
@@ -110,19 +110,13 @@ namespace MediaBrowser.Controller.Channels
Task<QueryResult<BaseItem>> GetChannelItemsInternal(ChannelItemQuery query, IProgress<double> progress, CancellationToken cancellationToken);
/// <summary>
- /// Gets the cached channel item media sources.
- /// </summary>
- /// <param name="id">The identifier.</param>
- /// <returns>IEnumerable{MediaSourceInfo}.</returns>
- IEnumerable<MediaSourceInfo> GetCachedChannelItemMediaSources(string id);
-
- /// <summary>
/// Gets the channel item media sources.
/// </summary>
/// <param name="id">The identifier.</param>
+ /// <param name="includeDynamicSources">if set to <c>true</c> [include dynamic sources].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{IEnumerable{MediaSourceInfo}}.</returns>
- Task<IEnumerable<MediaSourceInfo>> GetChannelItemMediaSources(string id, CancellationToken cancellationToken);
+ Task<IEnumerable<MediaSourceInfo>> GetChannelItemMediaSources(string id, bool includeDynamicSources, CancellationToken cancellationToken);
/// <summary>
/// Gets the channel folder.
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index 4a4ff17a0..93b71ae36 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Channels;
+using MediaBrowser.Controller.Collections;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
@@ -251,6 +252,7 @@ namespace MediaBrowser.Controller.Entities
public static IUserDataManager UserDataManager { get; set; }
public static ILiveTvManager LiveTvManager { get; set; }
public static IChannelManager ChannelManager { get; set; }
+ public static ICollectionManager CollectionManager { get; set; }
/// <summary>
/// Returns a <see cref="System.String" /> that represents this instance.
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index bfec0c26e..4614f2f8a 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -785,7 +785,7 @@ namespace MediaBrowser.Controller.Entities
protected QueryResult<BaseItem> SortAndFilter(IEnumerable<BaseItem> items, InternalItemsQuery query)
{
- return UserViewBuilder.SortAndFilter(items, null, query, LibraryManager, UserDataManager);
+ return UserViewBuilder.SortAndFilter(items, this, null, query, LibraryManager, UserDataManager);
}
/// <summary>
diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
index 91cb43291..1faa6c391 100644
--- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
+++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
@@ -29,6 +29,46 @@ namespace MediaBrowser.Controller.Entities
public string[] MediaTypes { get; set; }
public string[] IncludeItemTypes { get; set; }
public string[] ExcludeItemTypes { get; set; }
+ public string[] Genres { get; set; }
+ public string[] AllGenres { get; set; }
+
+ public bool? IsMissing { get; set; }
+ public bool? IsUnaired { get; set; }
+ public bool? IsVirtualUnaired { get; set; }
+ public bool? CollapseBoxSetItems { get; set; }
+
+ public string NameStartsWithOrGreater { get; set; }
+ public string NameStartsWith { get; set; }
+ public string NameLessThan { get; set; }
+
+ public string Person { get; set; }
+ public string AdjacentTo { get; set; }
+ public string[] PersonTypes { get; set; }
+
+ public bool? Is3D { get; set; }
+ public bool? IsHD { get; set; }
+ public bool? IsInBoxSet { get; set; }
+ public bool? IsLocked { get; set; }
+ public bool? IsUnidentified { get; set; }
+ public bool? IsPlaceHolder { get; set; }
+ public bool? IsYearMismatched { get; set; }
+
+ public bool? HasImdbId { get; set; }
+ public bool? HasOverview { get; set; }
+ public bool? HasTmdbId { get; set; }
+ public bool? HasOfficialRating { get; set; }
+ public bool? HasTvdbId { get; set; }
+ public bool? HasThemeSong { get; set; }
+ public bool? HasThemeVideo { get; set; }
+ public bool? HasSubtitles { get; set; }
+ public bool? HasSpecialFeature { get; set; }
+ public bool? HasTrailer { get; set; }
+ public bool? HasParentalRating { get; set; }
+
+ public string[] Studios { get; set; }
+ public ImageType[] ImageTypes { get; set; }
+ public VideoType[] VideoTypes { get; set; }
+ public int[] Years { get; set; }
public InternalItemsQuery()
{
@@ -36,6 +76,13 @@ namespace MediaBrowser.Controller.Entities
MediaTypes = new string[] { };
IncludeItemTypes = new string[] { };
ExcludeItemTypes = new string[] { };
+ AllGenres = new string[] { };
+ Genres = new string[] { };
+ Studios = new string[] { };
+ ImageTypes = new ImageType[] { };
+ VideoTypes = new VideoType[] { };
+ Years = new int[] { };
+ PersonTypes = new string[] { };
}
}
}
diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs
index 043c69e27..bcbaa967a 100644
--- a/MediaBrowser.Controller/Entities/UserView.cs
+++ b/MediaBrowser.Controller/Entities/UserView.cs
@@ -17,7 +17,7 @@ namespace MediaBrowser.Controller.Entities
public override Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
{
- return new UserViewBuilder(UserViewManager, LiveTvManager, ChannelManager, LibraryManager, Logger, UserDataManager, TVSeriesManager)
+ return new UserViewBuilder(UserViewManager, LiveTvManager, ChannelManager, LibraryManager, Logger, UserDataManager, TVSeriesManager, CollectionManager)
.GetUserItems(this, ViewType, query);
}
diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
index 8efa1b6bb..bf6cac87e 100644
--- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs
+++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
@@ -1,9 +1,12 @@
-using MediaBrowser.Controller.Channels;
+using System.IO;
+using MediaBrowser.Controller.Channels;
+using MediaBrowser.Controller.Collections;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
+using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.TV;
using MediaBrowser.Model.Channels;
using MediaBrowser.Model.Entities;
@@ -27,8 +30,9 @@ namespace MediaBrowser.Controller.Entities
private readonly ILogger _logger;
private readonly IUserDataManager _userDataManager;
private readonly ITVSeriesManager _tvSeriesManager;
+ private readonly ICollectionManager _collectionManager;
- public UserViewBuilder(IUserViewManager userViewManager, ILiveTvManager liveTvManager, IChannelManager channelManager, ILibraryManager libraryManager, ILogger logger, IUserDataManager userDataManager, ITVSeriesManager tvSeriesManager)
+ public UserViewBuilder(IUserViewManager userViewManager, ILiveTvManager liveTvManager, IChannelManager channelManager, ILibraryManager libraryManager, ILogger logger, IUserDataManager userDataManager, ITVSeriesManager tvSeriesManager, ICollectionManager collectionManager)
{
_userViewManager = userViewManager;
_liveTvManager = liveTvManager;
@@ -37,6 +41,7 @@ namespace MediaBrowser.Controller.Entities
_logger = logger;
_userDataManager = userDataManager;
_tvSeriesManager = tvSeriesManager;
+ _collectionManager = collectionManager;
}
public async Task<QueryResult<BaseItem>> GetUserItems(Folder parent, string viewType, InternalItemsQuery query)
@@ -102,17 +107,17 @@ namespace MediaBrowser.Controller.Entities
{
var result = await GetLiveTvFolders(user).ConfigureAwait(false);
- return GetResult(result, query);
+ return GetResult(result, parent, query);
}
case CollectionType.Folders:
- return GetResult(user.RootFolder.GetChildren(user, true), query);
+ return GetResult(user.RootFolder.GetChildren(user, true), parent, query);
case CollectionType.Games:
return await GetGameView(user, parent, query).ConfigureAwait(false);
case CollectionType.BoxSets:
- return GetResult(GetMediaFolders(user).SelectMany(i => i.GetRecursiveChildren(user)).OfType<BoxSet>(), query);
+ return GetResult(GetMediaFolders(user).SelectMany(i => i.GetRecursiveChildren(user)).OfType<BoxSet>(), parent, query);
case CollectionType.TvShows:
return await GetTvView(parent, user, query).ConfigureAwait(false);
@@ -205,7 +210,7 @@ namespace MediaBrowser.Controller.Entities
return GetFavoriteSongs(parent, user, query);
default:
- return GetResult(GetMediaFolders(user).SelectMany(i => i.GetChildren(user, true)), query);
+ return GetResult(GetMediaFolders(user).SelectMany(i => i.GetChildren(user, true)), parent, query);
}
}
@@ -218,7 +223,7 @@ namespace MediaBrowser.Controller.Entities
{
if (query.Recursive)
{
- return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }), query);
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }), parent, query);
}
var list = new List<BaseItem>();
@@ -233,7 +238,7 @@ namespace MediaBrowser.Controller.Entities
//list.Add(await GetUserView(CollectionType.MusicGenres, user, "5", parent).ConfigureAwait(false));
list.Add(await GetUserView(category, CollectionType.MusicFavorites, user, "6", parent).ConfigureAwait(false));
- return GetResult(list, query);
+ return GetResult(list, parent, query);
}
private async Task<QueryResult<BaseItem>> GetMusicFavorites(Folder parent, User user, InternalItemsQuery query)
@@ -246,7 +251,7 @@ namespace MediaBrowser.Controller.Entities
list.Add(await GetUserView(category, CollectionType.MusicFavoriteArtists, user, "1", parent).ConfigureAwait(false));
list.Add(await GetUserView(category, CollectionType.MusicFavoriteSongs, user, "2", parent).ConfigureAwait(false));
- return GetResult(list, query);
+ return GetResult(list, parent, query);
}
private QueryResult<BaseItem> GetMusicAlbumArtists(Folder parent, User user, InternalItemsQuery query)
@@ -270,7 +275,7 @@ namespace MediaBrowser.Controller.Entities
})
.Where(i => i != null);
- return GetResult(artists, query);
+ return GetResult(artists, parent, query);
}
private QueryResult<BaseItem> GetMusicArtists(Folder parent, User user, InternalItemsQuery query)
@@ -294,7 +299,7 @@ namespace MediaBrowser.Controller.Entities
})
.Where(i => i != null);
- return GetResult(artists, query);
+ return GetResult(artists, parent, query);
}
private QueryResult<BaseItem> GetFavoriteArtists(Folder parent, User user, InternalItemsQuery query)
@@ -318,17 +323,17 @@ namespace MediaBrowser.Controller.Entities
})
.Where(i => i != null && _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).IsFavorite);
- return GetResult(artists, query);
+ return GetResult(artists, parent, query);
}
private QueryResult<BaseItem> GetMusicAlbums(Folder parent, User user, InternalItemsQuery query)
{
- return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }).Where(i => i is MusicAlbum), query);
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }).Where(i => i is MusicAlbum), parent, query);
}
private QueryResult<BaseItem> GetMusicSongs(Folder parent, User user, InternalItemsQuery query)
{
- return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }).Where(i => i is Audio.Audio), query);
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }).Where(i => i is Audio.Audio), parent, query);
}
private QueryResult<BaseItem> GetMusicLatest(Folder parent, User user, InternalItemsQuery query)
@@ -336,14 +341,14 @@ namespace MediaBrowser.Controller.Entities
query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName };
query.SortOrder = SortOrder.Descending;
- return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }).Where(i => i is MusicVideo || i is Audio.Audio), GetSpecialItemsLimit(), query);
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }).Where(i => i is MusicVideo || i is Audio.Audio), parent, GetSpecialItemsLimit(), query);
}
private async Task<QueryResult<BaseItem>> GetMovieFolders(Folder parent, User user, InternalItemsQuery query)
{
if (query.Recursive)
{
- return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie || i is BoxSet), query);
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie || i is BoxSet), parent, query);
}
var list = new List<BaseItem>();
@@ -357,52 +362,52 @@ namespace MediaBrowser.Controller.Entities
list.Add(await GetUserView(category, CollectionType.MovieFavorites, user, "4", parent).ConfigureAwait(false));
//list.Add(await GetUserView(CollectionType.MovieGenres, user, "5", parent).ConfigureAwait(false));
- return GetResult(list, query);
+ return GetResult(list, parent, query);
}
private QueryResult<BaseItem> GetFavoriteMovies(Folder parent, User user, InternalItemsQuery query)
{
query.IsFavorite = true;
- return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie), query);
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie), parent, query);
}
private QueryResult<BaseItem> GetFavoriteSeries(Folder parent, User user, InternalItemsQuery query)
{
query.IsFavorite = true;
- return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).Where(i => i is Series), query);
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).Where(i => i is Series), parent, query);
}
private QueryResult<BaseItem> GetFavoriteEpisodes(Folder parent, User user, InternalItemsQuery query)
{
query.IsFavorite = true;
- return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).Where(i => i is Episode), query);
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).Where(i => i is Episode), parent, query);
}
private QueryResult<BaseItem> GetFavoriteSongs(Folder parent, User user, InternalItemsQuery query)
{
query.IsFavorite = true;
- return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Music }).Where(i => i is Audio.Audio), query);
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Music }).Where(i => i is Audio.Audio), parent, query);
}
private QueryResult<BaseItem> GetFavoriteAlbums(Folder parent, User user, InternalItemsQuery query)
{
query.IsFavorite = true;
- return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Music }).Where(i => i is MusicAlbum), query);
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Music }).Where(i => i is MusicAlbum), parent, query);
}
private QueryResult<BaseItem> GetMovieMovies(Folder parent, User user, InternalItemsQuery query)
{
- return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie), query);
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie), parent, query);
}
private QueryResult<BaseItem> GetMovieCollections(Folder parent, User user, InternalItemsQuery query)
{
- return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is BoxSet), query);
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is BoxSet), parent, query);
}
private QueryResult<BaseItem> GetMovieLatest(Folder parent, User user, InternalItemsQuery query)
@@ -410,7 +415,7 @@ namespace MediaBrowser.Controller.Entities
query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName };
query.SortOrder = SortOrder.Descending;
- return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie), GetSpecialItemsLimit(), query);
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie), parent, GetSpecialItemsLimit(), query);
}
private QueryResult<BaseItem> GetMovieResume(Folder parent, User user, InternalItemsQuery query)
@@ -419,7 +424,7 @@ namespace MediaBrowser.Controller.Entities
query.SortOrder = SortOrder.Descending;
query.IsResumable = true;
- return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie), GetSpecialItemsLimit(), query);
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie), parent, GetSpecialItemsLimit(), query);
}
private QueryResult<BaseItem> GetMovieGenres(Folder parent, User user, InternalItemsQuery query)
@@ -444,14 +449,14 @@ namespace MediaBrowser.Controller.Entities
})
.Where(i => i != null);
- return GetResult(genres, query);
+ return GetResult(genres, parent, query);
}
private async Task<QueryResult<BaseItem>> GetTvView(Folder parent, User user, InternalItemsQuery query)
{
if (query.Recursive)
{
- return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).Where(i => i is Series || i is Season || i is Episode), query);
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).Where(i => i is Series || i is Season || i is Episode), parent, query);
}
var list = new List<BaseItem>();
@@ -466,14 +471,14 @@ namespace MediaBrowser.Controller.Entities
list.Add(await GetUserView(category, CollectionType.TvFavoriteEpisodes, user, "5", parent).ConfigureAwait(false));
//list.Add(await GetUserView(CollectionType.TvGenres, user, "5", parent).ConfigureAwait(false));
- return GetResult(list, query);
+ return GetResult(list, parent, query);
}
private async Task<QueryResult<BaseItem>> GetGameView(User user, Folder parent, InternalItemsQuery query)
{
if (query.Recursive)
{
- return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }), query);
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }), parent, query);
}
var list = new List<BaseItem>();
@@ -486,7 +491,7 @@ namespace MediaBrowser.Controller.Entities
list.Add(await GetUserView(category, CollectionType.GameSystems, user, "3", parent).ConfigureAwait(false));
//list.Add(await GetUserView(CollectionType.GameGenres, user, "4", parent).ConfigureAwait(false));
- return GetResult(list, query);
+ return GetResult(list, parent, query);
}
private QueryResult<BaseItem> GetLatestGames(Folder parent, User user, InternalItemsQuery query)
@@ -494,7 +499,7 @@ namespace MediaBrowser.Controller.Entities
query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName };
query.SortOrder = SortOrder.Descending;
- return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }).OfType<Game>(), GetSpecialItemsLimit(), query);
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }).OfType<Game>(), parent, GetSpecialItemsLimit(), query);
}
private QueryResult<BaseItem> GetRecentlyPlayedGames(Folder parent, User user, InternalItemsQuery query)
@@ -503,14 +508,14 @@ namespace MediaBrowser.Controller.Entities
query.SortBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName };
query.SortOrder = SortOrder.Descending;
- return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }).OfType<Game>(), GetSpecialItemsLimit(), query);
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }).OfType<Game>(), parent, GetSpecialItemsLimit(), query);
}
private QueryResult<BaseItem> GetFavoriteGames(Folder parent, User user, InternalItemsQuery query)
{
query.IsFavorite = true;
- return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }).OfType<Game>(), query);
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }).OfType<Game>(), parent, query);
}
private QueryResult<BaseItem> GetTvLatest(Folder parent, User user, InternalItemsQuery query)
@@ -518,7 +523,7 @@ namespace MediaBrowser.Controller.Entities
query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName };
query.SortOrder = SortOrder.Descending;
- return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).OfType<Episode>(), GetSpecialItemsLimit(), query);
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).OfType<Episode>(), parent, GetSpecialItemsLimit(), query);
}
private QueryResult<BaseItem> GetTvNextUp(Folder parent, InternalItemsQuery query)
@@ -542,12 +547,12 @@ namespace MediaBrowser.Controller.Entities
query.SortOrder = SortOrder.Descending;
query.IsResumable = true;
- return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).OfType<Episode>(), GetSpecialItemsLimit(), query);
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).OfType<Episode>(), parent, GetSpecialItemsLimit(), query);
}
private QueryResult<BaseItem> GetTvSeries(Folder parent, User user, InternalItemsQuery query)
{
- return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).OfType<Series>(), query);
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).OfType<Series>(), parent, query);
}
private QueryResult<BaseItem> GetTvGenres(Folder parent, User user, InternalItemsQuery query)
@@ -572,12 +577,12 @@ namespace MediaBrowser.Controller.Entities
})
.Where(i => i != null);
- return GetResult(genres, query);
+ return GetResult(genres, parent, query);
}
private QueryResult<BaseItem> GetGameSystems(Folder parent, User user, InternalItemsQuery query)
{
- return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }).OfType<GameSystem>(), query);
+ return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }).OfType<GameSystem>(), parent, query);
}
private QueryResult<BaseItem> GetGameGenres(Folder parent, User user, InternalItemsQuery query)
@@ -602,7 +607,7 @@ namespace MediaBrowser.Controller.Entities
})
.Where(i => i != null);
- return GetResult(genres, query);
+ return GetResult(genres, parent, query);
}
private QueryResult<BaseItem> GetResult<T>(QueryResult<T> result)
@@ -616,21 +621,24 @@ namespace MediaBrowser.Controller.Entities
}
private QueryResult<BaseItem> GetResult<T>(IEnumerable<T> items,
+ BaseItem parentItem,
InternalItemsQuery query)
where T : BaseItem
{
- return GetResult(items, null, query);
+ return GetResult(items, parentItem, null, query);
}
private QueryResult<BaseItem> GetResult<T>(IEnumerable<T> items,
+ BaseItem parentItem,
int? totalRecordLimit,
InternalItemsQuery query)
where T : BaseItem
{
- return SortAndFilter(items, totalRecordLimit, query, _libraryManager, _userDataManager);
+ return SortAndFilter(items, parentItem, totalRecordLimit, query, _libraryManager, _userDataManager);
}
public static QueryResult<BaseItem> SortAndFilter(IEnumerable<BaseItem> items,
+ BaseItem parentItem,
int? totalRecordLimit,
InternalItemsQuery query,
ILibraryManager libraryManager,
@@ -640,9 +648,361 @@ namespace MediaBrowser.Controller.Entities
items = items.Where(i => Filter(i, user, query, userDataManager));
+ items = FilterVirtualEpisodes(items,
+ query.IsMissing,
+ query.IsVirtualUnaired,
+ query.IsUnaired);
+
+ items = CollapseBoxSetItemsIfNeeded(items, query, parentItem, user);
+
+ // This must be the last filter
+ if (!string.IsNullOrEmpty(query.AdjacentTo))
+ {
+ items = FilterForAdjacency(items, query.AdjacentTo);
+ }
+
return Sort(items, totalRecordLimit, query, libraryManager);
}
+ public static IEnumerable<BaseItem> CollapseBoxSetItemsIfNeeded(IEnumerable<BaseItem> items,
+ InternalItemsQuery query,
+ BaseItem parentItem,
+ User user)
+ {
+ if (CollapseBoxSetItems(query, parentItem, user))
+ {
+ items = BaseItem.CollectionManager.CollapseItemsWithinBoxSets(items, user);
+ }
+
+ items = ApplyPostCollectionCollapseFilters(query, items, user);
+
+ return items;
+ }
+
+ private static IEnumerable<BaseItem> ApplyPostCollectionCollapseFilters(InternalItemsQuery request,
+ IEnumerable<BaseItem> items,
+ User user)
+ {
+ if (!string.IsNullOrEmpty(request.NameStartsWithOrGreater))
+ {
+ items = items.Where(i => string.Compare(request.NameStartsWithOrGreater, i.SortName, StringComparison.CurrentCultureIgnoreCase) < 1);
+ }
+ if (!string.IsNullOrEmpty(request.NameStartsWith))
+ {
+ items = items.Where(i => string.Compare(request.NameStartsWith, i.SortName.Substring(0, 1), StringComparison.CurrentCultureIgnoreCase) == 0);
+ }
+
+ if (!string.IsNullOrEmpty(request.NameLessThan))
+ {
+ items = items.Where(i => string.Compare(request.NameLessThan, i.SortName, StringComparison.CurrentCultureIgnoreCase) == 1);
+ }
+
+ return items;
+ }
+
+ private static bool CollapseBoxSetItems(InternalItemsQuery query,
+ BaseItem parentItem,
+ User user)
+ {
+ // Could end up stuck in a loop like this
+ if (parentItem is BoxSet)
+ {
+ return false;
+ }
+
+ var param = query.CollapseBoxSetItems;
+
+ if (!param.HasValue)
+ {
+ if (user != null && !user.Configuration.GroupMoviesIntoBoxSets)
+ {
+ return false;
+ }
+
+ if (query.IncludeItemTypes.Contains("Movie", StringComparer.OrdinalIgnoreCase))
+ {
+ param = true;
+ }
+ }
+
+ return param.HasValue && param.Value && AllowBoxSetCollapsing(query);
+ }
+
+ private static bool AllowBoxSetCollapsing(InternalItemsQuery request)
+ {
+ if (request.IsFavorite.HasValue)
+ {
+ return false;
+ }
+ if (request.IsFavoriteOrLiked.HasValue)
+ {
+ return false;
+ }
+ if (request.IsLiked.HasValue)
+ {
+ return false;
+ }
+ if (request.IsPlayed.HasValue)
+ {
+ return false;
+ }
+ if (request.IsResumable.HasValue)
+ {
+ return false;
+ }
+ if (request.IsFolder.HasValue)
+ {
+ return false;
+ }
+
+ if (request.AllGenres.Length > 0)
+ {
+ return false;
+ }
+
+ if (request.Genres.Length > 0)
+ {
+ return false;
+ }
+
+ if (request.HasImdbId.HasValue)
+ {
+ return false;
+ }
+
+ if (request.HasOfficialRating.HasValue)
+ {
+ return false;
+ }
+
+ if (request.HasOverview.HasValue)
+ {
+ return false;
+ }
+
+ if (request.HasParentalRating.HasValue)
+ {
+ return false;
+ }
+
+ if (request.HasSpecialFeature.HasValue)
+ {
+ return false;
+ }
+
+ if (request.HasSubtitles.HasValue)
+ {
+ return false;
+ }
+
+ if (request.HasThemeSong.HasValue)
+ {
+ return false;
+ }
+
+ if (request.HasThemeVideo.HasValue)
+ {
+ return false;
+ }
+
+ if (request.HasTmdbId.HasValue)
+ {
+ return false;
+ }
+
+ if (request.HasTrailer.HasValue)
+ {
+ return false;
+ }
+
+ if (request.ImageTypes.Length > 0)
+ {
+ return false;
+ }
+
+ if (request.Is3D.HasValue)
+ {
+ return false;
+ }
+
+ if (request.IsHD.HasValue)
+ {
+ return false;
+ }
+
+ if (request.IsInBoxSet.HasValue)
+ {
+ return false;
+ }
+
+ if (request.IsLocked.HasValue)
+ {
+ return false;
+ }
+
+ if (request.IsPlaceHolder.HasValue)
+ {
+ return false;
+ }
+
+ if (request.IsPlayed.HasValue)
+ {
+ return false;
+ }
+
+ if (request.IsUnidentified.HasValue)
+ {
+ return false;
+ }
+
+ if (request.IsYearMismatched.HasValue)
+ {
+ return false;
+ }
+
+ if (!string.IsNullOrWhiteSpace(request.Person))
+ {
+ return false;
+ }
+
+ if (request.Studios.Length > 0)
+ {
+ return false;
+ }
+
+ if (request.VideoTypes.Length > 0)
+ {
+ return false;
+ }
+
+ if (request.Years.Length > 0)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ public static IEnumerable<BaseItem> FilterVirtualEpisodes(
+ IEnumerable<BaseItem> items,
+ bool? isMissing,
+ bool? isVirtualUnaired,
+ bool? isUnaired)
+ {
+ items = FilterVirtualSeasons(items, isMissing, isVirtualUnaired, isUnaired);
+
+ if (isMissing.HasValue)
+ {
+ var val = isMissing.Value;
+ items = items.Where(i =>
+ {
+ var e = i as Episode;
+ if (e != null)
+ {
+ return e.IsMissingEpisode == val;
+ }
+ return true;
+ });
+ }
+
+ if (isUnaired.HasValue)
+ {
+ var val = isUnaired.Value;
+ items = items.Where(i =>
+ {
+ var e = i as Episode;
+ if (e != null)
+ {
+ return e.IsUnaired == val;
+ }
+ return true;
+ });
+ }
+
+ if (isVirtualUnaired.HasValue)
+ {
+ var val = isVirtualUnaired.Value;
+ items = items.Where(i =>
+ {
+ var e = i as Episode;
+ if (e != null)
+ {
+ return e.IsVirtualUnaired == val;
+ }
+ return true;
+ });
+ }
+
+ return items;
+ }
+
+ private static IEnumerable<BaseItem> FilterVirtualSeasons(
+ IEnumerable<BaseItem> items,
+ bool? isMissing,
+ bool? isVirtualUnaired,
+ bool? isUnaired)
+ {
+ if (isMissing.HasValue && isVirtualUnaired.HasValue)
+ {
+ if (!isMissing.Value && !isVirtualUnaired.Value)
+ {
+ return items.Where(i =>
+ {
+ var e = i as Season;
+ if (e != null)
+ {
+ return !e.IsMissingOrVirtualUnaired;
+ }
+ return true;
+ });
+ }
+ }
+
+ 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> Sort(IEnumerable<BaseItem> items,
int? totalRecordLimit,
InternalItemsQuery query,
@@ -692,7 +1052,7 @@ namespace MediaBrowser.Controller.Entities
{
return false;
}
-
+
if (query.IsFolder.HasValue && query.IsFolder.Value != item.IsFolder)
{
return false;
@@ -755,6 +1115,334 @@ namespace MediaBrowser.Controller.Entities
}
}
+ if (query.IsInBoxSet.HasValue)
+ {
+ var val = query.IsInBoxSet.Value;
+ if (item.Parents.OfType<BoxSet>().Any() != val)
+ {
+ return false;
+ }
+ }
+
+ // Filter by Video3DFormat
+ if (query.Is3D.HasValue)
+ {
+ var val = query.Is3D.Value;
+ var video = item as Video;
+
+ if (video == null || val != video.Video3DFormat.HasValue)
+ {
+ return false;
+ }
+ }
+
+ if (query.IsHD.HasValue)
+ {
+ var val = query.IsHD.Value;
+ var video = item as Video;
+
+ if (video == null || val != video.IsHD)
+ {
+ return false;
+ }
+ }
+
+ if (query.IsUnidentified.HasValue)
+ {
+ var val = query.IsUnidentified.Value;
+ if (item.IsUnidentified != val)
+ {
+ return false;
+ }
+ }
+
+ if (query.IsLocked.HasValue)
+ {
+ var val = query.IsLocked.Value;
+ if (item.IsLocked != val)
+ {
+ return false;
+ }
+ }
+
+ if (query.HasOverview.HasValue)
+ {
+ var filterValue = query.HasOverview.Value;
+
+ var hasValue = !string.IsNullOrEmpty(item.Overview);
+
+ if (hasValue != filterValue)
+ {
+ return false;
+ }
+ }
+
+ if (query.HasImdbId.HasValue)
+ {
+ var filterValue = query.HasImdbId.Value;
+
+ var hasValue = !string.IsNullOrEmpty(item.GetProviderId(MetadataProviders.Imdb));
+
+ if (hasValue != filterValue)
+ {
+ return false;
+ }
+ }
+
+ if (query.HasTmdbId.HasValue)
+ {
+ var filterValue = query.HasTmdbId.Value;
+
+ var hasValue = !string.IsNullOrEmpty(item.GetProviderId(MetadataProviders.Tmdb));
+
+ if (hasValue != filterValue)
+ {
+ return false;
+ }
+ }
+
+ if (query.HasTvdbId.HasValue)
+ {
+ var filterValue = query.HasTvdbId.Value;
+
+ var hasValue = !string.IsNullOrEmpty(item.GetProviderId(MetadataProviders.Tvdb));
+
+ if (hasValue != filterValue)
+ {
+ return false;
+ }
+ }
+
+ if (query.IsYearMismatched.HasValue)
+ {
+ var filterValue = query.IsYearMismatched.Value;
+
+ if (IsYearMismatched(item) != filterValue)
+ {
+ return false;
+ }
+ }
+
+ if (query.HasOfficialRating.HasValue)
+ {
+ var filterValue = query.HasOfficialRating.Value;
+
+ var hasValue = !string.IsNullOrEmpty(item.OfficialRating);
+
+ if (hasValue != filterValue)
+ {
+ return false;
+ }
+ }
+
+ if (query.IsPlaceHolder.HasValue)
+ {
+ var filterValue = query.IsPlaceHolder.Value;
+
+ var isPlaceHolder = false;
+
+ var hasPlaceHolder = item as ISupportsPlaceHolders;
+
+ if (hasPlaceHolder != null)
+ {
+ isPlaceHolder = hasPlaceHolder.IsPlaceHolder;
+ }
+
+ if (isPlaceHolder != filterValue)
+ {
+ return false;
+ }
+ }
+
+ if (query.HasSpecialFeature.HasValue)
+ {
+ var filterValue = query.HasSpecialFeature.Value;
+
+ var movie = item as IHasSpecialFeatures;
+
+ if (movie != null)
+ {
+ var ok = filterValue
+ ? movie.SpecialFeatureIds.Count > 0
+ : movie.SpecialFeatureIds.Count == 0;
+
+ if (!ok)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ if (query.HasSubtitles.HasValue)
+ {
+ var val = query.HasSubtitles.Value;
+
+ var video = item as Video;
+
+ if (video == null || val != video.HasSubtitles)
+ {
+ return false;
+ }
+ }
+
+ if (query.HasParentalRating.HasValue)
+ {
+ var val = query.HasParentalRating.Value;
+
+ var rating = item.CustomRating;
+
+ if (string.IsNullOrEmpty(rating))
+ {
+ rating = item.OfficialRating;
+ }
+
+ if (val)
+ {
+ if (string.IsNullOrEmpty(rating))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (!string.IsNullOrEmpty(rating))
+ {
+ return false;
+ }
+ }
+ }
+
+ if (query.HasTrailer.HasValue)
+ {
+ var val = query.HasTrailer.Value;
+ var trailerCount = 0;
+
+ var hasTrailers = item as IHasTrailers;
+ if (hasTrailers != null)
+ {
+ trailerCount = hasTrailers.LocalTrailerIds.Count;
+ }
+
+ var ok = val ? trailerCount > 0 : trailerCount == 0;
+
+ if (!ok)
+ {
+ return false;
+ }
+ }
+
+ if (query.HasThemeSong.HasValue)
+ {
+ var filterValue = query.HasThemeSong.Value;
+
+ var themeCount = 0;
+ var iHasThemeMedia = item as IHasThemeMedia;
+
+ if (iHasThemeMedia != null)
+ {
+ themeCount = iHasThemeMedia.ThemeSongIds.Count;
+ }
+ var ok = filterValue ? themeCount > 0 : themeCount == 0;
+
+ if (!ok)
+ {
+ return false;
+ }
+ }
+
+ if (query.HasThemeVideo.HasValue)
+ {
+ var filterValue = query.HasThemeVideo.Value;
+
+ var themeCount = 0;
+ var iHasThemeMedia = item as IHasThemeMedia;
+
+ if (iHasThemeMedia != null)
+ {
+ themeCount = iHasThemeMedia.ThemeVideoIds.Count;
+ }
+ var ok = filterValue ? themeCount > 0 : themeCount == 0;
+
+ if (!ok)
+ {
+ return false;
+ }
+ }
+
+ // Apply genre filter
+ if (query.Genres.Length > 0 && !(query.Genres.Any(v => item.Genres.Contains(v, StringComparer.OrdinalIgnoreCase))))
+ {
+ return false;
+ }
+
+ // Apply genre filter
+ if (query.AllGenres.Length > 0 && !query.AllGenres.All(v => item.Genres.Contains(v, StringComparer.OrdinalIgnoreCase)))
+ {
+ return false;
+ }
+
+ // Filter by VideoType
+ if (query.VideoTypes.Length > 0)
+ {
+ var video = item as Video;
+ if (video == null || !query.VideoTypes.Contains(video.VideoType))
+ {
+ return false;
+ }
+ }
+
+ if (query.ImageTypes.Length > 0 && !query.ImageTypes.Any(item.HasImage))
+ {
+ return false;
+ }
+
+ // Apply studio filter
+ if (query.Studios.Length > 0 && !query.Studios.Any(v => item.Studios.Contains(v, StringComparer.OrdinalIgnoreCase)))
+ {
+ return false;
+ }
+
+ // Apply year filter
+ if (query.Years.Length > 0)
+ {
+ if (!(item.ProductionYear.HasValue && query.Years.Contains(item.ProductionYear.Value)))
+ {
+ return false;
+ }
+ }
+
+ // Apply person filter
+ if (!string.IsNullOrEmpty(query.Person))
+ {
+ var personTypes = query.PersonTypes;
+
+ if (personTypes.Length == 0)
+ {
+ if (!(item.People.Any(p => string.Equals(p.Name, query.Person, StringComparison.OrdinalIgnoreCase))))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ var types = personTypes;
+
+ var ok = new[] { item }.Any(i =>
+ i.People != null &&
+ i.People.Any(p =>
+ p.Name.Equals(query.Person, StringComparison.OrdinalIgnoreCase) && (types.Contains(p.Type, StringComparer.OrdinalIgnoreCase) || types.Contains(p.Role, StringComparer.OrdinalIgnoreCase))));
+
+ if (!ok)
+ {
+ return false;
+ }
+ }
+ }
+
return true;
}
@@ -768,7 +1456,7 @@ namespace MediaBrowser.Controller.Entities
.Where(i => !excludeFolderIds.Contains(i.Id) && !UserView.IsExcludedFromGrouping(i));
}
- private IEnumerable<Folder> GetMediaFolders(User user, string[] viewTypes)
+ private IEnumerable<Folder> GetMediaFolders(User user, IEnumerable<string> viewTypes)
{
return GetMediaFolders(user)
.Where(i =>
@@ -824,5 +1512,58 @@ namespace MediaBrowser.Controller.Entities
return view;
}
+
+ public static bool IsYearMismatched(BaseItem item)
+ {
+ if (item.ProductionYear.HasValue)
+ {
+ var path = item.Path;
+
+ if (!string.IsNullOrEmpty(path))
+ {
+ int? yearInName;
+ string name;
+ NameParser.ParseName(Path.GetFileName(path), out name, out yearInName);
+
+ // Go up a level if we didn't get a year
+ if (!yearInName.HasValue)
+ {
+ NameParser.ParseName(Path.GetFileName(Path.GetDirectoryName(path)), out name, out yearInName);
+ }
+
+ if (yearInName.HasValue)
+ {
+ return yearInName.Value != item.ProductionYear.Value;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public static IEnumerable<BaseItem> FilterForAdjacency(IEnumerable<BaseItem> items, string adjacentToId)
+ {
+ var list = items.ToList();
+
+ var adjacentToIdGuid = new Guid(adjacentToId);
+ var adjacentToItem = list.FirstOrDefault(i => i.Id == adjacentToIdGuid);
+
+ var index = list.IndexOf(adjacentToItem);
+
+ var previousId = Guid.Empty;
+ var nextId = Guid.Empty;
+
+ if (index > 0)
+ {
+ previousId = list[index - 1].Id;
+ }
+
+ if (index < list.Count - 1)
+ {
+ nextId = list[index + 1].Id;
+ }
+
+ return list.Where(i => i.Id == previousId || i.Id == nextId || i.Id == adjacentToIdGuid);
+ }
}
}
diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs
index 550bb3cfb..4d6b301d1 100644
--- a/MediaBrowser.Model/Dlna/StreamInfo.cs
+++ b/MediaBrowser.Model/Dlna/StreamInfo.cs
@@ -91,6 +91,13 @@ namespace MediaBrowser.Model.Dlna
throw new ArgumentNullException(baseUrl);
}
+ if (IsDirectStream && MediaSource != null && MediaSource.Protocol == MediaProtocol.Http)
+ {
+ if (MediaSource.RequiredHttpHeaders.Count == 0)
+ {
+ }
+ }
+
string dlnaCommand = BuildDlnaParam(this);
string extension = string.IsNullOrEmpty(Container) ? string.Empty : "." + Container;
diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs
index 40eb38669..cd0f14200 100644
--- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs
+++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs
@@ -273,13 +273,17 @@ namespace MediaBrowser.Providers.Movies
languages.Add("en");
}
+ var firstLetter = string.IsNullOrWhiteSpace(preferredLanguage)
+ ? string.Empty
+ : preferredLanguage.Substring(0, 1);
+
var allLanguages = localization.GetCultures()
.Select(i => i.TwoLetterISOLanguageName)
.Distinct(StringComparer.OrdinalIgnoreCase)
- .Where(i => !languages.Contains(i, StringComparer.OrdinalIgnoreCase))
+ .Where(i => !languages.Contains(i, StringComparer.OrdinalIgnoreCase) && i.StartsWith(firstLetter, StringComparison.OrdinalIgnoreCase))
.ToList();
- languages.AddRange(allLanguages);
+ //languages.AddRange(allLanguages);
return string.Join(",", languages.ToArray());
}
diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs b/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs
index c8aa90b99..af5248608 100644
--- a/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs
+++ b/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs
@@ -212,12 +212,10 @@ namespace MediaBrowser.Server.Implementations.Channels
}
var itemId = item.Id.ToString("N");
- var sources = await _manager.GetChannelItemMediaSources(itemId, cancellationToken)
+ var sources = await _manager.GetChannelItemMediaSources(itemId, false, cancellationToken)
.ConfigureAwait(false);
- var list = sources.ToList();
-
- var cachedVersions = list.Where(i => i.Protocol == MediaProtocol.File).ToList();
+ var cachedVersions = sources.Where(i => i.Protocol == MediaProtocol.File).ToList();
if (cachedVersions.Count > 0)
{
@@ -225,13 +223,6 @@ namespace MediaBrowser.Server.Implementations.Channels
return;
}
- var source = list.FirstOrDefault(i => i.Protocol == MediaProtocol.Http);
-
- if (source == null)
- {
- return;
- }
-
var channelItem = (IChannelMediaItem)item;
var destination = Path.Combine(path, channelItem.ChannelId, itemId);
diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
index 8fb6bb434..b9d218215 100644
--- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
+++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
@@ -244,7 +244,7 @@ namespace MediaBrowser.Server.Implementations.Channels
return item;
}
- public async Task<IEnumerable<MediaSourceInfo>> GetChannelItemMediaSources(string id, CancellationToken cancellationToken)
+ public async Task<IEnumerable<MediaSourceInfo>> GetChannelItemMediaSources(string id, bool includeDynamicSources, CancellationToken cancellationToken)
{
var item = (IChannelMediaItem)_libraryManager.GetItemById(id);
@@ -255,7 +255,7 @@ namespace MediaBrowser.Server.Implementations.Channels
IEnumerable<ChannelMediaInfo> results;
- if (requiresCallback != null)
+ if (requiresCallback != null && includeDynamicSources)
{
results = await GetChannelItemMediaSourcesInternal(requiresCallback, item.ExternalId, cancellationToken)
.ConfigureAwait(false);
@@ -374,6 +374,18 @@ namespace MediaBrowser.Server.Implementations.Channels
Id = id
};
+ var bitrate = (info.AudioBitrate ?? 0) + (info.VideoBitrate ?? 0);
+
+ if (bitrate > 0)
+ {
+ source.Bitrate = bitrate;
+ }
+
+ if (item is ChannelVideoItem && info.Protocol != MediaProtocol.Rtmp)
+ {
+
+ }
+
return source;
}
@@ -1447,7 +1459,7 @@ namespace MediaBrowser.Server.Implementations.Channels
IProgress<double> progress, CancellationToken cancellationToken)
{
var itemId = item.Id.ToString("N");
- var sources = await GetChannelItemMediaSources(itemId, cancellationToken)
+ var sources = await GetChannelItemMediaSources(itemId, true, cancellationToken)
.ConfigureAwait(false);
var list = sources.Where(i => i.Protocol == MediaProtocol.Http).ToList();
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json
index 15f4099ec..070d7a966 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json
@@ -519,7 +519,7 @@
"MediaInfoLongitude": "L\u00e4nge",
"MediaInfoShutterSpeed": "Verschlusszeit",
"MediaInfoSoftware": "Software",
- "HeaderIfYouLikeCheckTheseOut": "Wenn du {0} magst, schau dir einmal diese an...",
+ "HeaderIfYouLikeCheckTheseOut": "Wenn du {0} magst, schau dir einmal das an...",
"HeaderPlotKeywords": "Handlungsstichworte",
"HeaderMovies": "Filme",
"HeaderAlbums": "Alben",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json
index 5384b76cf..e3e3b4187 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json
@@ -469,7 +469,7 @@
"LabelResumePoint": "Point de reprise",
"ValueOneMovie": "1 Film",
"ValueMovieCount": "{0} films",
- "ValueOneTrailer": "1 Bande Annonce",
+ "ValueOneTrailer": "1 bande-annonce",
"ValueTrailerCount": "{0} bandes-annonces",
"ValueOneSeries": "1 S\u00e9rie",
"ValueSeriesCount": "{0} series",
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/fr.json b/MediaBrowser.Server.Implementations/Localization/Server/fr.json
index f40f8acc9..4ae3a5d0d 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/fr.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/fr.json
@@ -1020,7 +1020,7 @@
"LabelChannelDownloadPathHelp": "Sp\u00e9cifiez un chemin de t\u00e9l\u00e9chargements personnalis\u00e9 si besoin. Laissez vide pour t\u00e9l\u00e9charger dans un r\u00e9pertoire interne du programme.",
"LabelChannelDownloadAge": "Supprimer le contenu apr\u00e8s : (jours)",
"LabelChannelDownloadAgeHelp": "Le contenu t\u00e9l\u00e9charg\u00e9 plus vieux sera supprim\u00e9. Par contre, il sera toujours disponible par flux Internet (en ligne).",
- "ChannelSettingsFormHelp": "Installer des cha\u00eenes comme \"Trailers\" and \"Vimeo\" par le catalogue de Plugins.",
+ "ChannelSettingsFormHelp": "Installer des cha\u00eenes comme \"Trailers\" et \"Vimeo\" dans le catalogue des plugins.",
"LabelSelectCollection": "S\u00e9lectionner la collection :",
"ButtonOptions": "Options",
"ViewTypeMovies": "Films",
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/hr.json b/MediaBrowser.Server.Implementations/Localization/Server/hr.json
index 7481a1964..949e2a5e7 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/hr.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/hr.json
@@ -845,43 +845,43 @@
"OptionSpecialFeatures": "Specijalne opcije",
"HeaderCollections": "Kolekcije",
"LabelProfileCodecsHelp": "Odvojeno sa to\u010dka-zrezom. Ovo mo\u017ee ostaviti prazno kao bi bilo postavljeno za sve codecs.",
- "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
- "HeaderResponseProfile": "Response Profile",
- "LabelType": "Type:",
+ "LabelProfileContainersHelp": "Odvojeno sa to\u010dka-zrezom. Ovo mo\u017ee ostaviti prazno kao bi bilo postavljeno za sve spremnike.",
+ "HeaderResponseProfile": "Profil odziva",
+ "LabelType": "Tip:",
"LabelPersonRole": "Role:",
"LabelPersonRoleHelp": "Role is generally only applicable to actors.",
- "LabelProfileContainer": "Container:",
- "LabelProfileVideoCodecs": "Video codecs:",
- "LabelProfileAudioCodecs": "Audio codecs:",
- "LabelProfileCodecs": "Codecs:",
- "HeaderDirectPlayProfile": "Direct Play Profile",
- "HeaderTranscodingProfile": "Transcoding Profile",
- "HeaderCodecProfile": "Codec Profile",
- "HeaderCodecProfileHelp": "Codec profiles indicate the limitations of a device when playing specific codecs. If a limitation applies then the media will be transcoded, even if the codec is configured for direct play.",
- "HeaderContainerProfile": "Container Profile",
- "HeaderContainerProfileHelp": "Container profiles indicate the limitations of a device when playing specific formats. If a limitation applies then the media will be transcoded, even if the format is configured for direct play.",
+ "LabelProfileContainer": "Spremnik:",
+ "LabelProfileVideoCodecs": "Video kodek:",
+ "LabelProfileAudioCodecs": "Audio kodek:",
+ "LabelProfileCodecs": "Kodeki:",
+ "HeaderDirectPlayProfile": "Profil za direktnu reprodukciju",
+ "HeaderTranscodingProfile": "Profil transkodiranja",
+ "HeaderCodecProfile": "Profil kodeka",
+ "HeaderCodecProfileHelp": "Profili kodeka definiraju ograni\u010denja kada ure\u0111aji izvode sadr\u017eaj u specifi\u010dnom kodeku. Ako se ograni\u010denja podudaraju tada \u0107e sadr\u017eaj biti transkodiran, iako je kodek konfiguriran za direktno izvo\u0111enje.",
+ "HeaderContainerProfile": "Profil spremnika",
+ "HeaderContainerProfileHelp": "Profil spremnika definira ograni\u010denja za ure\u0111aje kada izvode specifi\u010dne formate. Ako se ograni\u010denja podudaraju tada \u0107e sadr\u017eaj biti transkodiran, iako je format konfiguriran za direktno izvo\u0111enje.",
"OptionProfileVideo": "Video",
"OptionProfileAudio": "Audio",
"OptionProfileVideoAudio": "Video Audio",
- "OptionProfilePhoto": "Photo",
- "LabelUserLibrary": "User library:",
- "LabelUserLibraryHelp": "Select which user library to display to the device. Leave empty to inherit the default setting.",
- "OptionPlainStorageFolders": "Display all folders as plain storage folders",
- "OptionPlainStorageFoldersHelp": "If enabled, all folders are represented in DIDL as \"object.container.storageFolder\" instead of a more specific type, such as \"object.container.person.musicArtist\".",
- "OptionPlainVideoItems": "Display all videos as plain video items",
- "OptionPlainVideoItemsHelp": "If enabled, all videos are represented in DIDL as \"object.item.videoItem\" instead of a more specific type, such as \"object.item.videoItem.movie\".",
- "LabelSupportedMediaTypes": "Supported Media Types:",
- "TabIdentification": "Identification",
+ "OptionProfilePhoto": "Slika",
+ "LabelUserLibrary": "Korisni\u010dka biblioteka:",
+ "LabelUserLibraryHelp": "Odaberite koju korisni\u010dku biblioteku \u0107e te prikazati ure\u0111aju. Ostavite prazno ako \u017eelite preuzeti definirane postavke.",
+ "OptionPlainStorageFolders": "Prika\u017ei sve mape kako jednostavne mape za skladi\u0161tenje",
+ "OptionPlainStorageFoldersHelp": "Ako je omogu\u0107eno, sve mape se prezentiraju u DIDL-u kao \"objekt.spremnik.skladi\u0161naMapa\" umjesto vi\u0161e specijaliziranog tipa kao \"objekt.spremnik.osoba.glazbaIzvo\u0111a\u010d\".",
+ "OptionPlainVideoItems": "Prika\u017ei sav video kao jednostavne video stavke.",
+ "OptionPlainVideoItemsHelp": "Ako je omogu\u0107eno, sav video se prezentira u DIDL-u kao \"objekt.stavka.videoStavka\" umjesto vi\u0161e specijaliziranog tipa kao \"objekt.stavka.videoStavka.film\".",
+ "LabelSupportedMediaTypes": "Podr\u017eani tipovi medija:",
+ "TabIdentification": "Identifikacija",
"HeaderIdentification": "Identification",
- "TabDirectPlay": "Direct Play",
- "TabContainers": "Containers",
- "TabCodecs": "Codecs",
- "TabResponses": "Responses",
- "HeaderProfileInformation": "Profile Information",
- "LabelEmbedAlbumArtDidl": "Embed album art in Didl",
- "LabelEmbedAlbumArtDidlHelp": "Some devices prefer this method for obtaining album art. Others may fail to play with this option enabled.",
- "LabelAlbumArtPN": "Album art PN:",
- "LabelAlbumArtHelp": "PN used for album art, within the dlna:profileID attribute on upnp:albumArtURI. Some clients require a specific value, regardless of the size of the image.",
+ "TabDirectPlay": "Direktna reprodukcija",
+ "TabContainers": "Spremnik",
+ "TabCodecs": "Kodek",
+ "TabResponses": "Odazivi",
+ "HeaderProfileInformation": "Informacija profila",
+ "LabelEmbedAlbumArtDidl": "Ugradi grafike albuma u Didl",
+ "LabelEmbedAlbumArtDidlHelp": "Neki ure\u0111aji podr\u017eavaju ovu metodu za prikaz grafike albuma. Drugi bi mogli imati problema sa ovom opcijom uklju\u010denom.",
+ "LabelAlbumArtPN": "Grafika albuma PN:",
+ "LabelAlbumArtHelp": "PN se koristi za grafiku albuma sa dlna:profilID atributom na upnp:albumGrafikaURI. Neki klijenti zahtijevaju specifi\u010dnu vrijednost bez obzira na veli\u010dinu slike.",
"LabelAlbumArtMaxWidth": "Album art max width:",
"LabelAlbumArtMaxWidthHelp": "Max resolution of album art exposed via upnp:albumArtURI.",
"LabelAlbumArtMaxHeight": "Album art max height:",
diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs
index f08a7771b..17c5b108a 100644
--- a/MediaBrowser.ServerApplication/ApplicationHost.cs
+++ b/MediaBrowser.ServerApplication/ApplicationHost.cs
@@ -218,6 +218,7 @@ namespace MediaBrowser.ServerApplication
private IAuthenticationRepository AuthenticationRepository { get; set; }
private ISyncRepository SyncRepository { get; set; }
private ITVSeriesManager TVSeriesManager { get; set; }
+ private ICollectionManager CollectionManager { get; set; }
private readonly StartupOptions _startupOptions;
private readonly string _remotePackageName;
@@ -494,8 +495,8 @@ namespace MediaBrowser.ServerApplication
var connectionManager = new ConnectionManager(dlnaManager, ServerConfigurationManager, LogManager.GetLogger("UpnpConnectionManager"), HttpClient);
RegisterSingleInstance<IConnectionManager>(connectionManager);
- var collectionManager = new CollectionManager(LibraryManager, FileSystemManager, LibraryMonitor, LogManager.GetLogger("CollectionManager"));
- RegisterSingleInstance<ICollectionManager>(collectionManager);
+ CollectionManager = new CollectionManager(LibraryManager, FileSystemManager, LibraryMonitor, LogManager.GetLogger("CollectionManager"));
+ RegisterSingleInstance(CollectionManager);
var playlistManager = new PlaylistManager(LibraryManager, FileSystemManager, LibraryMonitor, LogManager.GetLogger("PlaylistManager"), UserManager);
RegisterSingleInstance<IPlaylistManager>(playlistManager);
@@ -700,6 +701,7 @@ namespace MediaBrowser.ServerApplication
BaseItem.LiveTvManager = LiveTvManager;
Folder.UserViewManager = UserViewManager;
UserView.TVSeriesManager = TVSeriesManager;
+ BaseItem.CollectionManager = CollectionManager;
}
/// <summary>