From 818662e051a07b15a9ac15df177835d7e4ef236b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 28 Oct 2015 00:06:13 -0400 Subject: use ImageMagick scale method --- Emby.Drawing/ImageMagick/ImageMagickEncoder.cs | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'Emby.Drawing/ImageMagick/ImageMagickEncoder.cs') diff --git a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs index ed0760ee3..c5ba6d9c8 100644 --- a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs +++ b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs @@ -9,6 +9,7 @@ using System; using System.IO; using System.Linq; using CommonIO; +using MediaBrowser.Controller.Configuration; namespace Emby.Drawing.ImageMagick { @@ -18,13 +19,15 @@ namespace Emby.Drawing.ImageMagick private readonly IApplicationPaths _appPaths; private readonly IHttpClient _httpClient; private readonly IFileSystem _fileSystem; + private readonly IServerConfigurationManager _config; - public ImageMagickEncoder(ILogger logger, IApplicationPaths appPaths, IHttpClient httpClient, IFileSystem fileSystem) + public ImageMagickEncoder(ILogger logger, IApplicationPaths appPaths, IHttpClient httpClient, IFileSystem fileSystem, IServerConfigurationManager config) { _logger = logger; _appPaths = appPaths; _httpClient = httpClient; _fileSystem = fileSystem; + _config = config; LogVersion(); } @@ -137,11 +140,12 @@ namespace Emby.Drawing.ImageMagick { using (var originalImage = new MagickWand(inputPath)) { - originalImage.CurrentImage.ResizeImage(width, height); + ScaleImage(originalImage, width, height); DrawIndicator(originalImage, width, height, options); originalImage.CurrentImage.CompressionQuality = quality; + originalImage.CurrentImage.StripImage(); originalImage.SaveImage(outputPath); } @@ -152,12 +156,13 @@ namespace Emby.Drawing.ImageMagick { using (var originalImage = new MagickWand(inputPath)) { - originalImage.CurrentImage.ResizeImage(width, height); + ScaleImage(originalImage, width, height); wand.CurrentImage.CompositeImage(originalImage, CompositeOperator.OverCompositeOp, 0, 0); DrawIndicator(wand, width, height, options); wand.CurrentImage.CompressionQuality = quality; + wand.CurrentImage.StripImage(); wand.SaveImage(outputPath); } @@ -166,6 +171,18 @@ namespace Emby.Drawing.ImageMagick SaveDelay(); } + private void ScaleImage(MagickWand wand, int width, int height) + { + if (_config.Configuration.EnableHighQualityImageScaling) + { + wand.CurrentImage.ResizeImage(width, height); + } + else + { + wand.CurrentImage.ScaleImage(width, height); + } + } + /// /// Draws the indicator. /// -- cgit v1.2.3 From 9b998a068a2622f43ac813800654e357f94d0c21 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 28 Oct 2015 15:40:38 -0400 Subject: update image encoding --- Emby.Drawing/ImageMagick/ImageMagickEncoder.cs | 3 ++ MediaBrowser.Api/Movies/MoviesService.cs | 3 +- MediaBrowser.Api/TvShowsService.cs | 35 ++++++++----- .../Logging/NlogManager.cs | 2 +- .../Security/PluginSecurityManager.cs | 9 ++++ MediaBrowser.Common/MediaBrowser.Common.csproj | 1 + .../Security/PaymentRequiredException.cs | 8 +++ MediaBrowser.Controller/Entities/BaseItem.cs | 10 +++- .../Entities/InternalItemsQuery.cs | 11 ++++ MediaBrowser.Controller/Library/ILibraryManager.cs | 8 +++ .../LiveTv/LiveTvAudioRecording.cs | 1 - MediaBrowser.Controller/LiveTv/LiveTvProgram.cs | 35 +++++-------- .../LiveTv/LiveTvVideoRecording.cs | 1 - .../MediaBrowser.Controller.csproj | 1 + .../Net/PaymentRequiredException.cs | 15 ++++++ .../Providers/MetadataStatus.cs | 14 ----- MediaBrowser.Providers/Manager/MetadataService.cs | 22 +++++--- .../Dto/DtoService.cs | 8 ++- .../HttpServer/HttpListenerHost.cs | 4 +- .../HttpServer/LoggerUtils.cs | 5 +- .../SocketSharp/WebSocketSharpListener.cs | 10 +--- .../Library/LibraryManager.cs | 12 ++--- .../Library/SearchEngine.cs | 3 +- .../LiveTv/LiveTvManager.cs | 40 +++++++-------- .../Persistence/SqliteItemRepository.cs | 60 ++++++++++++++++++++-- .../Persistence/SqliteProviderInfoRepository.cs | 13 ++--- .../TV/TVSeriesManager.cs | 20 ++++++-- 27 files changed, 232 insertions(+), 122 deletions(-) create mode 100644 MediaBrowser.Common/Security/PaymentRequiredException.cs create mode 100644 MediaBrowser.Controller/Net/PaymentRequiredException.cs (limited to 'Emby.Drawing/ImageMagick/ImageMagickEncoder.cs') diff --git a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs index c5ba6d9c8..d097c8da3 100644 --- a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs +++ b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs @@ -136,6 +136,9 @@ namespace Emby.Drawing.ImageMagick public void EncodeImage(string inputPath, string outputPath, int width, int height, int quality, ImageProcessingOptions options) { + // Even if the caller specified 100, don't use it because it takes forever + quality = Math.Min(quality, 99); + if (string.IsNullOrWhiteSpace(options.BackgroundColor) || !HasTransparency(inputPath)) { using (var originalImage = new MagickWand(inputPath)) diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs index fe8bae1a5..1681c6fc6 100644 --- a/MediaBrowser.Api/Movies/MoviesService.cs +++ b/MediaBrowser.Api/Movies/MoviesService.cs @@ -379,9 +379,10 @@ namespace MediaBrowser.Api.Movies { foreach (var name in names) { - var itemsWithActor = _libraryManager.GetItemIds(new InternalItemsQuery + var itemsWithActor = _libraryManager.GetItemIds(new InternalItemsQuery(user) { Person = name + }); var items = allMovies diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index 29a4a8bb5..19d12fe65 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -159,7 +159,7 @@ namespace MediaBrowser.Api [ApiMember(Name = "StartItemId", Description = "Optional. Skip through the list until a given item is found.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] public string StartItemId { get; set; } - + /// /// Skips over a given number of items within the results. Use for paging. /// @@ -273,21 +273,32 @@ namespace MediaBrowser.Api { var user = _userManager.GetUserById(request.UserId); - var items = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, request.ParentId, i => i is Episode); + var minPremiereDate = DateTime.Now.Date.AddDays(-1).ToUniversalTime(); + + IEnumerable items; + + if (string.IsNullOrWhiteSpace(request.ParentId)) + { + items = _libraryManager.GetItems(new InternalItemsQuery(user) + { + IncludeItemTypes = new[] { typeof(Episode).Name }, + SortBy = new[] { "PremiereDate", "SortName" }, + SortOrder = SortOrder.Ascending, + MinPremiereDate = minPremiereDate + + }, user); + } + else + { + items = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, request.ParentId, i => i is Episode && (i.PremiereDate ?? DateTime.MinValue) >= minPremiereDate); + } var itemsList = _libraryManager .Sort(items, user, new[] { "PremiereDate", "AirTime", "SortName" }, SortOrder.Ascending) .Cast() .ToList(); - var unairedEpisodes = itemsList.Where(i => i.IsUnaired).ToList(); - - var minPremiereDate = DateTime.Now.Date.AddDays(-1).ToUniversalTime(); - var previousEpisodes = itemsList.Where(i => !i.IsUnaired && (i.PremiereDate ?? DateTime.MinValue) >= minPremiereDate).ToList(); - - previousEpisodes.AddRange(unairedEpisodes); - - var pagedItems = ApplyPaging(previousEpisodes, request.StartIndex, request.Limit); + var pagedItems = ApplyPaging(itemsList, request.StartIndex, request.Limit); var options = GetDtoOptions(request); @@ -440,7 +451,7 @@ namespace MediaBrowser.Api } episodes = season.GetEpisodes(user); - } + } else if (request.Season.HasValue) { var series = _libraryManager.GetItemById(request.Id) as Series; @@ -495,7 +506,7 @@ namespace MediaBrowser.Api .ToList(); var pagedItems = ApplyPaging(returnList, request.StartIndex, request.Limit); - + var dtoOptions = GetDtoOptions(request); var dtos = _dtoService.GetBaseItemDtos(pagedItems, dtoOptions, user) diff --git a/MediaBrowser.Common.Implementations/Logging/NlogManager.cs b/MediaBrowser.Common.Implementations/Logging/NlogManager.cs index 391e7c212..1bbcccd88 100644 --- a/MediaBrowser.Common.Implementations/Logging/NlogManager.cs +++ b/MediaBrowser.Common.Implementations/Logging/NlogManager.cs @@ -110,7 +110,7 @@ namespace MediaBrowser.Common.Implementations.Logging var logFile = new FileTarget { FileName = path, - Layout = "${longdate} ${level} - ${logger}: ${message}" + Layout = "${longdate} ${level} ${logger}: ${message}" }; logFile.Name = "ApplicationLogFile"; diff --git a/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs b/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs index c17a637fe..7cc31ad7a 100644 --- a/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs +++ b/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs @@ -219,6 +219,10 @@ namespace MediaBrowser.Common.Implementations.Security { SupporterKey = reg.key; } + else + { + throw new PaymentRequiredException(); + } } } @@ -227,6 +231,11 @@ namespace MediaBrowser.Common.Implementations.Security SaveAppStoreInfo(parameters); throw; } + catch (PaymentRequiredException) + { + SaveAppStoreInfo(parameters); + throw; + } catch (Exception e) { _logger.ErrorException("Error registering appstore purchase {0}", e, parameters ?? "NO PARMS SENT"); diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index b2f62dd21..ccdb319fe 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -89,6 +89,7 @@ + diff --git a/MediaBrowser.Common/Security/PaymentRequiredException.cs b/MediaBrowser.Common/Security/PaymentRequiredException.cs new file mode 100644 index 000000000..27b3e6961 --- /dev/null +++ b/MediaBrowser.Common/Security/PaymentRequiredException.cs @@ -0,0 +1,8 @@ +using System; + +namespace MediaBrowser.Common.Security +{ + public class PaymentRequiredException : Exception + { + } +} diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 19d5576c6..fdf035e8d 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -24,6 +24,7 @@ using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; using CommonIO; +using MediaBrowser.Model.LiveTv; namespace MediaBrowser.Controller.Entities { @@ -134,6 +135,13 @@ namespace MediaBrowser.Controller.Entities [IgnoreDataMember] public bool? IsHD { get; set; } + /// + /// Gets or sets the audio. + /// + /// The audio. + [IgnoreDataMember] + public ProgramAudio? Audio { get; set; } + /// /// Return the id that should be used to key display prefs for this item. /// Default is based on the type for everything except actual generic folders. @@ -178,7 +186,7 @@ namespace MediaBrowser.Controller.Entities } /// - /// Id of the program. + /// If this content came from an external service, the id of the content on that service /// [IgnoreDataMember] public string ExternalId diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index 785e2fd2b..786c96d36 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -75,6 +75,7 @@ namespace MediaBrowser.Controller.Entities public string[] Tags { get; set; } public string[] OfficialRatings { get; set; } + public DateTime? MinPremiereDate { get; set; } public DateTime? MinStartDate { get; set; } public DateTime? MaxStartDate { get; set; } public DateTime? MinEndDate { get; set; } @@ -121,5 +122,15 @@ namespace MediaBrowser.Controller.Entities ChannelIds = new string[] { }; ItemIds = new string[] { }; } + + public InternalItemsQuery(User user) + : this() + { + if (user != null) + { + var policy = user.Policy; + MaxParentalRating = policy.MaxParentalRating; + } + } } } diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index c7ab88524..96bb6e2b6 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -543,5 +543,13 @@ namespace MediaBrowser.Controller.Library /// Index of the image. /// Task. Task ConvertImageToLocal(IHasImages item, ItemImageInfo image, int imageIndex); + + /// + /// Gets the items. + /// + /// The query. + /// The user. + /// List<BaseItem>. + IEnumerable GetItems(InternalItemsQuery query, User user); } } \ No newline at end of file diff --git a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs index 03c05ec69..dd6a53d45 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs @@ -36,7 +36,6 @@ namespace MediaBrowser.Controller.LiveTv public bool IsLive { get; set; } [IgnoreDataMember] public bool IsPremiere { get; set; } - public ProgramAudio? Audio { get; set; } /// /// Gets the user data key. diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs index 96a3743d0..aa1a3b9c2 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs @@ -32,10 +32,11 @@ namespace MediaBrowser.Controller.LiveTv } /// - /// Gets or sets the type of the channel. + /// Gets or sets the name. /// - /// The type of the channel. - public ChannelType ChannelType { get; set; } + /// The name. + [IgnoreDataMember] + public string ServiceName { get; set; } /// /// The start date of the program, in UTC. @@ -43,18 +44,6 @@ namespace MediaBrowser.Controller.LiveTv [IgnoreDataMember] public DateTime StartDate { get; set; } - /// - /// Gets or sets the audio. - /// - /// The audio. - public ProgramAudio? Audio { get; set; } - - /// - /// Gets or sets the name of the service. - /// - /// The name of the service. - public string ServiceName { get; set; } - /// /// Gets or sets a value indicating whether this instance is repeat. /// @@ -145,14 +134,14 @@ namespace MediaBrowser.Controller.LiveTv } } - [IgnoreDataMember] - public override string MediaType - { - get - { - return ChannelType == ChannelType.TV ? Model.Entities.MediaType.Video : Model.Entities.MediaType.Audio; - } - } + //[IgnoreDataMember] + //public override string MediaType + //{ + // get + // { + // return ChannelType == ChannelType.TV ? Model.Entities.MediaType.Video : Model.Entities.MediaType.Audio; + // } + //} [IgnoreDataMember] public bool IsAiring diff --git a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs index 77404cfe8..de8764e6d 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs @@ -36,7 +36,6 @@ namespace MediaBrowser.Controller.LiveTv public bool IsLive { get; set; } [IgnoreDataMember] public bool IsPremiere { get; set; } - public ProgramAudio? Audio { get; set; } /// /// Gets the user data key. diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index bcf4de2a2..600674114 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -248,6 +248,7 @@ + diff --git a/MediaBrowser.Controller/Net/PaymentRequiredException.cs b/MediaBrowser.Controller/Net/PaymentRequiredException.cs new file mode 100644 index 000000000..e09fe092e --- /dev/null +++ b/MediaBrowser.Controller/Net/PaymentRequiredException.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MediaBrowser.Controller.Net +{ + /// + /// Corresponds to a 402 response code + /// + public class PaymentRequiredException : Exception + { + } +} diff --git a/MediaBrowser.Controller/Providers/MetadataStatus.cs b/MediaBrowser.Controller/Providers/MetadataStatus.cs index 9b946aee2..654d72e2a 100644 --- a/MediaBrowser.Controller/Providers/MetadataStatus.cs +++ b/MediaBrowser.Controller/Providers/MetadataStatus.cs @@ -40,22 +40,8 @@ namespace MediaBrowser.Controller.Providers /// The date last images refresh. public DateTime? DateLastImagesRefresh { get; set; } - /// - /// Gets or sets the last result error message. - /// - /// The last result error message. - public string LastErrorMessage { get; set; } - public DateTime? ItemDateModified { get; set; } - public void AddStatus(string errorMessage) - { - if (string.IsNullOrEmpty(LastErrorMessage)) - { - LastErrorMessage = errorMessage; - } - } - public bool IsDirty { get; private set; } public void SetDateLastMetadataRefresh(DateTime? date) diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index 6860aeff3..a7f58e32b 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -99,7 +99,6 @@ namespace MediaBrowser.Providers.Manager var updateType = ItemUpdateType.None; var refreshResult = GetLastResult(item); - refreshResult.LastErrorMessage = string.Empty; var itemImageProvider = new ItemImageProvider(Logger, ProviderManager, ServerConfigurationManager, FileSystem); var localImagesFailed = false; @@ -119,7 +118,6 @@ namespace MediaBrowser.Providers.Manager { localImagesFailed = true; Logger.ErrorException("Error validating images for {0}", ex, item.Path ?? item.Name ?? "Unknown name"); - refreshResult.AddStatus(ex.Message); } var metadataResult = new MetadataResult @@ -150,7 +148,6 @@ namespace MediaBrowser.Providers.Manager var result = await RefreshWithProviders(metadataResult, id, refreshOptions, providers, itemImageProvider, cancellationToken).ConfigureAwait(false); updateType = updateType | result.UpdateType; - refreshResult.AddStatus(result.ErrorMessage); if (result.Failures == 0) { refreshResult.SetDateLastMetadataRefresh(DateTime.UtcNow); @@ -172,7 +169,6 @@ namespace MediaBrowser.Providers.Manager var result = await itemImageProvider.RefreshImages(itemOfType, providers, refreshOptions, config, cancellationToken).ConfigureAwait(false); updateType = updateType | result.UpdateType; - refreshResult.AddStatus(result.ErrorMessage); if (result.Failures == 0) { refreshResult.SetDateLastImagesRefresh(DateTime.UtcNow); @@ -231,22 +227,32 @@ namespace MediaBrowser.Providers.Manager private DateTime GetLastRefreshDate(IHasMetadata item) { - if (item.DateLastRefreshed != default(DateTime)) + if (EnableDateLastRefreshed(item)) { return item.DateLastRefreshed; } + return item.DateLastSaved; + } + + private bool EnableDateLastRefreshed(IHasMetadata item) + { if (ServerConfigurationManager.Configuration.EnableDateLastRefresh) { - return item.DateLastRefreshed; + return true; + } + + if (item.DateLastRefreshed != default(DateTime)) + { + return true; } if (item is BoxSet || (item is IItemByName && !(item is MusicArtist))) { - return item.DateLastRefreshed; + return true; } - return item.DateLastSaved; + return false; } protected async Task SaveItem(MetadataResult result, ItemUpdateType reason, CancellationToken cancellationToken) diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 20e1eb543..fcda802f4 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -472,7 +472,7 @@ namespace MediaBrowser.Server.Implementations.Dto // These are just far too slow. // TODO: Disable for CollectionFolder - if (!(folder is UserRootFolder) && !(folder is UserView)) + if (!(folder is UserRootFolder) && !(folder is UserView) && !(folder is IChannelItem)) { SetSpecialCounts(folder, user, dto, fields, syncProgress); } @@ -1042,7 +1042,11 @@ namespace MediaBrowser.Server.Implementations.Dto dto.IsFolder = item.IsFolder; dto.MediaType = item.MediaType; dto.LocationType = item.LocationType; - dto.IsHD = item.IsHD; + if (item.IsHD.HasValue && item.IsHD.Value) + { + dto.IsHD = item.IsHD; + } + dto.Audio = item.Audio; dto.PreferredMetadataCountryCode = item.PreferredMetadataCountryCode; dto.PreferredMetadataLanguage = item.PreferredMetadataLanguage; diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index e8bb40ba1..6abfa0674 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -92,7 +92,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer {typeof (FileNotFoundException), 404}, {typeof (DirectoryNotFoundException), 404}, {typeof (SecurityException), 401}, - {typeof (UnauthorizedAccessException), 500} + {typeof (PaymentRequiredException), 402}, + {typeof (UnauthorizedAccessException), 500}, + {typeof (ApplicationException), 500} }; HostConfig.Instance.DebugMode = true; diff --git a/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs b/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs index 02ce38ef1..fae702023 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs @@ -16,7 +16,10 @@ namespace MediaBrowser.Server.Implementations.HttpServer /// The duration. public static void LogResponse(ILogger logger, int statusCode, string url, string endPoint, TimeSpan duration) { - logger.Info("HTTP Response {0} to {1}. Time: {2}ms. {3}", statusCode, endPoint, Convert.ToInt32(duration.TotalMilliseconds).ToString(CultureInfo.InvariantCulture), url); + var durationMs = duration.TotalMilliseconds; + var logSuffix = durationMs >= 1000 ? "ms (slow)" : "ms"; + + logger.Info("HTTP Response {0} to {1}. Time: {2}{3}. {4}", statusCode, endPoint, Convert.ToInt32(durationMs).ToString(CultureInfo.InvariantCulture), logSuffix, url); } } } diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs index f8178c115..9f80c8ac9 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs @@ -183,15 +183,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp /// The request. private static void LogRequest(ILogger logger, HttpListenerRequest request) { - var log = new StringBuilder(); - - var headers = string.Join(",", request.Headers.AllKeys.Where(i => !string.Equals(i, "cookie", StringComparison.OrdinalIgnoreCase) && !string.Equals(i, "Referer", StringComparison.OrdinalIgnoreCase)).Select(k => k + "=" + request.Headers[k])); - - log.AppendLine("Ip: " + request.RemoteEndPoint + ". Headers: " + headers); - - var type = request.IsWebSocketRequest ? "Web Socket" : "HTTP " + request.HttpMethod; - - logger.LogMultiline(type + " " + request.Url, LogSeverity.Info, log); + logger.Info("{0} {1}. UserAgent: {2}", (request.IsWebSocketRequest ? "WS" : "HTTP " + request.HttpMethod), request.Url, request.UserAgent ?? string.Empty); } private void HandleError(Exception ex, HttpListenerContext context) diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 92acd08d1..daa3d8ad4 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -1280,6 +1280,11 @@ namespace MediaBrowser.Server.Implementations.Library return ItemRepository.GetItemIdsList(query); } + public IEnumerable GetItems(InternalItemsQuery query, User user) + { + return GetItemIds(query).Select(GetItemById).Where(i => i.IsVisibleStandalone(user)); + } + /// /// Gets the intros. /// @@ -1811,14 +1816,9 @@ namespace MediaBrowser.Server.Implementations.Library isNew = true; } - if (!item.UserId.HasValue) + if (!item.UserId.HasValue || !string.Equals(viewType, item.ViewType, StringComparison.OrdinalIgnoreCase)) { item.UserId = user.Id; - await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false); - } - - if (!string.Equals(viewType, item.ViewType, StringComparison.OrdinalIgnoreCase)) - { item.ViewType = viewType; await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs index d6aff1192..108a891e0 100644 --- a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs +++ b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs @@ -157,12 +157,11 @@ namespace MediaBrowser.Server.Implementations.Library AddIfMissing(excludeItemTypes, typeof(CollectionFolder).Name); - var mediaItems = _libraryManager.GetItems(new InternalItemsQuery + var mediaItems = _libraryManager.GetItems(new InternalItemsQuery(user) { NameContains = searchTerm, ExcludeItemTypes = excludeItemTypes.ToArray(), IncludeItemTypes = includeItemTypes.ToArray(), - MaxParentalRating = user == null ? null : user.Policy.MaxParentalRating, Limit = (query.Limit.HasValue ? (int?)(query.Limit.Value * 3) : null), }).Items; diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index edfca0d6c..d7c9edae3 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -607,6 +607,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv var item = _libraryManager.GetItemById(id) as LiveTvProgram; var isNew = false; + var forceUpdate = false; if (item == null) { @@ -621,7 +622,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv }; } - item.ChannelType = channelType; + //item.ChannelType = channelType; + if (!string.Equals(item.ServiceName, serviceName, StringComparison.Ordinal)) + { + forceUpdate = true; + } item.ServiceName = serviceName; item.Audio = info.Audio; @@ -666,7 +671,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv { await _libraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false); } - else if (string.IsNullOrWhiteSpace(info.Etag)) + else if (forceUpdate || string.IsNullOrWhiteSpace(info.Etag)) { await _libraryManager.UpdateItem(item, ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false); } @@ -814,7 +819,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv public async Task> GetPrograms(ProgramQuery query, DtoOptions options, CancellationToken cancellationToken) { - var internalQuery = new InternalItemsQuery + var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId); + + var internalQuery = new InternalItemsQuery(user) { IncludeItemTypes = new[] { typeof(LiveTvProgram).Name }, MinEndDate = query.MinEndDate, @@ -832,11 +839,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv SortOrder = query.SortOrder ?? SortOrder.Ascending }; - var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId); if (user != null) { - internalQuery.MaxParentalRating = user.Policy.MaxParentalRating; - if (user.Policy.BlockUnratedItems.Contains(UnratedItem.LiveTvProgram)) { internalQuery.HasParentalRating = true; @@ -874,7 +878,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv public async Task> GetRecommendedProgramsInternal(RecommendedProgramQuery query, CancellationToken cancellationToken) { - var internalQuery = new InternalItemsQuery + var user = _userManager.GetUserById(query.UserId); + + var internalQuery = new InternalItemsQuery(user) { IncludeItemTypes = new[] { typeof(LiveTvProgram).Name }, IsAiring = query.IsAiring, @@ -895,11 +901,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv } } - var user = _userManager.GetUserById(query.UserId); if (user != null) { - internalQuery.MaxParentalRating = user.Policy.MaxParentalRating; - if (user.Policy.BlockUnratedItems.Contains(UnratedItem.LiveTvProgram)) { internalQuery.HasParentalRating = true; @@ -1037,6 +1040,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv { var internalProgram = GetInternalProgram(program.Id); + if (string.IsNullOrWhiteSpace(internalProgram.ServiceName)) + { + continue; + } + List timerList; if (!timers.TryGetValue(internalProgram.ServiceName, out timerList)) { @@ -1052,7 +1060,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv } } - var timer = timerList.FirstOrDefault(i => string.Equals(i.ProgramId, internalProgram.ExternalId, StringComparison.OrdinalIgnoreCase)); if (timer != null) @@ -1429,18 +1436,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv public void AddInfoToProgramDto(BaseItem item, BaseItemDto dto, bool addChannelInfo, User user = null) { var program = (LiveTvProgram)item; - var service = GetService(program); - - dto.Id = _tvDtoService.GetInternalProgramId(service.Name, program.ExternalId).ToString("N"); dto.StartDate = program.StartDate; dto.EpisodeTitle = program.EpisodeTitle; - dto.Audio = program.Audio; - if (program.IsHD.HasValue && program.IsHD.Value) - { - dto.IsHD = program.IsHD; - } if (program.IsRepeat) { dto.IsRepeat = program.IsRepeat; @@ -1499,7 +1498,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv var info = recording; - dto.Id = item.Id.ToString("N"); dto.SeriesTimerId = string.IsNullOrEmpty(info.SeriesTimerId) ? null : _tvDtoService.GetInternalSeriesTimerId(service.Name, info.SeriesTimerId).ToString("N"); @@ -1508,8 +1506,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv dto.RecordingStatus = info.Status; dto.IsRepeat = info.IsRepeat; dto.EpisodeTitle = info.EpisodeTitle; - dto.Audio = info.Audio; - dto.IsHD = info.IsHD; dto.IsMovie = info.IsMovie; dto.IsSeries = info.IsSeries; dto.IsSports = info.IsSports; diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 256b057d9..730632bb3 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -19,6 +19,7 @@ using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Controller.Channels; +using MediaBrowser.Model.LiveTv; namespace MediaBrowser.Server.Implementations.Persistence { @@ -76,7 +77,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _deleteStreamsCommand; private IDbCommand _saveStreamCommand; - private const int LatestSchemaVersion = 16; + private const int LatestSchemaVersion = 17; /// /// Initializes a new instance of the class. @@ -202,7 +203,9 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection.AddColumn(_logger, "TypedBaseItems", "IsInMixedFolder", "BIT"); _connection.AddColumn(_logger, "TypedBaseItems", "LockedFields", "Text"); _connection.AddColumn(_logger, "TypedBaseItems", "Studios", "Text"); - + _connection.AddColumn(_logger, "TypedBaseItems", "Audio", "Text"); + _connection.AddColumn(_logger, "TypedBaseItems", "ExternalServiceId", "Text"); + PrepareStatements(); new MediaStreamColumns(_connection, _logger).AddColumns(); @@ -311,7 +314,10 @@ namespace MediaBrowser.Server.Implementations.Persistence "DateCreated", "DateModified", "guid", - "Genres" + "Genres", + "ParentId", + "Audio", + "ExternalServiceId" }; private readonly string[] _mediaStreamSaveColumns = @@ -403,7 +409,9 @@ namespace MediaBrowser.Server.Implementations.Persistence "DateLastSaved", "IsInMixedFolder", "LockedFields", - "Studios" + "Studios", + "Audio", + "ExternalServiceId" }; _saveItemCommand = _connection.CreateCommand(); _saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values ("; @@ -637,6 +645,25 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.LockedFields.Select(i => i.ToString()).ToArray()); _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Studios.ToArray()); + if (item.Audio.HasValue) + { + _saveItemCommand.GetParameter(index++).Value = item.Audio.Value.ToString(); + } + else + { + _saveItemCommand.GetParameter(index++).Value = null; + } + + var tvItem = item as ILiveTvItem; + if (tvItem != null) + { + _saveItemCommand.GetParameter(index++).Value = tvItem.ServiceName; + } + else + { + _saveItemCommand.GetParameter(index++).Value = null; + } + _saveItemCommand.Transaction = transaction; _saveItemCommand.ExecuteNonQuery(); @@ -940,6 +967,25 @@ namespace MediaBrowser.Server.Implementations.Persistence item.Genres = reader.GetString(40).Split('|').Where(i => !string.IsNullOrWhiteSpace(i)).ToList(); } + if (!reader.IsDBNull(41)) + { + item.ParentId = reader.GetGuid(41); + } + + if (!reader.IsDBNull(42)) + { + item.Audio = (ProgramAudio)Enum.Parse(typeof(ProgramAudio), reader.GetString(42), true); + } + + if (!reader.IsDBNull(43)) + { + var tvItem = item as ILiveTvItem; + if (tvItem != null) + { + item.ForcedSortName = reader.GetString(43); + } + } + return item; } @@ -1668,6 +1714,12 @@ namespace MediaBrowser.Server.Implementations.Persistence cmd.Parameters.Add(cmd, "@MinStartDate", DbType.Date).Value = query.MinStartDate.Value; } + if (query.MinPremiereDate.HasValue) + { + whereClauses.Add("PremiereDate>=@MinPremiereDate"); + cmd.Parameters.Add(cmd, "@MinPremiereDate", DbType.Date).Value = query.MinPremiereDate.Value; + } + if (query.MaxStartDate.HasValue) { whereClauses.Add("StartDate<=@MaxStartDate"); diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs index e7853b458..a63b93dc7 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs @@ -47,7 +47,7 @@ namespace MediaBrowser.Server.Implementations.Persistence string[] queries = { - "create table if not exists MetadataStatus (ItemId GUID PRIMARY KEY, ItemName TEXT, ItemType TEXT, SeriesName TEXT, DateLastMetadataRefresh datetime, DateLastImagesRefresh datetime, LastErrorMessage TEXT, ItemDateModified DateTimeNull)", + "create table if not exists MetadataStatus (ItemId GUID PRIMARY KEY, ItemName TEXT, ItemType TEXT, SeriesName TEXT, DateLastMetadataRefresh datetime, DateLastImagesRefresh datetime, ItemDateModified DateTimeNull)", "create index if not exists idx_MetadataStatus on MetadataStatus(ItemId)", //pragmas @@ -71,7 +71,6 @@ namespace MediaBrowser.Server.Implementations.Persistence "SeriesName", "DateLastMetadataRefresh", "DateLastImagesRefresh", - "LastErrorMessage", "ItemDateModified" }; @@ -185,12 +184,7 @@ namespace MediaBrowser.Server.Implementations.Persistence if (!reader.IsDBNull(6)) { - result.LastErrorMessage = reader.GetString(6); - } - - if (!reader.IsDBNull(7)) - { - result.ItemDateModified = reader.GetDateTime(7).ToUniversalTime(); + result.ItemDateModified = reader.GetDateTime(6).ToUniversalTime(); } return result; @@ -219,8 +213,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveStatusCommand.GetParameter(3).Value = status.SeriesName; _saveStatusCommand.GetParameter(4).Value = status.DateLastMetadataRefresh; _saveStatusCommand.GetParameter(5).Value = status.DateLastImagesRefresh; - _saveStatusCommand.GetParameter(6).Value = status.LastErrorMessage; - _saveStatusCommand.GetParameter(7).Value = status.ItemDateModified; + _saveStatusCommand.GetParameter(6).Value = status.ItemDateModified; _saveStatusCommand.Transaction = transaction; diff --git a/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs b/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs index f34b43e43..93ebd0a1c 100644 --- a/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs +++ b/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs @@ -36,8 +36,22 @@ namespace MediaBrowser.Server.Implementations.TV ? new string[] { } : new[] { request.ParentId }; - var items = GetAllLibraryItems(user, parentIds, i => i is Series) - .Cast(); + IEnumerable items; + + if (parentIds.Length == 0) + { + items = _libraryManager.GetItems(new InternalItemsQuery(user) + { + IncludeItemTypes = new[] { typeof(Series).Name }, + SortOrder = SortOrder.Ascending + + }, user).Cast(); + } + else + { + items = GetAllLibraryItems(user, parentIds, i => i is Series) + .Cast(); + } // Avoid implicitly captured closure var episodes = GetNextUpEpisodes(request, user, items); @@ -64,7 +78,7 @@ namespace MediaBrowser.Server.Implementations.TV return GetResult(episodes, null, request); } - private IEnumerable GetAllLibraryItems(User user, string[] parentIds, Func filter) + private IEnumerable GetAllLibraryItems(User user, string[] parentIds, Func filter) { if (parentIds.Length > 0) { -- cgit v1.2.3 From 81bb469fe1ba61d6ff39f6473e5d4beab1764e4e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 9 Nov 2015 13:18:37 -0500 Subject: reduce image processing --- Emby.Drawing/GDI/GDIImageEncoder.cs | 4 +- Emby.Drawing/IImageEncoder.cs | 3 +- Emby.Drawing/ImageMagick/ImageMagickEncoder.cs | 2 +- Emby.Drawing/ImageProcessor.cs | 84 ++++-- Emby.Drawing/NullImageEncoder.cs | 2 +- MediaBrowser.Api/Images/ImageService.cs | 70 +---- MediaBrowser.Controller/Drawing/IImageProcessor.cs | 5 +- .../Drawing/ImageProcessingOptions.cs | 39 ++- MediaBrowser.Controller/Entities/BaseItem.cs | 13 +- .../Entities/UserViewBuilder.cs | 321 +-------------------- MediaBrowser.Model/Entities/CollectionType.cs | 20 -- MediaBrowser.Model/Session/GeneralCommandType.cs | 4 +- .../Manager/ItemImageProvider.cs | 7 +- .../UserViews/DynamicImageProvider.cs | 4 +- 14 files changed, 137 insertions(+), 441 deletions(-) (limited to 'Emby.Drawing/ImageMagick/ImageMagickEncoder.cs') diff --git a/Emby.Drawing/GDI/GDIImageEncoder.cs b/Emby.Drawing/GDI/GDIImageEncoder.cs index 530613741..11c9eb8e9 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 4469075a6..bfd382bb7 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 d097c8da3..d18ee1caa 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 a24987c05..902ade448 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 30ea36329..1638a675a 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 8114f9f22..e2354a54b 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 e1e98857f..058bf70cd 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 e6bf86853..2b80b701e 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 5b0af42e8..d9b7b1ae7 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 4d5f14f8c..87f45ec8e 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 a259f4c07..dfd8f309c 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 79220f066..64b61678e 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 0533e6ca0..fcb208a05 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 cdffadcd7..167b5706e 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 -- cgit v1.2.3 From ccc7f5da7125465aebd485b0d5ddc5a0ea0df1c2 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 12 Nov 2015 14:27:14 -0500 Subject: update image magick encoder --- Emby.Drawing/ImageMagick/ImageMagickEncoder.cs | 27 +++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'Emby.Drawing/ImageMagick/ImageMagickEncoder.cs') diff --git a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs index d18ee1caa..64ddf7e88 100644 --- a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs +++ b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs @@ -90,7 +90,7 @@ namespace Emby.Drawing.ImageMagick wand.SaveImage(tmpPath); } } - catch + catch { //_logger.ErrorException("Error loading webp: ", ex); _webpAvailable = false; @@ -148,7 +148,7 @@ namespace Emby.Drawing.ImageMagick DrawIndicator(originalImage, width, height, options); originalImage.CurrentImage.CompressionQuality = quality; - originalImage.CurrentImage.StripImage(); + //originalImage.CurrentImage.StripImage(); originalImage.SaveImage(outputPath); } @@ -165,7 +165,7 @@ namespace Emby.Drawing.ImageMagick DrawIndicator(wand, width, height, options); wand.CurrentImage.CompressionQuality = quality; - wand.CurrentImage.StripImage(); + //wand.CurrentImage.StripImage(); wand.SaveImage(outputPath); } @@ -176,14 +176,15 @@ namespace Emby.Drawing.ImageMagick private void ScaleImage(MagickWand wand, int width, int height) { - if (_config.Configuration.EnableHighQualityImageScaling) - { - wand.CurrentImage.ResizeImage(width, height); - } - else - { - wand.CurrentImage.ScaleImage(width, height); - } + wand.CurrentImage.ResizeImage(width, height); + //if (_config.Configuration.EnableHighQualityImageScaling) + //{ + // wand.CurrentImage.ResizeImage(width, height); + //} + //else + //{ + // wand.CurrentImage.ScaleImage(width, height); + //} } /// @@ -251,8 +252,8 @@ namespace Emby.Drawing.ImageMagick private void SaveDelay() { // For some reason the images are not always getting released right away - var task = Task.Delay(300); - Task.WaitAll(task); + //var task = Task.Delay(300); + //Task.WaitAll(task); } public string Name -- cgit v1.2.3 From 0d5903f21583afbeed279699d72b512427aa33a9 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 12 Nov 2015 14:31:25 -0500 Subject: update image magick encoder --- Emby.Drawing/ImageMagick/ImageMagickEncoder.cs | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'Emby.Drawing/ImageMagick/ImageMagickEncoder.cs') diff --git a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs index 64ddf7e88..5ca674888 100644 --- a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs +++ b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs @@ -148,7 +148,7 @@ namespace Emby.Drawing.ImageMagick DrawIndicator(originalImage, width, height, options); originalImage.CurrentImage.CompressionQuality = quality; - //originalImage.CurrentImage.StripImage(); + originalImage.CurrentImage.StripImage(); originalImage.SaveImage(outputPath); } @@ -165,7 +165,7 @@ namespace Emby.Drawing.ImageMagick DrawIndicator(wand, width, height, options); wand.CurrentImage.CompressionQuality = quality; - //wand.CurrentImage.StripImage(); + wand.CurrentImage.StripImage(); wand.SaveImage(outputPath); } @@ -176,15 +176,14 @@ namespace Emby.Drawing.ImageMagick private void ScaleImage(MagickWand wand, int width, int height) { - wand.CurrentImage.ResizeImage(width, height); - //if (_config.Configuration.EnableHighQualityImageScaling) - //{ - // wand.CurrentImage.ResizeImage(width, height); - //} - //else - //{ - // wand.CurrentImage.ScaleImage(width, height); - //} + if (_config.Configuration.EnableHighQualityImageScaling) + { + wand.CurrentImage.ResizeImage(width, height); + } + else + { + wand.CurrentImage.ScaleImage(width, height); + } } /// -- cgit v1.2.3 From 30229982bab747bfa695123038f9c5d90dd5ac9a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 4 Jan 2016 14:40:59 -0500 Subject: auto install vcredist --- Emby.Drawing/ImageMagick/ImageMagickEncoder.cs | 7 ++- .../BaseApplicationHost.cs | 2 +- MediaBrowser.ServerApplication/MainStartup.cs | 69 ++++++++++++++++++++++ .../MediaBrowser.ServerApplication.csproj | 4 ++ 4 files changed, 80 insertions(+), 2 deletions(-) (limited to 'Emby.Drawing/ImageMagick/ImageMagickEncoder.cs') diff --git a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs index 5ca674888..12a98edff 100644 --- a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs +++ b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs @@ -72,11 +72,16 @@ namespace Emby.Drawing.ImageMagick private void LogVersion() { - _logger.Info("ImageMagick version: " + Wand.VersionString); + _logger.Info("ImageMagick version: " + GetVersion()); TestWebp(); Wand.SetMagickThreadCount(1); } + public static string GetVersion() + { + return Wand.VersionString; + } + private bool _webpAvailable = true; private void TestWebp() { diff --git a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs index 6dc97100d..2a93efcde 100644 --- a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs +++ b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs @@ -133,7 +133,7 @@ namespace MediaBrowser.Common.Implementations /// Gets the HTTP client. /// /// The HTTP client. - protected IHttpClient HttpClient { get; private set; } + public IHttpClient HttpClient { get; private set; } /// /// Gets the network manager. /// diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs index 69b78e02b..ac6fd1bbe 100644 --- a/MediaBrowser.ServerApplication/MainStartup.cs +++ b/MediaBrowser.ServerApplication/MainStartup.cs @@ -18,7 +18,9 @@ using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using CommonIO.Windows; +using Emby.Drawing.ImageMagick; using ImageMagickSharp; +using MediaBrowser.Common.Net; using MediaBrowser.Server.Implementations.Logging; namespace MediaBrowser.ServerApplication @@ -251,6 +253,9 @@ namespace MediaBrowser.ServerApplication { Task.WaitAll(task); + task = InstallVcredistIfNeeded(_appHost, _logger); + Task.WaitAll(task); + SystemEvents.SessionEnding += SystemEvents_SessionEnding; SystemEvents.SessionSwitch += SystemEvents_SessionSwitch; @@ -568,6 +573,70 @@ namespace MediaBrowser.ServerApplication } } + private static async Task InstallVcredistIfNeeded(ApplicationHost appHost, ILogger logger) + { + try + { + var version = ImageMagickEncoder.GetVersion(); + return; + } + catch (Exception ex) + { + logger.ErrorException("Error loading ImageMagick", ex); + } + + try + { + await InstallVcredist().ConfigureAwait(false); + } + catch (Exception ex) + { + logger.ErrorException("Error installing ImageMagick", ex); + } + } + + private async static Task InstallVcredist() + { + var httpClient = _appHost.HttpClient; + + var tmp = await httpClient.GetTempFile(new HttpRequestOptions + { + Url = GetVcredistUrl(), + Progress = new Progress() + + }).ConfigureAwait(false); + + var exePath = Path.ChangeExtension(tmp, ".exe"); + File.Copy(tmp, exePath); + + var startInfo = new ProcessStartInfo + { + FileName = exePath, + + CreateNoWindow = true, + WindowStyle = ProcessWindowStyle.Hidden, + Verb = "runas", + ErrorDialog = false + }; + + using (var process = Process.Start(startInfo)) + { + process.WaitForExit(); + } + } + + private static string GetVcredistUrl() + { + if (Environment.Is64BitProcess) + { + return "https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2013/vcredist_x64.exe"; + } + + // TODO: ARM url - https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2013/vcredist_arm.exe + + return "https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2013/vcredist_x86.exe"; + } + /// /// Sets the error mode. /// diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index ddae4ee5a..e8d5b6d27 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -1055,6 +1055,10 @@ + + {08fff49b-f175-4807-a2b5-73b0ebd9f716} + Emby.Drawing + {4fd51ac5-2c16-4308-a993-c3a84f3b4582} MediaBrowser.Api -- cgit v1.2.3