support null image encoder

This commit is contained in:
Luke Pulverenti 2015-10-26 01:29:32 -04:00
parent 2890c71af9
commit c80e1df1ca
24 changed files with 333 additions and 96 deletions

View File

@ -75,6 +75,7 @@
<Compile Include="ImageProcessor.cs" /> <Compile Include="ImageProcessor.cs" />
<Compile Include="ImageMagick\PercentPlayedDrawer.cs" /> <Compile Include="ImageMagick\PercentPlayedDrawer.cs" />
<Compile Include="ImageMagick\PlayedIndicatorDrawer.cs" /> <Compile Include="ImageMagick\PlayedIndicatorDrawer.cs" />
<Compile Include="NullImageEncoder.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ImageMagick\UnplayedCountIndicator.cs" /> <Compile Include="ImageMagick\UnplayedCountIndicator.cs" />
</ItemGroup> </ItemGroup>
@ -99,6 +100,9 @@
<ItemGroup> <ItemGroup>
<None Include="packages.config" /> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<EmbeddedResource Include="GDI\empty.png" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- 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. Other similar extension points exist, see Microsoft.Common.targets.

View File

@ -1,5 +1,4 @@
using MediaBrowser.Common.IO; using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using System; using System;
@ -23,7 +22,20 @@ namespace Emby.Drawing.GDI
_fileSystem = fileSystem; _fileSystem = fileSystem;
_logger = logger; _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 public string[] SupportedInputFormats
@ -253,5 +265,15 @@ namespace Emby.Drawing.GDI
{ {
get { return "GDI"; } get { return "GDI"; }
} }
public bool SupportsImageCollageCreation
{
get { return true; }
}
public bool SupportsImageEncoding
{
get { return true; }
}
} }
} }

BIN
Emby.Drawing/GDI/empty.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

View File

@ -17,12 +17,6 @@ namespace Emby.Drawing
/// <value>The supported output formats.</value> /// <value>The supported output formats.</value>
ImageFormat[] SupportedOutputFormats { get; } ImageFormat[] SupportedOutputFormats { get; }
/// <summary> /// <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. /// Crops the white space.
/// </summary> /// </summary>
/// <param name="inputPath">The input path.</param> /// <param name="inputPath">The input path.</param>
@ -49,5 +43,17 @@ namespace Emby.Drawing
/// </summary> /// </summary>
/// <value>The name.</value> /// <value>The name.</value>
string Name { get; } 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; }
} }
} }

View File

@ -9,7 +9,6 @@ using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using CommonIO; using CommonIO;
using MediaBrowser.Common.IO;
namespace Emby.Drawing.ImageMagick namespace Emby.Drawing.ImageMagick
{ {
@ -27,7 +26,7 @@ namespace Emby.Drawing.ImageMagick
_httpClient = httpClient; _httpClient = httpClient;
_fileSystem = fileSystem; _fileSystem = fileSystem;
LogImageMagickVersion(); LogVersion();
} }
public string[] SupportedInputFormats public string[] SupportedInputFormats
@ -68,7 +67,7 @@ namespace Emby.Drawing.ImageMagick
} }
} }
private void LogImageMagickVersion() private void LogVersion()
{ {
_logger.Info("ImageMagick version: " + Wand.VersionString); _logger.Info("ImageMagick version: " + Wand.VersionString);
TestWebp(); TestWebp();
@ -88,9 +87,9 @@ namespace Emby.Drawing.ImageMagick
wand.SaveImage(tmpPath); wand.SaveImage(tmpPath);
} }
} }
catch (Exception ex) catch
{ {
_logger.ErrorException("Error loading webp: ", ex); //_logger.ErrorException("Error loading webp: ", ex);
_webpAvailable = false; _webpAvailable = false;
} }
} }
@ -255,5 +254,15 @@ namespace Emby.Drawing.ImageMagick
throw new ObjectDisposedException(GetType().Name); throw new ObjectDisposedException(GetType().Name);
} }
} }
public bool SupportsImageCollageCreation
{
get { return true; }
}
public bool SupportsImageEncoding
{
get { return true; }
}
} }
} }

View File

@ -354,14 +354,14 @@ namespace Emby.Drawing.ImageMagick
private MagickWand BuildSquareCollageWand(List<string> paths, int width, int height) 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())) using (var wandImages = new MagickWand(inputPaths.ToArray()))
{ {
var wand = new MagickWand(width, height); var wand = new MagickWand(width, height);
wand.OpenImage("gradient:#111111-#111111"); wand.OpenImage("gradient:#111111-#111111");
using (var draw = new DrawingWand()) using (var draw = new DrawingWand())
{ {
var iSlice = Convert.ToInt32(width * .225); var iSlice = Convert.ToInt32(width * .3);
int iTrans = Convert.ToInt32(height * .25); int iTrans = Convert.ToInt32(height * .25);
int iHeight = Convert.ToInt32(height * .63); int iHeight = Convert.ToInt32(height * .63);
var horizontalImagePadding = Convert.ToInt32(width * 0.02); var horizontalImagePadding = Convert.ToInt32(width * 0.02);

View File

@ -110,6 +110,15 @@ namespace Emby.Drawing
} }
} }
public bool SupportsImageCollageCreation
{
get
{
return _imageEncoder.SupportsImageCollageCreation;
}
}
private string ResizedImageCachePath private string ResizedImageCachePath
{ {
get get
@ -170,6 +179,11 @@ namespace Emby.Drawing
var originalImagePath = originalImage.Path; var originalImagePath = originalImage.Path;
if (!_imageEncoder.SupportsImageEncoding)
{
return originalImagePath;
}
if (options.HasDefaultOptions(originalImagePath) && options.Enhancers.Count == 0 && !options.CropWhiteSpace) if (options.HasDefaultOptions(originalImagePath) && options.Enhancers.Count == 0 && !options.CropWhiteSpace)
{ {
// Just spit out the original file if all the options are default // Just spit out the original file if all the options are default
@ -178,7 +192,7 @@ namespace Emby.Drawing
var dateModified = originalImage.DateModified; var dateModified = originalImage.DateModified;
if (options.CropWhiteSpace) if (options.CropWhiteSpace && _imageEncoder.SupportsImageEncoding)
{ {
var tuple = await GetWhitespaceCroppedImage(originalImagePath, dateModified).ConfigureAwait(false); var tuple = await GetWhitespaceCroppedImage(originalImagePath, dateModified).ConfigureAwait(false);
@ -295,6 +309,11 @@ namespace Emby.Drawing
_imageEncoder.CropWhiteSpace(originalImagePath, croppedImagePath); _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) catch (Exception ex)
{ {
// We have to have a catch-all here because some of the .net image methods throw a plain old Exception // We have to have a catch-all here because some of the .net image methods throw a plain old Exception

View 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()
{
}
}
}

View File

@ -564,7 +564,14 @@ namespace MediaBrowser.Api.Images
}).ToList() : new List<IImageEnhancer>(); }).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 contentType = GetMimeType(format, imageInfo.Path);
var cacheGuid = new Guid(_imageProcessor.GetImageCacheTag(item, imageInfo, supportedImageEnhancers)); var cacheGuid = new Guid(_imageProcessor.GetImageCacheTag(item, imageInfo, supportedImageEnhancers));
@ -585,6 +592,7 @@ namespace MediaBrowser.Api.Images
return GetImageResult(item, return GetImageResult(item,
request, request,
imageInfo, imageInfo,
cropwhitespace,
format, format,
supportedImageEnhancers, supportedImageEnhancers,
contentType, contentType,
@ -597,6 +605,7 @@ namespace MediaBrowser.Api.Images
private async Task<object> GetImageResult(IHasImages item, private async Task<object> GetImageResult(IHasImages item,
ImageRequest request, ImageRequest request,
ItemImageInfo image, ItemImageInfo image,
bool cropwhitespace,
ImageFormat format, ImageFormat format,
List<IImageEnhancer> enhancers, List<IImageEnhancer> enhancers,
string contentType, string contentType,
@ -604,13 +613,6 @@ namespace MediaBrowser.Api.Images
IDictionary<string, string> headers, IDictionary<string, string> headers,
bool isHeadRequest) bool isHeadRequest)
{ {
var cropwhitespace = request.Type == ImageType.Logo || request.Type == ImageType.Art;
if (request.CropWhitespace.HasValue)
{
cropwhitespace = request.CropWhitespace.Value;
}
var options = new ImageProcessingOptions var options = new ImageProcessingOptions
{ {
CropWhiteSpace = cropwhitespace, 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)) 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(); var serverFormats = _imageProcessor.GetSupportedImageOutputFormats();
if (serverFormats.Contains(ImageFormat.Webp) && // Client doesn't care about format, so start with webp if supported
GetClientSupportedFormats().Contains(ImageFormat.Webp)) if (serverFormats.Contains(ImageFormat.Webp) && clientSupportedFormats.Contains(ImageFormat.Webp))
{ {
return ImageFormat.Webp; return ImageFormat.Webp;
} }
@ -668,10 +697,7 @@ namespace MediaBrowser.Api.Images
return ImageFormat.Png; return ImageFormat.Png;
} }
var extension = Path.GetExtension(image.Path); if (inputFormat.HasValue && inputFormat.Value == ImageFormat.Jpg)
if (string.Equals(extension, ".jpg", StringComparison.OrdinalIgnoreCase) ||
string.Equals(extension, ".jpeg", StringComparison.OrdinalIgnoreCase))
{ {
return ImageFormat.Jpg; return ImageFormat.Jpg;
} }
@ -682,7 +708,7 @@ namespace MediaBrowser.Api.Images
private ImageFormat[] GetClientSupportedFormats() private ImageFormat[] GetClientSupportedFormats()
{ {
var supportsWebP = (Request.AcceptTypes ?? new string[] {}).Contains("image/webp", StringComparer.OrdinalIgnoreCase); var supportsWebP = (Request.AcceptTypes ?? new string[] { }).Contains("image/webp", StringComparer.OrdinalIgnoreCase);
var userAgent = Request.UserAgent ?? string.Empty; var userAgent = Request.UserAgent ?? string.Empty;

View File

@ -52,7 +52,7 @@ namespace MediaBrowser.Api.Library
/// Gets or sets the path. /// Gets or sets the path.
/// </summary> /// </summary>
/// <value>The path.</value> /// <value>The path.</value>
public string Path { get; set; } public string[] Paths { get; set; }
} }
[Route("/Library/VirtualFolders", "DELETE")] [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 + "."); 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 finally

View File

@ -105,5 +105,11 @@ namespace MediaBrowser.Controller.Drawing
/// </summary> /// </summary>
/// <param name="options">The options.</param> /// <param name="options">The options.</param>
Task CreateImageCollage(ImageCollageOptions options); 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; }
} }
} }

View File

@ -87,22 +87,26 @@ namespace MediaBrowser.Providers.Movies
if (string.IsNullOrEmpty(tmdbId)) if (string.IsNullOrEmpty(tmdbId))
{ {
movieInfo = await MovieDbProvider.Current.FetchMainResult(imdbId, false, language, cancellationToken).ConfigureAwait(false); movieInfo = await MovieDbProvider.Current.FetchMainResult(imdbId, false, language, cancellationToken).ConfigureAwait(false);
if (movieInfo == null) return item; if (movieInfo != null)
{
tmdbId = movieInfo.id.ToString(_usCulture);
tmdbId = movieInfo.id.ToString(_usCulture); dataFilePath = MovieDbProvider.Current.GetDataFilePath(tmdbId, language);
_fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath));
dataFilePath = MovieDbProvider.Current.GetDataFilePath(tmdbId, language); _jsonSerializer.SerializeToFile(movieInfo, dataFilePath);
_fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath)); }
_jsonSerializer.SerializeToFile(movieInfo, dataFilePath);
} }
await MovieDbProvider.Current.EnsureMovieInfo(tmdbId, language, cancellationToken).ConfigureAwait(false); if (!string.IsNullOrWhiteSpace(tmdbId))
{
await MovieDbProvider.Current.EnsureMovieInfo(tmdbId, language, cancellationToken).ConfigureAwait(false);
dataFilePath = dataFilePath ?? MovieDbProvider.Current.GetDataFilePath(tmdbId, language); dataFilePath = dataFilePath ?? MovieDbProvider.Current.GetDataFilePath(tmdbId, language);
movieInfo = movieInfo ?? _jsonSerializer.DeserializeFromFile<MovieDbProvider.CompleteMovieData>(dataFilePath); movieInfo = movieInfo ?? _jsonSerializer.DeserializeFromFile<MovieDbProvider.CompleteMovieData>(dataFilePath);
ProcessMainInfo(item, preferredCountryCode, movieInfo); ProcessMainInfo(item, preferredCountryCode, movieInfo);
item.HasMetadata = true; item.HasMetadata = true;
}
return item; return item;
} }

View File

@ -16,9 +16,11 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Net;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using CommonIO; using CommonIO;
using MediaBrowser.Model.Net;
namespace MediaBrowser.Providers.Movies namespace MediaBrowser.Providers.Movies
{ {
@ -116,7 +118,7 @@ namespace MediaBrowser.Providers.Movies
public Task<MetadataResult<T>> GetItemMetadata<T>(ItemLookupInfo id, CancellationToken cancellationToken) public Task<MetadataResult<T>> GetItemMetadata<T>(ItemLookupInfo id, CancellationToken cancellationToken)
where T : BaseItem, new() where T : BaseItem, new()
{ {
var movieDb = new GenericMovieDbInfo<T>(_logger, _jsonSerializer, _libraryManager, _fileSystem); var movieDb = new GenericMovieDbInfo<T>(_logger, _jsonSerializer, _libraryManager, _fileSystem);
return movieDb.GetMetadata(id, cancellationToken); return movieDb.GetMetadata(id, cancellationToken);
} }
@ -211,7 +213,7 @@ namespace MediaBrowser.Providers.Movies
var dataFilePath = GetDataFilePath(id, preferredMetadataLanguage); var dataFilePath = GetDataFilePath(id, preferredMetadataLanguage);
_fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath)); _fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath));
_jsonSerializer.SerializeToFile(mainResult, dataFilePath); _jsonSerializer.SerializeToFile(mainResult, dataFilePath);
} }
@ -309,17 +311,30 @@ namespace MediaBrowser.Providers.Movies
var cacheMode = isTmdbId ? CacheMode.None : CacheMode.Unconditional; var cacheMode = isTmdbId ? CacheMode.None : CacheMode.Unconditional;
var cacheLength = TimeSpan.FromDays(3); var cacheLength = TimeSpan.FromDays(3);
using (var json = await GetMovieDbResponse(new HttpRequestOptions try
{ {
Url = url, using (var json = await GetMovieDbResponse(new HttpRequestOptions
CancellationToken = cancellationToken, {
AcceptHeader = AcceptHeader, Url = url,
CacheMode = cacheMode, CancellationToken = cancellationToken,
CacheLength = cacheLength AcceptHeader = AcceptHeader,
CacheMode = cacheMode,
CacheLength = cacheLength
}).ConfigureAwait(false)) }).ConfigureAwait(false))
{
mainResult = _jsonSerializer.DeserializeFromStream<CompleteMovieData>(json);
}
}
catch (HttpException ex)
{ {
mainResult = _jsonSerializer.DeserializeFromStream<CompleteMovieData>(json); // 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(); cancellationToken.ThrowIfCancellationRequested();

View File

@ -10,6 +10,7 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Server.Implementations.Photos; using MediaBrowser.Server.Implementations.Photos;
using MoreLinq; using MoreLinq;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using CommonIO; using CommonIO;
@ -74,7 +75,27 @@ namespace MediaBrowser.Server.Implementations.Collections
.DistinctBy(i => i.Id) .DistinctBy(i => i.Id)
.ToList(); .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;
} }
} }
} }

View File

@ -265,6 +265,11 @@ namespace MediaBrowser.Server.Implementations.Devices
return true; return true;
} }
if (policy.IsAdministrator)
{
return true;
}
return ListHelper.ContainsIgnoreCase(policy.EnabledDevices, id); return ListHelper.ContainsIgnoreCase(policy.EnabledDevices, id);
} }
} }

View File

@ -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. // 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 // 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 // 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; string val;
_tempIgnoredPaths.TryRemove(path, out val); _tempIgnoredPaths.TryRemove(path, out val);

View File

@ -675,7 +675,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
Name = info.Name, Name = info.Name,
EpisodeTitle = info.EpisodeTitle, EpisodeTitle = info.EpisodeTitle,
ProgramId = info.Id, ProgramId = info.Id,
HasImage = info.HasImage,
ImagePath = info.ImagePath, ImagePath = info.ImagePath,
ImageUrl = info.ImageUrl, ImageUrl = info.ImageUrl,
OriginalAirDate = info.OriginalAirDate, OriginalAirDate = info.OriginalAirDate,

View File

@ -333,7 +333,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
IsRepeat = repeat, IsRepeat = repeat,
IsSeries = showType.IndexOf("series", StringComparison.OrdinalIgnoreCase) != -1, IsSeries = showType.IndexOf("series", StringComparison.OrdinalIgnoreCase) != -1,
ImageUrl = imageUrl, ImageUrl = imageUrl,
HasImage = details.hasImageArtwork,
IsKids = string.Equals(details.audience, "children", StringComparison.OrdinalIgnoreCase), IsKids = string.Equals(details.audience, "children", StringComparison.OrdinalIgnoreCase),
IsSports = showType.IndexOf("sports", StringComparison.OrdinalIgnoreCase) != -1, IsSports = showType.IndexOf("sports", StringComparison.OrdinalIgnoreCase) != -1,
IsMovie = showType.IndexOf("movie", StringComparison.OrdinalIgnoreCase) != -1 || showType.IndexOf("film", StringComparison.OrdinalIgnoreCase) != -1, IsMovie = showType.IndexOf("movie", StringComparison.OrdinalIgnoreCase) != -1 || showType.IndexOf("film", StringComparison.OrdinalIgnoreCase) != -1,

View File

@ -46,11 +46,6 @@ namespace MediaBrowser.Server.Implementations.Persistence
} }
} }
protected virtual void DisposeInternal()
{
}
protected abstract void CloseConnection(); protected abstract void CloseConnection();
} }
} }

View File

@ -92,11 +92,11 @@ namespace MediaBrowser.Server.Implementations.Photos
string cacheKey, string cacheKey,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
var outputPath = Path.Combine(ApplicationPaths.TempDirectory, Guid.NewGuid() + ".png"); var outputPathWithoutExtension = Path.Combine(ApplicationPaths.TempDirectory, Guid.NewGuid().ToString("N"));
FileSystem.CreateDirectory(Path.GetDirectoryName(outputPath)); FileSystem.CreateDirectory(Path.GetDirectoryName(outputPathWithoutExtension));
var imageCreated = await CreateImage(item, itemsWithImages, outputPath, imageType, 0).ConfigureAwait(false); string outputPath = await CreateImage(item, itemsWithImages, outputPathWithoutExtension, imageType, 0).ConfigureAwait(false);
if (!imageCreated) if (string.IsNullOrWhiteSpace(outputPath))
{ {
return ItemUpdateType.None; return ItemUpdateType.None;
} }
@ -117,7 +117,7 @@ namespace MediaBrowser.Server.Implementations.Photos
return parts.GetMD5().ToString("N"); 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); return CreateCollage(primaryItem, items, outputPath, 640, 360);
} }
@ -144,22 +144,22 @@ namespace MediaBrowser.Server.Implementations.Photos
.Where(i => !string.IsNullOrWhiteSpace(i)); .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); 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); 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); 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)); FileSystem.CreateDirectory(Path.GetDirectoryName(outputPath));
@ -173,11 +173,16 @@ namespace MediaBrowser.Server.Implementations.Photos
if (options.InputPaths.Length == 0) if (options.InputPaths.Length == 0)
{ {
return Task.FromResult(false); return null;
} }
ImageProcessor.CreateImageCollage(options); if (!ImageProcessor.SupportsImageCollageCreation)
return Task.FromResult(true); {
return null;
}
await ImageProcessor.CreateImageCollage(options).ConfigureAwait(false);
return outputPath;
} }
public string Name public string Name
@ -185,17 +190,19 @@ namespace MediaBrowser.Server.Implementations.Photos
get { return "Dynamic Image Provider"; } get { return "Dynamic Image Provider"; }
} }
protected virtual async Task<bool> CreateImage(IHasImages item, protected virtual async Task<string> CreateImage(IHasImages item,
List<BaseItem> itemsWithImages, List<BaseItem> itemsWithImages,
string outputPath, string outputPathWithoutExtension,
ImageType imageType, ImageType imageType,
int imageIndex) int imageIndex)
{ {
if (itemsWithImages.Count == 0) if (itemsWithImages.Count == 0)
{ {
return false; return null;
} }
string outputPath = Path.ChangeExtension(outputPathWithoutExtension, ".png");
if (imageType == ImageType.Thumb) if (imageType == ImageType.Thumb)
{ {
return await CreateThumbCollage(item, itemsWithImages, outputPath).ConfigureAwait(false); 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); 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); return await CreateSquareCollage(item, itemsWithImages, outputPath).ConfigureAwait(false);
} }
@ -320,7 +327,7 @@ namespace MediaBrowser.Server.Implementations.Photos
var random = DateTime.Now.DayOfYear % MaxImageAgeDays; var random = DateTime.Now.DayOfYear % MaxImageAgeDays;
return items return items
.OrderBy(i => (random + "" + items.IndexOf(i)).GetMD5()) .OrderBy(i => (random + string.Empty + items.IndexOf(i)).GetMD5())
.Take(limit) .Take(limit)
.OrderBy(i => i.Name) .OrderBy(i => i.Name)
.ToList(); .ToList();

View File

@ -1,9 +1,9 @@
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Providers;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using CommonIO; using CommonIO;
@ -20,9 +20,26 @@ namespace MediaBrowser.Server.Implementations.Photos
protected override Task<List<BaseItem>> GetItemsWithImages(IHasImages item) protected override Task<List<BaseItem>> GetItemsWithImages(IHasImages item)
{ {
var photoAlbum = (PhotoAlbum)item; var photoAlbum = (PhotoAlbum)item;
var items = GetFinalItems(photoAlbum.Children.ToList()); var items = GetFinalItems(photoAlbum.Children.ToList(), 1);
return Task.FromResult(items); 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;
}
} }
} }

View File

@ -10,6 +10,7 @@ using MediaBrowser.Server.Implementations.Photos;
using MoreLinq; using MoreLinq;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using CommonIO; using CommonIO;
@ -97,13 +98,15 @@ namespace MediaBrowser.Server.Implementations.UserViews
return item is CollectionFolder; 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 (imageType == ImageType.Primary)
{ {
if (itemsWithImages.Count == 0) if (itemsWithImages.Count == 0)
{ {
return false; return null;
} }
return await CreateThumbCollage(item, itemsWithImages, outputPath, 960, 540).ConfigureAwait(false); return await CreateThumbCollage(item, itemsWithImages, outputPath, 960, 540).ConfigureAwait(false);

View File

@ -11,6 +11,7 @@ using MediaBrowser.Server.Implementations.Photos;
using MoreLinq; using MoreLinq;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using CommonIO; using CommonIO;
@ -161,14 +162,16 @@ namespace MediaBrowser.Server.Implementations.UserViews
return collectionStripViewTypes.Contains(view.ViewType ?? string.Empty); 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; var view = (UserView)item;
if (imageType == ImageType.Primary && IsUsingCollectionStrip(view)) if (imageType == ImageType.Primary && IsUsingCollectionStrip(view))
{ {
if (itemsWithImages.Count == 0) if (itemsWithImages.Count == 0)
{ {
return false; return null;
} }
return await CreateThumbCollage(item, itemsWithImages, outputPath, 960, 540).ConfigureAwait(false); return await CreateThumbCollage(item, itemsWithImages, outputPath, 960, 540).ConfigureAwait(false);

View File

@ -577,11 +577,20 @@ namespace MediaBrowser.Server.Startup.Common
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.ErrorException("Error loading ImageMagick. Will revert to GDI.", ex); Logger.Error("Error loading ImageMagick. Will revert to GDI.");
} }
} }
return new GDIImageEncoder(FileSystemManager, LogManager.GetLogger("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) protected override INetworkManager CreateNetworkManager(ILogger logger)