diff --git a/MediaBrowser.Api/ConfigurationService.cs b/MediaBrowser.Api/ConfigurationService.cs index ce6ca015de..f6edea86e2 100644 --- a/MediaBrowser.Api/ConfigurationService.cs +++ b/MediaBrowser.Api/ConfigurationService.cs @@ -124,7 +124,7 @@ namespace MediaBrowser.Api public void Post(AutoSetMetadataOptions request) { - _configurationManager.DisableMetadataService("Media Browser Xml"); + _configurationManager.DisableMetadataService("Media Browser Legacy Xml"); _configurationManager.SaveConfiguration(); } diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 9c8075bfb0..c716ee1506 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -995,7 +995,7 @@ namespace MediaBrowser.Api.Playback 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); - state.SegmentLength = 6; - var container = Path.GetExtension(state.RequestedUrl); if (string.IsNullOrEmpty(container)) diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs index b6423ed2fc..d26259a3ae 100644 --- a/MediaBrowser.Api/Playback/StreamState.cs +++ b/MediaBrowser.Api/Playback/StreamState.cs @@ -63,11 +63,14 @@ namespace MediaBrowser.Api.Playback public string LiveTvStreamId { get; set; } - public int SegmentLength = 10; + public int SegmentLength = 6; public int HlsListSize { - get { return ReadInputAtNativeFramerate ? 100 : 1440; } + get + { + return ReadInputAtNativeFramerate ? 1000 : 0; + } } public long? RunTimeTicks; diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs index c313966a5d..4b29f49d8d 100644 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ b/MediaBrowser.Controller/Entities/UserView.cs @@ -26,7 +26,7 @@ namespace MediaBrowser.Controller.Entities } return new UserViewBuilder(UserViewManager, LiveTvManager, ChannelManager, LibraryManager, Logger, UserDataManager, TVSeriesManager, CollectionManager) - .GetUserItems(parent, ViewType, query); + .GetUserItems(parent, this, ViewType, query); } public override IEnumerable GetChildren(User user, bool includeLinkedChildren) diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index cd579f7ad8..a76a284693 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -44,7 +44,7 @@ namespace MediaBrowser.Controller.Entities _collectionManager = collectionManager; } - public async Task> GetUserItems(Folder parent, string viewType, InternalItemsQuery query) + public async Task> GetUserItems(Folder queryParent, Folder displayParent, string viewType, InternalItemsQuery query) { var user = query.User; @@ -107,110 +107,125 @@ namespace MediaBrowser.Controller.Entities { var result = await GetLiveTvFolders(user).ConfigureAwait(false); - return GetResult(result, parent, query); + return GetResult(result, queryParent, query); } case CollectionType.Folders: - return GetResult(user.RootFolder.GetChildren(user, true), parent, query); + return GetResult(user.RootFolder.GetChildren(user, true), queryParent, query); case CollectionType.Games: - return await GetGameView(user, parent, query).ConfigureAwait(false); + return await GetGameView(user, queryParent, query).ConfigureAwait(false); case CollectionType.BoxSets: - return GetResult(GetMediaFolders(user).SelectMany(i => i.GetRecursiveChildren(user)).OfType(), parent, query); + return GetResult(GetMediaFolders(user).SelectMany(i => i.GetRecursiveChildren(user)).OfType(), queryParent, query); case CollectionType.TvShows: - return await GetTvView(parent, user, query).ConfigureAwait(false); + return await GetTvView(queryParent, user, query).ConfigureAwait(false); case CollectionType.Music: - return await GetMusicFolders(parent, user, query).ConfigureAwait(false); + return await GetMusicFolders(queryParent, user, query).ConfigureAwait(false); 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: - 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: - return GetGameSystems(parent, user, query); + return GetGameSystems(queryParent, user, query); case SpecialFolder.LatestGames: - return GetLatestGames(parent, user, query); + return GetLatestGames(queryParent, user, query); case SpecialFolder.RecentlyPlayedGames: - return GetRecentlyPlayedGames(parent, user, query); + return GetRecentlyPlayedGames(queryParent, user, query); case SpecialFolder.GameFavorites: - return GetFavoriteGames(parent, user, query); + return GetFavoriteGames(queryParent, user, query); case SpecialFolder.TvShowSeries: - return GetTvSeries(parent, user, query); + return GetTvSeries(queryParent, user, query); 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: - return GetTvResume(parent, user, query); + return GetTvResume(queryParent, user, query); case SpecialFolder.TvNextUp: - return GetTvNextUp(parent, query); + return GetTvNextUp(queryParent, query); case SpecialFolder.TvLatest: - return GetTvLatest(parent, user, query); + return GetTvLatest(queryParent, user, query); case SpecialFolder.MovieFavorites: - return GetFavoriteMovies(parent, user, query); + return GetFavoriteMovies(queryParent, user, query); case SpecialFolder.MovieLatest: - return GetMovieLatest(parent, user, query); + return GetMovieLatest(queryParent, user, query); 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: - return GetMovieResume(parent, user, query); + return GetMovieResume(queryParent, user, query); case SpecialFolder.MovieMovies: - return GetMovieMovies(parent, user, query); + return GetMovieMovies(queryParent, user, query); case SpecialFolder.MovieCollections: - return GetMovieCollections(parent, user, query); + return GetMovieCollections(queryParent, user, query); case SpecialFolder.MusicLatest: - return GetMusicLatest(parent, user, query); + return GetMusicLatest(queryParent, user, query); case SpecialFolder.MusicAlbums: - return GetMusicAlbums(parent, user, query); + return GetMusicAlbums(queryParent, user, query); case SpecialFolder.MusicAlbumArtists: - return GetMusicAlbumArtists(parent, user, query); + return GetMusicAlbumArtists(queryParent, user, query); case SpecialFolder.MusicArtists: - return GetMusicArtists(parent, user, query); + return GetMusicArtists(queryParent, user, query); case SpecialFolder.MusicSongs: - return GetMusicSongs(parent, user, query); + return GetMusicSongs(queryParent, user, query); case SpecialFolder.TvFavoriteEpisodes: - return GetFavoriteEpisodes(parent, user, query); + return GetFavoriteEpisodes(queryParent, user, query); case SpecialFolder.TvFavoriteSeries: - return GetFavoriteSeries(parent, user, query); + return GetFavoriteSeries(queryParent, user, query); case SpecialFolder.MusicFavorites: - return await GetMusicFavorites(parent, user, query).ConfigureAwait(false); + return await GetMusicFavorites(queryParent, user, query).ConfigureAwait(false); case SpecialFolder.MusicFavoriteAlbums: - return GetFavoriteAlbums(parent, user, query); + return GetFavoriteAlbums(queryParent, user, query); case SpecialFolder.MusicFavoriteArtists: - return GetFavoriteArtists(parent, user, query); + return GetFavoriteArtists(queryParent, user, query); case SpecialFolder.MusicFavoriteSongs: - return GetFavoriteSongs(parent, user, query); + return GetFavoriteSongs(queryParent, user, query); 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.MusicAlbums, user, "1", 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.MusicGenres, user, "5", 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.MusicFavorites, user, "6", parent).ConfigureAwait(false)); return GetResult(list, parent, query); @@ -250,6 +265,59 @@ namespace MediaBrowser.Controller.Entities return GetResult(list, parent, query); } + private async Task> 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> 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() + .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 GetMusicAlbumArtists(Folder parent, User user, InternalItemsQuery query) { 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.MovieCollections, user, "3", 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); } @@ -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); } - private QueryResult GetMovieGenres(Folder parent, User user, InternalItemsQuery query) + private async Task> 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) .SelectMany(i => i.Genres) .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); } + private async Task> 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> GetTvView(Folder parent, User user, InternalItemsQuery query) { 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.TvFavoriteSeries, user, "4", 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); } @@ -479,7 +559,7 @@ namespace MediaBrowser.Controller.Entities 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.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); } @@ -545,9 +625,9 @@ namespace MediaBrowser.Controller.Entities return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).OfType(), parent, query); } - private QueryResult GetTvGenres(Folder parent, User user, InternalItemsQuery query) + private async Task> 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() .SelectMany(i => i.Genres) .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); } + private async Task> 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 GetGameSystems(Folder parent, User user, InternalItemsQuery query) { return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }).OfType(), parent, query); } - private QueryResult GetGameGenres(Folder parent, User user, InternalItemsQuery query) + private async Task> 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() + .Where(i => i.Genres.Contains(displayParent.Name, StringComparer.OrdinalIgnoreCase)); + + return GetResult(items, queryParent, query); + } + + private async Task> GetGameGenres(Folder parent, User user, InternalItemsQuery query) + { + var tasks = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }) .OfType() .SelectMany(i => i.Genres) .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); } @@ -611,24 +715,24 @@ namespace MediaBrowser.Controller.Entities } private QueryResult GetResult(IEnumerable items, - BaseItem parentItem, + BaseItem queryParent, InternalItemsQuery query) where T : BaseItem { - return GetResult(items, parentItem, null, query); + return GetResult(items, queryParent, null, query); } private QueryResult GetResult(IEnumerable items, - BaseItem parentItem, + BaseItem queryParent, int? totalRecordLimit, InternalItemsQuery query) where T : BaseItem { - return SortAndFilter(items, parentItem, totalRecordLimit, query, _libraryManager, _userDataManager); + return SortAndFilter(items, queryParent, totalRecordLimit, query, _libraryManager, _userDataManager); } public static QueryResult SortAndFilter(IEnumerable items, - BaseItem parentItem, + BaseItem queryParent, int? totalRecordLimit, InternalItemsQuery query, ILibraryManager libraryManager, @@ -643,7 +747,7 @@ namespace MediaBrowser.Controller.Entities query.IsVirtualUnaired, query.IsUnaired); - items = CollapseBoxSetItemsIfNeeded(items, query, parentItem, user); + items = CollapseBoxSetItemsIfNeeded(items, query, queryParent, user); // This must be the last filter if (!string.IsNullOrEmpty(query.AdjacentTo)) @@ -656,10 +760,10 @@ namespace MediaBrowser.Controller.Entities public static IEnumerable CollapseBoxSetItemsIfNeeded(IEnumerable items, InternalItemsQuery query, - BaseItem parentItem, + BaseItem queryParent, User user) { - if (CollapseBoxSetItems(query, parentItem, user)) + if (CollapseBoxSetItems(query, queryParent, user)) { items = BaseItem.CollectionManager.CollapseItemsWithinBoxSets(items, user); } @@ -691,11 +795,11 @@ namespace MediaBrowser.Controller.Entities } private static bool CollapseBoxSetItems(InternalItemsQuery query, - BaseItem parentItem, + BaseItem queryParent, User user) { // Could end up stuck in a loop like this - if (parentItem is BoxSet) + if (queryParent is BoxSet) { return false; } @@ -1488,7 +1592,7 @@ namespace MediaBrowser.Controller.Entities }); } - private IEnumerable GetMediaFolders(Folder parent, User user, string[] viewTypes) + private IEnumerable GetMediaFolders(Folder parent, User user, IEnumerable viewTypes) { if (parent == null || parent is UserView) { @@ -1498,7 +1602,7 @@ namespace MediaBrowser.Controller.Entities return new[] { parent }; } - private IEnumerable GetRecursiveChildren(Folder parent, User user, string[] viewTypes) + private IEnumerable GetRecursiveChildren(Folder parent, User user, IEnumerable viewTypes) { if (parent == null || parent is UserView) { @@ -1521,7 +1625,15 @@ namespace MediaBrowser.Controller.Entities return list; } - private async Task GetUserView(string type, User user, string sortName, Folder parent) + private async Task 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 GetUserView(string type, User user, string sortName, BaseItem parent) { var view = await _userViewManager.GetUserView(parent.Id.ToString("N"), type, user, sortName, CancellationToken.None) .ConfigureAwait(false); diff --git a/MediaBrowser.Controller/Library/IUserViewManager.cs b/MediaBrowser.Controller/Library/IUserViewManager.cs index 12dc9c0b2e..727ccd00a6 100644 --- a/MediaBrowser.Controller/Library/IUserViewManager.cs +++ b/MediaBrowser.Controller/Library/IUserViewManager.cs @@ -10,6 +10,9 @@ namespace MediaBrowser.Controller.Library { Task> GetUserViews(UserViewQuery query, CancellationToken cancellationToken); + Task GetUserView(string name, string parentId, string type, User user, string sortName, + CancellationToken cancellationToken); + Task GetUserView(string type, string sortName, CancellationToken cancellationToken); Task GetUserView(string category, string type, User user, string sortName, CancellationToken cancellationToken); diff --git a/MediaBrowser.LocalMetadata/BaseXmlProvider.cs b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs index 5eb067dcd2..6f8047e4ce 100644 --- a/MediaBrowser.LocalMetadata/BaseXmlProvider.cs +++ b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs @@ -78,13 +78,22 @@ namespace MediaBrowser.LocalMetadata { get { - return "Media Browser Xml"; + return XmlProviderUtils.Name; } } + } static class XmlProviderUtils { + public static string Name + { + get + { + return "Media Browser Legacy Xml"; + } + } + internal static readonly SemaphoreSlim XmlParsingResourcePool = new SemaphoreSlim(4, 4); } } diff --git a/MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs index 8cbe69551b..f041756548 100644 --- a/MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs @@ -15,7 +15,7 @@ namespace MediaBrowser.LocalMetadata.Savers { get { - return "Media Browser Xml"; + return XmlProviderUtils.Name; } } diff --git a/MediaBrowser.LocalMetadata/Savers/ChannelXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/ChannelXmlSaver.cs index b111f6d157..03fdf2bc80 100644 --- a/MediaBrowser.LocalMetadata/Savers/ChannelXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/ChannelXmlSaver.cs @@ -41,7 +41,7 @@ namespace MediaBrowser.LocalMetadata.Savers { get { - return "Media Browser Xml"; + return XmlProviderUtils.Name; } } diff --git a/MediaBrowser.LocalMetadata/Savers/EpisodeXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/EpisodeXmlSaver.cs index 06c13eb8bd..673d8bc419 100644 --- a/MediaBrowser.LocalMetadata/Savers/EpisodeXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/EpisodeXmlSaver.cs @@ -45,7 +45,7 @@ namespace MediaBrowser.LocalMetadata.Savers { get { - return "Media Browser Xml"; + return XmlProviderUtils.Name; } } diff --git a/MediaBrowser.LocalMetadata/Savers/FolderXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/FolderXmlSaver.cs index 7efa55420d..fa3d7d87db 100644 --- a/MediaBrowser.LocalMetadata/Savers/FolderXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/FolderXmlSaver.cs @@ -18,7 +18,7 @@ namespace MediaBrowser.LocalMetadata.Savers { get { - return "Media Browser Xml"; + return XmlProviderUtils.Name; } } diff --git a/MediaBrowser.LocalMetadata/Savers/GameSystemXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/GameSystemXmlSaver.cs index e1fc3b8cc7..ebb401f545 100644 --- a/MediaBrowser.LocalMetadata/Savers/GameSystemXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/GameSystemXmlSaver.cs @@ -15,7 +15,7 @@ namespace MediaBrowser.LocalMetadata.Savers { get { - return "Media Browser Xml"; + return XmlProviderUtils.Name; } } diff --git a/MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs index 11f6db77c6..108c6a9e2c 100644 --- a/MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs @@ -20,7 +20,7 @@ namespace MediaBrowser.LocalMetadata.Savers { get { - return "Media Browser Xml"; + return XmlProviderUtils.Name; } } diff --git a/MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs index 84d41c8e2f..6fe9f88f04 100644 --- a/MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs @@ -30,7 +30,7 @@ namespace MediaBrowser.LocalMetadata.Savers { get { - return "Media Browser Xml"; + return XmlProviderUtils.Name; } } diff --git a/MediaBrowser.LocalMetadata/Savers/PersonXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/PersonXmlSaver.cs index 835256ca74..9c6fb39bd2 100644 --- a/MediaBrowser.LocalMetadata/Savers/PersonXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/PersonXmlSaver.cs @@ -18,7 +18,7 @@ namespace MediaBrowser.LocalMetadata.Savers { get { - return "Media Browser Xml"; + return XmlProviderUtils.Name; } } diff --git a/MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs index 169f0b6ee0..16c4373815 100644 --- a/MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs @@ -16,7 +16,7 @@ namespace MediaBrowser.LocalMetadata.Savers { get { - return "Media Browser Xml"; + return XmlProviderUtils.Name; } } diff --git a/MediaBrowser.LocalMetadata/Savers/SeasonXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/SeasonXmlSaver.cs index 610652c6b6..a112f22fa9 100644 --- a/MediaBrowser.LocalMetadata/Savers/SeasonXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/SeasonXmlSaver.cs @@ -17,7 +17,7 @@ namespace MediaBrowser.LocalMetadata.Savers { get { - return "Media Browser Xml"; + return XmlProviderUtils.Name; } } diff --git a/MediaBrowser.LocalMetadata/Savers/SeriesXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/SeriesXmlSaver.cs index 885dccdb65..c94770bdbf 100644 --- a/MediaBrowser.LocalMetadata/Savers/SeriesXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/SeriesXmlSaver.cs @@ -25,7 +25,7 @@ namespace MediaBrowser.LocalMetadata.Savers { get { - return "Media Browser Xml"; + return XmlProviderUtils.Name; } } diff --git a/MediaBrowser.Model/ApiClient/IApiClient.cs b/MediaBrowser.Model/ApiClient/IApiClient.cs index 89c7312238..114dd30953 100644 --- a/MediaBrowser.Model/ApiClient/IApiClient.cs +++ b/MediaBrowser.Model/ApiClient/IApiClient.cs @@ -121,6 +121,16 @@ namespace MediaBrowser.Model.ApiClient /// Task{SearchHintResult}. Task GetSearchHintsAsync(SearchQuery query); + /// + /// Gets the filters. + /// + /// The user identifier. + /// The parent identifier. + /// The media types. + /// The item types. + /// Task<QueryFilters>. + Task GetFilters(string userId, string parentId, string[] mediaTypes, string[] itemTypes); + /// /// Gets the theme videos async. /// diff --git a/MediaBrowser.Model/ApiClient/IConnectionManager.cs b/MediaBrowser.Model/ApiClient/IConnectionManager.cs index f234bb714d..bf7ef71854 100644 --- a/MediaBrowser.Model/ApiClient/IConnectionManager.cs +++ b/MediaBrowser.Model/ApiClient/IConnectionManager.cs @@ -60,6 +60,14 @@ namespace MediaBrowser.Model.ApiClient /// The cancellation token. /// Task<ConnectionResult>. Task Connect(CancellationToken cancellationToken); + + /// + /// Connects the specified API client. + /// + /// The API client. + /// The cancellation token. + /// Task<ConnectionResult>. + Task Connect(IApiClient apiClient, CancellationToken cancellationToken); /// /// Connects the specified server. diff --git a/MediaBrowser.Model/Entities/CollectionType.cs b/MediaBrowser.Model/Entities/CollectionType.cs index 9cd7999b0b..a4413f67aa 100644 --- a/MediaBrowser.Model/Entities/CollectionType.cs +++ b/MediaBrowser.Model/Entities/CollectionType.cs @@ -35,6 +35,7 @@ public const string TvShowSeries = "TvShowSeries"; public const string TvGenres = "TvGenres"; + public const string TvGenre = "TvGenre"; public const string TvLatest = "TvLatest"; public const string TvNextUp = "TvNextUp"; public const string TvResume = "TvResume"; @@ -47,17 +48,20 @@ public const string MovieCollections = "MovieCollections"; public const string MovieFavorites = "MovieFavorites"; public const string MovieGenres = "MovieGenres"; + public const string MovieGenre = "MovieGenre"; public const string LatestGames = "LatestGames"; public const string RecentlyPlayedGames = "RecentlyPlayedGames"; public const string GameSystems = "GameSystems"; public const string GameGenres = "GameGenres"; public const string GameFavorites = "GameFavorites"; + public const string GameGenre = "GameGenre"; public const string MusicArtists = "MusicArtists"; public const string MusicAlbumArtists = "MusicAlbumArtists"; public const string MusicAlbums = "MusicAlbums"; public const string MusicGenres = "MusicGenres"; + public const string MusicGenre = "MusicGenre"; public const string MusicLatest = "MusicLatest"; public const string MusicSongs = "MusicSongs"; public const string MusicFavorites = "MusicFavorites"; diff --git a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs index d2d435414c..46c32cc562 100644 --- a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs @@ -148,11 +148,16 @@ namespace MediaBrowser.Server.Implementations.Library .ThenBy(i => i.SortName); } + public Task GetUserView(string name, string parentId, string type, User user, string sortName, CancellationToken cancellationToken) + { + return _libraryManager.GetSpecialFolder(user, name, parentId, type, sortName, cancellationToken); + } + public Task GetUserView(string parentId, string type, User user, string sortName, CancellationToken cancellationToken) { 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 GetUserView(string type, string sortName, CancellationToken cancellationToken) diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json index a484cbbb87..21658f3ff6 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json @@ -288,7 +288,7 @@ "LabelPremiereProgram": "PREMIERE", "LabelHDProgram": "HD", "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", "MessagePleaseRestart": "Please restart to finish updating.", "ButtonRestart": "Restart", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index 1d52a42ae5..a1591156ca 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -145,9 +145,11 @@ "OptionBudget": "Budget", "OptionRevenue": "Revenue", "OptionPoster": "Poster", + "OptionPosterCard": "Poster card", "OptionBackdrop": "Backdrop", "OptionTimeline": "Timeline", "OptionThumb": "Thumb", + "OptionThumbCard": "Thumb card", "OptionBanner": "Banner", "OptionCriticRating": "Critic Rating", "OptionVideoBitrate": "Video Bitrate", @@ -455,7 +457,7 @@ "LinkApiDocumentation": "Api Documentation", "LabelFriendlyServerName": "Friendly server name:", "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.", "LabelReadHowYouCanContribute": "Read about how you can contribute.", "HeaderNewCollection": "New Collection", @@ -847,6 +849,8 @@ "ViewTypeTvShows": "TV", "ViewTypeGames": "Games", "ViewTypeMusic": "Music", + "ViewTypeMusicGenres": "Genres", + "ViewTypeMusicArtists": "Artists", "ViewTypeBoxSets": "Collections", "ViewTypeChannels": "Channels", "ViewTypeLiveTV": "Live TV", diff --git a/MediaBrowser.Server.Implementations/Music/MusicDynamicImageProvider.cs b/MediaBrowser.Server.Implementations/Music/MusicDynamicImageProvider.cs index 8463575297..a26e3819e2 100644 --- a/MediaBrowser.Server.Implementations/Music/MusicDynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Music/MusicDynamicImageProvider.cs @@ -1,5 +1,6 @@ using MediaBrowser.Common.IO; using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; @@ -8,6 +9,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using MoreLinq; namespace MediaBrowser.Server.Implementations.Music { @@ -36,7 +38,42 @@ namespace MediaBrowser.Server.Implementations.Music }).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) @@ -50,6 +87,7 @@ namespace MediaBrowser.Server.Implementations.Music SpecialFolder.TvFavoriteEpisodes, SpecialFolder.TvFavoriteSeries, SpecialFolder.TvGenres, + SpecialFolder.TvGenre, SpecialFolder.TvLatest, SpecialFolder.TvNextUp, SpecialFolder.TvResume, @@ -58,12 +96,14 @@ namespace MediaBrowser.Server.Implementations.Music SpecialFolder.MovieCollections, SpecialFolder.MovieFavorites, SpecialFolder.MovieGenres, + SpecialFolder.MovieGenre, SpecialFolder.MovieLatest, SpecialFolder.MovieMovies, SpecialFolder.MovieResume, SpecialFolder.GameFavorites, SpecialFolder.GameGenres, + SpecialFolder.GameGenre, SpecialFolder.GameSystems, SpecialFolder.LatestGames, SpecialFolder.RecentlyPlayedGames, @@ -72,6 +112,7 @@ namespace MediaBrowser.Server.Implementations.Music SpecialFolder.MusicAlbumArtists, SpecialFolder.MusicAlbums, SpecialFolder.MusicGenres, + SpecialFolder.MusicGenre, SpecialFolder.MusicLatest, SpecialFolder.MusicSongs, SpecialFolder.MusicFavorites, diff --git a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj index a0c8336f31..6aed66744c 100644 --- a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj +++ b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj @@ -173,6 +173,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/MediaBrowser.Server.Mono/mediabrowser.sh b/MediaBrowser.Server.Mono/mediabrowser.sh new file mode 100644 index 0000000000..45884de3e0 --- /dev/null +++ b/MediaBrowser.Server.Mono/mediabrowser.sh @@ -0,0 +1,2 @@ +#!/bin/sh +mono MediaBrowser.Server.Mono.exe \ No newline at end of file diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index c321b4c09b..d8358909e9 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -82,6 +82,7 @@ using MediaBrowser.Server.Implementations.Sync; using MediaBrowser.Server.Implementations.Themes; using MediaBrowser.Server.Implementations.TV; using MediaBrowser.Server.Startup.Common.FFMpeg; +using MediaBrowser.Server.Startup.Common.Migrations; using MediaBrowser.WebDashboard.Api; using MediaBrowser.XbmcMetadata.Providers; using System; @@ -322,84 +323,10 @@ namespace MediaBrowser.Server.Startup.Common private void PerformVersionMigration() { - DeleteDeprecatedModules(); - - if (!ServerConfigurationManager.Configuration.PlaylistImagesDeleted) - { - 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); - } + new MigrateUserFolders(ApplicationPaths).Run(); + new PlaylistImages(ServerConfigurationManager).Run(); + new RenameXbmcOptions(ServerConfigurationManager).Run(); + new RenameXmlOptions(ServerConfigurationManager).Run(); } /// diff --git a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj index 3f04694b95..da0e896e65 100644 --- a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj +++ b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj @@ -60,6 +60,11 @@ + + + + + diff --git a/MediaBrowser.Server.Startup.Common/Migrations/IVersionMigration.cs b/MediaBrowser.Server.Startup.Common/Migrations/IVersionMigration.cs new file mode 100644 index 0000000000..a6a8c1a356 --- /dev/null +++ b/MediaBrowser.Server.Startup.Common/Migrations/IVersionMigration.cs @@ -0,0 +1,8 @@ + +namespace MediaBrowser.Server.Startup.Common.Migrations +{ + public interface IVersionMigration + { + void Run(); + } +} diff --git a/MediaBrowser.Server.Startup.Common/Migrations/MigrateUserFolders.cs b/MediaBrowser.Server.Startup.Common/Migrations/MigrateUserFolders.cs new file mode 100644 index 0000000000..5e3df5701e --- /dev/null +++ b/MediaBrowser.Server.Startup.Common/Migrations/MigrateUserFolders.cs @@ -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) + { + } + } + } +} diff --git a/MediaBrowser.Server.Startup.Common/Migrations/PlaylistImages.cs b/MediaBrowser.Server.Startup.Common/Migrations/PlaylistImages.cs new file mode 100644 index 0000000000..f6ddf58476 --- /dev/null +++ b/MediaBrowser.Server.Startup.Common/Migrations/PlaylistImages.cs @@ -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) + { + + } + } + } +} diff --git a/MediaBrowser.Server.Startup.Common/Migrations/RenameXbmcOptions.cs b/MediaBrowser.Server.Startup.Common/Migrations/RenameXbmcOptions.cs new file mode 100644 index 0000000000..efc34c1d89 --- /dev/null +++ b/MediaBrowser.Server.Startup.Common/Migrations/RenameXbmcOptions.cs @@ -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; + } + } +} diff --git a/MediaBrowser.Server.Startup.Common/Migrations/RenameXmlOptions.cs b/MediaBrowser.Server.Startup.Common/Migrations/RenameXmlOptions.cs new file mode 100644 index 0000000000..3034fad31b --- /dev/null +++ b/MediaBrowser.Server.Startup.Common/Migrations/RenameXmlOptions.cs @@ -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; + } + } +} diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index 8b73107bf3..b5c4bef903 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -69,6 +69,11 @@ namespace MediaBrowser.XbmcMetadata.Parsers Fetch(item, userDataList, metadataFile, settings, cancellationToken); } + protected virtual bool SupportsUrlAfterClosingXmlTag + { + get { return false; } + } + /// /// Fetches the specified item. /// @@ -79,6 +84,30 @@ namespace MediaBrowser.XbmcMetadata.Parsers /// The cancellation token. private void Fetch(T item, List 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)) { // Need to handle a url after the xml data diff --git a/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs index 7cf987f9c6..2a275320ff 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs @@ -28,6 +28,14 @@ namespace MediaBrowser.XbmcMetadata.Parsers Fetch(item, userDataList, metadataFile, cancellationToken); } + protected override bool SupportsUrlAfterClosingXmlTag + { + get + { + return true; + } + } + /// /// Fetches the data from XML node. /// diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs index 73358cb21c..86e92530f1 100644 --- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs @@ -131,7 +131,7 @@ namespace MediaBrowser.XbmcMetadata.Savers { get { - return "Xbmc Nfo"; + return "Nfo"; } } diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index 4b95fcf598..dd529093f5 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common.Internal - 3.0.506 + 3.0.507 MediaBrowser.Common.Internal Luke ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption. Copyright © Media Browser 2013 - + diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index a5dfc58508..dac65b65b2 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.506 + 3.0.507 MediaBrowser.Common Media Browser Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Model.Signed.nuspec b/Nuget/MediaBrowser.Model.Signed.nuspec index 4b74621512..6517c99a05 100644 --- a/Nuget/MediaBrowser.Model.Signed.nuspec +++ b/Nuget/MediaBrowser.Model.Signed.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Model.Signed - 3.0.506 + 3.0.507 MediaBrowser.Model - Signed Edition Media Browser Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index a5e6f216c6..0d017c293f 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.506 + 3.0.507 Media Browser.Server.Core Media Browser Team ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains core components required to build plugins for Media Browser Server. Copyright © Media Browser 2013 - +