mirror of
				https://github.com/jellyfin/jellyfin.git
				synced 2025-11-02 18:47:18 -05:00 
			
		
		
		
	fixes #945 - Add genre views to dlna
This commit is contained in:
		
							parent
							
								
									4d0a47e555
								
							
						
					
					
						commit
						1fea9ad926
					
				@ -124,7 +124,7 @@ namespace MediaBrowser.Api
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        public void Post(AutoSetMetadataOptions request)
 | 
					        public void Post(AutoSetMetadataOptions request)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _configurationManager.DisableMetadataService("Media Browser Xml");
 | 
					            _configurationManager.DisableMetadataService("Media Browser Legacy Xml");
 | 
				
			||||||
            _configurationManager.SaveConfiguration();
 | 
					            _configurationManager.SaveConfiguration();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -995,7 +995,7 @@ namespace MediaBrowser.Api.Playback
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                if (state.ReadInputAtNativeFramerate)
 | 
					                if (state.ReadInputAtNativeFramerate)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    await Task.Delay(1000, cancellationTokenSource.Token).ConfigureAwait(false);
 | 
					                    await Task.Delay(1500, cancellationTokenSource.Token).ConfigureAwait(false);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1619,8 +1619,6 @@ namespace MediaBrowser.Api.Playback
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            AttachMediaStreamInfo(state, mediaStreams, videoRequest, url);
 | 
					            AttachMediaStreamInfo(state, mediaStreams, videoRequest, url);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            state.SegmentLength = 6;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            var container = Path.GetExtension(state.RequestedUrl);
 | 
					            var container = Path.GetExtension(state.RequestedUrl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (string.IsNullOrEmpty(container))
 | 
					            if (string.IsNullOrEmpty(container))
 | 
				
			||||||
 | 
				
			|||||||
@ -63,11 +63,14 @@ namespace MediaBrowser.Api.Playback
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        public string LiveTvStreamId { get; set; }
 | 
					        public string LiveTvStreamId { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public int SegmentLength = 10;
 | 
					        public int SegmentLength = 6;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public int HlsListSize
 | 
					        public int HlsListSize
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            get { return ReadInputAtNativeFramerate ? 100 : 1440; }
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return ReadInputAtNativeFramerate ? 1000 : 0;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public long? RunTimeTicks;
 | 
					        public long? RunTimeTicks;
 | 
				
			||||||
 | 
				
			|||||||
@ -26,7 +26,7 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return new UserViewBuilder(UserViewManager, LiveTvManager, ChannelManager, LibraryManager, Logger, UserDataManager, TVSeriesManager, CollectionManager)
 | 
					            return new UserViewBuilder(UserViewManager, LiveTvManager, ChannelManager, LibraryManager, Logger, UserDataManager, TVSeriesManager, CollectionManager)
 | 
				
			||||||
                .GetUserItems(parent, ViewType, query);
 | 
					                .GetUserItems(parent, this, ViewType, query);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
 | 
					        public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
 | 
				
			||||||
 | 
				
			|||||||
@ -44,7 +44,7 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
            _collectionManager = collectionManager;
 | 
					            _collectionManager = collectionManager;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public async Task<QueryResult<BaseItem>> GetUserItems(Folder parent, string viewType, InternalItemsQuery query)
 | 
					        public async Task<QueryResult<BaseItem>> GetUserItems(Folder queryParent, Folder displayParent, string viewType, InternalItemsQuery query)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var user = query.User;
 | 
					            var user = query.User;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -107,110 +107,125 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        var result = await GetLiveTvFolders(user).ConfigureAwait(false);
 | 
					                        var result = await GetLiveTvFolders(user).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        return GetResult(result, parent, query);
 | 
					                        return GetResult(result, queryParent, query);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case CollectionType.Folders:
 | 
					                case CollectionType.Folders:
 | 
				
			||||||
                    return GetResult(user.RootFolder.GetChildren(user, true), parent, query);
 | 
					                    return GetResult(user.RootFolder.GetChildren(user, true), queryParent, query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case CollectionType.Games:
 | 
					                case CollectionType.Games:
 | 
				
			||||||
                    return await GetGameView(user, parent, query).ConfigureAwait(false);
 | 
					                    return await GetGameView(user, queryParent, query).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case CollectionType.BoxSets:
 | 
					                case CollectionType.BoxSets:
 | 
				
			||||||
                    return GetResult(GetMediaFolders(user).SelectMany(i => i.GetRecursiveChildren(user)).OfType<BoxSet>(), parent, query);
 | 
					                    return GetResult(GetMediaFolders(user).SelectMany(i => i.GetRecursiveChildren(user)).OfType<BoxSet>(), queryParent, query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case CollectionType.TvShows:
 | 
					                case CollectionType.TvShows:
 | 
				
			||||||
                    return await GetTvView(parent, user, query).ConfigureAwait(false);
 | 
					                    return await GetTvView(queryParent, user, query).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case CollectionType.Music:
 | 
					                case CollectionType.Music:
 | 
				
			||||||
                    return await GetMusicFolders(parent, user, query).ConfigureAwait(false);
 | 
					                    return await GetMusicFolders(queryParent, user, query).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case CollectionType.Movies:
 | 
					                case CollectionType.Movies:
 | 
				
			||||||
                    return await GetMovieFolders(parent, user, query).ConfigureAwait(false);
 | 
					                    return await GetMovieFolders(queryParent, user, query).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                case SpecialFolder.MusicGenres:
 | 
				
			||||||
 | 
					                    return await GetMusicGenres(queryParent, user, query).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                case SpecialFolder.MusicGenre:
 | 
				
			||||||
 | 
					                    return await GetMusicGenreItems(queryParent, displayParent, user, query).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case SpecialFolder.GameGenres:
 | 
					                case SpecialFolder.GameGenres:
 | 
				
			||||||
                    return GetGameGenres(parent, user, query);
 | 
					                    return await GetGameGenres(queryParent, user, query).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                case SpecialFolder.GameGenre:
 | 
				
			||||||
 | 
					                    return await GetGameGenreItems(queryParent, displayParent, user, query).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case SpecialFolder.GameSystems:
 | 
					                case SpecialFolder.GameSystems:
 | 
				
			||||||
                    return GetGameSystems(parent, user, query);
 | 
					                    return GetGameSystems(queryParent, user, query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case SpecialFolder.LatestGames:
 | 
					                case SpecialFolder.LatestGames:
 | 
				
			||||||
                    return GetLatestGames(parent, user, query);
 | 
					                    return GetLatestGames(queryParent, user, query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case SpecialFolder.RecentlyPlayedGames:
 | 
					                case SpecialFolder.RecentlyPlayedGames:
 | 
				
			||||||
                    return GetRecentlyPlayedGames(parent, user, query);
 | 
					                    return GetRecentlyPlayedGames(queryParent, user, query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case SpecialFolder.GameFavorites:
 | 
					                case SpecialFolder.GameFavorites:
 | 
				
			||||||
                    return GetFavoriteGames(parent, user, query);
 | 
					                    return GetFavoriteGames(queryParent, user, query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case SpecialFolder.TvShowSeries:
 | 
					                case SpecialFolder.TvShowSeries:
 | 
				
			||||||
                    return GetTvSeries(parent, user, query);
 | 
					                    return GetTvSeries(queryParent, user, query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case SpecialFolder.TvGenres:
 | 
					                case SpecialFolder.TvGenres:
 | 
				
			||||||
                    return GetTvGenres(parent, user, query);
 | 
					                    return await GetTvGenres(queryParent, user, query).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                case SpecialFolder.TvGenre:
 | 
				
			||||||
 | 
					                    return await GetTvGenreItems(queryParent, displayParent, user, query).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case SpecialFolder.TvResume:
 | 
					                case SpecialFolder.TvResume:
 | 
				
			||||||
                    return GetTvResume(parent, user, query);
 | 
					                    return GetTvResume(queryParent, user, query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case SpecialFolder.TvNextUp:
 | 
					                case SpecialFolder.TvNextUp:
 | 
				
			||||||
                    return GetTvNextUp(parent, query);
 | 
					                    return GetTvNextUp(queryParent, query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case SpecialFolder.TvLatest:
 | 
					                case SpecialFolder.TvLatest:
 | 
				
			||||||
                    return GetTvLatest(parent, user, query);
 | 
					                    return GetTvLatest(queryParent, user, query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case SpecialFolder.MovieFavorites:
 | 
					                case SpecialFolder.MovieFavorites:
 | 
				
			||||||
                    return GetFavoriteMovies(parent, user, query);
 | 
					                    return GetFavoriteMovies(queryParent, user, query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case SpecialFolder.MovieLatest:
 | 
					                case SpecialFolder.MovieLatest:
 | 
				
			||||||
                    return GetMovieLatest(parent, user, query);
 | 
					                    return GetMovieLatest(queryParent, user, query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case SpecialFolder.MovieGenres:
 | 
					                case SpecialFolder.MovieGenres:
 | 
				
			||||||
                    return GetMovieGenres(parent, user, query);
 | 
					                    return await GetMovieGenres(queryParent, user, query).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                case SpecialFolder.MovieGenre:
 | 
				
			||||||
 | 
					                    return await GetMovieGenreItems(queryParent, displayParent, user, query).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case SpecialFolder.MovieResume:
 | 
					                case SpecialFolder.MovieResume:
 | 
				
			||||||
                    return GetMovieResume(parent, user, query);
 | 
					                    return GetMovieResume(queryParent, user, query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case SpecialFolder.MovieMovies:
 | 
					                case SpecialFolder.MovieMovies:
 | 
				
			||||||
                    return GetMovieMovies(parent, user, query);
 | 
					                    return GetMovieMovies(queryParent, user, query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case SpecialFolder.MovieCollections:
 | 
					                case SpecialFolder.MovieCollections:
 | 
				
			||||||
                    return GetMovieCollections(parent, user, query);
 | 
					                    return GetMovieCollections(queryParent, user, query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case SpecialFolder.MusicLatest:
 | 
					                case SpecialFolder.MusicLatest:
 | 
				
			||||||
                    return GetMusicLatest(parent, user, query);
 | 
					                    return GetMusicLatest(queryParent, user, query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case SpecialFolder.MusicAlbums:
 | 
					                case SpecialFolder.MusicAlbums:
 | 
				
			||||||
                    return GetMusicAlbums(parent, user, query);
 | 
					                    return GetMusicAlbums(queryParent, user, query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case SpecialFolder.MusicAlbumArtists:
 | 
					                case SpecialFolder.MusicAlbumArtists:
 | 
				
			||||||
                    return GetMusicAlbumArtists(parent, user, query);
 | 
					                    return GetMusicAlbumArtists(queryParent, user, query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case SpecialFolder.MusicArtists:
 | 
					                case SpecialFolder.MusicArtists:
 | 
				
			||||||
                    return GetMusicArtists(parent, user, query);
 | 
					                    return GetMusicArtists(queryParent, user, query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case SpecialFolder.MusicSongs:
 | 
					                case SpecialFolder.MusicSongs:
 | 
				
			||||||
                    return GetMusicSongs(parent, user, query);
 | 
					                    return GetMusicSongs(queryParent, user, query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case SpecialFolder.TvFavoriteEpisodes:
 | 
					                case SpecialFolder.TvFavoriteEpisodes:
 | 
				
			||||||
                    return GetFavoriteEpisodes(parent, user, query);
 | 
					                    return GetFavoriteEpisodes(queryParent, user, query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case SpecialFolder.TvFavoriteSeries:
 | 
					                case SpecialFolder.TvFavoriteSeries:
 | 
				
			||||||
                    return GetFavoriteSeries(parent, user, query);
 | 
					                    return GetFavoriteSeries(queryParent, user, query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case SpecialFolder.MusicFavorites:
 | 
					                case SpecialFolder.MusicFavorites:
 | 
				
			||||||
                    return await GetMusicFavorites(parent, user, query).ConfigureAwait(false);
 | 
					                    return await GetMusicFavorites(queryParent, user, query).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case SpecialFolder.MusicFavoriteAlbums:
 | 
					                case SpecialFolder.MusicFavoriteAlbums:
 | 
				
			||||||
                    return GetFavoriteAlbums(parent, user, query);
 | 
					                    return GetFavoriteAlbums(queryParent, user, query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case SpecialFolder.MusicFavoriteArtists:
 | 
					                case SpecialFolder.MusicFavoriteArtists:
 | 
				
			||||||
                    return GetFavoriteArtists(parent, user, query);
 | 
					                    return GetFavoriteArtists(queryParent, user, query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case SpecialFolder.MusicFavoriteSongs:
 | 
					                case SpecialFolder.MusicFavoriteSongs:
 | 
				
			||||||
                    return GetFavoriteSongs(parent, user, query);
 | 
					                    return GetFavoriteSongs(queryParent, user, query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                default:
 | 
					                default:
 | 
				
			||||||
                    return GetResult(GetMediaFolders(user).SelectMany(i => i.GetChildren(user, true)), parent, query);
 | 
					                    return GetResult(GetMediaFolders(user).SelectMany(i => i.GetChildren(user, true)), queryParent, query);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -231,9 +246,9 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
            list.Add(await GetUserView(SpecialFolder.MusicLatest, user, "0", parent).ConfigureAwait(false));
 | 
					            list.Add(await GetUserView(SpecialFolder.MusicLatest, user, "0", parent).ConfigureAwait(false));
 | 
				
			||||||
            list.Add(await GetUserView(SpecialFolder.MusicAlbums, user, "1", parent).ConfigureAwait(false));
 | 
					            list.Add(await GetUserView(SpecialFolder.MusicAlbums, user, "1", parent).ConfigureAwait(false));
 | 
				
			||||||
            list.Add(await GetUserView(SpecialFolder.MusicAlbumArtists, user, "2", parent).ConfigureAwait(false));
 | 
					            list.Add(await GetUserView(SpecialFolder.MusicAlbumArtists, user, "2", parent).ConfigureAwait(false));
 | 
				
			||||||
            list.Add(await GetUserView(SpecialFolder.MusicSongs, user, "3", parent).ConfigureAwait(false));
 | 
					            list.Add(await GetUserView(SpecialFolder.MusicArtists, user, "3", parent).ConfigureAwait(false));
 | 
				
			||||||
            //list.Add(await GetUserView(SpecialFolder.MusicArtists, user, "3", parent).ConfigureAwait(false));
 | 
					            list.Add(await GetUserView(SpecialFolder.MusicSongs, user, "4", parent).ConfigureAwait(false));
 | 
				
			||||||
            //list.Add(await GetUserView(SpecialFolder.MusicGenres, user, "5", parent).ConfigureAwait(false));
 | 
					            list.Add(await GetUserView(SpecialFolder.MusicGenres, user, "5", parent).ConfigureAwait(false));
 | 
				
			||||||
            list.Add(await GetUserView(SpecialFolder.MusicFavorites, user, "6", parent).ConfigureAwait(false));
 | 
					            list.Add(await GetUserView(SpecialFolder.MusicFavorites, user, "6", parent).ConfigureAwait(false));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return GetResult(list, parent, query);
 | 
					            return GetResult(list, parent, query);
 | 
				
			||||||
@ -250,6 +265,59 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
            return GetResult(list, parent, query);
 | 
					            return GetResult(list, parent, query);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private async Task<QueryResult<BaseItem>> GetMusicGenres(Folder parent, User user, InternalItemsQuery query)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var tasks = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos })
 | 
				
			||||||
 | 
					                .Where(i => !i.IsFolder)
 | 
				
			||||||
 | 
					                .SelectMany(i => i.Genres)
 | 
				
			||||||
 | 
					                .Distinct(StringComparer.OrdinalIgnoreCase)
 | 
				
			||||||
 | 
					                .Select(i =>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    try
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        return _libraryManager.GetMusicGenre(i);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    catch
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        // Full exception logged at lower levels
 | 
				
			||||||
 | 
					                        _logger.Error("Error getting genre");
 | 
				
			||||||
 | 
					                        return null;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .Where(i => i != null)
 | 
				
			||||||
 | 
					                .Select(i => GetUserView(i.Name, SpecialFolder.MusicGenre, user, i.SortName, parent));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var genres = await Task.WhenAll(tasks).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return GetResult(genres, parent, query);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private async Task<QueryResult<BaseItem>> GetMusicGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var items = GetRecursiveChildren(queryParent, user, new[] { CollectionType.Music, CollectionType.MusicVideos })
 | 
				
			||||||
 | 
					                .Where(i => !i.IsFolder)
 | 
				
			||||||
 | 
					                .Where(i => i.Genres.Contains(displayParent.Name, StringComparer.OrdinalIgnoreCase))
 | 
				
			||||||
 | 
					                .OfType<IHasAlbumArtist>()
 | 
				
			||||||
 | 
					                .SelectMany(i => i.AlbumArtists)
 | 
				
			||||||
 | 
					                .Distinct(StringComparer.OrdinalIgnoreCase)
 | 
				
			||||||
 | 
					                .Select(i =>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    try
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        return _libraryManager.GetArtist(i);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    catch
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        // Already logged at lower levels
 | 
				
			||||||
 | 
					                        return null;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .Where(i => i != null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return GetResult(items, queryParent, query);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private QueryResult<BaseItem> GetMusicAlbumArtists(Folder parent, User user, InternalItemsQuery query)
 | 
					        private QueryResult<BaseItem> GetMusicAlbumArtists(Folder parent, User user, InternalItemsQuery query)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var artists = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos })
 | 
					            var artists = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos })
 | 
				
			||||||
@ -354,7 +422,7 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
            list.Add(await GetUserView(SpecialFolder.MovieMovies, user, "2", parent).ConfigureAwait(false));
 | 
					            list.Add(await GetUserView(SpecialFolder.MovieMovies, user, "2", parent).ConfigureAwait(false));
 | 
				
			||||||
            list.Add(await GetUserView(SpecialFolder.MovieCollections, user, "3", parent).ConfigureAwait(false));
 | 
					            list.Add(await GetUserView(SpecialFolder.MovieCollections, user, "3", parent).ConfigureAwait(false));
 | 
				
			||||||
            list.Add(await GetUserView(SpecialFolder.MovieFavorites, user, "4", parent).ConfigureAwait(false));
 | 
					            list.Add(await GetUserView(SpecialFolder.MovieFavorites, user, "4", parent).ConfigureAwait(false));
 | 
				
			||||||
            //list.Add(await GetUserView(CollectionType.MovieGenres, user, "5", parent).ConfigureAwait(false));
 | 
					            list.Add(await GetUserView(SpecialFolder.MovieGenres, user, "5", parent).ConfigureAwait(false));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return GetResult(list, parent, query);
 | 
					            return GetResult(list, parent, query);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -421,9 +489,9 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
            return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie), parent, 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)
 | 
					        private async Task<QueryResult<BaseItem>> GetMovieGenres(Folder parent, User user, InternalItemsQuery query)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var genres = GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty })
 | 
					            var tasks = GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty })
 | 
				
			||||||
                .Where(i => i is Movie)
 | 
					                .Where(i => i is Movie)
 | 
				
			||||||
                .SelectMany(i => i.Genres)
 | 
					                .SelectMany(i => i.Genres)
 | 
				
			||||||
                .Distinct(StringComparer.OrdinalIgnoreCase)
 | 
					                .Distinct(StringComparer.OrdinalIgnoreCase)
 | 
				
			||||||
@ -441,11 +509,23 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
                .Where(i => i != null);
 | 
					                .Where(i => i != null)
 | 
				
			||||||
 | 
					                .Select(i => GetUserView(i.Name, SpecialFolder.MovieGenre, user, i.SortName, parent));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var genres = await Task.WhenAll(tasks).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return GetResult(genres, parent, query);
 | 
					            return GetResult(genres, parent, query);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private async Task<QueryResult<BaseItem>> GetMovieGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var items = GetRecursiveChildren(queryParent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty })
 | 
				
			||||||
 | 
					                .Where(i => i is Movie)
 | 
				
			||||||
 | 
					                .Where(i => i.Genres.Contains(displayParent.Name, StringComparer.OrdinalIgnoreCase));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return GetResult(items, queryParent, query);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private async Task<QueryResult<BaseItem>> GetTvView(Folder parent, User user, InternalItemsQuery query)
 | 
					        private async Task<QueryResult<BaseItem>> GetTvView(Folder parent, User user, InternalItemsQuery query)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (query.Recursive)
 | 
					            if (query.Recursive)
 | 
				
			||||||
@ -461,7 +541,7 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
            list.Add(await GetUserView(SpecialFolder.TvShowSeries, user, "3", parent).ConfigureAwait(false));
 | 
					            list.Add(await GetUserView(SpecialFolder.TvShowSeries, user, "3", parent).ConfigureAwait(false));
 | 
				
			||||||
            list.Add(await GetUserView(SpecialFolder.TvFavoriteSeries, user, "4", parent).ConfigureAwait(false));
 | 
					            list.Add(await GetUserView(SpecialFolder.TvFavoriteSeries, user, "4", parent).ConfigureAwait(false));
 | 
				
			||||||
            list.Add(await GetUserView(SpecialFolder.TvFavoriteEpisodes, user, "5", parent).ConfigureAwait(false));
 | 
					            list.Add(await GetUserView(SpecialFolder.TvFavoriteEpisodes, user, "5", parent).ConfigureAwait(false));
 | 
				
			||||||
            //list.Add(await GetUserView(SpecialFolder.TvGenres, user, "5", parent).ConfigureAwait(false));
 | 
					            list.Add(await GetUserView(SpecialFolder.TvGenres, user, "6", parent).ConfigureAwait(false));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return GetResult(list, parent, query);
 | 
					            return GetResult(list, parent, query);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -479,7 +559,7 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
            list.Add(await GetUserView(SpecialFolder.RecentlyPlayedGames, user, "1", parent).ConfigureAwait(false));
 | 
					            list.Add(await GetUserView(SpecialFolder.RecentlyPlayedGames, user, "1", parent).ConfigureAwait(false));
 | 
				
			||||||
            list.Add(await GetUserView(SpecialFolder.GameFavorites, user, "2", parent).ConfigureAwait(false));
 | 
					            list.Add(await GetUserView(SpecialFolder.GameFavorites, user, "2", parent).ConfigureAwait(false));
 | 
				
			||||||
            list.Add(await GetUserView(SpecialFolder.GameSystems, user, "3", parent).ConfigureAwait(false));
 | 
					            list.Add(await GetUserView(SpecialFolder.GameSystems, user, "3", parent).ConfigureAwait(false));
 | 
				
			||||||
            //list.Add(await GetUserView(SpecialFolder.GameGenres, user, "4", parent).ConfigureAwait(false));
 | 
					            list.Add(await GetUserView(SpecialFolder.GameGenres, user, "4", parent).ConfigureAwait(false));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return GetResult(list, parent, query);
 | 
					            return GetResult(list, parent, query);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -545,9 +625,9 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
            return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).OfType<Series>(), parent, 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)
 | 
					        private async Task<QueryResult<BaseItem>> GetTvGenres(Folder parent, User user, InternalItemsQuery query)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var genres = GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty })
 | 
					            var tasks = GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty })
 | 
				
			||||||
                .OfType<Series>()
 | 
					                .OfType<Series>()
 | 
				
			||||||
                .SelectMany(i => i.Genres)
 | 
					                .SelectMany(i => i.Genres)
 | 
				
			||||||
                .Distinct(StringComparer.OrdinalIgnoreCase)
 | 
					                .Distinct(StringComparer.OrdinalIgnoreCase)
 | 
				
			||||||
@ -565,19 +645,40 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
                .Where(i => i != null);
 | 
					                .Where(i => i != null)
 | 
				
			||||||
 | 
					                .Select(i => GetUserView(i.Name, SpecialFolder.TvGenre, user, i.SortName, parent));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var genres = await Task.WhenAll(tasks).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return GetResult(genres, parent, query);
 | 
					            return GetResult(genres, parent, query);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private async Task<QueryResult<BaseItem>> GetTvGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var items = GetRecursiveChildren(queryParent, user, new[] { CollectionType.TvShows, string.Empty })
 | 
				
			||||||
 | 
					                .Where(i => i is Series)
 | 
				
			||||||
 | 
					                .Where(i => i.Genres.Contains(displayParent.Name, StringComparer.OrdinalIgnoreCase));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return GetResult(items, queryParent, query);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private QueryResult<BaseItem> GetGameSystems(Folder parent, User user, InternalItemsQuery query)
 | 
					        private QueryResult<BaseItem> GetGameSystems(Folder parent, User user, InternalItemsQuery query)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }).OfType<GameSystem>(), parent, query);
 | 
					            return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }).OfType<GameSystem>(), parent, query);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private QueryResult<BaseItem> GetGameGenres(Folder parent, User user, InternalItemsQuery query)
 | 
					        private async Task<QueryResult<BaseItem>> GetGameGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var genres = GetRecursiveChildren(parent, user, new[] { CollectionType.Games })
 | 
					            var items = GetRecursiveChildren(queryParent, user, new[] { CollectionType.Games })
 | 
				
			||||||
 | 
					                .OfType<Game>()
 | 
				
			||||||
 | 
					                .Where(i => i.Genres.Contains(displayParent.Name, StringComparer.OrdinalIgnoreCase));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return GetResult(items, queryParent, query);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private async Task<QueryResult<BaseItem>> GetGameGenres(Folder parent, User user, InternalItemsQuery query)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var tasks = GetRecursiveChildren(parent, user, new[] { CollectionType.Games })
 | 
				
			||||||
                .OfType<Game>()
 | 
					                .OfType<Game>()
 | 
				
			||||||
                .SelectMany(i => i.Genres)
 | 
					                .SelectMany(i => i.Genres)
 | 
				
			||||||
                .Distinct(StringComparer.OrdinalIgnoreCase)
 | 
					                .Distinct(StringComparer.OrdinalIgnoreCase)
 | 
				
			||||||
@ -595,7 +696,10 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
                .Where(i => i != null);
 | 
					                .Where(i => i != null)
 | 
				
			||||||
 | 
					                .Select(i => GetUserView(i.Name, SpecialFolder.GameGenre, user, i.SortName, parent));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var genres = await Task.WhenAll(tasks).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return GetResult(genres, parent, query);
 | 
					            return GetResult(genres, parent, query);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -611,24 +715,24 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private QueryResult<BaseItem> GetResult<T>(IEnumerable<T> items,
 | 
					        private QueryResult<BaseItem> GetResult<T>(IEnumerable<T> items,
 | 
				
			||||||
            BaseItem parentItem,
 | 
					            BaseItem queryParent,
 | 
				
			||||||
            InternalItemsQuery query)
 | 
					            InternalItemsQuery query)
 | 
				
			||||||
            where T : BaseItem
 | 
					            where T : BaseItem
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return GetResult(items, parentItem, null, query);
 | 
					            return GetResult(items, queryParent, null, query);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private QueryResult<BaseItem> GetResult<T>(IEnumerable<T> items,
 | 
					        private QueryResult<BaseItem> GetResult<T>(IEnumerable<T> items,
 | 
				
			||||||
            BaseItem parentItem,
 | 
					            BaseItem queryParent,
 | 
				
			||||||
            int? totalRecordLimit,
 | 
					            int? totalRecordLimit,
 | 
				
			||||||
            InternalItemsQuery query)
 | 
					            InternalItemsQuery query)
 | 
				
			||||||
            where T : BaseItem
 | 
					            where T : BaseItem
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return SortAndFilter(items, parentItem, totalRecordLimit, query, _libraryManager, _userDataManager);
 | 
					            return SortAndFilter(items, queryParent, totalRecordLimit, query, _libraryManager, _userDataManager);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public static QueryResult<BaseItem> SortAndFilter(IEnumerable<BaseItem> items,
 | 
					        public static QueryResult<BaseItem> SortAndFilter(IEnumerable<BaseItem> items,
 | 
				
			||||||
            BaseItem parentItem,
 | 
					            BaseItem queryParent,
 | 
				
			||||||
            int? totalRecordLimit,
 | 
					            int? totalRecordLimit,
 | 
				
			||||||
            InternalItemsQuery query,
 | 
					            InternalItemsQuery query,
 | 
				
			||||||
            ILibraryManager libraryManager,
 | 
					            ILibraryManager libraryManager,
 | 
				
			||||||
@ -643,7 +747,7 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
                query.IsVirtualUnaired,
 | 
					                query.IsVirtualUnaired,
 | 
				
			||||||
                query.IsUnaired);
 | 
					                query.IsUnaired);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            items = CollapseBoxSetItemsIfNeeded(items, query, parentItem, user);
 | 
					            items = CollapseBoxSetItemsIfNeeded(items, query, queryParent, user);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // This must be the last filter
 | 
					            // This must be the last filter
 | 
				
			||||||
            if (!string.IsNullOrEmpty(query.AdjacentTo))
 | 
					            if (!string.IsNullOrEmpty(query.AdjacentTo))
 | 
				
			||||||
@ -656,10 +760,10 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        public static IEnumerable<BaseItem> CollapseBoxSetItemsIfNeeded(IEnumerable<BaseItem> items,
 | 
					        public static IEnumerable<BaseItem> CollapseBoxSetItemsIfNeeded(IEnumerable<BaseItem> items,
 | 
				
			||||||
            InternalItemsQuery query,
 | 
					            InternalItemsQuery query,
 | 
				
			||||||
            BaseItem parentItem,
 | 
					            BaseItem queryParent,
 | 
				
			||||||
            User user)
 | 
					            User user)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (CollapseBoxSetItems(query, parentItem, user))
 | 
					            if (CollapseBoxSetItems(query, queryParent, user))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                items = BaseItem.CollectionManager.CollapseItemsWithinBoxSets(items, user);
 | 
					                items = BaseItem.CollectionManager.CollapseItemsWithinBoxSets(items, user);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -691,11 +795,11 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private static bool CollapseBoxSetItems(InternalItemsQuery query,
 | 
					        private static bool CollapseBoxSetItems(InternalItemsQuery query,
 | 
				
			||||||
            BaseItem parentItem,
 | 
					            BaseItem queryParent,
 | 
				
			||||||
            User user)
 | 
					            User user)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            // Could end up stuck in a loop like this
 | 
					            // Could end up stuck in a loop like this
 | 
				
			||||||
            if (parentItem is BoxSet)
 | 
					            if (queryParent is BoxSet)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return false;
 | 
					                return false;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -1488,7 +1592,7 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
                });
 | 
					                });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private IEnumerable<Folder> GetMediaFolders(Folder parent, User user, string[] viewTypes)
 | 
					        private IEnumerable<Folder> GetMediaFolders(Folder parent, User user, IEnumerable<string> viewTypes)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (parent == null || parent is UserView)
 | 
					            if (parent == null || parent is UserView)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@ -1498,7 +1602,7 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
            return new[] { parent };
 | 
					            return new[] { parent };
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private IEnumerable<BaseItem> GetRecursiveChildren(Folder parent, User user, string[] viewTypes)
 | 
					        private IEnumerable<BaseItem> GetRecursiveChildren(Folder parent, User user, IEnumerable<string> viewTypes)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (parent == null || parent is UserView)
 | 
					            if (parent == null || parent is UserView)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@ -1521,7 +1625,15 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
            return list;
 | 
					            return list;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private async Task<UserView> GetUserView(string type, User user, string sortName, Folder parent)
 | 
					        private async Task<UserView> GetUserView(string name, string type, User user, string sortName, BaseItem parent)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var view = await _userViewManager.GetUserView(name, parent.Id.ToString("N"), type, user, sortName, CancellationToken.None)
 | 
				
			||||||
 | 
					                        .ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return view;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private async Task<UserView> GetUserView(string type, User user, string sortName, BaseItem parent)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var view = await _userViewManager.GetUserView(parent.Id.ToString("N"), type, user, sortName, CancellationToken.None)
 | 
					            var view = await _userViewManager.GetUserView(parent.Id.ToString("N"), type, user, sortName, CancellationToken.None)
 | 
				
			||||||
                        .ConfigureAwait(false);
 | 
					                        .ConfigureAwait(false);
 | 
				
			||||||
 | 
				
			|||||||
@ -10,6 +10,9 @@ namespace MediaBrowser.Controller.Library
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        Task<IEnumerable<Folder>> GetUserViews(UserViewQuery query, CancellationToken cancellationToken);
 | 
					        Task<IEnumerable<Folder>> GetUserViews(UserViewQuery query, CancellationToken cancellationToken);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Task<UserView> GetUserView(string name, string parentId, string type, User user, string sortName,
 | 
				
			||||||
 | 
					            CancellationToken cancellationToken);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Task<UserView> GetUserView(string type, string sortName, CancellationToken cancellationToken);
 | 
					        Task<UserView> GetUserView(string type, string sortName, CancellationToken cancellationToken);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Task<UserView> GetUserView(string category, string type, User user, string sortName, CancellationToken cancellationToken);
 | 
					        Task<UserView> GetUserView(string category, string type, User user, string sortName, CancellationToken cancellationToken);
 | 
				
			||||||
 | 
				
			|||||||
@ -78,13 +78,22 @@ namespace MediaBrowser.LocalMetadata
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            get
 | 
					            get
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return "Media Browser Xml";
 | 
					                return XmlProviderUtils.Name;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static class XmlProviderUtils
 | 
					    static class XmlProviderUtils
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        public static string Name
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return "Media Browser Legacy Xml";
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        internal static readonly SemaphoreSlim XmlParsingResourcePool = new SemaphoreSlim(4, 4);
 | 
					        internal static readonly SemaphoreSlim XmlParsingResourcePool = new SemaphoreSlim(4, 4);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -15,7 +15,7 @@ namespace MediaBrowser.LocalMetadata.Savers
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            get
 | 
					            get
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return "Media Browser Xml";
 | 
					                return XmlProviderUtils.Name;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -41,7 +41,7 @@ namespace MediaBrowser.LocalMetadata.Savers
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            get
 | 
					            get
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return "Media Browser Xml";
 | 
					                return XmlProviderUtils.Name;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -45,7 +45,7 @@ namespace MediaBrowser.LocalMetadata.Savers
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            get
 | 
					            get
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return "Media Browser Xml";
 | 
					                return XmlProviderUtils.Name;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -18,7 +18,7 @@ namespace MediaBrowser.LocalMetadata.Savers
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            get
 | 
					            get
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return "Media Browser Xml";
 | 
					                return XmlProviderUtils.Name;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -15,7 +15,7 @@ namespace MediaBrowser.LocalMetadata.Savers
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            get
 | 
					            get
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return "Media Browser Xml";
 | 
					                return XmlProviderUtils.Name;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -20,7 +20,7 @@ namespace MediaBrowser.LocalMetadata.Savers
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            get
 | 
					            get
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return "Media Browser Xml";
 | 
					                return XmlProviderUtils.Name;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -30,7 +30,7 @@ namespace MediaBrowser.LocalMetadata.Savers
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            get
 | 
					            get
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return "Media Browser Xml";
 | 
					                return XmlProviderUtils.Name;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -18,7 +18,7 @@ namespace MediaBrowser.LocalMetadata.Savers
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            get
 | 
					            get
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return "Media Browser Xml";
 | 
					                return XmlProviderUtils.Name;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,7 @@ namespace MediaBrowser.LocalMetadata.Savers
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            get
 | 
					            get
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return "Media Browser Xml";
 | 
					                return XmlProviderUtils.Name;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -17,7 +17,7 @@ namespace MediaBrowser.LocalMetadata.Savers
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            get
 | 
					            get
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return "Media Browser Xml";
 | 
					                return XmlProviderUtils.Name;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -25,7 +25,7 @@ namespace MediaBrowser.LocalMetadata.Savers
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            get
 | 
					            get
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return "Media Browser Xml";
 | 
					                return XmlProviderUtils.Name;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -121,6 +121,16 @@ namespace MediaBrowser.Model.ApiClient
 | 
				
			|||||||
        /// <returns>Task{SearchHintResult}.</returns>
 | 
					        /// <returns>Task{SearchHintResult}.</returns>
 | 
				
			||||||
        Task<SearchHintResult> GetSearchHintsAsync(SearchQuery query);
 | 
					        Task<SearchHintResult> GetSearchHintsAsync(SearchQuery query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Gets the filters.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="userId">The user identifier.</param>
 | 
				
			||||||
 | 
					        /// <param name="parentId">The parent identifier.</param>
 | 
				
			||||||
 | 
					        /// <param name="mediaTypes">The media types.</param>
 | 
				
			||||||
 | 
					        /// <param name="itemTypes">The item types.</param>
 | 
				
			||||||
 | 
					        /// <returns>Task<QueryFilters>.</returns>
 | 
				
			||||||
 | 
					        Task<QueryFilters> GetFilters(string userId, string parentId, string[] mediaTypes, string[] itemTypes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Gets the theme videos async.
 | 
					        /// Gets the theme videos async.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
 | 
				
			|||||||
@ -61,6 +61,14 @@ namespace MediaBrowser.Model.ApiClient
 | 
				
			|||||||
        /// <returns>Task<ConnectionResult>.</returns>
 | 
					        /// <returns>Task<ConnectionResult>.</returns>
 | 
				
			||||||
        Task<ConnectionResult> Connect(CancellationToken cancellationToken);
 | 
					        Task<ConnectionResult> Connect(CancellationToken cancellationToken);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Connects the specified API client.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="apiClient">The API client.</param>
 | 
				
			||||||
 | 
					        /// <param name="cancellationToken">The cancellation token.</param>
 | 
				
			||||||
 | 
					        /// <returns>Task<ConnectionResult>.</returns>
 | 
				
			||||||
 | 
					        Task<ConnectionResult> Connect(IApiClient apiClient, CancellationToken cancellationToken);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Connects the specified server.
 | 
					        /// Connects the specified server.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
 | 
				
			|||||||
@ -35,6 +35,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        public const string TvShowSeries = "TvShowSeries";
 | 
					        public const string TvShowSeries = "TvShowSeries";
 | 
				
			||||||
        public const string TvGenres = "TvGenres";
 | 
					        public const string TvGenres = "TvGenres";
 | 
				
			||||||
 | 
					        public const string TvGenre = "TvGenre";
 | 
				
			||||||
        public const string TvLatest = "TvLatest";
 | 
					        public const string TvLatest = "TvLatest";
 | 
				
			||||||
        public const string TvNextUp = "TvNextUp";
 | 
					        public const string TvNextUp = "TvNextUp";
 | 
				
			||||||
        public const string TvResume = "TvResume";
 | 
					        public const string TvResume = "TvResume";
 | 
				
			||||||
@ -47,17 +48,20 @@
 | 
				
			|||||||
        public const string MovieCollections = "MovieCollections";
 | 
					        public const string MovieCollections = "MovieCollections";
 | 
				
			||||||
        public const string MovieFavorites = "MovieFavorites";
 | 
					        public const string MovieFavorites = "MovieFavorites";
 | 
				
			||||||
        public const string MovieGenres = "MovieGenres";
 | 
					        public const string MovieGenres = "MovieGenres";
 | 
				
			||||||
 | 
					        public const string MovieGenre = "MovieGenre";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public const string LatestGames = "LatestGames";
 | 
					        public const string LatestGames = "LatestGames";
 | 
				
			||||||
        public const string RecentlyPlayedGames = "RecentlyPlayedGames";
 | 
					        public const string RecentlyPlayedGames = "RecentlyPlayedGames";
 | 
				
			||||||
        public const string GameSystems = "GameSystems";
 | 
					        public const string GameSystems = "GameSystems";
 | 
				
			||||||
        public const string GameGenres = "GameGenres";
 | 
					        public const string GameGenres = "GameGenres";
 | 
				
			||||||
        public const string GameFavorites = "GameFavorites";
 | 
					        public const string GameFavorites = "GameFavorites";
 | 
				
			||||||
 | 
					        public const string GameGenre = "GameGenre";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public const string MusicArtists = "MusicArtists";
 | 
					        public const string MusicArtists = "MusicArtists";
 | 
				
			||||||
        public const string MusicAlbumArtists = "MusicAlbumArtists";
 | 
					        public const string MusicAlbumArtists = "MusicAlbumArtists";
 | 
				
			||||||
        public const string MusicAlbums = "MusicAlbums";
 | 
					        public const string MusicAlbums = "MusicAlbums";
 | 
				
			||||||
        public const string MusicGenres = "MusicGenres";
 | 
					        public const string MusicGenres = "MusicGenres";
 | 
				
			||||||
 | 
					        public const string MusicGenre = "MusicGenre";
 | 
				
			||||||
        public const string MusicLatest = "MusicLatest";
 | 
					        public const string MusicLatest = "MusicLatest";
 | 
				
			||||||
        public const string MusicSongs = "MusicSongs";
 | 
					        public const string MusicSongs = "MusicSongs";
 | 
				
			||||||
        public const string MusicFavorites = "MusicFavorites";
 | 
					        public const string MusicFavorites = "MusicFavorites";
 | 
				
			||||||
 | 
				
			|||||||
@ -148,11 +148,16 @@ namespace MediaBrowser.Server.Implementations.Library
 | 
				
			|||||||
                .ThenBy(i => i.SortName);
 | 
					                .ThenBy(i => i.SortName);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public Task<UserView> GetUserView(string name, string parentId, string type, User user, string sortName, CancellationToken cancellationToken)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return _libraryManager.GetSpecialFolder(user, name, parentId, type, sortName, cancellationToken);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public Task<UserView> GetUserView(string parentId, string type, User user, string sortName, CancellationToken cancellationToken)
 | 
					        public Task<UserView> GetUserView(string parentId, string type, User user, string sortName, CancellationToken cancellationToken)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var name = _localizationManager.GetLocalizedString("ViewType" + type);
 | 
					            var name = _localizationManager.GetLocalizedString("ViewType" + type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return _libraryManager.GetSpecialFolder(user, name, parentId, type, sortName, cancellationToken);
 | 
					            return GetUserView(name, parentId, type, user, sortName, cancellationToken);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public Task<UserView> GetUserView(string type, string sortName, CancellationToken cancellationToken)
 | 
					        public Task<UserView> GetUserView(string type, string sortName, CancellationToken cancellationToken)
 | 
				
			||||||
 | 
				
			|||||||
@ -288,7 +288,7 @@
 | 
				
			|||||||
    "LabelPremiereProgram": "PREMIERE",
 | 
					    "LabelPremiereProgram": "PREMIERE",
 | 
				
			||||||
    "LabelHDProgram": "HD",
 | 
					    "LabelHDProgram": "HD",
 | 
				
			||||||
    "HeaderChangeFolderType": "Change Folder Type",
 | 
					    "HeaderChangeFolderType": "Change Folder Type",
 | 
				
			||||||
    "HeaderChangeFolderTypeHelp": "To change the folder type, please remove and rebuild the collection with the new type.",
 | 
					    "HeaderChangeFolderTypeHelp": "To change the type, please remove and rebuild the folder with the new type.",
 | 
				
			||||||
    "HeaderAlert": "Alert",
 | 
					    "HeaderAlert": "Alert",
 | 
				
			||||||
    "MessagePleaseRestart": "Please restart to finish updating.",
 | 
					    "MessagePleaseRestart": "Please restart to finish updating.",
 | 
				
			||||||
    "ButtonRestart": "Restart",
 | 
					    "ButtonRestart": "Restart",
 | 
				
			||||||
 | 
				
			|||||||
@ -145,9 +145,11 @@
 | 
				
			|||||||
    "OptionBudget": "Budget",
 | 
					    "OptionBudget": "Budget",
 | 
				
			||||||
    "OptionRevenue": "Revenue",
 | 
					    "OptionRevenue": "Revenue",
 | 
				
			||||||
    "OptionPoster": "Poster",
 | 
					    "OptionPoster": "Poster",
 | 
				
			||||||
 | 
					    "OptionPosterCard":  "Poster card",
 | 
				
			||||||
    "OptionBackdrop": "Backdrop",
 | 
					    "OptionBackdrop": "Backdrop",
 | 
				
			||||||
    "OptionTimeline": "Timeline",
 | 
					    "OptionTimeline": "Timeline",
 | 
				
			||||||
    "OptionThumb": "Thumb",
 | 
					    "OptionThumb": "Thumb",
 | 
				
			||||||
 | 
					    "OptionThumbCard": "Thumb card",
 | 
				
			||||||
    "OptionBanner": "Banner",
 | 
					    "OptionBanner": "Banner",
 | 
				
			||||||
    "OptionCriticRating": "Critic Rating",
 | 
					    "OptionCriticRating": "Critic Rating",
 | 
				
			||||||
    "OptionVideoBitrate": "Video Bitrate",
 | 
					    "OptionVideoBitrate": "Video Bitrate",
 | 
				
			||||||
@ -455,7 +457,7 @@
 | 
				
			|||||||
    "LinkApiDocumentation": "Api Documentation",
 | 
					    "LinkApiDocumentation": "Api Documentation",
 | 
				
			||||||
    "LabelFriendlyServerName": "Friendly server name:",
 | 
					    "LabelFriendlyServerName": "Friendly server name:",
 | 
				
			||||||
    "LabelFriendlyServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.",
 | 
					    "LabelFriendlyServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.",
 | 
				
			||||||
    "LabelPreferredDisplayLanguage": "Preferred display language",
 | 
					    "LabelPreferredDisplayLanguage": "Preferred display language:",
 | 
				
			||||||
    "LabelPreferredDisplayLanguageHelp": "Translating Media Browser is an ongoing project and is not yet complete.",
 | 
					    "LabelPreferredDisplayLanguageHelp": "Translating Media Browser is an ongoing project and is not yet complete.",
 | 
				
			||||||
    "LabelReadHowYouCanContribute": "Read about how you can contribute.",
 | 
					    "LabelReadHowYouCanContribute": "Read about how you can contribute.",
 | 
				
			||||||
    "HeaderNewCollection": "New Collection",
 | 
					    "HeaderNewCollection": "New Collection",
 | 
				
			||||||
@ -847,6 +849,8 @@
 | 
				
			|||||||
    "ViewTypeTvShows": "TV",
 | 
					    "ViewTypeTvShows": "TV",
 | 
				
			||||||
    "ViewTypeGames": "Games",
 | 
					    "ViewTypeGames": "Games",
 | 
				
			||||||
    "ViewTypeMusic": "Music",
 | 
					    "ViewTypeMusic": "Music",
 | 
				
			||||||
 | 
					    "ViewTypeMusicGenres": "Genres",
 | 
				
			||||||
 | 
					    "ViewTypeMusicArtists": "Artists",
 | 
				
			||||||
    "ViewTypeBoxSets": "Collections",
 | 
					    "ViewTypeBoxSets": "Collections",
 | 
				
			||||||
    "ViewTypeChannels": "Channels",
 | 
					    "ViewTypeChannels": "Channels",
 | 
				
			||||||
    "ViewTypeLiveTV": "Live TV",
 | 
					    "ViewTypeLiveTV": "Live TV",
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,6 @@
 | 
				
			|||||||
using MediaBrowser.Common.IO;
 | 
					using MediaBrowser.Common.IO;
 | 
				
			||||||
using MediaBrowser.Controller.Entities;
 | 
					using MediaBrowser.Controller.Entities;
 | 
				
			||||||
 | 
					using MediaBrowser.Controller.Entities.TV;
 | 
				
			||||||
using MediaBrowser.Controller.Library;
 | 
					using MediaBrowser.Controller.Library;
 | 
				
			||||||
using MediaBrowser.Controller.Providers;
 | 
					using MediaBrowser.Controller.Providers;
 | 
				
			||||||
using MediaBrowser.Model.Entities;
 | 
					using MediaBrowser.Model.Entities;
 | 
				
			||||||
@ -8,6 +9,7 @@ using System;
 | 
				
			|||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using System.Linq;
 | 
					using System.Linq;
 | 
				
			||||||
using System.Threading.Tasks;
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using MoreLinq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace MediaBrowser.Server.Implementations.Music
 | 
					namespace MediaBrowser.Server.Implementations.Music
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -36,7 +38,42 @@ namespace MediaBrowser.Server.Implementations.Music
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            }).ConfigureAwait(false);
 | 
					            }).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return GetFinalItems(result.Items.Where(i => i.HasImage(ImageType.Primary)).ToList());
 | 
					            var items = result.Items.Select(i =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var episode = i as Episode;
 | 
				
			||||||
 | 
					                if (episode != null)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    var series = episode.Series;
 | 
				
			||||||
 | 
					                    if (series != null)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        return series;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    var episodeSeason = episode.Season;
 | 
				
			||||||
 | 
					                    if (episodeSeason != null)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        return episodeSeason;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    return episode;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                var season = i as Season;
 | 
				
			||||||
 | 
					                if (season != null)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    var series = season.Series;
 | 
				
			||||||
 | 
					                    if (series != null)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        return series;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    return season;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            }).DistinctBy(i => i.Id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return GetFinalItems(items.Where(i => i.HasImage(ImageType.Primary)).ToList());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected override bool Supports(IHasImages item)
 | 
					        protected override bool Supports(IHasImages item)
 | 
				
			||||||
@ -50,6 +87,7 @@ namespace MediaBrowser.Server.Implementations.Music
 | 
				
			|||||||
                    SpecialFolder.TvFavoriteEpisodes,
 | 
					                    SpecialFolder.TvFavoriteEpisodes,
 | 
				
			||||||
                    SpecialFolder.TvFavoriteSeries,
 | 
					                    SpecialFolder.TvFavoriteSeries,
 | 
				
			||||||
                    SpecialFolder.TvGenres,
 | 
					                    SpecialFolder.TvGenres,
 | 
				
			||||||
 | 
					                    SpecialFolder.TvGenre,
 | 
				
			||||||
                    SpecialFolder.TvLatest,
 | 
					                    SpecialFolder.TvLatest,
 | 
				
			||||||
                    SpecialFolder.TvNextUp,
 | 
					                    SpecialFolder.TvNextUp,
 | 
				
			||||||
                    SpecialFolder.TvResume,
 | 
					                    SpecialFolder.TvResume,
 | 
				
			||||||
@ -58,12 +96,14 @@ namespace MediaBrowser.Server.Implementations.Music
 | 
				
			|||||||
                    SpecialFolder.MovieCollections,
 | 
					                    SpecialFolder.MovieCollections,
 | 
				
			||||||
                    SpecialFolder.MovieFavorites,
 | 
					                    SpecialFolder.MovieFavorites,
 | 
				
			||||||
                    SpecialFolder.MovieGenres,
 | 
					                    SpecialFolder.MovieGenres,
 | 
				
			||||||
 | 
					                    SpecialFolder.MovieGenre,
 | 
				
			||||||
                    SpecialFolder.MovieLatest,
 | 
					                    SpecialFolder.MovieLatest,
 | 
				
			||||||
                    SpecialFolder.MovieMovies,
 | 
					                    SpecialFolder.MovieMovies,
 | 
				
			||||||
                    SpecialFolder.MovieResume,
 | 
					                    SpecialFolder.MovieResume,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    SpecialFolder.GameFavorites,
 | 
					                    SpecialFolder.GameFavorites,
 | 
				
			||||||
                    SpecialFolder.GameGenres,
 | 
					                    SpecialFolder.GameGenres,
 | 
				
			||||||
 | 
					                    SpecialFolder.GameGenre,
 | 
				
			||||||
                    SpecialFolder.GameSystems,
 | 
					                    SpecialFolder.GameSystems,
 | 
				
			||||||
                    SpecialFolder.LatestGames,
 | 
					                    SpecialFolder.LatestGames,
 | 
				
			||||||
                    SpecialFolder.RecentlyPlayedGames,
 | 
					                    SpecialFolder.RecentlyPlayedGames,
 | 
				
			||||||
@ -72,6 +112,7 @@ namespace MediaBrowser.Server.Implementations.Music
 | 
				
			|||||||
                    SpecialFolder.MusicAlbumArtists,
 | 
					                    SpecialFolder.MusicAlbumArtists,
 | 
				
			||||||
                    SpecialFolder.MusicAlbums,
 | 
					                    SpecialFolder.MusicAlbums,
 | 
				
			||||||
                    SpecialFolder.MusicGenres,
 | 
					                    SpecialFolder.MusicGenres,
 | 
				
			||||||
 | 
					                    SpecialFolder.MusicGenre,
 | 
				
			||||||
                    SpecialFolder.MusicLatest,
 | 
					                    SpecialFolder.MusicLatest,
 | 
				
			||||||
                    SpecialFolder.MusicSongs,
 | 
					                    SpecialFolder.MusicSongs,
 | 
				
			||||||
                    SpecialFolder.MusicFavorites,
 | 
					                    SpecialFolder.MusicFavorites,
 | 
				
			||||||
 | 
				
			|||||||
@ -173,6 +173,9 @@
 | 
				
			|||||||
    <None Include="MediaBrowser.MediaInfo.dll.config">
 | 
					    <None Include="MediaBrowser.MediaInfo.dll.config">
 | 
				
			||||||
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
					      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
				
			||||||
    </None>
 | 
					    </None>
 | 
				
			||||||
 | 
					    <None Include="mediabrowser.sh">
 | 
				
			||||||
 | 
					      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
				
			||||||
 | 
					    </None>
 | 
				
			||||||
    <None Include="packages.config" />
 | 
					    <None Include="packages.config" />
 | 
				
			||||||
    <None Include="System.Data.SQLite.dll.config">
 | 
					    <None Include="System.Data.SQLite.dll.config">
 | 
				
			||||||
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
					      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								MediaBrowser.Server.Mono/mediabrowser.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								MediaBrowser.Server.Mono/mediabrowser.sh
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					mono MediaBrowser.Server.Mono.exe
 | 
				
			||||||
@ -82,6 +82,7 @@ using MediaBrowser.Server.Implementations.Sync;
 | 
				
			|||||||
using MediaBrowser.Server.Implementations.Themes;
 | 
					using MediaBrowser.Server.Implementations.Themes;
 | 
				
			||||||
using MediaBrowser.Server.Implementations.TV;
 | 
					using MediaBrowser.Server.Implementations.TV;
 | 
				
			||||||
using MediaBrowser.Server.Startup.Common.FFMpeg;
 | 
					using MediaBrowser.Server.Startup.Common.FFMpeg;
 | 
				
			||||||
 | 
					using MediaBrowser.Server.Startup.Common.Migrations;
 | 
				
			||||||
using MediaBrowser.WebDashboard.Api;
 | 
					using MediaBrowser.WebDashboard.Api;
 | 
				
			||||||
using MediaBrowser.XbmcMetadata.Providers;
 | 
					using MediaBrowser.XbmcMetadata.Providers;
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
@ -322,84 +323,10 @@ namespace MediaBrowser.Server.Startup.Common
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        private void PerformVersionMigration()
 | 
					        private void PerformVersionMigration()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            DeleteDeprecatedModules();
 | 
					            new MigrateUserFolders(ApplicationPaths).Run();
 | 
				
			||||||
 | 
					            new PlaylistImages(ServerConfigurationManager).Run();
 | 
				
			||||||
            if (!ServerConfigurationManager.Configuration.PlaylistImagesDeleted)
 | 
					            new RenameXbmcOptions(ServerConfigurationManager).Run();
 | 
				
			||||||
            {
 | 
					            new RenameXmlOptions(ServerConfigurationManager).Run();
 | 
				
			||||||
                DeletePlaylistImages();
 | 
					 | 
				
			||||||
                ServerConfigurationManager.Configuration.PlaylistImagesDeleted = true;
 | 
					 | 
				
			||||||
                ServerConfigurationManager.SaveConfiguration();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        private void DeletePlaylistImages()
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            try
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                var path = Path.Combine(ApplicationPaths.DataPath, "playlists");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                var files = Directory.GetFiles(path, "*", SearchOption.AllDirectories)
 | 
					 | 
				
			||||||
                    .Where(i => BaseItem.SupportedImageExtensions.Contains(Path.GetExtension(i) ?? string.Empty))
 | 
					 | 
				
			||||||
                    .ToList();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                foreach (var file in files)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    try
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        File.Delete(file);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    catch (IOException)
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            catch (IOException)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        private void DeleteDeprecatedModules()
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            try
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                MigrateUserFolders();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            catch (IOException)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            try
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                File.Delete(Path.Combine(ApplicationPaths.PluginsPath, "MBPhoto.dll"));
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            catch (IOException)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                // Not there, no big deal
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            try
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                File.Delete(Path.Combine(ApplicationPaths.PluginsPath, "MediaBrowser.Plugins.XbmcMetadata.dll"));
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            catch (IOException)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                // Not there, no big deal
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        private void MigrateUserFolders()
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            var rootPath = ApplicationPaths.RootFolderPath;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            var folders = new DirectoryInfo(rootPath).EnumerateDirectories("*", SearchOption.TopDirectoryOnly).Where(i => !string.Equals(i.Name, "default", StringComparison.OrdinalIgnoreCase))
 | 
					 | 
				
			||||||
                .ToList();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            foreach (var folder in folders)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                Directory.Delete(folder.FullName, true);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
 | 
				
			|||||||
@ -60,6 +60,11 @@
 | 
				
			|||||||
    <Compile Include="FFMpeg\FFMpegDownloadInfo.cs" />
 | 
					    <Compile Include="FFMpeg\FFMpegDownloadInfo.cs" />
 | 
				
			||||||
    <Compile Include="FFMpeg\FFMpegInfo.cs" />
 | 
					    <Compile Include="FFMpeg\FFMpegInfo.cs" />
 | 
				
			||||||
    <Compile Include="INativeApp.cs" />
 | 
					    <Compile Include="INativeApp.cs" />
 | 
				
			||||||
 | 
					    <Compile Include="Migrations\IVersionMigration.cs" />
 | 
				
			||||||
 | 
					    <Compile Include="Migrations\MigrateUserFolders.cs" />
 | 
				
			||||||
 | 
					    <Compile Include="Migrations\PlaylistImages.cs" />
 | 
				
			||||||
 | 
					    <Compile Include="Migrations\RenameXbmcOptions.cs" />
 | 
				
			||||||
 | 
					    <Compile Include="Migrations\RenameXmlOptions.cs" />
 | 
				
			||||||
    <Compile Include="NativeEnvironment.cs" />
 | 
					    <Compile Include="NativeEnvironment.cs" />
 | 
				
			||||||
    <Compile Include="Properties\AssemblyInfo.cs" />
 | 
					    <Compile Include="Properties\AssemblyInfo.cs" />
 | 
				
			||||||
    <Compile Include="StartupOptions.cs" />
 | 
					    <Compile Include="StartupOptions.cs" />
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					namespace MediaBrowser.Server.Startup.Common.Migrations
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public interface IVersionMigration
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        void Run();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					using MediaBrowser.Controller;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.IO;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace MediaBrowser.Server.Startup.Common.Migrations
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class MigrateUserFolders : IVersionMigration
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private readonly IServerApplicationPaths _appPaths;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public MigrateUserFolders(IServerApplicationPaths appPaths)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _appPaths = appPaths;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Run()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            try
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var rootPath = _appPaths.RootFolderPath;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                var folders = new DirectoryInfo(rootPath).EnumerateDirectories("*", SearchOption.TopDirectoryOnly).Where(i => !string.Equals(i.Name, "default", StringComparison.OrdinalIgnoreCase))
 | 
				
			||||||
 | 
					                    .ToList();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                foreach (var folder in folders)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Directory.Delete(folder.FullName, true);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            catch (IOException)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					using MediaBrowser.Controller.Configuration;
 | 
				
			||||||
 | 
					using MediaBrowser.Controller.Entities;
 | 
				
			||||||
 | 
					using System.IO;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace MediaBrowser.Server.Startup.Common.Migrations
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class PlaylistImages : IVersionMigration
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private readonly IServerConfigurationManager _config;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public PlaylistImages(IServerConfigurationManager config)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _config = config;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Run()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (!_config.Configuration.PlaylistImagesDeleted)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                DeletePlaylistImages();
 | 
				
			||||||
 | 
					                _config.Configuration.PlaylistImagesDeleted = true;
 | 
				
			||||||
 | 
					                _config.SaveConfiguration();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void DeletePlaylistImages()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            try
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var path = Path.Combine(_config.ApplicationPaths.DataPath, "playlists");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                var files = Directory.GetFiles(path, "*", SearchOption.AllDirectories)
 | 
				
			||||||
 | 
					                    .Where(i => BaseItem.SupportedImageExtensions.Contains(Path.GetExtension(i) ?? string.Empty))
 | 
				
			||||||
 | 
					                    .ToList();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                foreach (var file in files)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    try
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        File.Delete(file);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    catch (IOException)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            catch (IOException)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,56 @@
 | 
				
			|||||||
 | 
					using MediaBrowser.Controller.Configuration;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace MediaBrowser.Server.Startup.Common.Migrations
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class RenameXbmcOptions
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private readonly IServerConfigurationManager _config;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public RenameXbmcOptions(IServerConfigurationManager config)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _config = config;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Run()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var changed = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            foreach (var option in _config.Configuration.MetadataOptions)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (Migrate(option.DisabledMetadataSavers))
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    changed = true;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if (Migrate(option.LocalMetadataReaderOrder))
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    changed = true;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (changed)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _config.SaveConfiguration();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private bool Migrate(string[] options)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var changed = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (options != null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                for (var i = 0; i < options.Length; i++)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    if (string.Equals(options[i], "Xbmc Nfo", StringComparison.OrdinalIgnoreCase))
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        options[i] = "Nfo";
 | 
				
			||||||
 | 
					                        changed = true;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return changed;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,56 @@
 | 
				
			|||||||
 | 
					using MediaBrowser.Controller.Configuration;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace MediaBrowser.Server.Startup.Common.Migrations
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class RenameXmlOptions
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private readonly IServerConfigurationManager _config;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public RenameXmlOptions(IServerConfigurationManager config)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _config = config;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Run()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var changed = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            foreach (var option in _config.Configuration.MetadataOptions)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (Migrate(option.DisabledMetadataSavers))
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    changed = true;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if (Migrate(option.LocalMetadataReaderOrder))
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    changed = true;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (changed)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _config.SaveConfiguration();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private bool Migrate(string[] options)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var changed = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (options != null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                for (var i = 0; i < options.Length; i++)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    if (string.Equals(options[i], "Media Browser Xml", StringComparison.OrdinalIgnoreCase))
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        options[i] = "Media Browser Legacy Xml";
 | 
				
			||||||
 | 
					                        changed = true;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return changed;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -69,6 +69,11 @@ namespace MediaBrowser.XbmcMetadata.Parsers
 | 
				
			|||||||
            Fetch(item, userDataList, metadataFile, settings, cancellationToken);
 | 
					            Fetch(item, userDataList, metadataFile, settings, cancellationToken);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected virtual bool SupportsUrlAfterClosingXmlTag
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get { return false; }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Fetches the specified item.
 | 
					        /// Fetches the specified item.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
@ -79,6 +84,30 @@ namespace MediaBrowser.XbmcMetadata.Parsers
 | 
				
			|||||||
        /// <param name="cancellationToken">The cancellation token.</param>
 | 
					        /// <param name="cancellationToken">The cancellation token.</param>
 | 
				
			||||||
        private void Fetch(T item, List<UserItemData> userDataList, string metadataFile, XmlReaderSettings settings, CancellationToken cancellationToken)
 | 
					        private void Fetch(T item, List<UserItemData> userDataList, string metadataFile, XmlReaderSettings settings, CancellationToken cancellationToken)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            if (!SupportsUrlAfterClosingXmlTag)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                using (var streamReader = BaseNfoSaver.GetStreamReader(metadataFile))
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    // Use XmlReader for best performance
 | 
				
			||||||
 | 
					                    using (var reader = XmlReader.Create(streamReader, settings))
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        reader.MoveToContent();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        // Loop through each element
 | 
				
			||||||
 | 
					                        while (reader.Read())
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            cancellationToken.ThrowIfCancellationRequested();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            if (reader.NodeType == XmlNodeType.Element)
 | 
				
			||||||
 | 
					                            {
 | 
				
			||||||
 | 
					                                FetchDataFromXmlNode(reader, item, userDataList);
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            using (var streamReader = BaseNfoSaver.GetStreamReader(metadataFile))
 | 
					            using (var streamReader = BaseNfoSaver.GetStreamReader(metadataFile))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // Need to handle a url after the xml data
 | 
					                // Need to handle a url after the xml data
 | 
				
			||||||
 | 
				
			|||||||
@ -28,6 +28,14 @@ namespace MediaBrowser.XbmcMetadata.Parsers
 | 
				
			|||||||
            Fetch(item, userDataList, metadataFile, cancellationToken);
 | 
					            Fetch(item, userDataList, metadataFile, cancellationToken);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected override bool SupportsUrlAfterClosingXmlTag
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Fetches the data from XML node.
 | 
					        /// Fetches the data from XML node.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
 | 
				
			|||||||
@ -131,7 +131,7 @@ namespace MediaBrowser.XbmcMetadata.Savers
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            get
 | 
					            get
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return "Xbmc Nfo";
 | 
					                return "Nfo";
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,7 @@
 | 
				
			|||||||
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
 | 
					<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
 | 
				
			||||||
    <metadata>
 | 
					    <metadata>
 | 
				
			||||||
        <id>MediaBrowser.Common.Internal</id>
 | 
					        <id>MediaBrowser.Common.Internal</id>
 | 
				
			||||||
        <version>3.0.506</version>
 | 
					        <version>3.0.507</version>
 | 
				
			||||||
        <title>MediaBrowser.Common.Internal</title>
 | 
					        <title>MediaBrowser.Common.Internal</title>
 | 
				
			||||||
        <authors>Luke</authors>
 | 
					        <authors>Luke</authors>
 | 
				
			||||||
        <owners>ebr,Luke,scottisafool</owners>
 | 
					        <owners>ebr,Luke,scottisafool</owners>
 | 
				
			||||||
@ -12,7 +12,7 @@
 | 
				
			|||||||
        <description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description>
 | 
					        <description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description>
 | 
				
			||||||
        <copyright>Copyright © Media Browser 2013</copyright>
 | 
					        <copyright>Copyright © Media Browser 2013</copyright>
 | 
				
			||||||
        <dependencies>
 | 
					        <dependencies>
 | 
				
			||||||
            <dependency id="MediaBrowser.Common" version="3.0.506" />
 | 
					            <dependency id="MediaBrowser.Common" version="3.0.507" />
 | 
				
			||||||
            <dependency id="NLog" version="3.1.0.0" />
 | 
					            <dependency id="NLog" version="3.1.0.0" />
 | 
				
			||||||
            <dependency id="SimpleInjector" version="2.6.1" />
 | 
					            <dependency id="SimpleInjector" version="2.6.1" />
 | 
				
			||||||
            <dependency id="sharpcompress" version="0.10.2" />
 | 
					            <dependency id="sharpcompress" version="0.10.2" />
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,7 @@
 | 
				
			|||||||
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
 | 
					<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
 | 
				
			||||||
    <metadata>
 | 
					    <metadata>
 | 
				
			||||||
        <id>MediaBrowser.Common</id>
 | 
					        <id>MediaBrowser.Common</id>
 | 
				
			||||||
        <version>3.0.506</version>
 | 
					        <version>3.0.507</version>
 | 
				
			||||||
        <title>MediaBrowser.Common</title>
 | 
					        <title>MediaBrowser.Common</title>
 | 
				
			||||||
        <authors>Media Browser Team</authors>
 | 
					        <authors>Media Browser Team</authors>
 | 
				
			||||||
        <owners>ebr,Luke,scottisafool</owners>
 | 
					        <owners>ebr,Luke,scottisafool</owners>
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,7 @@
 | 
				
			|||||||
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
 | 
					<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
 | 
				
			||||||
    <metadata>
 | 
					    <metadata>
 | 
				
			||||||
        <id>MediaBrowser.Model.Signed</id>
 | 
					        <id>MediaBrowser.Model.Signed</id>
 | 
				
			||||||
        <version>3.0.506</version>
 | 
					        <version>3.0.507</version>
 | 
				
			||||||
        <title>MediaBrowser.Model - Signed Edition</title>
 | 
					        <title>MediaBrowser.Model - Signed Edition</title>
 | 
				
			||||||
        <authors>Media Browser Team</authors>
 | 
					        <authors>Media Browser Team</authors>
 | 
				
			||||||
        <owners>ebr,Luke,scottisafool</owners>
 | 
					        <owners>ebr,Luke,scottisafool</owners>
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,7 @@
 | 
				
			|||||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
 | 
					<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
 | 
				
			||||||
    <metadata>
 | 
					    <metadata>
 | 
				
			||||||
        <id>MediaBrowser.Server.Core</id>
 | 
					        <id>MediaBrowser.Server.Core</id>
 | 
				
			||||||
        <version>3.0.506</version>
 | 
					        <version>3.0.507</version>
 | 
				
			||||||
        <title>Media Browser.Server.Core</title>
 | 
					        <title>Media Browser.Server.Core</title>
 | 
				
			||||||
        <authors>Media Browser Team</authors>
 | 
					        <authors>Media Browser Team</authors>
 | 
				
			||||||
        <owners>ebr,Luke,scottisafool</owners>
 | 
					        <owners>ebr,Luke,scottisafool</owners>
 | 
				
			||||||
@ -12,7 +12,7 @@
 | 
				
			|||||||
        <description>Contains core components required to build plugins for Media Browser Server.</description>
 | 
					        <description>Contains core components required to build plugins for Media Browser Server.</description>
 | 
				
			||||||
        <copyright>Copyright © Media Browser 2013</copyright>
 | 
					        <copyright>Copyright © Media Browser 2013</copyright>
 | 
				
			||||||
        <dependencies>
 | 
					        <dependencies>
 | 
				
			||||||
            <dependency id="MediaBrowser.Common" version="3.0.506" />
 | 
					            <dependency id="MediaBrowser.Common" version="3.0.507" />
 | 
				
			||||||
        </dependencies>
 | 
					        </dependencies>
 | 
				
			||||||
    </metadata>
 | 
					    </metadata>
 | 
				
			||||||
    <files>
 | 
					    <files>
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user