diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index 120a4cedb..8ceec8529 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -18,6 +18,7 @@ using System.Threading; using System.Threading.Tasks; using CommonIO; using Emby.Drawing.Common; +using MediaBrowser.Controller.Library; namespace Emby.Drawing { @@ -53,18 +54,20 @@ namespace Emby.Drawing private readonly IServerApplicationPaths _appPaths; private readonly IImageEncoder _imageEncoder; private readonly SemaphoreSlim _imageProcessingSemaphore; + private readonly Func _libraryManager; public ImageProcessor(ILogger logger, IServerApplicationPaths appPaths, IFileSystem fileSystem, IJsonSerializer jsonSerializer, IImageEncoder imageEncoder, - int maxConcurrentImageProcesses) + int maxConcurrentImageProcesses, Func libraryManager) { _logger = logger; _fileSystem = fileSystem; _jsonSerializer = jsonSerializer; _imageEncoder = imageEncoder; + _libraryManager = libraryManager; _appPaths = appPaths; ImageEnhancers = new List(); @@ -158,7 +161,14 @@ namespace Emby.Drawing throw new ArgumentNullException("options"); } - var originalImagePath = options.Image.Path; + var originalImage = options.Image; + + if (!originalImage.IsLocalFile) + { + originalImage = await _libraryManager().ConvertImageToLocal(options.Item, originalImage, options.ImageIndex).ConfigureAwait(false); + } + + var originalImagePath = originalImage.Path; if (options.HasDefaultOptions(originalImagePath) && options.Enhancers.Count == 0 && !options.CropWhiteSpace) { @@ -166,7 +176,7 @@ namespace Emby.Drawing return originalImagePath; } - var dateModified = options.Image.DateModified; + var dateModified = originalImage.DateModified; if (options.CropWhiteSpace) { @@ -181,7 +191,7 @@ namespace Emby.Drawing var tuple = await GetEnhancedImage(new ItemImageInfo { DateModified = dateModified, - Type = options.Image.Type, + Type = originalImage.Type, Path = originalImagePath }, options.Item, options.ImageIndex, options.Enhancers).ConfigureAwait(false); @@ -360,21 +370,16 @@ namespace Emby.Drawing return GetCachePath(ResizedImageCachePath, filename, "." + format.ToString().ToLower()); } - /// - /// Gets the size of the image. - /// - /// The path. - /// ImageSize. - public ImageSize GetImageSize(string path) - { - return GetImageSize(path, _fileSystem.GetLastWriteTimeUtc(path), false); - } - public ImageSize GetImageSize(ItemImageInfo info) { return GetImageSize(info.Path, info.DateModified, false); } + public ImageSize GetImageSize(string path) + { + return GetImageSize(path, _fileSystem.GetLastWriteTimeUtc(path), false); + } + /// /// Gets the size of the image. /// @@ -800,7 +805,6 @@ namespace Emby.Drawing return false; } - }); } diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs index d264b896d..65b837eac 100644 --- a/MediaBrowser.Api/Images/ImageService.cs +++ b/MediaBrowser.Api/Images/ImageService.cs @@ -319,10 +319,13 @@ namespace MediaBrowser.Api.Images try { - var size = _imageProcessor.GetImageSize(info); + if (info.IsLocalFile) + { + var size = _imageProcessor.GetImageSize(info); - width = Convert.ToInt32(size.Width); - height = Convert.ToInt32(size.Height); + width = Convert.ToInt32(size.Width); + height = Convert.ToInt32(size.Height); + } } catch { diff --git a/MediaBrowser.Api/Social/SharingService.cs b/MediaBrowser.Api/Social/SharingService.cs index 608008455..7d61c24ec 100644 --- a/MediaBrowser.Api/Social/SharingService.cs +++ b/MediaBrowser.Api/Social/SharingService.cs @@ -124,7 +124,7 @@ namespace MediaBrowser.Api.Social Task.WaitAll(task); } - public object Get(GetShareImage request) + public async Task Get(GetShareImage request) { var share = _sharingManager.GetShareInfo(request.Id); @@ -143,7 +143,21 @@ namespace MediaBrowser.Api.Social if (image != null) { - return ToStaticFileResult(image.Path); + if (image.IsLocalFile) + { + return ToStaticFileResult(image.Path); + } + + try + { + // Don't fail the request over this + var updatedImage = await _libraryManager.ConvertImageToLocal(item, image, 0).ConfigureAwait(false); + return ToStaticFileResult(updatedImage.Path); + } + catch + { + + } } // Grab a dlna icon if nothing else is available diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs index aeb817392..fea6b979d 100644 --- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs +++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs @@ -25,13 +25,6 @@ namespace MediaBrowser.Controller.Drawing /// The image enhancers. IEnumerable ImageEnhancers { get; } - /// - /// Gets the size of the image. - /// - /// The path. - /// ImageSize. - ImageSize GetImageSize(string path); - /// /// Gets the size of the image. /// @@ -39,6 +32,13 @@ namespace MediaBrowser.Controller.Drawing /// ImageSize. ImageSize GetImageSize(ItemImageInfo info); + /// + /// Gets the size of the image. + /// + /// The path. + /// ImageSize. + ImageSize GetImageSize(string path); + /// /// Adds the parts. /// diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 22ca607ba..a342cf0e3 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -597,7 +597,7 @@ namespace MediaBrowser.Controller.Entities /// Gets or sets the custom rating. /// /// The custom rating. - [IgnoreDataMember] + //[IgnoreDataMember] public string CustomRating { get; set; } /// @@ -628,7 +628,7 @@ namespace MediaBrowser.Controller.Entities /// Gets or sets the community rating. /// /// The community rating. - [IgnoreDataMember] + //[IgnoreDataMember] public float? CommunityRating { get; set; } /// @@ -654,7 +654,7 @@ namespace MediaBrowser.Controller.Entities /// This could be episode number, album track number, etc. /// /// The index number. - [IgnoreDataMember] + //[IgnoreDataMember] public int? IndexNumber { get; set; } /// @@ -1432,6 +1432,23 @@ namespace MediaBrowser.Controller.Entities return GetImageInfo(type, imageIndex) != null; } + public void SetImage(ItemImageInfo image, int index) + { + if (image.Type == ImageType.Chapter) + { + throw new ArgumentException("Cannot set chapter images using SetImagePath"); + } + + var existingImage = GetImageInfo(image.Type, index); + + if (existingImage != null) + { + ImageInfos.Remove(existingImage); + } + + ImageInfos.Add(image); + } + public void SetImagePath(ImageType type, int index, FileSystemMetadata file) { if (type == ImageType.Chapter) @@ -1473,18 +1490,21 @@ namespace MediaBrowser.Controller.Entities // Remove it from the item RemoveImage(info); - // Delete the source file - var currentFile = new FileInfo(info.Path); - - // Deletion will fail if the file is hidden so remove the attribute first - if (currentFile.Exists) + if (info.IsLocalFile) { - if ((currentFile.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden) - { - currentFile.Attributes &= ~FileAttributes.Hidden; - } + // Delete the source file + var currentFile = new FileInfo(info.Path); - FileSystem.DeleteFile(currentFile.FullName); + // Deletion will fail if the file is hidden so remove the attribute first + if (currentFile.Exists) + { + if ((currentFile.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden) + { + currentFile.Attributes &= ~FileAttributes.Hidden; + } + + FileSystem.DeleteFile(currentFile.FullName); + } } return UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); @@ -1505,11 +1525,16 @@ namespace MediaBrowser.Controller.Entities /// public bool ValidateImages(IDirectoryService directoryService) { - var allDirectories = ImageInfos.Select(i => System.IO.Path.GetDirectoryName(i.Path)).Distinct(StringComparer.OrdinalIgnoreCase).ToList(); - var allFiles = allDirectories.SelectMany(directoryService.GetFiles).Select(i => i.FullName).ToList(); + var allFiles = ImageInfos + .Where(i => i.IsLocalFile) + .Select(i => System.IO.Path.GetDirectoryName(i.Path)) + .Distinct(StringComparer.OrdinalIgnoreCase) + .SelectMany(directoryService.GetFiles) + .Select(i => i.FullName) + .ToList(); var deletedImages = ImageInfos - .Where(image => !allFiles.Contains(image.Path, StringComparer.OrdinalIgnoreCase)) + .Where(image => image.IsLocalFile && !allFiles.Contains(image.Path, StringComparer.OrdinalIgnoreCase)) .ToList(); if (deletedImages.Count > 0) @@ -1619,7 +1644,10 @@ namespace MediaBrowser.Controller.Entities } else { - existing.DateModified = FileSystem.GetLastWriteTimeUtc(newImage); + if (existing.IsLocalFile) + { + existing.DateModified = FileSystem.GetLastWriteTimeUtc(newImage); + } } } @@ -1628,7 +1656,7 @@ namespace MediaBrowser.Controller.Entities var newImagePaths = images.Select(i => i.FullName).ToList(); var deleted = existingImages - .Where(i => !newImagePaths.Contains(i.Path, StringComparer.OrdinalIgnoreCase) && !FileSystem.FileExists(i.Path)) + .Where(i => i.IsLocalFile && !newImagePaths.Contains(i.Path, StringComparer.OrdinalIgnoreCase) && !FileSystem.FileExists(i.Path)) .ToList(); ImageInfos = ImageInfos.Except(deleted).ToList(); @@ -1679,6 +1707,12 @@ namespace MediaBrowser.Controller.Entities return Task.FromResult(true); } + if (!info1.IsLocalFile || !info2.IsLocalFile) + { + // TODO: Not supported yet + return Task.FromResult(true); + } + var path1 = info1.Path; var path2 = info2.Path; diff --git a/MediaBrowser.Controller/Entities/IHasImages.cs b/MediaBrowser.Controller/Entities/IHasImages.cs index ef478c516..da729176d 100644 --- a/MediaBrowser.Controller/Entities/IHasImages.cs +++ b/MediaBrowser.Controller/Entities/IHasImages.cs @@ -2,9 +2,11 @@ using MediaBrowser.Model.Entities; using System.Collections.Generic; using System.IO; +using System.Threading; using System.Threading.Tasks; using CommonIO; using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Library; namespace MediaBrowser.Controller.Entities { @@ -191,6 +193,21 @@ namespace MediaBrowser.Controller.Entities /// /// The image. void RemoveImage(ItemImageInfo image); + + /// + /// Updates to repository. + /// + /// The update reason. + /// The cancellation token. + /// Task. + Task UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken); + + /// + /// Sets the image. + /// + /// The image. + /// The index. + void SetImage(ItemImageInfo image, int index); } public static class HasImagesExtensions diff --git a/MediaBrowser.Controller/Entities/IHasMetadata.cs b/MediaBrowser.Controller/Entities/IHasMetadata.cs index 4eb25718e..473ee120e 100644 --- a/MediaBrowser.Controller/Entities/IHasMetadata.cs +++ b/MediaBrowser.Controller/Entities/IHasMetadata.cs @@ -36,14 +36,6 @@ namespace MediaBrowser.Controller.Entities /// The date last refreshed. DateTime DateLastRefreshed { get; set; } - /// - /// Updates to repository. - /// - /// The update reason. - /// The cancellation token. - /// Task. - Task UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken); - /// /// This is called before any metadata refresh and returns true or false indicating if changes were made /// diff --git a/MediaBrowser.Controller/Entities/ItemImageInfo.cs b/MediaBrowser.Controller/Entities/ItemImageInfo.cs index 9f3074c5e..bb113e596 100644 --- a/MediaBrowser.Controller/Entities/ItemImageInfo.cs +++ b/MediaBrowser.Controller/Entities/ItemImageInfo.cs @@ -29,6 +29,13 @@ namespace MediaBrowser.Controller.Entities { get { + if (Path != null) + { + if (Path.StartsWith("http", StringComparison.OrdinalIgnoreCase)) + { + return false; + } + } return true; } } diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 980a3bbb5..c7ab88524 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -534,5 +534,14 @@ namespace MediaBrowser.Controller.Library /// To. /// System.String. string SubstitutePath(string path, string from, string to); + + /// + /// Converts the image to local. + /// + /// The item. + /// The image. + /// Index of the image. + /// Task. + Task ConvertImageToLocal(IHasImages item, ItemImageInfo image, int imageIndex); } } \ No newline at end of file diff --git a/MediaBrowser.Controller/LiveTv/ITunerHost.cs b/MediaBrowser.Controller/LiveTv/ITunerHost.cs index bedbcffe3..2e3a71f70 100644 --- a/MediaBrowser.Controller/LiveTv/ITunerHost.cs +++ b/MediaBrowser.Controller/LiveTv/ITunerHost.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Model.Dto; +using System; +using MediaBrowser.Model.Dto; using MediaBrowser.Model.LiveTv; using System.Collections.Generic; using System.Threading; @@ -37,7 +38,7 @@ namespace MediaBrowser.Controller.LiveTv /// The stream identifier. /// The cancellation token. /// Task<MediaSourceInfo>. - Task GetChannelStream(string channelId, string streamId, CancellationToken cancellationToken); + Task> GetChannelStream(string channelId, string streamId, CancellationToken cancellationToken); /// /// Gets the channel stream media sources. /// diff --git a/MediaBrowser.Controller/Providers/DynamicImageResponse.cs b/MediaBrowser.Controller/Providers/DynamicImageResponse.cs index 71a937cd9..fdd1891ed 100644 --- a/MediaBrowser.Controller/Providers/DynamicImageResponse.cs +++ b/MediaBrowser.Controller/Providers/DynamicImageResponse.cs @@ -1,12 +1,14 @@ using System; using System.IO; using MediaBrowser.Model.Drawing; +using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.Controller.Providers { public class DynamicImageResponse { public string Path { get; set; } + public MediaProtocol Protocol { get; set; } public Stream Stream { get; set; } public ImageFormat Format { get; set; } public bool HasImage { get; set; } diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 06a35ac0d..dfcafa32d 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -226,11 +226,15 @@ namespace MediaBrowser.Model.Configuration public bool EnableDateLastRefresh { get; set; } + public string[] Migrations { get; set; } + /// /// Initializes a new instance of the class. /// public ServerConfiguration() { + Migrations = new string[] {}; + ImageSavingConvention = ImageSavingConvention.Compatible; PublicPort = 8096; PublicHttpsPort = 8920; diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index 4106d3dca..9d183c880 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -136,7 +136,7 @@ namespace MediaBrowser.Providers.Manager source = memoryStream; - var currentPath = GetCurrentImagePath(item, type, index); + var currentImage = GetCurrentImage(item, type, index); using (source) { @@ -160,8 +160,10 @@ namespace MediaBrowser.Providers.Manager SetImagePath(item, type, imageIndex, paths[0]); // Delete the current path - if (!string.IsNullOrEmpty(currentPath) && !paths.Contains(currentPath, StringComparer.OrdinalIgnoreCase)) + if (currentImage != null && currentImage.IsLocalFile && !paths.Contains(currentImage.Path, StringComparer.OrdinalIgnoreCase)) { + var currentPath = currentImage.Path; + _libraryMonitor.ReportFileSystemChangeBeginning(currentPath); try @@ -301,9 +303,9 @@ namespace MediaBrowser.Providers.Manager /// or /// imageIndex /// - private string GetCurrentImagePath(IHasImages item, ImageType type, int imageIndex) + private ItemImageInfo GetCurrentImage(IHasImages item, ImageType type, int imageIndex) { - return item.GetImagePath(type, imageIndex); + return item.GetImageInfo(type, imageIndex); } /// diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index b39deba89..cfa3e67f5 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -17,6 +17,7 @@ using System.Net; using System.Threading; using System.Threading.Tasks; using CommonIO; +using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.Providers.Manager { @@ -138,11 +139,24 @@ namespace MediaBrowser.Providers.Manager { if (!string.IsNullOrEmpty(response.Path)) { - var mimeType = MimeTypes.GetMimeType(response.Path); + if (response.Protocol == MediaProtocol.Http) + { + _logger.Debug("Setting image url into item {0}", item.Id); + item.SetImage(new ItemImageInfo + { + Path = response.Path, + Type = imageType - var stream = _fileSystem.GetFileStream(response.Path, FileMode.Open, FileAccess.Read, FileShare.Read, true); + }, 0); + } + else + { + var mimeType = MimeTypes.GetMimeType(response.Path); - await _providerManager.SaveImage(item, stream, mimeType, imageType, null, response.InternalCacheKey, cancellationToken).ConfigureAwait(false); + var stream = _fileSystem.GetFileStream(response.Path, FileMode.Open, FileAccess.Read, FileShare.Read, true); + + await _providerManager.SaveImage(item, stream, mimeType, imageType, null, response.InternalCacheKey, cancellationToken).ConfigureAwait(false); + } } else { @@ -391,7 +405,7 @@ namespace MediaBrowser.Providers.Manager else { var existing = item.GetImageInfo(type, 0); - if (existing != null && !_fileSystem.FileExists(existing.Path)) + if (existing != null && !_fileSystem.FileExists(existing.Path)) { item.RemoveImage(existing); changed = true; diff --git a/MediaBrowser.Providers/Music/AlbumImageFromSongProvider.cs b/MediaBrowser.Providers/Music/AlbumImageFromSongProvider.cs index 2ba700b09..7abe9cc07 100644 --- a/MediaBrowser.Providers/Music/AlbumImageFromSongProvider.cs +++ b/MediaBrowser.Providers/Music/AlbumImageFromSongProvider.cs @@ -22,13 +22,15 @@ namespace MediaBrowser.Providers.Music var image = album.GetRecursiveChildren() .OfType