mirror of
				https://github.com/jellyfin/jellyfin.git
				synced 2025-10-31 10:37:22 -04:00 
			
		
		
		
	support null image encoder
This commit is contained in:
		
							parent
							
								
									2890c71af9
								
							
						
					
					
						commit
						c80e1df1ca
					
				| @ -75,6 +75,7 @@ | ||||
|     <Compile Include="ImageProcessor.cs" /> | ||||
|     <Compile Include="ImageMagick\PercentPlayedDrawer.cs" /> | ||||
|     <Compile Include="ImageMagick\PlayedIndicatorDrawer.cs" /> | ||||
|     <Compile Include="NullImageEncoder.cs" /> | ||||
|     <Compile Include="Properties\AssemblyInfo.cs" /> | ||||
|     <Compile Include="ImageMagick\UnplayedCountIndicator.cs" /> | ||||
|   </ItemGroup> | ||||
| @ -99,6 +100,9 @@ | ||||
|   <ItemGroup> | ||||
|     <None Include="packages.config" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <EmbeddedResource Include="GDI\empty.png" /> | ||||
|   </ItemGroup> | ||||
|   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | ||||
|   <!-- To modify your build process, add your task inside one of the targets below and uncomment it.  | ||||
|        Other similar extension points exist, see Microsoft.Common.targets. | ||||
|  | ||||
| @ -1,5 +1,4 @@ | ||||
| using MediaBrowser.Common.IO; | ||||
| using MediaBrowser.Controller.Drawing; | ||||
| using MediaBrowser.Controller.Drawing; | ||||
| using MediaBrowser.Model.Drawing; | ||||
| using MediaBrowser.Model.Logging; | ||||
| using System; | ||||
| @ -23,7 +22,20 @@ namespace Emby.Drawing.GDI | ||||
|             _fileSystem = fileSystem; | ||||
|             _logger = logger; | ||||
| 
 | ||||
|             _logger.Info("GDI image processor initialized"); | ||||
|             LogInfo(); | ||||
|         } | ||||
| 
 | ||||
|         private void LogInfo() | ||||
|         { | ||||
|             _logger.Info("GDIImageEncoder starting"); | ||||
|             using (var stream = GetType().Assembly.GetManifestResourceStream(GetType().Namespace + ".empty.png")) | ||||
|             { | ||||
|                 using (var img = Image.FromStream(stream)) | ||||
|                 { | ||||
|                      | ||||
|                 } | ||||
|             } | ||||
|             _logger.Info("GDIImageEncoder started"); | ||||
|         } | ||||
| 
 | ||||
|         public string[] SupportedInputFormats | ||||
| @ -253,5 +265,15 @@ namespace Emby.Drawing.GDI | ||||
|         { | ||||
|             get { return "GDI"; } | ||||
|         } | ||||
| 
 | ||||
|         public bool SupportsImageCollageCreation | ||||
|         { | ||||
|             get { return true; } | ||||
|         } | ||||
| 
 | ||||
|         public bool SupportsImageEncoding | ||||
|         { | ||||
|             get { return true; } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
							
								
								
									
										
											BIN
										
									
								
								Emby.Drawing/GDI/empty.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Emby.Drawing/GDI/empty.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 158 B | 
| @ -17,12 +17,6 @@ namespace Emby.Drawing | ||||
|         /// <value>The supported output formats.</value> | ||||
|         ImageFormat[] SupportedOutputFormats { get; } | ||||
|         /// <summary> | ||||
|         /// Gets the size of the image. | ||||
|         /// </summary> | ||||
|         /// <param name="path">The path.</param> | ||||
|         /// <returns>ImageSize.</returns> | ||||
|         ImageSize GetImageSize(string path); | ||||
|         /// <summary> | ||||
|         /// Crops the white space. | ||||
|         /// </summary> | ||||
|         /// <param name="inputPath">The input path.</param> | ||||
| @ -49,5 +43,17 @@ namespace Emby.Drawing | ||||
|         /// </summary> | ||||
|         /// <value>The name.</value> | ||||
|         string Name { get; } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets a value indicating whether [supports image collage creation]. | ||||
|         /// </summary> | ||||
|         /// <value><c>true</c> if [supports image collage creation]; otherwise, <c>false</c>.</value> | ||||
|         bool SupportsImageCollageCreation { get; } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets a value indicating whether [supports image encoding]. | ||||
|         /// </summary> | ||||
|         /// <value><c>true</c> if [supports image encoding]; otherwise, <c>false</c>.</value> | ||||
|         bool SupportsImageEncoding { get; } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -9,7 +9,6 @@ using System; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using CommonIO; | ||||
| using MediaBrowser.Common.IO; | ||||
| 
 | ||||
| namespace Emby.Drawing.ImageMagick | ||||
| { | ||||
| @ -27,7 +26,7 @@ namespace Emby.Drawing.ImageMagick | ||||
|             _httpClient = httpClient; | ||||
|             _fileSystem = fileSystem; | ||||
| 
 | ||||
|             LogImageMagickVersion(); | ||||
|             LogVersion(); | ||||
|         } | ||||
| 
 | ||||
|         public string[] SupportedInputFormats | ||||
| @ -68,7 +67,7 @@ namespace Emby.Drawing.ImageMagick | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private void LogImageMagickVersion() | ||||
|         private void LogVersion() | ||||
|         { | ||||
|             _logger.Info("ImageMagick version: " + Wand.VersionString); | ||||
|             TestWebp(); | ||||
| @ -88,9 +87,9 @@ namespace Emby.Drawing.ImageMagick | ||||
|                     wand.SaveImage(tmpPath); | ||||
|                 } | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             catch  | ||||
|             { | ||||
|                 _logger.ErrorException("Error loading webp: ", ex); | ||||
|                 //_logger.ErrorException("Error loading webp: ", ex); | ||||
|                 _webpAvailable = false; | ||||
|             } | ||||
|         } | ||||
| @ -255,5 +254,15 @@ namespace Emby.Drawing.ImageMagick | ||||
|                 throw new ObjectDisposedException(GetType().Name); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public bool SupportsImageCollageCreation | ||||
|         { | ||||
|             get { return true; } | ||||
|         } | ||||
| 
 | ||||
|         public bool SupportsImageEncoding | ||||
|         { | ||||
|             get { return true; } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -354,14 +354,14 @@ namespace Emby.Drawing.ImageMagick | ||||
| 
 | ||||
|         private MagickWand BuildSquareCollageWand(List<string> paths, int width, int height) | ||||
|         { | ||||
|             var inputPaths = ImageHelpers.ProjectPaths(paths, 4); | ||||
|             var inputPaths = ImageHelpers.ProjectPaths(paths, 3); | ||||
|             using (var wandImages = new MagickWand(inputPaths.ToArray())) | ||||
|             { | ||||
|                 var wand = new MagickWand(width, height); | ||||
|                 wand.OpenImage("gradient:#111111-#111111"); | ||||
|                 using (var draw = new DrawingWand()) | ||||
|                 { | ||||
|                     var iSlice = Convert.ToInt32(width * .225); | ||||
|                     var iSlice = Convert.ToInt32(width * .3); | ||||
|                     int iTrans = Convert.ToInt32(height * .25); | ||||
|                     int iHeight = Convert.ToInt32(height * .63); | ||||
|                     var horizontalImagePadding = Convert.ToInt32(width * 0.02); | ||||
|  | ||||
| @ -110,6 +110,15 @@ namespace Emby.Drawing | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         public bool SupportsImageCollageCreation | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return _imageEncoder.SupportsImageCollageCreation; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private string ResizedImageCachePath | ||||
|         { | ||||
|             get | ||||
| @ -170,6 +179,11 @@ namespace Emby.Drawing | ||||
| 
 | ||||
|             var originalImagePath = originalImage.Path; | ||||
| 
 | ||||
|             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 | ||||
| @ -178,7 +192,7 @@ namespace Emby.Drawing | ||||
| 
 | ||||
|             var dateModified = originalImage.DateModified; | ||||
| 
 | ||||
|             if (options.CropWhiteSpace) | ||||
|             if (options.CropWhiteSpace && _imageEncoder.SupportsImageEncoding) | ||||
|             { | ||||
|                 var tuple = await GetWhitespaceCroppedImage(originalImagePath, dateModified).ConfigureAwait(false); | ||||
| 
 | ||||
| @ -295,6 +309,11 @@ namespace Emby.Drawing | ||||
| 
 | ||||
|                 _imageEncoder.CropWhiteSpace(originalImagePath, croppedImagePath); | ||||
|             } | ||||
|             catch (NotImplementedException) | ||||
|             { | ||||
|                 // No need to spam the log with an error message | ||||
|                 return new Tuple<string, DateTime>(originalImagePath, dateModified); | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 // We have to have a catch-all here because some of the .net image methods throw a plain old Exception | ||||
|  | ||||
							
								
								
									
										64
									
								
								Emby.Drawing/NullImageEncoder.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								Emby.Drawing/NullImageEncoder.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,64 @@ | ||||
| using System; | ||||
| using MediaBrowser.Controller.Drawing; | ||||
| using MediaBrowser.Model.Drawing; | ||||
| 
 | ||||
| namespace Emby.Drawing | ||||
| { | ||||
|     public class NullImageEncoder : IImageEncoder | ||||
|     { | ||||
|         public string[] SupportedInputFormats | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return new[] | ||||
|                 { | ||||
|                     "png", | ||||
|                     "jpeg", | ||||
|                     "jpg" | ||||
|                 }; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public ImageFormat[] SupportedOutputFormats | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return new[] { ImageFormat.Jpg, ImageFormat.Png }; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public void CropWhiteSpace(string inputPath, string outputPath) | ||||
|         { | ||||
|             throw new NotImplementedException(); | ||||
|         } | ||||
| 
 | ||||
|         public void EncodeImage(string inputPath, string outputPath, int width, int height, int quality, ImageProcessingOptions options) | ||||
|         { | ||||
|             throw new NotImplementedException(); | ||||
|         } | ||||
| 
 | ||||
|         public void CreateImageCollage(ImageCollageOptions options) | ||||
|         { | ||||
|             throw new NotImplementedException(); | ||||
|         } | ||||
| 
 | ||||
|         public string Name | ||||
|         { | ||||
|             get { return "Null Image Encoder"; } | ||||
|         } | ||||
| 
 | ||||
|         public bool SupportsImageCollageCreation | ||||
|         { | ||||
|             get { return false; } | ||||
|         } | ||||
| 
 | ||||
|         public bool SupportsImageEncoding | ||||
|         { | ||||
|             get { return false; } | ||||
|         } | ||||
| 
 | ||||
|         public void Dispose() | ||||
|         { | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -564,7 +564,14 @@ namespace MediaBrowser.Api.Images | ||||
| 
 | ||||
|             }).ToList() : new List<IImageEnhancer>(); | ||||
| 
 | ||||
|             var format = GetOutputFormat(request, imageInfo, supportedImageEnhancers); | ||||
|             var cropwhitespace = request.Type == ImageType.Logo || request.Type == ImageType.Art; | ||||
| 
 | ||||
|             if (request.CropWhitespace.HasValue) | ||||
|             { | ||||
|                 cropwhitespace = request.CropWhitespace.Value; | ||||
|             } | ||||
| 
 | ||||
|             var format = GetOutputFormat(request, imageInfo, cropwhitespace, supportedImageEnhancers); | ||||
|             var contentType = GetMimeType(format, imageInfo.Path); | ||||
| 
 | ||||
|             var cacheGuid = new Guid(_imageProcessor.GetImageCacheTag(item, imageInfo, supportedImageEnhancers)); | ||||
| @ -585,6 +592,7 @@ namespace MediaBrowser.Api.Images | ||||
|             return GetImageResult(item, | ||||
|                 request, | ||||
|                 imageInfo, | ||||
|                 cropwhitespace, | ||||
|                 format, | ||||
|                 supportedImageEnhancers, | ||||
|                 contentType, | ||||
| @ -597,6 +605,7 @@ namespace MediaBrowser.Api.Images | ||||
|         private async Task<object> GetImageResult(IHasImages item, | ||||
|             ImageRequest request, | ||||
|             ItemImageInfo image, | ||||
|             bool cropwhitespace, | ||||
|             ImageFormat format, | ||||
|             List<IImageEnhancer> enhancers, | ||||
|             string contentType, | ||||
| @ -604,13 +613,6 @@ namespace MediaBrowser.Api.Images | ||||
|             IDictionary<string, string> headers, | ||||
|             bool isHeadRequest) | ||||
|         { | ||||
|             var cropwhitespace = request.Type == ImageType.Logo || request.Type == ImageType.Art; | ||||
| 
 | ||||
|             if (request.CropWhitespace.HasValue) | ||||
|             { | ||||
|                 cropwhitespace = request.CropWhitespace.Value; | ||||
|             } | ||||
| 
 | ||||
|             var options = new ImageProcessingOptions | ||||
|             { | ||||
|                 CropWhiteSpace = cropwhitespace, | ||||
| @ -644,7 +646,7 @@ namespace MediaBrowser.Api.Images | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|         private ImageFormat GetOutputFormat(ImageRequest request, ItemImageInfo image, List<IImageEnhancer> enhancers) | ||||
|         private ImageFormat GetOutputFormat(ImageRequest request, ItemImageInfo image, bool cropwhitespace, List<IImageEnhancer> enhancers) | ||||
|         { | ||||
|             if (!string.IsNullOrWhiteSpace(request.Format)) | ||||
|             { | ||||
| @ -655,10 +657,37 @@ namespace MediaBrowser.Api.Images | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             var extension = Path.GetExtension(image.Path); | ||||
|             ImageFormat? inputFormat = null; | ||||
| 
 | ||||
|             if (string.Equals(extension, ".jpg", StringComparison.OrdinalIgnoreCase) || | ||||
|                 string.Equals(extension, ".jpeg", StringComparison.OrdinalIgnoreCase)) | ||||
|             { | ||||
|                 inputFormat = ImageFormat.Jpg; | ||||
|             } | ||||
|             else if (string.Equals(extension, ".png", StringComparison.OrdinalIgnoreCase)) | ||||
|             { | ||||
|                 inputFormat = ImageFormat.Png; | ||||
|             } | ||||
| 
 | ||||
|             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(); | ||||
| 
 | ||||
|             if (serverFormats.Contains(ImageFormat.Webp) && | ||||
|                 GetClientSupportedFormats().Contains(ImageFormat.Webp)) | ||||
|             // Client doesn't care about format, so start with webp if supported | ||||
|             if (serverFormats.Contains(ImageFormat.Webp) && clientSupportedFormats.Contains(ImageFormat.Webp)) | ||||
|             { | ||||
|                 return ImageFormat.Webp; | ||||
|             } | ||||
| @ -668,10 +697,7 @@ namespace MediaBrowser.Api.Images | ||||
|                 return ImageFormat.Png; | ||||
|             } | ||||
| 
 | ||||
|             var extension = Path.GetExtension(image.Path); | ||||
| 
 | ||||
|             if (string.Equals(extension, ".jpg", StringComparison.OrdinalIgnoreCase) || | ||||
|                 string.Equals(extension, ".jpeg", StringComparison.OrdinalIgnoreCase)) | ||||
|             if (inputFormat.HasValue && inputFormat.Value == ImageFormat.Jpg) | ||||
|             { | ||||
|                 return ImageFormat.Jpg; | ||||
|             } | ||||
|  | ||||
| @ -52,7 +52,7 @@ namespace MediaBrowser.Api.Library | ||||
|         /// Gets or sets the path. | ||||
|         /// </summary> | ||||
|         /// <value>The path.</value> | ||||
|         public string Path { get; set; } | ||||
|         public string[] Paths { get; set; } | ||||
|     } | ||||
| 
 | ||||
|     [Route("/Library/VirtualFolders", "DELETE")] | ||||
| @ -207,11 +207,12 @@ namespace MediaBrowser.Api.Library | ||||
|                 throw new ArgumentException("There is already a media library with the name " + name + "."); | ||||
|             } | ||||
| 
 | ||||
|             if (!string.IsNullOrWhiteSpace(request.Path)) | ||||
|             if (request.Paths != null) | ||||
|             { | ||||
|                 if (!_fileSystem.DirectoryExists(request.Path)) | ||||
|                 var invalidpath = request.Paths.FirstOrDefault(i => !_fileSystem.DirectoryExists(i)); | ||||
|                 if (invalidpath != null) | ||||
|                 { | ||||
|                     throw new DirectoryNotFoundException("The specified folder does not exist."); | ||||
|                     throw new ArgumentException("The specified path does not exist: " + invalidpath + "."); | ||||
|                 } | ||||
|             } | ||||
|              | ||||
| @ -231,9 +232,12 @@ namespace MediaBrowser.Api.Library | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 if (!string.IsNullOrWhiteSpace(request.Path)) | ||||
|                 if (request.Paths != null) | ||||
|                 { | ||||
|                     LibraryHelpers.AddMediaPath(_fileSystem, request.Name, request.Path, _appPaths); | ||||
|                     foreach (var path in request.Paths) | ||||
|                     { | ||||
|                         LibraryHelpers.AddMediaPath(_fileSystem, request.Name, path, _appPaths); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             finally | ||||
|  | ||||
| @ -105,5 +105,11 @@ namespace MediaBrowser.Controller.Drawing | ||||
|         /// </summary> | ||||
|         /// <param name="options">The options.</param> | ||||
|         Task CreateImageCollage(ImageCollageOptions options); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets a value indicating whether [supports image collage creation]. | ||||
|         /// </summary> | ||||
|         /// <value><c>true</c> if [supports image collage creation]; otherwise, <c>false</c>.</value> | ||||
|         bool SupportsImageCollageCreation { get; } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -87,15 +87,18 @@ namespace MediaBrowser.Providers.Movies | ||||
|             if (string.IsNullOrEmpty(tmdbId)) | ||||
|             { | ||||
|                 movieInfo = await MovieDbProvider.Current.FetchMainResult(imdbId, false, language, cancellationToken).ConfigureAwait(false); | ||||
|                 if (movieInfo == null) return item; | ||||
| 
 | ||||
|                 if (movieInfo != null) | ||||
|                 { | ||||
|                     tmdbId = movieInfo.id.ToString(_usCulture); | ||||
| 
 | ||||
|                     dataFilePath = MovieDbProvider.Current.GetDataFilePath(tmdbId, language); | ||||
|                     _fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath)); | ||||
|                     _jsonSerializer.SerializeToFile(movieInfo, dataFilePath); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (!string.IsNullOrWhiteSpace(tmdbId)) | ||||
|             { | ||||
|                 await MovieDbProvider.Current.EnsureMovieInfo(tmdbId, language, cancellationToken).ConfigureAwait(false); | ||||
| 
 | ||||
|                 dataFilePath = dataFilePath ?? MovieDbProvider.Current.GetDataFilePath(tmdbId, language); | ||||
| @ -103,6 +106,7 @@ namespace MediaBrowser.Providers.Movies | ||||
| 
 | ||||
|                 ProcessMainInfo(item, preferredCountryCode, movieInfo); | ||||
|                 item.HasMetadata = true; | ||||
|             } | ||||
| 
 | ||||
|             return item; | ||||
|         } | ||||
|  | ||||
| @ -16,9 +16,11 @@ using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Globalization; | ||||
| using System.IO; | ||||
| using System.Net; | ||||
| using System.Threading; | ||||
| using System.Threading.Tasks; | ||||
| using CommonIO; | ||||
| using MediaBrowser.Model.Net; | ||||
| 
 | ||||
| namespace MediaBrowser.Providers.Movies | ||||
| { | ||||
| @ -309,6 +311,8 @@ namespace MediaBrowser.Providers.Movies | ||||
|             var cacheMode = isTmdbId ? CacheMode.None : CacheMode.Unconditional; | ||||
|             var cacheLength = TimeSpan.FromDays(3); | ||||
| 
 | ||||
|             try | ||||
|             { | ||||
|                 using (var json = await GetMovieDbResponse(new HttpRequestOptions | ||||
|                 { | ||||
|                     Url = url, | ||||
| @ -321,6 +325,17 @@ namespace MediaBrowser.Providers.Movies | ||||
|                 { | ||||
|                     mainResult = _jsonSerializer.DeserializeFromStream<CompleteMovieData>(json); | ||||
|                 } | ||||
|             } | ||||
|             catch (HttpException ex) | ||||
|             { | ||||
|                 // Return null so that callers know there is no metadata for this id | ||||
|                 if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.NotFound) | ||||
|                 { | ||||
|                     return null; | ||||
|                 } | ||||
| 
 | ||||
|                 throw; | ||||
|             } | ||||
| 
 | ||||
|             cancellationToken.ThrowIfCancellationRequested(); | ||||
| 
 | ||||
|  | ||||
| @ -10,6 +10,7 @@ using MediaBrowser.Model.Entities; | ||||
| using MediaBrowser.Server.Implementations.Photos; | ||||
| using MoreLinq; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Threading.Tasks; | ||||
| using CommonIO; | ||||
| @ -74,7 +75,27 @@ namespace MediaBrowser.Server.Implementations.Collections | ||||
|                 .DistinctBy(i => i.Id) | ||||
|                 .ToList(); | ||||
| 
 | ||||
|             return Task.FromResult(GetFinalItems(items)); | ||||
|             return Task.FromResult(GetFinalItems(items, 2)); | ||||
|         } | ||||
| 
 | ||||
|         protected override async Task<string> CreateImage(IHasImages item, List<BaseItem> itemsWithImages, string outputPathWithoutExtension, ImageType imageType, int imageIndex) | ||||
|         { | ||||
|             var image = itemsWithImages | ||||
|                 .Where(i => i.HasImage(ImageType.Primary) && i.GetImageInfo(ImageType.Primary, 0).IsLocalFile && Path.HasExtension(i.GetImagePath(ImageType.Primary))) | ||||
|                 .Select(i => i.GetImagePath(ImageType.Primary)) | ||||
|                 .FirstOrDefault(); | ||||
| 
 | ||||
|             if (string.IsNullOrWhiteSpace(image)) | ||||
|             { | ||||
|                 return null; | ||||
|             } | ||||
| 
 | ||||
|             var ext = Path.GetExtension(image); | ||||
| 
 | ||||
|             var outputPath = Path.ChangeExtension(outputPathWithoutExtension, ext); | ||||
|             File.Copy(image, outputPath); | ||||
| 
 | ||||
|             return outputPath; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -265,6 +265,11 @@ namespace MediaBrowser.Server.Implementations.Devices | ||||
|                 return true; | ||||
|             } | ||||
| 
 | ||||
|             if (policy.IsAdministrator) | ||||
|             { | ||||
|                 return true; | ||||
|             } | ||||
| 
 | ||||
|             return ListHelper.ContainsIgnoreCase(policy.EnabledDevices, id); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -88,7 +88,7 @@ namespace MediaBrowser.Server.Implementations.IO | ||||
|             // This is an arbitraty amount of time, but delay it because file system writes often trigger events long after the file was actually written to. | ||||
|             // Seeing long delays in some situations, especially over the network, sometimes up to 45 seconds | ||||
|             // But if we make this delay too high, we risk missing legitimate changes, such as user adding a new file, or hand-editing metadata | ||||
|             await Task.Delay(20000).ConfigureAwait(false); | ||||
|             await Task.Delay(25000).ConfigureAwait(false); | ||||
| 
 | ||||
|             string val; | ||||
|             _tempIgnoredPaths.TryRemove(path, out val); | ||||
|  | ||||
| @ -675,7 +675,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV | ||||
|                     Name = info.Name, | ||||
|                     EpisodeTitle = info.EpisodeTitle, | ||||
|                     ProgramId = info.Id, | ||||
|                     HasImage = info.HasImage, | ||||
|                     ImagePath = info.ImagePath, | ||||
|                     ImageUrl = info.ImageUrl, | ||||
|                     OriginalAirDate = info.OriginalAirDate, | ||||
|  | ||||
| @ -333,7 +333,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings | ||||
|                 IsRepeat = repeat, | ||||
|                 IsSeries = showType.IndexOf("series", StringComparison.OrdinalIgnoreCase) != -1, | ||||
|                 ImageUrl = imageUrl, | ||||
|                 HasImage = details.hasImageArtwork, | ||||
|                 IsKids = string.Equals(details.audience, "children", StringComparison.OrdinalIgnoreCase), | ||||
|                 IsSports = showType.IndexOf("sports", StringComparison.OrdinalIgnoreCase) != -1, | ||||
|                 IsMovie = showType.IndexOf("movie", StringComparison.OrdinalIgnoreCase) != -1 || showType.IndexOf("film", StringComparison.OrdinalIgnoreCase) != -1, | ||||
|  | ||||
| @ -46,11 +46,6 @@ namespace MediaBrowser.Server.Implementations.Persistence | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         protected virtual void DisposeInternal() | ||||
|         { | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         protected abstract void CloseConnection(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -92,11 +92,11 @@ namespace MediaBrowser.Server.Implementations.Photos | ||||
|             string cacheKey, | ||||
|             CancellationToken cancellationToken) | ||||
|         { | ||||
|             var outputPath = Path.Combine(ApplicationPaths.TempDirectory, Guid.NewGuid() + ".png"); | ||||
|             FileSystem.CreateDirectory(Path.GetDirectoryName(outputPath)); | ||||
|             var imageCreated = await CreateImage(item, itemsWithImages, outputPath, imageType, 0).ConfigureAwait(false); | ||||
|             var outputPathWithoutExtension = Path.Combine(ApplicationPaths.TempDirectory, Guid.NewGuid().ToString("N")); | ||||
|             FileSystem.CreateDirectory(Path.GetDirectoryName(outputPathWithoutExtension)); | ||||
|             string outputPath = await CreateImage(item, itemsWithImages, outputPathWithoutExtension, imageType, 0).ConfigureAwait(false); | ||||
| 
 | ||||
|             if (!imageCreated) | ||||
|             if (string.IsNullOrWhiteSpace(outputPath)) | ||||
|             { | ||||
|                 return ItemUpdateType.None; | ||||
|             } | ||||
| @ -117,7 +117,7 @@ namespace MediaBrowser.Server.Implementations.Photos | ||||
|             return parts.GetMD5().ToString("N"); | ||||
|         } | ||||
| 
 | ||||
|         protected Task<bool> CreateThumbCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath) | ||||
|         protected Task<string> CreateThumbCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath) | ||||
|         { | ||||
|             return CreateCollage(primaryItem, items, outputPath, 640, 360); | ||||
|         } | ||||
| @ -144,22 +144,22 @@ namespace MediaBrowser.Server.Implementations.Photos | ||||
|                 .Where(i => !string.IsNullOrWhiteSpace(i)); | ||||
|         } | ||||
| 
 | ||||
|         protected Task<bool> CreatePosterCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath) | ||||
|         protected Task<string> CreatePosterCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath) | ||||
|         { | ||||
|             return CreateCollage(primaryItem, items, outputPath, 400, 600); | ||||
|         } | ||||
| 
 | ||||
|         protected Task<bool> CreateSquareCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath) | ||||
|         protected Task<string> CreateSquareCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath) | ||||
|         { | ||||
|             return CreateCollage(primaryItem, items, outputPath, 600, 600); | ||||
|         } | ||||
| 
 | ||||
|         protected Task<bool> CreateThumbCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath, int width, int height) | ||||
|         protected Task<string> CreateThumbCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath, int width, int height) | ||||
|         { | ||||
|             return CreateCollage(primaryItem, items, outputPath, width, height); | ||||
|         } | ||||
| 
 | ||||
|         private Task<bool> CreateCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath, int width, int height) | ||||
|         private async Task<string> CreateCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath, int width, int height) | ||||
|         { | ||||
|             FileSystem.CreateDirectory(Path.GetDirectoryName(outputPath)); | ||||
| 
 | ||||
| @ -173,11 +173,16 @@ namespace MediaBrowser.Server.Implementations.Photos | ||||
| 
 | ||||
|             if (options.InputPaths.Length == 0) | ||||
|             { | ||||
|                 return Task.FromResult(false); | ||||
|                 return null; | ||||
|             } | ||||
| 
 | ||||
|             ImageProcessor.CreateImageCollage(options); | ||||
|             return Task.FromResult(true); | ||||
|             if (!ImageProcessor.SupportsImageCollageCreation) | ||||
|             { | ||||
|                 return null; | ||||
|             } | ||||
| 
 | ||||
|             await ImageProcessor.CreateImageCollage(options).ConfigureAwait(false); | ||||
|             return outputPath; | ||||
|         } | ||||
| 
 | ||||
|         public string Name | ||||
| @ -185,17 +190,19 @@ namespace MediaBrowser.Server.Implementations.Photos | ||||
|             get { return "Dynamic Image Provider"; } | ||||
|         } | ||||
| 
 | ||||
|         protected virtual async Task<bool> CreateImage(IHasImages item, | ||||
|         protected virtual async Task<string> CreateImage(IHasImages item, | ||||
|             List<BaseItem> itemsWithImages, | ||||
|             string outputPath, | ||||
|             string outputPathWithoutExtension, | ||||
|             ImageType imageType, | ||||
|             int imageIndex) | ||||
|         { | ||||
|             if (itemsWithImages.Count == 0) | ||||
|             { | ||||
|                 return false; | ||||
|                 return null; | ||||
|             } | ||||
| 
 | ||||
|             string outputPath = Path.ChangeExtension(outputPathWithoutExtension, ".png"); | ||||
| 
 | ||||
|             if (imageType == ImageType.Thumb) | ||||
|             { | ||||
|                 return await CreateThumbCollage(item, itemsWithImages, outputPath).ConfigureAwait(false); | ||||
| @ -207,7 +214,7 @@ namespace MediaBrowser.Server.Implementations.Photos | ||||
|                 { | ||||
|                     return await CreateSquareCollage(item, itemsWithImages, outputPath).ConfigureAwait(false); | ||||
|                 } | ||||
|                 if (item is PhotoAlbum || item is Playlist) | ||||
|                 if (item is Playlist) | ||||
|                 { | ||||
|                     return await CreateSquareCollage(item, itemsWithImages, outputPath).ConfigureAwait(false); | ||||
|                 } | ||||
| @ -320,7 +327,7 @@ namespace MediaBrowser.Server.Implementations.Photos | ||||
|             var random = DateTime.Now.DayOfYear % MaxImageAgeDays; | ||||
| 
 | ||||
|             return items | ||||
|                 .OrderBy(i => (random + "" + items.IndexOf(i)).GetMD5()) | ||||
|                 .OrderBy(i => (random + string.Empty + items.IndexOf(i)).GetMD5()) | ||||
|                 .Take(limit) | ||||
|                 .OrderBy(i => i.Name) | ||||
|                 .ToList(); | ||||
|  | ||||
| @ -1,9 +1,9 @@ | ||||
| using MediaBrowser.Common.Configuration; | ||||
| using MediaBrowser.Common.IO; | ||||
| using MediaBrowser.Controller.Drawing; | ||||
| using MediaBrowser.Controller.Entities; | ||||
| using MediaBrowser.Controller.Providers; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Threading.Tasks; | ||||
| using CommonIO; | ||||
| @ -20,9 +20,26 @@ namespace MediaBrowser.Server.Implementations.Photos | ||||
|         protected override Task<List<BaseItem>> GetItemsWithImages(IHasImages item) | ||||
|         { | ||||
|             var photoAlbum = (PhotoAlbum)item; | ||||
|             var items = GetFinalItems(photoAlbum.Children.ToList()); | ||||
|             var items = GetFinalItems(photoAlbum.Children.ToList(), 1); | ||||
| 
 | ||||
|             return Task.FromResult(items); | ||||
|         } | ||||
| 
 | ||||
|         protected override async Task<string> CreateImage(IHasImages item, List<BaseItem> itemsWithImages, string outputPathWithoutExtension, Model.Entities.ImageType imageType, int imageIndex) | ||||
|         { | ||||
|             var photoFile = itemsWithImages.Where(i => Path.HasExtension(i.Path)).Select(i => i.Path).FirstOrDefault(); | ||||
| 
 | ||||
|             if (string.IsNullOrWhiteSpace(photoFile)) | ||||
|             { | ||||
|                 return null; | ||||
|             } | ||||
| 
 | ||||
|             var ext = Path.GetExtension(photoFile); | ||||
| 
 | ||||
|             var outputPath = Path.ChangeExtension(outputPathWithoutExtension, ext); | ||||
|             File.Copy(photoFile, outputPath); | ||||
| 
 | ||||
|             return outputPath; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -10,6 +10,7 @@ using MediaBrowser.Server.Implementations.Photos; | ||||
| using MoreLinq; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Threading.Tasks; | ||||
| using CommonIO; | ||||
| @ -97,13 +98,15 @@ namespace MediaBrowser.Server.Implementations.UserViews | ||||
|             return item is CollectionFolder; | ||||
|         } | ||||
| 
 | ||||
|         protected override async Task<bool> CreateImage(IHasImages item, List<BaseItem> itemsWithImages, string outputPath, ImageType imageType, int imageIndex) | ||||
|         protected override async Task<string> CreateImage(IHasImages item, List<BaseItem> itemsWithImages, string outputPathWithoutExtension, ImageType imageType, int imageIndex) | ||||
|         { | ||||
|             var outputPath = Path.ChangeExtension(outputPathWithoutExtension, ".png"); | ||||
| 
 | ||||
|             if (imageType == ImageType.Primary) | ||||
|             { | ||||
|                 if (itemsWithImages.Count == 0) | ||||
|                 { | ||||
|                     return false; | ||||
|                     return null; | ||||
|                 } | ||||
| 
 | ||||
|                 return await CreateThumbCollage(item, itemsWithImages, outputPath, 960, 540).ConfigureAwait(false); | ||||
|  | ||||
| @ -11,6 +11,7 @@ using MediaBrowser.Server.Implementations.Photos; | ||||
| using MoreLinq; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Threading.Tasks; | ||||
| using CommonIO; | ||||
| @ -161,14 +162,16 @@ namespace MediaBrowser.Server.Implementations.UserViews | ||||
|             return collectionStripViewTypes.Contains(view.ViewType ?? string.Empty); | ||||
|         } | ||||
| 
 | ||||
|         protected override async Task<bool> CreateImage(IHasImages item, List<BaseItem> itemsWithImages, string outputPath, ImageType imageType, int imageIndex) | ||||
|         protected override async Task<string> CreateImage(IHasImages item, List<BaseItem> itemsWithImages, string outputPathWithoutExtension, ImageType imageType, int imageIndex) | ||||
|         { | ||||
|             var outputPath = Path.ChangeExtension(outputPathWithoutExtension, ".png"); | ||||
| 
 | ||||
|             var view = (UserView)item; | ||||
|             if (imageType == ImageType.Primary && IsUsingCollectionStrip(view)) | ||||
|             { | ||||
|                 if (itemsWithImages.Count == 0) | ||||
|                 { | ||||
|                     return false; | ||||
|                     return null; | ||||
|                 } | ||||
| 
 | ||||
|                 return await CreateThumbCollage(item, itemsWithImages, outputPath, 960, 540).ConfigureAwait(false); | ||||
|  | ||||
| @ -577,12 +577,21 @@ namespace MediaBrowser.Server.Startup.Common | ||||
|                 } | ||||
|                 catch (Exception ex) | ||||
|                 { | ||||
|                     Logger.ErrorException("Error loading ImageMagick. Will revert to GDI.", ex); | ||||
|                     Logger.Error("Error loading ImageMagick. Will revert to GDI."); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             try | ||||
|             { | ||||
|                 return new GDIImageEncoder(FileSystemManager, LogManager.GetLogger("GDI")); | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 Logger.Error("Error loading GDI. Will revert to NullImageEncoder."); | ||||
|             } | ||||
| 
 | ||||
|             return new NullImageEncoder(); | ||||
|         } | ||||
| 
 | ||||
|         protected override INetworkManager CreateNetworkManager(ILogger logger) | ||||
|         { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user