Pārlūkot izejas kodu

resolve moviedb issues

Luke Pulverenti 10 gadi atpakaļ
vecāks
revīzija
4999f19485

+ 1 - 1
MediaBrowser.Api/Playback/BaseStreamingService.cs

@@ -1718,7 +1718,7 @@ namespace MediaBrowser.Api.Playback
             string mediaSourceId,
             string mediaSourceId,
             CancellationToken cancellationToken)
             CancellationToken cancellationToken)
         {
         {
-            var channelMediaSources = await ChannelManager.GetChannelItemMediaSources(id, cancellationToken)
+            var channelMediaSources = await ChannelManager.GetChannelItemMediaSources(id, true, cancellationToken)
                 .ConfigureAwait(false);
                 .ConfigureAwait(false);
 
 
             var list = channelMediaSources.ToList();
             var list = channelMediaSources.ToList();

+ 2 - 2
MediaBrowser.Api/TvShowsService.cs

@@ -344,7 +344,7 @@ namespace MediaBrowser.Api
             // This must be the last filter
             // This must be the last filter
             if (!string.IsNullOrEmpty(request.AdjacentTo))
             if (!string.IsNullOrEmpty(request.AdjacentTo))
             {
             {
-                seasons = ItemsService.FilterForAdjacency(seasons, request.AdjacentTo)
+                seasons = UserViewBuilder.FilterForAdjacency(seasons, request.AdjacentTo)
                     .Cast<Season>();
                     .Cast<Season>();
             }
             }
 
 
@@ -434,7 +434,7 @@ namespace MediaBrowser.Api
             // This must be the last filter
             // This must be the last filter
             if (!string.IsNullOrEmpty(request.AdjacentTo))
             if (!string.IsNullOrEmpty(request.AdjacentTo))
             {
             {
-                episodes = ItemsService.FilterForAdjacency(episodes, request.AdjacentTo)
+                episodes = UserViewBuilder.FilterForAdjacency(episodes, request.AdjacentTo)
                     .Cast<Episode>();
                     .Cast<Episode>();
             }
             }
 
 

+ 1 - 1
MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs

@@ -188,7 +188,7 @@ namespace MediaBrowser.Api.UserLibrary
             var imageTypes = request.GetImageTypes().ToList();
             var imageTypes = request.GetImageTypes().ToList();
             if (imageTypes.Count > 0)
             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();
             var filters = request.GetFilters().ToList();

+ 443 - 744
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")]
         [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 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>
     /// <summary>
@@ -331,21 +368,21 @@ namespace MediaBrowser.Api.UserLibrary
                 items = ApplyFilter(items, filter, user, _userDataRepository);
                 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);
             items = _libraryManager.Sort(items, user, request.GetOrderBy(), request.SortOrder ?? SortOrder.Ascending);
 
 
             // This must be the last filter
             // This must be the last filter
             if (!string.IsNullOrEmpty(request.AdjacentTo))
             if (!string.IsNullOrEmpty(request.AdjacentTo))
             {
             {
-                items = FilterForAdjacency(items, request.AdjacentTo);
+                items = UserViewBuilder.FilterForAdjacency(items, request.AdjacentTo);
             }
             }
 
 
             var itemsArray = items.ToList();
             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>
         /// <summary>
         /// Gets the items to serialize.
         /// Gets the items to serialize.
         /// </summary>
         /// </summary>
@@ -486,9 +496,48 @@ namespace MediaBrowser.Api.UserLibrary
                 Filter = (i, u) => ApplyAdditionalFilters(request, i, u, true),
                 Filter = (i, u) => ApplyAdditionalFilters(request, i, u, true),
 
 
                 Limit = request.Limit,
                 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())
             foreach (var filter in request.GetFilters())
             {
             {
                 switch (filter)
                 switch (filter)
@@ -610,121 +659,6 @@ namespace MediaBrowser.Api.UserLibrary
             return items;
             return items;
         }
         }
 
 
-        private IEnumerable<BaseItem> FilterVirtualEpisodes(GetItems request, IEnumerable<BaseItem> items, User user)
-        {
-            items = FilterVirtualSeasons(request, items, user);
-
-            if (request.IsMissing.HasValue)
-            {
-                var val = request.IsMissing.Value;
-                items = items.Where(i =>
-                {
-                    var e = i as Episode;
-                    if (e != null)
-                    {
-                        return e.IsMissingEpisode == val;
-                    }
-                    return true;
-                });
-            }
-
-            if (request.IsUnaired.HasValue)
-            {
-                var val = request.IsUnaired.Value;
-                items = items.Where(i =>
-                {
-                    var e = i as Episode;
-                    if (e != null)
-                    {
-                        return e.IsUnaired == val;
-                    }
-                    return true;
-                });
-            }
-
-            if (request.IsVirtualUnaired.HasValue)
-            {
-                var val = request.IsVirtualUnaired.Value;
-                items = items.Where(i =>
-                {
-                    var e = i as Episode;
-                    if (e != null)
-                    {
-                        return e.IsVirtualUnaired == val;
-                    }
-                    return true;
-                });
-            }
-
-            return items;
-        }
-
-        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 (!isMissing && !isVirtualUnaired)
-                {
-                    return items.Where(i =>
-                    {
-                        var e = i as Season;
-                        if (e != null)
-                        {
-                            return !e.IsMissingOrVirtualUnaired;
-                        }
-                        return true;
-                    });
-                }
-            }
-
-            if (request.IsMissing.HasValue)
-            {
-                var val = request.IsMissing.Value;
-                items = items.Where(i =>
-                {
-                    var e = i as Season;
-                    if (e != null)
-                    {
-                        return e.IsMissingSeason == val;
-                    }
-                    return true;
-                });
-            }
-
-            if (request.IsUnaired.HasValue)
-            {
-                var val = request.IsUnaired.Value;
-                items = items.Where(i =>
-                {
-                    var e = i as Season;
-                    if (e != null)
-                    {
-                        return e.IsUnaired == val;
-                    }
-                    return true;
-                });
-            }
-
-            if (request.IsVirtualUnaired.HasValue)
-            {
-                var val = request.IsVirtualUnaired.Value;
-                items = items.Where(i =>
-                {
-                    var e = i as Season;
-                    if (e != null)
-                    {
-                        return e.IsVirtualUnaired == val;
-                    }
-                    return true;
-                });
-            }
-
-            return items;
-        }
-
         private bool ApplyAdditionalFilters(GetItems request, BaseItem i, User user, bool isPreFiltered)
         private bool ApplyAdditionalFilters(GetItems request, BaseItem i, User user, bool isPreFiltered)
         {
         {
             if (!isPreFiltered)
             if (!isPreFiltered)
@@ -760,130 +694,185 @@ namespace MediaBrowser.Api.UserLibrary
                 {
                 {
                     return false;
                     return false;
                 }
                 }
-            }
 
 
-            if (request.MinCommunityRating.HasValue)
-            {
-                var val = request.MinCommunityRating.Value;
+                if (request.IsInBoxSet.HasValue)
+                {
+                    var val = request.IsInBoxSet.Value;
+                    if (i.Parents.OfType<BoxSet>().Any() != val)
+                    {
+                        return false;
+                    }
+                }
 
 
-                if (!(i.CommunityRating.HasValue && i.CommunityRating >= val))
+                // Filter by Video3DFormat
+                if (request.Is3D.HasValue)
                 {
                 {
-                    return false;
+                    var val = request.Is3D.Value;
+                    var video = i as Video;
+
+                    if (video == null || val != video.Video3DFormat.HasValue)
+                    {
+                        return false;
+                    }
                 }
                 }
-            }
 
 
-            if (request.MinCriticRating.HasValue)
-            {
-                var val = request.MinCriticRating.Value;
+                if (request.IsHD.HasValue)
+                {
+                    var val = request.IsHD.Value;
+                    var video = i as Video;
 
 
-                var hasCriticRating = i as IHasCriticRating;
+                    if (video == null || val != video.IsHD)
+                    {
+                        return false;
+                    }
+                }
 
 
-                if (hasCriticRating != null)
+                if (request.IsUnidentified.HasValue)
                 {
                 {
-                    if (!(hasCriticRating.CriticRating.HasValue && hasCriticRating.CriticRating >= val))
+                    var val = request.IsUnidentified.Value;
+                    if (i.IsUnidentified != val)
                     {
                     {
                         return false;
                         return false;
                     }
                     }
                 }
                 }
-                else
+
+                if (request.IsLocked.HasValue)
                 {
                 {
-                    return false;
+                    var val = request.IsLocked.Value;
+                    if (i.IsLocked != val)
+                    {
+                        return false;
+                    }
                 }
                 }
-            }
 
 
-            // Artists
-            if (!string.IsNullOrEmpty(request.Artists))
-            {
-                var artists = request.Artists.Split('|');
+                if (request.HasOverview.HasValue)
+                {
+                    var filterValue = request.HasOverview.Value;
 
 
-                var audio = i as IHasArtist;
+                    var hasValue = !string.IsNullOrEmpty(i.Overview);
 
 
-                if (!(audio != null && artists.Any(audio.HasArtist)))
-                {
-                    return false;
+                    if (hasValue != filterValue)
+                    {
+                        return false;
+                    }
                 }
                 }
-            }
 
 
-            // Albums
-            if (!string.IsNullOrEmpty(request.Albums))
-            {
-                var albums = request.Albums.Split('|');
+                if (request.HasImdbId.HasValue)
+                {
+                    var filterValue = request.HasImdbId.Value;
 
 
-                var audio = i as Audio;
+                    var hasValue = !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Imdb));
 
 
-                if (audio != null)
-                {
-                    if (!albums.Any(a => string.Equals(a, audio.Album, StringComparison.OrdinalIgnoreCase)))
+                    if (hasValue != filterValue)
                     {
                     {
                         return false;
                         return false;
                     }
                     }
                 }
                 }
 
 
-                var album = i as MusicAlbum;
-
-                if (album != null)
+                if (request.HasTmdbId.HasValue)
                 {
                 {
-                    if (!albums.Any(a => string.Equals(a, album.Name, StringComparison.OrdinalIgnoreCase)))
+                    var filterValue = request.HasTmdbId.Value;
+
+                    var hasValue = !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Tmdb));
+
+                    if (hasValue != filterValue)
                     {
                     {
                         return false;
                         return false;
                     }
                     }
                 }
                 }
 
 
-                var musicVideo = i as MusicVideo;
-
-                if (musicVideo != null)
+                if (request.HasTvdbId.HasValue)
                 {
                 {
-                    if (!albums.Any(a => string.Equals(a, musicVideo.Album, StringComparison.OrdinalIgnoreCase)))
+                    var filterValue = request.HasTvdbId.Value;
+
+                    var hasValue = !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Tvdb));
+
+                    if (hasValue != filterValue)
                     {
                     {
                         return false;
                         return false;
                     }
                     }
                 }
                 }
 
 
-                return false;
-            }
-
-            // Min index number
-            if (request.MinIndexNumber.HasValue)
-            {
-                if (!(i.IndexNumber.HasValue && i.IndexNumber.Value >= request.MinIndexNumber.Value))
+                if (request.IsYearMismatched.HasValue)
                 {
                 {
-                    return false;
+                    var filterValue = request.IsYearMismatched.Value;
+
+                    if (UserViewBuilder.IsYearMismatched(i) != filterValue)
+                    {
+                        return false;
+                    }
                 }
                 }
-            }
 
 
-            // Min official rating
-            if (!string.IsNullOrEmpty(request.MinOfficialRating))
-            {
-                var level = _localization.GetRatingLevel(request.MinOfficialRating);
+                if (request.HasOfficialRating.HasValue)
+                {
+                    var filterValue = request.HasOfficialRating.Value;
 
 
-                if (level.HasValue)
+                    var hasValue = !string.IsNullOrEmpty(i.OfficialRating);
+
+                    if (hasValue != filterValue)
+                    {
+                        return false;
+                    }
+                }
+
+                if (request.IsPlaceHolder.HasValue)
                 {
                 {
-                    var rating = i.CustomRating;
+                    var filterValue = request.IsPlaceHolder.Value;
 
 
-                    if (string.IsNullOrEmpty(rating))
+                    var isPlaceHolder = false;
+
+                    var hasPlaceHolder = i as ISupportsPlaceHolders;
+
+                    if (hasPlaceHolder != null)
                     {
                     {
-                        rating = i.OfficialRating;
+                        isPlaceHolder = hasPlaceHolder.IsPlaceHolder;
                     }
                     }
 
 
-                    if (!string.IsNullOrEmpty(rating))
+                    if (isPlaceHolder != filterValue)
                     {
                     {
-                        var itemLevel = _localization.GetRatingLevel(rating);
+                        return false;
+                    }
+                }
 
 
-                        if (!(!itemLevel.HasValue || itemLevel.Value >= level.Value))
+                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;
                             return false;
                         }
                         }
                     }
                     }
+                    else
+                    {
+                        return false;
+                    }
                 }
                 }
-            }
 
 
-            // Max official rating
-            if (!string.IsNullOrEmpty(request.MaxOfficialRating))
-            {
-                var level = _localization.GetRatingLevel(request.MaxOfficialRating);
+                if (request.HasSubtitles.HasValue)
+                {
+                    var val = request.HasSubtitles.Value;
 
 
-                if (level.HasValue)
+                    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;
                     var rating = i.CustomRating;
 
 
                     if (string.IsNullOrEmpty(rating))
                     if (string.IsNullOrEmpty(rating))
@@ -891,246 +880,176 @@ namespace MediaBrowser.Api.UserLibrary
                         rating = i.OfficialRating;
                         rating = i.OfficialRating;
                     }
                     }
 
 
-                    if (!string.IsNullOrEmpty(rating))
+                    if (val)
                     {
                     {
-                        var itemLevel = _localization.GetRatingLevel(rating);
-
-                        if (!(!itemLevel.HasValue || itemLevel.Value <= level.Value))
+                        if (string.IsNullOrEmpty(rating))
+                        {
+                            return false;
+                        }
+                    }
+                    else
+                    {
+                        if (!string.IsNullOrEmpty(rating))
                         {
                         {
                             return false;
                             return false;
                         }
                         }
                     }
                     }
                 }
                 }
-            }
 
 
-            // LocationTypes
-            if (!string.IsNullOrEmpty(request.LocationTypes))
-            {
-                var vals = request.LocationTypes.Split(',');
-                if (!vals.Contains(i.LocationType.ToString(), StringComparer.OrdinalIgnoreCase))
+                if (request.HasTrailer.HasValue)
                 {
                 {
-                    return false;
-                }
-            }
+                    var val = request.HasTrailer.Value;
+                    var trailerCount = 0;
 
 
-            // ExcludeLocationTypes
-            if (!string.IsNullOrEmpty(request.ExcludeLocationTypes))
-            {
-                var vals = request.ExcludeLocationTypes.Split(',');
-                if (vals.Contains(i.LocationType.ToString(), StringComparer.OrdinalIgnoreCase))
-                {
-                    return false;
-                }
-            }
+                    var hasTrailers = i as IHasTrailers;
+                    if (hasTrailers != null)
+                    {
+                        trailerCount = hasTrailers.LocalTrailerIds.Count;
+                    }
 
 
-            if (!string.IsNullOrEmpty(request.AlbumArtistStartsWithOrGreater))
-            {
-                var ok = new[] { i }.OfType<IHasAlbumArtist>()
-                    .Any(p => string.Compare(request.AlbumArtistStartsWithOrGreater, p.AlbumArtists.FirstOrDefault(), StringComparison.CurrentCultureIgnoreCase) < 1);
+                    var ok = val ? trailerCount > 0 : trailerCount == 0;
 
 
-                if (!ok)
-                {
-                    return false;
+                    if (!ok)
+                    {
+                        return false;
+                    }
                 }
                 }
-            }
-
-            // Filter by Series Status
-            if (!string.IsNullOrEmpty(request.SeriesStatus))
-            {
-                var vals = request.SeriesStatus.Split(',');
 
 
-                var ok = new[] { i }.OfType<Series>().Any(p => p.Status.HasValue && vals.Contains(p.Status.Value.ToString(), StringComparer.OrdinalIgnoreCase));
-
-                if (!ok)
+                if (request.HasThemeSong.HasValue)
                 {
                 {
-                    return false;
-                }
-            }
+                    var filterValue = request.HasThemeSong.Value;
 
 
-            // Filter by Series AirDays
-            if (!string.IsNullOrEmpty(request.AirDays))
-            {
-                var days = request.AirDays.Split(',').Select(d => (DayOfWeek)Enum.Parse(typeof(DayOfWeek), d, true));
+                    var themeCount = 0;
+                    var iHasThemeMedia = i as IHasThemeMedia;
 
 
-                var ok = new[] { i }.OfType<Series>().Any(p => p.AirDays != null && days.Any(d => p.AirDays.Contains(d)));
+                    if (iHasThemeMedia != null)
+                    {
+                        themeCount = iHasThemeMedia.ThemeSongIds.Count;
+                    }
+                    var ok = filterValue ? themeCount > 0 : themeCount == 0;
 
 
-                if (!ok)
-                {
-                    return false;
+                    if (!ok)
+                    {
+                        return false;
+                    }
                 }
                 }
-            }
-
-            // Filter by Video3DFormat
-            if (request.Is3D.HasValue)
-            {
-                var val = request.Is3D.Value;
-                var video = i as Video;
 
 
-                if (video == null || val != video.Video3DFormat.HasValue)
+                if (request.HasThemeVideo.HasValue)
                 {
                 {
-                    return false;
-                }
-            }
+                    var filterValue = request.HasThemeVideo.Value;
 
 
-            // Filter by VideoType
-            if (!string.IsNullOrEmpty(request.VideoTypes))
-            {
-                var types = request.VideoTypes.Split(',');
+                    var themeCount = 0;
+                    var iHasThemeMedia = i as IHasThemeMedia;
 
 
-                var video = i as Video;
-                if (video == null || !types.Contains(video.VideoType.ToString(), StringComparer.OrdinalIgnoreCase))
-                {
-                    return false;
-                }
-            }
+                    if (iHasThemeMedia != null)
+                    {
+                        themeCount = iHasThemeMedia.ThemeVideoIds.Count;
+                    }
+                    var ok = filterValue ? themeCount > 0 : themeCount == 0;
 
 
-            var imageTypes = request.GetImageTypes().ToList();
-            if (imageTypes.Count > 0)
-            {
-                if (!(imageTypes.Any(imageType => HasImage(i, imageType))))
-                {
-                    return false;
+                    if (!ok)
+                    {
+                        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))))
+                // Apply genre filter
+                var genres = request.GetGenres();
+                if (genres.Length > 0 && !(genres.Any(v => i.Genres.Contains(v, StringComparer.OrdinalIgnoreCase))))
                 {
                 {
                     return false;
                     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)))
+                // Apply genre filter
+                var allGenres = request.GetAllGenres();
+                if (allGenres.Length > 0 && !allGenres.All(v => i.Genres.Contains(v, StringComparer.OrdinalIgnoreCase)))
                 {
                 {
                     return false;
                     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)))
+                // Filter by VideoType
+                if (!string.IsNullOrEmpty(request.VideoTypes))
                 {
                 {
-                    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;
+                    var types = request.VideoTypes.Split(',');
 
 
-                if (string.IsNullOrEmpty(personTypes))
-                {
-                    if (!(i.People.Any(p => string.Equals(p.Name, request.Person, StringComparison.OrdinalIgnoreCase))))
+                    var video = i as Video;
+                    if (video == null || !types.Contains(video.VideoType.ToString(), StringComparer.OrdinalIgnoreCase))
                     {
                     {
                         return false;
                         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)
+                var imageTypes = request.GetImageTypes().ToList();
+                if (imageTypes.Count > 0)
+                {
+                    if (!(imageTypes.Any(i.HasImage)))
                     {
                     {
                         return false;
                         return false;
                     }
                     }
                 }
                 }
-            }
-
-            if (request.HasTrailer.HasValue)
-            {
-                var val = request.HasTrailer.Value;
-                var trailerCount = 0;
 
 
-                var hasTrailers = i as IHasTrailers;
-                if (hasTrailers != null)
+                // Apply studio filter
+                var studios = request.GetStudios();
+                if (studios.Length > 0 && !studios.Any(v => i.Studios.Contains(v, StringComparer.OrdinalIgnoreCase)))
                 {
                 {
-                    trailerCount = hasTrailers.LocalTrailerIds.Count;
+                    return false;
                 }
                 }
 
 
-                var ok = val ? trailerCount > 0 : trailerCount == 0;
-
-                if (!ok)
+                // Apply year filter
+                var years = request.GetYears();
+                if (years.Length > 0 && !(i.ProductionYear.HasValue && years.Contains(i.ProductionYear.Value)))
                 {
                 {
                     return false;
                     return false;
                 }
                 }
-            }
 
 
-            if (request.HasThemeSong.HasValue)
-            {
-                var filterValue = request.HasThemeSong.Value;
+                // Apply person filter
+                if (!string.IsNullOrEmpty(request.Person))
+                {
+                    var personTypes = request.GetPersonTypes();
 
 
-                var themeCount = 0;
-                var iHasThemeMedia = i as IHasThemeMedia;
+                    if (personTypes.Length == 0)
+                    {
+                        if (!(i.People.Any(p => string.Equals(p.Name, request.Person, StringComparison.OrdinalIgnoreCase))))
+                        {
+                            return false;
+                        }
+                    }
+                    else
+                    {
+                        var types = personTypes;
 
 
-                if (iHasThemeMedia != null)
-                {
-                    themeCount = iHasThemeMedia.ThemeSongIds.Count;
-                }
-                var ok = filterValue ? themeCount > 0 : themeCount == 0;
+                        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 (!ok)
+                        {
+                            return false;
+                        }
+                    }
                 }
                 }
             }
             }
 
 
-            if (request.HasThemeVideo.HasValue)
+            if (request.MinCommunityRating.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;
+                var val = request.MinCommunityRating.Value;
 
 
-                if (!ok)
+                if (!(i.CommunityRating.HasValue && i.CommunityRating >= val))
                 {
                 {
                     return false;
                     return false;
                 }
                 }
             }
             }
 
 
-            if (request.MinPlayers.HasValue)
+            if (request.MinCriticRating.HasValue)
             {
             {
-                var filterValue = request.MinPlayers.Value;
+                var val = request.MinCriticRating.Value;
 
 
-                var game = i as Game;
+                var hasCriticRating = i as IHasCriticRating;
 
 
-                if (game != null)
+                if (hasCriticRating != null)
                 {
                 {
-                    var players = game.PlayersSupported ?? 1;
-
-                    var ok = players >= filterValue;
-
-                    if (!ok)
+                    if (!(hasCriticRating.CriticRating.HasValue && hasCriticRating.CriticRating >= val))
                     {
                     {
                         return false;
                         return false;
                     }
                     }
@@ -1141,504 +1060,284 @@ namespace MediaBrowser.Api.UserLibrary
                 }
                 }
             }
             }
 
 
-            if (request.MaxPlayers.HasValue)
+            // Artists
+            if (!string.IsNullOrEmpty(request.Artists))
             {
             {
-                var filterValue = request.MaxPlayers.Value;
-
-                var game = i as Game;
-
-                if (game != null)
-                {
-                    var players = game.PlayersSupported ?? 1;
+                var artists = request.Artists.Split('|');
 
 
-                    var ok = players <= filterValue;
+                var audio = i as IHasArtist;
 
 
-                    if (!ok)
-                    {
-                        return false;
-                    }
-                }
-                else
+                if (!(audio != null && artists.Any(audio.HasArtist)))
                 {
                 {
                     return false;
                     return false;
                 }
                 }
             }
             }
 
 
-            if (request.HasSpecialFeature.HasValue)
+            // Albums
+            if (!string.IsNullOrEmpty(request.Albums))
             {
             {
-                var filterValue = request.HasSpecialFeature.Value;
+                var albums = request.Albums.Split('|');
 
 
-                var movie = i as IHasSpecialFeatures;
+                var audio = i as Audio;
 
 
-                if (movie != null)
+                if (audio != null)
                 {
                 {
-                    var ok = filterValue
-                        ? movie.SpecialFeatureIds.Count > 0
-                        : movie.SpecialFeatureIds.Count == 0;
-
-                    if (!ok)
+                    if (!albums.Any(a => string.Equals(a, audio.Album, StringComparison.OrdinalIgnoreCase)))
                     {
                     {
                         return false;
                         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;
-                }
+                var album = i as MusicAlbum;
 
 
-                if (val)
+                if (album != null)
                 {
                 {
-                    if (string.IsNullOrEmpty(rating))
+                    if (!albums.Any(a => string.Equals(a, album.Name, StringComparison.OrdinalIgnoreCase)))
                     {
                     {
                         return false;
                         return false;
                     }
                     }
                 }
                 }
-                else
+
+                var musicVideo = i as MusicVideo;
+
+                if (musicVideo != null)
                 {
                 {
-                    if (!string.IsNullOrEmpty(rating))
+                    if (!albums.Any(a => string.Equals(a, musicVideo.Album, StringComparison.OrdinalIgnoreCase)))
                     {
                     {
                         return false;
                         return false;
                     }
                     }
                 }
                 }
-            }
-
-            if (request.IsHD.HasValue)
-            {
-                var val = request.IsHD.Value;
-                var video = i as Video;
 
 
-                if (video == null || val != video.IsHD)
-                {
-                    return false;
-                }
+                return false;
             }
             }
 
 
-            if (request.IsInBoxSet.HasValue)
+            // Min index number
+            if (request.MinIndexNumber.HasValue)
             {
             {
-                var val = request.IsHD.Value;
-                if (i.Parents.OfType<BoxSet>().Any() != val)
+                if (!(i.IndexNumber.HasValue && i.IndexNumber.Value >= request.MinIndexNumber.Value))
                 {
                 {
                     return false;
                     return false;
                 }
                 }
             }
             }
 
 
-            if (request.IsUnidentified.HasValue)
+            // Min official rating
+            if (!string.IsNullOrEmpty(request.MinOfficialRating))
             {
             {
-                var val = request.IsUnidentified.Value;
-                if (i.IsUnidentified != val)
-                {
-                    return false;
-                }
-            }
+                var level = _localization.GetRatingLevel(request.MinOfficialRating);
 
 
-            if (request.IsLocked.HasValue)
-            {
-                var val = request.IsLocked.Value;
-                if (i.IsLocked != val)
+                if (level.HasValue)
                 {
                 {
-                    return false;
-                }
-            }
-
-            if (request.ParentIndexNumber.HasValue)
-            {
-                var filterValue = request.ParentIndexNumber.Value;
-
-                var episode = i as Episode;
+                    var rating = i.CustomRating;
 
 
-                if (episode != null)
-                {
-                    if (episode.ParentIndexNumber.HasValue && episode.ParentIndexNumber.Value != filterValue)
+                    if (string.IsNullOrEmpty(rating))
                     {
                     {
-                        return false;
+                        rating = i.OfficialRating;
                     }
                     }
-                }
-
-                var song = i as Audio;
 
 
-                if (song != null)
-                {
-                    if (song.ParentIndexNumber.HasValue && song.ParentIndexNumber.Value != filterValue)
+                    if (!string.IsNullOrEmpty(rating))
                     {
                     {
-                        return false;
+                        var itemLevel = _localization.GetRatingLevel(rating);
+
+                        if (!(!itemLevel.HasValue || itemLevel.Value >= level.Value))
+                        {
+                            return false;
+                        }
                     }
                     }
                 }
                 }
             }
             }
 
 
-            if (request.AiredDuringSeason.HasValue)
+            // Max official rating
+            if (!string.IsNullOrEmpty(request.MaxOfficialRating))
             {
             {
-                var episode = i as Episode;
+                var level = _localization.GetRatingLevel(request.MaxOfficialRating);
 
 
-                if (episode == null)
+                if (level.HasValue)
                 {
                 {
-                    return false;
-                }
+                    var rating = i.CustomRating;
 
 
-                if (!Series.FilterEpisodesBySeason(new[] { episode }, request.AiredDuringSeason.Value, true).Any())
-                {
-                    return false;
+                    if (string.IsNullOrEmpty(rating))
+                    {
+                        rating = i.OfficialRating;
+                    }
+
+                    if (!string.IsNullOrEmpty(rating))
+                    {
+                        var itemLevel = _localization.GetRatingLevel(rating);
+
+                        if (!(!itemLevel.HasValue || itemLevel.Value <= level.Value))
+                        {
+                            return false;
+                        }
+                    }
                 }
                 }
             }
             }
 
 
-            if (!string.IsNullOrEmpty(request.MinPremiereDate))
+            // LocationTypes
+            if (!string.IsNullOrEmpty(request.LocationTypes))
             {
             {
-                var date = DateTime.Parse(request.MinPremiereDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
-
-                if (!(i.PremiereDate.HasValue && i.PremiereDate.Value >= date))
+                var vals = request.LocationTypes.Split(',');
+                if (!vals.Contains(i.LocationType.ToString(), StringComparer.OrdinalIgnoreCase))
                 {
                 {
                     return false;
                     return false;
                 }
                 }
             }
             }
 
 
-            if (!string.IsNullOrEmpty(request.MaxPremiereDate))
+            // ExcludeLocationTypes
+            if (!string.IsNullOrEmpty(request.ExcludeLocationTypes))
             {
             {
-                var date = DateTime.Parse(request.MaxPremiereDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
-
-                if (!(i.PremiereDate.HasValue && i.PremiereDate.Value <= date))
+                var vals = request.ExcludeLocationTypes.Split(',');
+                if (vals.Contains(i.LocationType.ToString(), StringComparer.OrdinalIgnoreCase))
                 {
                 {
                     return false;
                     return false;
                 }
                 }
             }
             }
 
 
-            if (request.HasOverview.HasValue)
+            if (!string.IsNullOrEmpty(request.AlbumArtistStartsWithOrGreater))
             {
             {
-                var filterValue = request.HasOverview.Value;
-
-                var hasValue = !string.IsNullOrEmpty(i.Overview);
+                var ok = new[] { i }.OfType<IHasAlbumArtist>()
+                    .Any(p => string.Compare(request.AlbumArtistStartsWithOrGreater, p.AlbumArtists.FirstOrDefault(), StringComparison.CurrentCultureIgnoreCase) < 1);
 
 
-                if (hasValue != filterValue)
+                if (!ok)
                 {
                 {
                     return false;
                     return false;
                 }
                 }
             }
             }
 
 
-            if (request.HasImdbId.HasValue)
+            // Filter by Series Status
+            if (!string.IsNullOrEmpty(request.SeriesStatus))
             {
             {
-                var filterValue = request.HasImdbId.Value;
+                var vals = request.SeriesStatus.Split(',');
 
 
-                var hasValue = !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Imdb));
+                var ok = new[] { i }.OfType<Series>().Any(p => p.Status.HasValue && vals.Contains(p.Status.Value.ToString(), StringComparer.OrdinalIgnoreCase));
 
 
-                if (hasValue != filterValue)
+                if (!ok)
                 {
                 {
                     return false;
                     return false;
                 }
                 }
             }
             }
 
 
-            if (request.HasTmdbId.HasValue)
+            // Filter by Series AirDays
+            if (!string.IsNullOrEmpty(request.AirDays))
             {
             {
-                var filterValue = request.HasTmdbId.Value;
+                var days = request.AirDays.Split(',').Select(d => (DayOfWeek)Enum.Parse(typeof(DayOfWeek), d, true));
 
 
-                var hasValue = !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Tmdb));
+                var ok = new[] { i }.OfType<Series>().Any(p => p.AirDays != null && days.Any(d => p.AirDays.Contains(d)));
 
 
-                if (hasValue != filterValue)
+                if (!ok)
                 {
                 {
                     return false;
                     return false;
                 }
                 }
             }
             }
 
 
-            if (request.HasTvdbId.HasValue)
+            if (request.MinPlayers.HasValue)
             {
             {
-                var filterValue = request.HasTvdbId.Value;
+                var filterValue = request.MinPlayers.Value;
 
 
-                var hasValue = !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Tvdb));
+                var game = i as Game;
 
 
-                if (hasValue != filterValue)
+                if (game != null)
                 {
                 {
-                    return false;
-                }
-            }
+                    var players = game.PlayersSupported ?? 1;
 
 
-            if (request.IsYearMismatched.HasValue)
-            {
-                var filterValue = request.IsYearMismatched.Value;
+                    var ok = players >= filterValue;
 
 
-                if (IsYearMismatched(i) != filterValue)
+                    if (!ok)
+                    {
+                        return false;
+                    }
+                }
+                else
                 {
                 {
                     return false;
                     return false;
                 }
                 }
             }
             }
 
 
-            if (request.HasOfficialRating.HasValue)
+            if (request.MaxPlayers.HasValue)
             {
             {
-                var filterValue = request.HasOfficialRating.Value;
+                var filterValue = request.MaxPlayers.Value;
 
 
-                var hasValue = !string.IsNullOrEmpty(i.OfficialRating);
+                var game = i as Game;
 
 
-                if (hasValue != filterValue)
+                if (game != null)
                 {
                 {
-                    return false;
-                }
-            }
-
-            if (request.IsPlaceHolder.HasValue)
-            {
-                var filterValue = request.IsPlaceHolder.Value;
-
-                var isPlaceHolder = false;
+                    var players = game.PlayersSupported ?? 1;
 
 
-                var hasPlaceHolder = i as ISupportsPlaceHolders;
+                    var ok = players <= filterValue;
 
 
-                if (hasPlaceHolder != null)
-                {
-                    isPlaceHolder = hasPlaceHolder.IsPlaceHolder;
+                    if (!ok)
+                    {
+                        return false;
+                    }
                 }
                 }
-
-                if (isPlaceHolder != filterValue)
+                else
                 {
                 {
                     return false;
                     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))
+            if (request.ParentIndexNumber.HasValue)
             {
             {
-                items = items.Where(i => string.Compare(request.NameLessThan, i.SortName, StringComparison.CurrentCultureIgnoreCase) == 1);
-            }
-
-            return items;
-        }
+                var filterValue = request.ParentIndexNumber.Value;
 
 
-        private bool IsYearMismatched(BaseItem item)
-        {
-            if (item.ProductionYear.HasValue)
-            {
-                var path = item.Path;
+                var episode = i as Episode;
 
 
-                if (!string.IsNullOrEmpty(path))
+                if (episode != null)
                 {
                 {
-                    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)
+                    if (episode.ParentIndexNumber.HasValue && episode.ParentIndexNumber.Value != filterValue)
                     {
                     {
-                        NameParser.ParseName(Path.GetFileName(Path.GetDirectoryName(path)), out name, out yearInName);
+                        return false;
                     }
                     }
+                }
 
 
-                    if (yearInName.HasValue)
+                var song = i as Audio;
+
+                if (song != null)
+                {
+                    if (song.ParentIndexNumber.HasValue && song.ParentIndexNumber.Value != filterValue)
                     {
                     {
-                        return yearInName.Value != item.ProductionYear.Value;
+                        return false;
                     }
                     }
                 }
                 }
             }
             }
 
 
-            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)
+            if (request.AiredDuringSeason.HasValue)
             {
             {
-                return false;
-            }
+                var episode = i as Episode;
 
 
-            if (request.IsUnidentified.HasValue)
-            {
-                return false;
-            }
+                if (episode == null)
+                {
+                    return false;
+                }
 
 
-            if (request.IsYearMismatched.HasValue)
-            {
-                return false;
+                if (!Series.FilterEpisodesBySeason(new[] { episode }, request.AiredDuringSeason.Value, true).Any())
+                {
+                    return false;
+                }
             }
             }
 
 
-            if (!string.IsNullOrWhiteSpace(request.Person))
+            if (!string.IsNullOrEmpty(request.MinPremiereDate))
             {
             {
-                return false;
-            }
+                var date = DateTime.Parse(request.MinPremiereDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
 
 
-            if (!string.IsNullOrWhiteSpace(request.Studios))
-            {
-                return false;
+                if (!(i.PremiereDate.HasValue && i.PremiereDate.Value >= date))
+                {
+                    return false;
+                }
             }
             }
 
 
-            if (!string.IsNullOrWhiteSpace(request.VideoTypes))
+            if (!string.IsNullOrEmpty(request.MaxPremiereDate))
             {
             {
-                return false;
-            }
+                var date = DateTime.Parse(request.MaxPremiereDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
 
 
-            if (!string.IsNullOrWhiteSpace(request.Years))
-            {
-                return false;
+                if (!(i.PremiereDate.HasValue && i.PremiereDate.Value <= date))
+                {
+                    return false;
+                }
             }
             }
 
 
             return true;
             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>
         /// <summary>
         /// Applies the paging.
         /// Applies the paging.
         /// </summary>
         /// </summary>

+ 19 - 0
MediaBrowser.Controller/Channels/ChannelAudioItem.cs

@@ -1,9 +1,11 @@
 using MediaBrowser.Controller.Entities.Audio;
 using MediaBrowser.Controller.Entities.Audio;
 using MediaBrowser.Model.Channels;
 using MediaBrowser.Model.Channels;
 using MediaBrowser.Model.Configuration;
 using MediaBrowser.Model.Configuration;
+using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Linq;
 using System.Linq;
+using System.Threading;
 
 
 namespace MediaBrowser.Controller.Channels
 namespace MediaBrowser.Controller.Channels
 {
 {
@@ -69,5 +71,22 @@ namespace MediaBrowser.Controller.Channels
         {
         {
             return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N"));
             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;
+        }
     }
     }
 }
 }

+ 10 - 1
MediaBrowser.Controller/Channels/ChannelVideoItem.cs

@@ -7,6 +7,7 @@ using MediaBrowser.Model.Entities;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Globalization;
 using System.Globalization;
 using System.Linq;
 using System.Linq;
+using System.Threading;
 
 
 namespace MediaBrowser.Controller.Channels
 namespace MediaBrowser.Controller.Channels
 {
 {
@@ -90,7 +91,15 @@ namespace MediaBrowser.Controller.Channels
         {
         {
             var list = base.GetMediaSources(enablePathSubstitution).ToList();
             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;
             return list;
         }
         }

+ 2 - 8
MediaBrowser.Controller/Channels/IChannelManager.cs

@@ -109,20 +109,14 @@ namespace MediaBrowser.Controller.Channels
         /// <returns>Task&lt;QueryResult&lt;BaseItem&gt;&gt;.</returns>
         /// <returns>Task&lt;QueryResult&lt;BaseItem&gt;&gt;.</returns>
         Task<QueryResult<BaseItem>> GetChannelItemsInternal(ChannelItemQuery query, IProgress<double> progress, CancellationToken cancellationToken);
         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>
         /// <summary>
         /// Gets the channel item media sources.
         /// Gets the channel item media sources.
         /// </summary>
         /// </summary>
         /// <param name="id">The identifier.</param>
         /// <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>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task{IEnumerable{MediaSourceInfo}}.</returns>
         /// <returns>Task{IEnumerable{MediaSourceInfo}}.</returns>
-        Task<IEnumerable<MediaSourceInfo>> GetChannelItemMediaSources(string id, CancellationToken cancellationToken);
+        Task<IEnumerable<MediaSourceInfo>> GetChannelItemMediaSources(string id, bool includeDynamicSources, CancellationToken cancellationToken);
 
 
         /// <summary>
         /// <summary>
         /// Gets the channel folder.
         /// Gets the channel folder.

+ 2 - 0
MediaBrowser.Controller/Entities/BaseItem.cs

@@ -1,6 +1,7 @@
 using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Controller.Channels;
 using MediaBrowser.Controller.Channels;
+using MediaBrowser.Controller.Collections;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.LiveTv;
 using MediaBrowser.Controller.LiveTv;
@@ -251,6 +252,7 @@ namespace MediaBrowser.Controller.Entities
         public static IUserDataManager UserDataManager { get; set; }
         public static IUserDataManager UserDataManager { get; set; }
         public static ILiveTvManager LiveTvManager { get; set; }
         public static ILiveTvManager LiveTvManager { get; set; }
         public static IChannelManager ChannelManager { get; set; }
         public static IChannelManager ChannelManager { get; set; }
+        public static ICollectionManager CollectionManager { get; set; }
 
 
         /// <summary>
         /// <summary>
         /// Returns a <see cref="System.String" /> that represents this instance.
         /// Returns a <see cref="System.String" /> that represents this instance.

+ 1 - 1
MediaBrowser.Controller/Entities/Folder.cs

@@ -785,7 +785,7 @@ namespace MediaBrowser.Controller.Entities
 
 
         protected QueryResult<BaseItem> SortAndFilter(IEnumerable<BaseItem> items, InternalItemsQuery query)
         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>
         /// <summary>

+ 47 - 0
MediaBrowser.Controller/Entities/InternalItemsQuery.cs

@@ -29,6 +29,46 @@ namespace MediaBrowser.Controller.Entities
         public string[] MediaTypes { get; set; }
         public string[] MediaTypes { get; set; }
         public string[] IncludeItemTypes { get; set; }
         public string[] IncludeItemTypes { get; set; }
         public string[] ExcludeItemTypes { 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()
         public InternalItemsQuery()
         {
         {
@@ -36,6 +76,13 @@ namespace MediaBrowser.Controller.Entities
             MediaTypes = new string[] { };
             MediaTypes = new string[] { };
             IncludeItemTypes = new string[] { };
             IncludeItemTypes = new string[] { };
             ExcludeItemTypes = 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[] { };
         }
         }
     }
     }
 }
 }

+ 1 - 1
MediaBrowser.Controller/Entities/UserView.cs

@@ -17,7 +17,7 @@ namespace MediaBrowser.Controller.Entities
 
 
         public override Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
         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);
                 .GetUserItems(this, ViewType, query);
         }
         }
 
 

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 731 - 43
MediaBrowser.Controller/Entities/UserViewBuilder.cs


+ 7 - 0
MediaBrowser.Model/Dlna/StreamInfo.cs

@@ -91,6 +91,13 @@ namespace MediaBrowser.Model.Dlna
                 throw new ArgumentNullException(baseUrl);
                 throw new ArgumentNullException(baseUrl);
             }
             }
 
 
+            if (IsDirectStream && MediaSource != null && MediaSource.Protocol == MediaProtocol.Http)
+            {
+                if (MediaSource.RequiredHttpHeaders.Count == 0)
+                {
+                }
+            }
+
             string dlnaCommand = BuildDlnaParam(this);
             string dlnaCommand = BuildDlnaParam(this);
 
 
             string extension = string.IsNullOrEmpty(Container) ? string.Empty : "." + Container;
             string extension = string.IsNullOrEmpty(Container) ? string.Empty : "." + Container;

+ 6 - 2
MediaBrowser.Providers/Movies/MovieDbProvider.cs

@@ -273,13 +273,17 @@ namespace MediaBrowser.Providers.Movies
                 languages.Add("en");
                 languages.Add("en");
             }
             }
 
 
+            var firstLetter = string.IsNullOrWhiteSpace(preferredLanguage)
+                ? string.Empty
+                : preferredLanguage.Substring(0, 1);
+
             var allLanguages = localization.GetCultures()
             var allLanguages = localization.GetCultures()
                 .Select(i => i.TwoLetterISOLanguageName)
                 .Select(i => i.TwoLetterISOLanguageName)
                 .Distinct(StringComparer.OrdinalIgnoreCase)
                 .Distinct(StringComparer.OrdinalIgnoreCase)
-                .Where(i => !languages.Contains(i, StringComparer.OrdinalIgnoreCase))
+                .Where(i => !languages.Contains(i, StringComparer.OrdinalIgnoreCase) && i.StartsWith(firstLetter, StringComparison.OrdinalIgnoreCase))
                 .ToList();
                 .ToList();
 
 
-            languages.AddRange(allLanguages);
+            //languages.AddRange(allLanguages);
 
 
             return string.Join(",", languages.ToArray());
             return string.Join(",", languages.ToArray());
         }
         }

+ 2 - 11
MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs

@@ -212,12 +212,10 @@ namespace MediaBrowser.Server.Implementations.Channels
             }
             }
 
 
             var itemId = item.Id.ToString("N");
             var itemId = item.Id.ToString("N");
-            var sources = await _manager.GetChannelItemMediaSources(itemId, cancellationToken)
+            var sources = await _manager.GetChannelItemMediaSources(itemId, false, cancellationToken)
                 .ConfigureAwait(false);
                 .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)
             if (cachedVersions.Count > 0)
             {
             {
@@ -225,13 +223,6 @@ namespace MediaBrowser.Server.Implementations.Channels
                 return;
                 return;
             }
             }
 
 
-            var source = list.FirstOrDefault(i => i.Protocol == MediaProtocol.Http);
-
-            if (source == null)
-            {
-                return;
-            }
-
             var channelItem = (IChannelMediaItem)item;
             var channelItem = (IChannelMediaItem)item;
 
 
             var destination = Path.Combine(path, channelItem.ChannelId, itemId);
             var destination = Path.Combine(path, channelItem.ChannelId, itemId);

+ 15 - 3
MediaBrowser.Server.Implementations/Channels/ChannelManager.cs

@@ -244,7 +244,7 @@ namespace MediaBrowser.Server.Implementations.Channels
             return item;
             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);
             var item = (IChannelMediaItem)_libraryManager.GetItemById(id);
 
 
@@ -255,7 +255,7 @@ namespace MediaBrowser.Server.Implementations.Channels
 
 
             IEnumerable<ChannelMediaInfo> results;
             IEnumerable<ChannelMediaInfo> results;
 
 
-            if (requiresCallback != null)
+            if (requiresCallback != null && includeDynamicSources)
             {
             {
                 results = await GetChannelItemMediaSourcesInternal(requiresCallback, item.ExternalId, cancellationToken)
                 results = await GetChannelItemMediaSourcesInternal(requiresCallback, item.ExternalId, cancellationToken)
                             .ConfigureAwait(false);
                             .ConfigureAwait(false);
@@ -374,6 +374,18 @@ namespace MediaBrowser.Server.Implementations.Channels
                 Id = id
                 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;
             return source;
         }
         }
 
 
@@ -1447,7 +1459,7 @@ namespace MediaBrowser.Server.Implementations.Channels
             IProgress<double> progress, CancellationToken cancellationToken)
             IProgress<double> progress, CancellationToken cancellationToken)
         {
         {
             var itemId = item.Id.ToString("N");
             var itemId = item.Id.ToString("N");
-            var sources = await GetChannelItemMediaSources(itemId, cancellationToken)
+            var sources = await GetChannelItemMediaSources(itemId, true, cancellationToken)
                 .ConfigureAwait(false);
                 .ConfigureAwait(false);
 
 
             var list = sources.Where(i => i.Protocol == MediaProtocol.Http).ToList();
             var list = sources.Where(i => i.Protocol == MediaProtocol.Http).ToList();

+ 1 - 1
MediaBrowser.Server.Implementations/Localization/JavaScript/de.json

@@ -519,7 +519,7 @@
     "MediaInfoLongitude": "L\u00e4nge",
     "MediaInfoLongitude": "L\u00e4nge",
     "MediaInfoShutterSpeed": "Verschlusszeit",
     "MediaInfoShutterSpeed": "Verschlusszeit",
     "MediaInfoSoftware": "Software",
     "MediaInfoSoftware": "Software",
-    "HeaderIfYouLikeCheckTheseOut": "Wenn du {0} magst, schau dir einmal diese an...",
+    "HeaderIfYouLikeCheckTheseOut": "Wenn du {0} magst, schau dir einmal das an...",
     "HeaderPlotKeywords": "Handlungsstichworte",
     "HeaderPlotKeywords": "Handlungsstichworte",
     "HeaderMovies": "Filme",
     "HeaderMovies": "Filme",
     "HeaderAlbums": "Alben",
     "HeaderAlbums": "Alben",

+ 1 - 1
MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json

@@ -469,7 +469,7 @@
     "LabelResumePoint": "Point de reprise",
     "LabelResumePoint": "Point de reprise",
     "ValueOneMovie": "1 Film",
     "ValueOneMovie": "1 Film",
     "ValueMovieCount": "{0} films",
     "ValueMovieCount": "{0} films",
-    "ValueOneTrailer": "1 Bande Annonce",
+    "ValueOneTrailer": "1 bande-annonce",
     "ValueTrailerCount": "{0} bandes-annonces",
     "ValueTrailerCount": "{0} bandes-annonces",
     "ValueOneSeries": "1 S\u00e9rie",
     "ValueOneSeries": "1 S\u00e9rie",
     "ValueSeriesCount": "{0} series",
     "ValueSeriesCount": "{0} series",

+ 1 - 1
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.",
     "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)",
     "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).",
     "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 :",
     "LabelSelectCollection": "S\u00e9lectionner la collection :",
     "ButtonOptions": "Options",
     "ButtonOptions": "Options",
     "ViewTypeMovies": "Films",
     "ViewTypeMovies": "Films",

+ 31 - 31
MediaBrowser.Server.Implementations/Localization/Server/hr.json

@@ -845,43 +845,43 @@
     "OptionSpecialFeatures": "Specijalne opcije",
     "OptionSpecialFeatures": "Specijalne opcije",
     "HeaderCollections": "Kolekcije",
     "HeaderCollections": "Kolekcije",
     "LabelProfileCodecsHelp": "Odvojeno sa to\u010dka-zrezom. Ovo mo\u017ee ostaviti prazno kao bi bilo postavljeno za sve codecs.",
     "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:",
     "LabelPersonRole": "Role:",
     "LabelPersonRoleHelp": "Role is generally only applicable to actors.",
     "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",
     "OptionProfileVideo": "Video",
     "OptionProfileAudio": "Audio",
     "OptionProfileAudio": "Audio",
     "OptionProfileVideoAudio": "Video 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",
     "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:",
     "LabelAlbumArtMaxWidth": "Album art max width:",
     "LabelAlbumArtMaxWidthHelp": "Max resolution of album art exposed via upnp:albumArtURI.",
     "LabelAlbumArtMaxWidthHelp": "Max resolution of album art exposed via upnp:albumArtURI.",
     "LabelAlbumArtMaxHeight": "Album art max height:",
     "LabelAlbumArtMaxHeight": "Album art max height:",

+ 4 - 2
MediaBrowser.ServerApplication/ApplicationHost.cs

@@ -218,6 +218,7 @@ namespace MediaBrowser.ServerApplication
         private IAuthenticationRepository AuthenticationRepository { get; set; }
         private IAuthenticationRepository AuthenticationRepository { get; set; }
         private ISyncRepository SyncRepository { get; set; }
         private ISyncRepository SyncRepository { get; set; }
         private ITVSeriesManager TVSeriesManager { get; set; }
         private ITVSeriesManager TVSeriesManager { get; set; }
+        private ICollectionManager CollectionManager { get; set; }
 
 
         private readonly StartupOptions _startupOptions;
         private readonly StartupOptions _startupOptions;
         private readonly string _remotePackageName;
         private readonly string _remotePackageName;
@@ -494,8 +495,8 @@ namespace MediaBrowser.ServerApplication
             var connectionManager = new ConnectionManager(dlnaManager, ServerConfigurationManager, LogManager.GetLogger("UpnpConnectionManager"), HttpClient);
             var connectionManager = new ConnectionManager(dlnaManager, ServerConfigurationManager, LogManager.GetLogger("UpnpConnectionManager"), HttpClient);
             RegisterSingleInstance<IConnectionManager>(connectionManager);
             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);
             var playlistManager = new PlaylistManager(LibraryManager, FileSystemManager, LibraryMonitor, LogManager.GetLogger("PlaylistManager"), UserManager);
             RegisterSingleInstance<IPlaylistManager>(playlistManager);
             RegisterSingleInstance<IPlaylistManager>(playlistManager);
@@ -700,6 +701,7 @@ namespace MediaBrowser.ServerApplication
             BaseItem.LiveTvManager = LiveTvManager;
             BaseItem.LiveTvManager = LiveTvManager;
             Folder.UserViewManager = UserViewManager;
             Folder.UserViewManager = UserViewManager;
             UserView.TVSeriesManager = TVSeriesManager;
             UserView.TVSeriesManager = TVSeriesManager;
+            BaseItem.CollectionManager = CollectionManager;
         }
         }
 
 
         /// <summary>
         /// <summary>

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels