diff --git a/Emby.Drawing/GDI/GDIImageEncoder.cs b/Emby.Drawing/GDI/GDIImageEncoder.cs index 5306137411..11c9eb8e91 100644 --- a/Emby.Drawing/GDI/GDIImageEncoder.cs +++ b/Emby.Drawing/GDI/GDIImageEncoder.cs @@ -89,7 +89,7 @@ namespace Emby.Drawing.GDI } } - public void EncodeImage(string inputPath, string cacheFilePath, int width, int height, int quality, ImageProcessingOptions options) + public void EncodeImage(string inputPath, string cacheFilePath, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) { var hasPostProcessing = !string.IsNullOrEmpty(options.BackgroundColor) || options.UnplayedCount.HasValue || options.AddPlayedIndicator || options.PercentPlayed > 0; @@ -98,8 +98,6 @@ namespace Emby.Drawing.GDI var newWidth = Convert.ToInt32(width); var newHeight = Convert.ToInt32(height); - var selectedOutputFormat = options.OutputFormat; - // Graphics.FromImage will throw an exception if the PixelFormat is Indexed, so we need to handle that here // Also, Webp only supports Format32bppArgb and Format32bppRgb var pixelFormat = selectedOutputFormat == ImageFormat.Webp diff --git a/Emby.Drawing/IImageEncoder.cs b/Emby.Drawing/IImageEncoder.cs index 4469075a6d..bfd382bb7c 100644 --- a/Emby.Drawing/IImageEncoder.cs +++ b/Emby.Drawing/IImageEncoder.cs @@ -31,7 +31,8 @@ namespace Emby.Drawing /// The height. /// The quality. /// The options. - void EncodeImage(string inputPath, string outputPath, int width, int height, int quality, ImageProcessingOptions options); + /// The output format. + void EncodeImage(string inputPath, string outputPath, int width, int height, int quality, ImageProcessingOptions options, ImageFormat outputFormat); /// /// Creates the image collage. diff --git a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs index d097c8da3e..d18ee1caab 100644 --- a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs +++ b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs @@ -134,7 +134,7 @@ namespace Emby.Drawing.ImageMagick string.Equals(ext, ".webp", StringComparison.OrdinalIgnoreCase); } - public void EncodeImage(string inputPath, string outputPath, int width, int height, int quality, ImageProcessingOptions options) + public void EncodeImage(string inputPath, string outputPath, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) { // Even if the caller specified 100, don't use it because it takes forever quality = Math.Min(quality, 99); diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index a24987c057..902ade448f 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -19,6 +19,7 @@ using System.Threading.Tasks; using CommonIO; using Emby.Drawing.Common; using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Net; namespace Emby.Drawing { @@ -152,7 +153,7 @@ namespace Emby.Drawing { var file = await ProcessImage(options).ConfigureAwait(false); - using (var fileStream = _fileSystem.GetFileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read, true)) + using (var fileStream = _fileSystem.GetFileStream(file.Item1, FileMode.Open, FileAccess.Read, FileShare.Read, true)) { await fileStream.CopyToAsync(toStream).ConfigureAwait(false); } @@ -163,7 +164,7 @@ namespace Emby.Drawing return _imageEncoder.SupportedOutputFormats; } - public async Task ProcessImage(ImageProcessingOptions options) + public async Task> ProcessImage(ImageProcessingOptions options) { if (options == null) { @@ -181,13 +182,7 @@ namespace Emby.Drawing if (!_imageEncoder.SupportsImageEncoding) { - return originalImagePath; - } - - if (options.HasDefaultOptions(originalImagePath) && options.Enhancers.Count == 0 && !options.CropWhiteSpace) - { - // Just spit out the original file if all the options are default - return originalImagePath; + return new Tuple(originalImagePath, MimeTypes.GetMimeType(originalImagePath)); } var dateModified = originalImage.DateModified; @@ -214,19 +209,31 @@ namespace Emby.Drawing dateModified = tuple.Item2; } - var newSizeInfo = GetNewImageSize(originalImagePath, dateModified, options); - var newSize = newSizeInfo.Item1; - var isSizeChanged = newSizeInfo.Item2; + if (options.HasDefaultOptions(originalImagePath)) + { + // Just spit out the original file if all the options are default + return new Tuple(originalImagePath, MimeTypes.GetMimeType(originalImagePath)); + } - if (options.HasDefaultOptionsWithoutSize(originalImagePath) && !isSizeChanged && options.Enhancers.Count == 0) + ImageSize? originalImageSize; + try { - // Just spit out the original file if the new size equals the old - return originalImagePath; + originalImageSize = GetImageSize(originalImagePath, dateModified, true); + if (options.HasDefaultOptions(originalImagePath, originalImageSize.Value)) + { + // Just spit out the original file if all the options are default + return new Tuple(originalImagePath, MimeTypes.GetMimeType(originalImagePath)); + } + } + catch + { + originalImageSize = null; } + var newSize = GetNewImageSize(options, originalImageSize); var quality = options.Quality; - var outputFormat = GetOutputFormat(options.OutputFormat); + var outputFormat = GetOutputFormat(options.SupportedOutputFormats[0]); var cacheFilePath = GetCacheFilePath(originalImagePath, newSize, quality, dateModified, outputFormat, options.AddPlayedIndicator, options.PercentPlayed, options.UnplayedCount, options.BackgroundColor); var semaphore = GetLock(cacheFilePath); @@ -250,7 +257,7 @@ namespace Emby.Drawing imageProcessingLockTaken = true; - _imageEncoder.EncodeImage(originalImagePath, cacheFilePath, newWidth, newHeight, quality, options); + _imageEncoder.EncodeImage(originalImagePath, cacheFilePath, newWidth, newHeight, quality, options, outputFormat); } } finally @@ -263,27 +270,48 @@ namespace Emby.Drawing semaphore.Release(); } - return cacheFilePath; + return new Tuple(cacheFilePath, GetMimeType(outputFormat, cacheFilePath)); } - private Tuple GetNewImageSize(string originalImagePath, DateTime dateModified, ImageProcessingOptions options) + private string GetMimeType(ImageFormat format, string path) { - try + if (format == ImageFormat.Bmp) + { + return MimeTypes.GetMimeType("i.bmp"); + } + if (format == ImageFormat.Gif) + { + return MimeTypes.GetMimeType("i.gif"); + } + if (format == ImageFormat.Jpg) + { + return MimeTypes.GetMimeType("i.jpg"); + } + if (format == ImageFormat.Png) + { + return MimeTypes.GetMimeType("i.png"); + } + if (format == ImageFormat.Webp) { - var originalImageSize = GetImageSize(originalImagePath, dateModified, true); + return MimeTypes.GetMimeType("i.webp"); + } - // Determine the output size based on incoming parameters - var newSize = DrawingUtils.Resize(originalImageSize, options.Width, options.Height, options.MaxWidth, options.MaxHeight); + return MimeTypes.GetMimeType(path); + } - return new Tuple(newSize, !newSize.Equals(originalImageSize)); - } - catch + private ImageSize GetNewImageSize(ImageProcessingOptions options, ImageSize? originalImageSize) + { + if (originalImageSize.HasValue) { - return new Tuple(GetSizeEstimage(options), true); + // Determine the output size based on incoming parameters + var newSize = DrawingUtils.Resize(originalImageSize.Value, options.Width, options.Height, options.MaxWidth, options.MaxHeight); + + return newSize; } + return GetSizeEstimate(options); } - private ImageSize GetSizeEstimage(ImageProcessingOptions options) + private ImageSize GetSizeEstimate(ImageProcessingOptions options) { if (options.Width.HasValue && options.Height.HasValue) { diff --git a/Emby.Drawing/NullImageEncoder.cs b/Emby.Drawing/NullImageEncoder.cs index 30ea363290..1638a675ac 100644 --- a/Emby.Drawing/NullImageEncoder.cs +++ b/Emby.Drawing/NullImageEncoder.cs @@ -32,7 +32,7 @@ namespace Emby.Drawing throw new NotImplementedException(); } - public void EncodeImage(string inputPath, string outputPath, int width, int height, int quality, ImageProcessingOptions options) + public void EncodeImage(string inputPath, string outputPath, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) { throw new NotImplementedException(); } diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs index 8114f9f228..e2354a54b5 100644 --- a/MediaBrowser.Api/Images/ImageService.cs +++ b/MediaBrowser.Api/Images/ImageService.cs @@ -571,8 +571,7 @@ namespace MediaBrowser.Api.Images cropwhitespace = request.CropWhitespace.Value; } - var format = GetOutputFormat(request, imageInfo, cropwhitespace, supportedImageEnhancers); - var contentType = GetMimeType(format, imageInfo.Path); + var outputFormats = GetOutputFormats(request, imageInfo, cropwhitespace, supportedImageEnhancers); var cacheGuid = new Guid(_imageProcessor.GetImageCacheTag(item, imageInfo, supportedImageEnhancers)); @@ -593,9 +592,8 @@ namespace MediaBrowser.Api.Images request, imageInfo, cropwhitespace, - format, + outputFormats, supportedImageEnhancers, - contentType, cacheDuration, responseHeaders, isHeadRequest) @@ -606,9 +604,8 @@ namespace MediaBrowser.Api.Images ImageRequest request, ItemImageInfo image, bool cropwhitespace, - ImageFormat format, + List supportedFormats, List enhancers, - string contentType, TimeSpan? cacheDuration, IDictionary headers, bool isHeadRequest) @@ -629,10 +626,10 @@ namespace MediaBrowser.Api.Images PercentPlayed = request.PercentPlayed ?? 0, UnplayedCount = request.UnplayedCount, BackgroundColor = request.BackgroundColor, - OutputFormat = format + SupportedOutputFormats = supportedFormats }; - var file = await _imageProcessor.ProcessImage(options).ConfigureAwait(false); + var imageResult = await _imageProcessor.ProcessImage(options).ConfigureAwait(false); headers["Vary"] = "Accept"; @@ -640,20 +637,20 @@ namespace MediaBrowser.Api.Images { CacheDuration = cacheDuration, ResponseHeaders = headers, - ContentType = contentType, + ContentType = imageResult.Item2, IsHeadRequest = isHeadRequest, - Path = file + Path = imageResult.Item1 }); } - private ImageFormat GetOutputFormat(ImageRequest request, ItemImageInfo image, bool cropwhitespace, List enhancers) + private List GetOutputFormats(ImageRequest request, ItemImageInfo image, bool cropwhitespace, List enhancers) { if (!string.IsNullOrWhiteSpace(request.Format)) { ImageFormat format; if (Enum.TryParse(request.Format, true, out format)) { - return format; + return new List { format }; } } @@ -671,39 +668,30 @@ namespace MediaBrowser.Api.Images } var clientSupportedFormats = GetClientSupportedFormats(); - if (inputFormat.HasValue && clientSupportedFormats.Contains(inputFormat.Value) && enhancers.Count == 0) - { - if ((request.Quality ?? 100) == 100 && !request.Height.HasValue && !request.Width.HasValue && - !request.AddPlayedIndicator && !request.PercentPlayed.HasValue && !request.UnplayedCount.HasValue && string.IsNullOrWhiteSpace(request.BackgroundColor)) - { - // TODO: Allow this when specfying max width/height if the value is in range - if (!cropwhitespace && !request.MaxHeight.HasValue && !request.MaxWidth.HasValue) - { - return inputFormat.Value; - } - } - } var serverFormats = _imageProcessor.GetSupportedImageOutputFormats(); + var outputFormats = new List(); // Client doesn't care about format, so start with webp if supported if (serverFormats.Contains(ImageFormat.Webp) && clientSupportedFormats.Contains(ImageFormat.Webp)) { - return ImageFormat.Webp; + outputFormats.Add(ImageFormat.Webp); } if (enhancers.Count > 0) { - return ImageFormat.Png; + outputFormats.Add(ImageFormat.Png); } if (inputFormat.HasValue && inputFormat.Value == ImageFormat.Jpg) { - return ImageFormat.Jpg; + outputFormats.Add(ImageFormat.Jpg); } // We can't predict if there will be transparency or not, so play it safe - return ImageFormat.Png; + outputFormats.Add(ImageFormat.Png); + + return outputFormats; } private ImageFormat[] GetClientSupportedFormats() @@ -730,32 +718,6 @@ namespace MediaBrowser.Api.Images return new[] { ImageFormat.Jpg, ImageFormat.Png }; } - private string GetMimeType(ImageFormat format, string path) - { - if (format == ImageFormat.Bmp) - { - return MimeTypes.GetMimeType("i.bmp"); - } - if (format == ImageFormat.Gif) - { - return MimeTypes.GetMimeType("i.gif"); - } - if (format == ImageFormat.Jpg) - { - return MimeTypes.GetMimeType("i.jpg"); - } - if (format == ImageFormat.Png) - { - return MimeTypes.GetMimeType("i.png"); - } - if (format == ImageFormat.Webp) - { - return MimeTypes.GetMimeType("i.webp"); - } - - return MimeTypes.GetMimeType(path); - } - /// /// Gets the image path. /// diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs index e1e98857ff..058bf70cd3 100644 --- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs +++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller.Entities; +using System; +using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Entities; @@ -83,7 +84,7 @@ namespace MediaBrowser.Controller.Drawing /// /// The options. /// Task. - Task ProcessImage(ImageProcessingOptions options); + Task> ProcessImage(ImageProcessingOptions options); /// /// Gets the enhanced image. diff --git a/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs b/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs index e6bf86853a..2b80b701e0 100644 --- a/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs +++ b/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs @@ -4,6 +4,7 @@ using MediaBrowser.Model.Drawing; using System; using System.Collections.Generic; using System.IO; +using System.Linq; namespace MediaBrowser.Controller.Drawing { @@ -29,7 +30,7 @@ namespace MediaBrowser.Controller.Drawing public List Enhancers { get; set; } - public ImageFormat OutputFormat { get; set; } + public List SupportedOutputFormats { get; set; } public bool AddPlayedIndicator { get; set; } @@ -48,19 +49,47 @@ namespace MediaBrowser.Controller.Drawing !MaxHeight.HasValue; } + public bool HasDefaultOptions(string originalImagePath, ImageSize size) + { + if (!HasDefaultOptionsWithoutSize(originalImagePath)) + { + return false; + } + + if (Width.HasValue && !size.Width.Equals(Width.Value)) + { + return false; + } + if (Height.HasValue && !size.Height.Equals(Height.Value)) + { + return false; + } + if (MaxWidth.HasValue && size.Width > MaxWidth.Value) + { + return false; + } + if (MaxHeight.HasValue && size.Height > MaxHeight.Value) + { + return false; + } + + return true; + } + public bool HasDefaultOptionsWithoutSize(string originalImagePath) { - return (Quality == 100) && - IsOutputFormatDefault(originalImagePath) && + return (Quality >= 90) && + IsFormatSupported(originalImagePath) && !AddPlayedIndicator && PercentPlayed.Equals(0) && !UnplayedCount.HasValue && string.IsNullOrEmpty(BackgroundColor); } - private bool IsOutputFormatDefault(string originalImagePath) + private bool IsFormatSupported(string originalImagePath) { - return string.Equals(Path.GetExtension(originalImagePath), "." + OutputFormat, StringComparison.OrdinalIgnoreCase); + var ext = Path.GetExtension(originalImagePath); + return SupportedOutputFormats.Any(outputFormat => string.Equals(ext, "." + outputFormat, StringComparison.OrdinalIgnoreCase)); } } } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 5b0af42e89..d9b7b1ae7e 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -690,9 +690,10 @@ namespace MediaBrowser.Controller.Entities [IgnoreDataMember] public int? ParentIndexNumber { get; set; } - public virtual string GetOfficialRatingForComparison(bool inherit) + [IgnoreDataMember] + public string OfficialRatingForComparison { - if (inherit) + get { if (!string.IsNullOrWhiteSpace(OfficialRating)) { @@ -702,13 +703,11 @@ namespace MediaBrowser.Controller.Entities var parent = DisplayParent; if (parent != null) { - return parent.GetOfficialRatingForComparison(inherit); + return parent.OfficialRatingForComparison; } return null; } - - return OfficialRating; } [IgnoreDataMember] @@ -1141,7 +1140,7 @@ namespace MediaBrowser.Controller.Entities if (string.IsNullOrWhiteSpace(rating)) { - rating = GetOfficialRatingForComparison(true); + rating = OfficialRatingForComparison; } if (string.IsNullOrWhiteSpace(rating)) @@ -1190,7 +1189,7 @@ namespace MediaBrowser.Controller.Entities if (string.IsNullOrWhiteSpace(rating)) { - rating = GetOfficialRatingForComparison(true); + rating = OfficialRatingForComparison; } if (string.IsNullOrWhiteSpace(rating)) diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index 4d5f14f8c7..87f45ec8e5 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -125,7 +125,14 @@ namespace MediaBrowser.Controller.Entities case CollectionType.HomeVideos: case CollectionType.Games: case CollectionType.MusicVideos: + case CollectionType.Music: + { + if (query.Recursive) + { + return GetResult(queryParent.GetRecursiveChildren(user, true), queryParent, query); + } return GetResult(queryParent.GetChildren(user, true), queryParent, query); + } case CollectionType.Folders: return GetResult(user.RootFolder.GetChildren(user, true), queryParent, query); @@ -139,36 +146,9 @@ namespace MediaBrowser.Controller.Entities case CollectionType.TvShows: return await GetTvView(queryParent, user, query).ConfigureAwait(false); - case CollectionType.Music: - return await GetMusicFolders(queryParent, user, query).ConfigureAwait(false); - case CollectionType.Movies: 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 await GetGameGenres(queryParent, user, query).ConfigureAwait(false); - - case SpecialFolder.GameGenre: - return await GetGameGenreItems(queryParent, displayParent, user, query).ConfigureAwait(false); - - case SpecialFolder.GameSystems: - return GetGameSystems(queryParent, user, query); - - case SpecialFolder.LatestGames: - return GetLatestGames(queryParent, user, query); - - case SpecialFolder.RecentlyPlayedGames: - return GetRecentlyPlayedGames(queryParent, user, query); - - case SpecialFolder.GameFavorites: - return GetFavoriteGames(queryParent, user, query); - case SpecialFolder.TvShowSeries: return GetTvSeries(queryParent, user, query); @@ -208,42 +188,12 @@ namespace MediaBrowser.Controller.Entities case SpecialFolder.MovieCollections: return GetMovieCollections(queryParent, user, query); - case SpecialFolder.MusicLatest: - return GetMusicLatest(queryParent, user, query); - - case SpecialFolder.MusicPlaylists: - return await GetMusicPlaylists(queryParent, user, query).ConfigureAwait(false); - - case SpecialFolder.MusicAlbums: - return GetMusicAlbums(queryParent, user, query); - - case SpecialFolder.MusicAlbumArtists: - return GetMusicAlbumArtists(queryParent, user, query); - - case SpecialFolder.MusicArtists: - return GetMusicArtists(queryParent, user, query); - - case SpecialFolder.MusicSongs: - return GetMusicSongs(queryParent, user, query); - case SpecialFolder.TvFavoriteEpisodes: return GetFavoriteEpisodes(queryParent, user, query); case SpecialFolder.TvFavoriteSeries: return GetFavoriteSeries(queryParent, user, query); - case SpecialFolder.MusicFavorites: - return await GetMusicFavorites(queryParent, user, query).ConfigureAwait(false); - - case SpecialFolder.MusicFavoriteAlbums: - return GetFavoriteAlbums(queryParent, user, query); - - case SpecialFolder.MusicFavoriteArtists: - return GetFavoriteArtists(queryParent, user, query); - - case SpecialFolder.MusicFavoriteSongs: - return GetFavoriteSongs(queryParent, user, query); - default: { if (queryParent is UserView) @@ -270,154 +220,6 @@ namespace MediaBrowser.Controller.Entities return 50; } - private async Task> GetMusicFolders(Folder parent, User user, InternalItemsQuery query) - { - if (query.Recursive) - { - var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }, i => FilterItem(i, query)); - - return PostFilterAndSort(items, parent, null, query); - } - - var list = new List(); - - list.Add(await GetUserView(SpecialFolder.MusicLatest, "0", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.MusicPlaylists, "1", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.MusicAlbums, "2", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.MusicAlbumArtists, "3", parent).ConfigureAwait(false)); - //list.Add(await GetUserView(SpecialFolder.MusicArtists, user, "4", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.MusicSongs, "5", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.MusicGenres, "6", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.MusicFavorites, "7", parent).ConfigureAwait(false)); - - return GetResult(list, parent, query); - } - - private async Task> GetMusicFavorites(Folder parent, User user, InternalItemsQuery query) - { - var list = new List(); - - list.Add(await GetUserView(SpecialFolder.MusicFavoriteAlbums, "0", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.MusicFavoriteArtists, "1", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.MusicFavoriteSongs, "2", parent).ConfigureAwait(false)); - - 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) - .DistinctNames() - .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, 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(); - - var artists = _libraryManager.GetAlbumArtists(items); - - return GetResult(artists, queryParent, query); - } - - private QueryResult GetMusicAlbumArtists(Folder parent, User user, InternalItemsQuery query) - { - var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }) - .Where(i => !i.IsFolder) - .OfType(); - - var artists = _libraryManager.GetAlbumArtists(items); - - return GetResult(artists, parent, query); - } - - private QueryResult GetMusicArtists(Folder parent, User user, InternalItemsQuery query) - { - var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }) - .Where(i => !i.IsFolder) - .OfType(); - - var artists = _libraryManager.GetArtists(items); - - return GetResult(artists, parent, query); - } - - private QueryResult GetFavoriteArtists(Folder parent, User user, InternalItemsQuery query) - { - var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }) - .Where(i => !i.IsFolder) - .OfType(); - - var artists = _libraryManager.GetAlbumArtists(items).Where(i => _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).IsFavorite); - - return GetResult(artists, parent, query); - } - - private Task> GetMusicPlaylists(Folder parent, User user, InternalItemsQuery query) - { - query.IncludeItemTypes = new[] { "Playlist" }; - query.Recursive = true; - - return parent.GetItems(query); - } - - private QueryResult GetMusicAlbums(Folder parent, User user, InternalItemsQuery query) - { - var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }, i => (i is MusicAlbum) && FilterItem(i, query)); - - return PostFilterAndSort(items, parent, null, query); - } - - private QueryResult GetMusicSongs(Folder parent, User user, InternalItemsQuery query) - { - var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }, i => (i is Audio.Audio) && FilterItem(i, query)); - - return PostFilterAndSort(items, parent, null, query); - } - - private QueryResult GetMusicLatest(Folder parent, User user, InternalItemsQuery query) - { - var items = _userViewManager.GetLatestItems(new LatestItemsQuery - { - UserId = user.Id.ToString("N"), - Limit = GetSpecialItemsLimit(), - IncludeItemTypes = new[] { typeof(Audio.Audio).Name }, - ParentId = (parent == null ? null : parent.Id.ToString("N")), - GroupItems = true - - }).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null); - - query.SortBy = new string[] { }; - - //var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }, i => i is MusicVideo || i is Audio.Audio && FilterItem(i, query)); - - return PostFilterAndSort(items, parent, null, query); - } - private async Task> GetMovieFolders(Folder parent, User user, InternalItemsQuery query) { if (query.Recursive) @@ -476,24 +278,6 @@ namespace MediaBrowser.Controller.Entities return PostFilterAndSort(items, parent, null, query); } - private QueryResult GetFavoriteSongs(Folder parent, User user, InternalItemsQuery query) - { - query.IsFavorite = true; - - var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music }, i => (i is Audio.Audio) && FilterItem(i, query)); - - return PostFilterAndSort(items, parent, null, query); - } - - private QueryResult GetFavoriteAlbums(Folder parent, User user, InternalItemsQuery query) - { - query.IsFavorite = true; - - var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music }, i => (i is MusicAlbum) && FilterItem(i, query)); - - return PostFilterAndSort(items, parent, null, query); - } - private QueryResult GetMovieMovies(Folder parent, User user, InternalItemsQuery query) { var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }, i => (i is Movie) && FilterItem(i, query)); @@ -613,54 +397,6 @@ namespace MediaBrowser.Controller.Entities return GetResult(list, parent, query); } - private async Task> GetGameView(User user, Folder parent, InternalItemsQuery query) - { - if (query.Recursive) - { - var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => FilterItem(i, query)); - return PostFilterAndSort(items, parent, null, query); - } - - var list = new List(); - - list.Add(await GetUserView(SpecialFolder.LatestGames, "0", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.RecentlyPlayedGames, "1", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.GameFavorites, "2", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.GameSystems, "3", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.GameGenres, "4", parent).ConfigureAwait(false)); - - return GetResult(list, parent, query); - } - - private QueryResult GetLatestGames(Folder parent, User user, InternalItemsQuery query) - { - query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName }; - query.SortOrder = SortOrder.Descending; - - var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => i is Game && FilterItem(i, query)); - - return PostFilterAndSort(items, parent, GetSpecialItemsLimit(), query); - } - - private QueryResult GetRecentlyPlayedGames(Folder parent, User user, InternalItemsQuery query) - { - query.IsPlayed = true; - query.SortBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName }; - query.SortOrder = SortOrder.Descending; - - var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => i is Game && FilterItem(i, query)); - - return PostFilterAndSort(items, parent, GetSpecialItemsLimit(), query); - } - - private QueryResult GetFavoriteGames(Folder parent, User user, InternalItemsQuery query) - { - query.IsFavorite = true; - - var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => i is Game && FilterItem(i, query)); - return PostFilterAndSort(items, parent, null, query); - } - private QueryResult GetTvLatest(Folder parent, User user, InternalItemsQuery query) { query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName }; @@ -741,49 +477,6 @@ namespace MediaBrowser.Controller.Entities return GetResult(items, queryParent, query); } - private QueryResult GetGameSystems(Folder parent, User user, InternalItemsQuery query) - { - var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => i is GameSystem && FilterItem(i, query)); - - return PostFilterAndSort(items, parent, null, query); - } - - private async Task> GetGameGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query) - { - var items = GetRecursiveChildren(queryParent, user, new[] { CollectionType.Games }, - i => i is Game && 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) - .DistinctNames() - .Select(i => - { - try - { - return _libraryManager.GetGameGenre(i); - } - catch - { - // Full exception logged at lower levels - _logger.Error("Error getting game genre"); - return null; - } - - }) - .Where(i => i != null) - .Select(i => GetUserView(i.Name, SpecialFolder.GameGenre, i.SortName, parent)); - - var genres = await Task.WhenAll(tasks).ConfigureAwait(false); - - return GetResult(genres, parent, query); - } - private QueryResult GetResult(QueryResult result) where T : BaseItem { diff --git a/MediaBrowser.Model/Entities/CollectionType.cs b/MediaBrowser.Model/Entities/CollectionType.cs index a259f4c077..dfd8f309c8 100644 --- a/MediaBrowser.Model/Entities/CollectionType.cs +++ b/MediaBrowser.Model/Entities/CollectionType.cs @@ -47,25 +47,5 @@ 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 MusicPlaylists = "MusicPlaylists"; - public const string MusicSongs = "MusicSongs"; - public const string MusicFavorites = "MusicFavorites"; - public const string MusicFavoriteArtists = "MusicFavoriteArtists"; - public const string MusicFavoriteAlbums = "MusicFavoriteAlbums"; - public const string MusicFavoriteSongs = "MusicFavoriteSongs"; } } diff --git a/MediaBrowser.Model/Session/GeneralCommandType.cs b/MediaBrowser.Model/Session/GeneralCommandType.cs index 79220f0662..64b61678e2 100644 --- a/MediaBrowser.Model/Session/GeneralCommandType.cs +++ b/MediaBrowser.Model/Session/GeneralCommandType.cs @@ -34,6 +34,8 @@ DisplayContent = 26, GoToSearch = 27, DisplayMessage = 28, - SetRepeatMode = 29 + SetRepeatMode = 29, + ChannelUp = 30, + ChannelDown = 31 } } \ No newline at end of file diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index 0533e6ca08..fcb208a054 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -527,6 +527,11 @@ namespace MediaBrowser.Providers.Manager { var newIndex = item.AllowsMultipleImages(imageType) ? item.GetImages(imageType).Count() : 0; + SaveImageStub(item, imageType, url, newIndex); + } + + private void SaveImageStub(IHasImages item, ImageType imageType, string url, int newIndex) + { item.SetImage(new ItemImageInfo { Path = url, @@ -555,7 +560,7 @@ namespace MediaBrowser.Providers.Manager { SaveImageStub(item, imageType, url); result.UpdateType = result.UpdateType | ItemUpdateType.ImageUpdate; - return; + continue; } try diff --git a/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs b/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs index cdffadcd7d..167b5706ee 100644 --- a/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs @@ -54,9 +54,7 @@ namespace MediaBrowser.Server.Implementations.UserViews return new List(); } - if (string.Equals(view.ViewType, SpecialFolder.GameGenre, StringComparison.OrdinalIgnoreCase) || - string.Equals(view.ViewType, SpecialFolder.MusicGenre, StringComparison.OrdinalIgnoreCase) || - string.Equals(view.ViewType, SpecialFolder.MovieGenre, StringComparison.OrdinalIgnoreCase) || + if (string.Equals(view.ViewType, SpecialFolder.MovieGenre, StringComparison.OrdinalIgnoreCase) || string.Equals(view.ViewType, SpecialFolder.TvGenre, StringComparison.OrdinalIgnoreCase)) { var userItemsResult = await view.GetItems(new InternalItemsQuery