aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Server.Implementations
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Server.Implementations')
-rw-r--r--MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs131
-rw-r--r--MediaBrowser.Server.Implementations/Dto/DtoService.cs12
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/HttpServer.cs3
-rw-r--r--MediaBrowser.Server.Implementations/IO/DirectoryWatchers.cs16
-rw-r--r--MediaBrowser.Server.Implementations/Providers/ImageSaver.cs13
-rw-r--r--MediaBrowser.Server.Implementations/Sorting/CriticRatingComparer.cs4
6 files changed, 117 insertions, 62 deletions
diff --git a/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs b/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs
index a439251db..78dcf6fd0 100644
--- a/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs
+++ b/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs
@@ -3,11 +3,11 @@ using MediaBrowser.Common.IO;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Serialization;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -25,7 +25,7 @@ namespace MediaBrowser.Server.Implementations.Drawing
/// <summary>
/// Class ImageProcessor
/// </summary>
- public class ImageProcessor : IImageProcessor
+ public class ImageProcessor : IImageProcessor, IDisposable
{
/// <summary>
/// The us culture
@@ -35,7 +35,7 @@ namespace MediaBrowser.Server.Implementations.Drawing
/// <summary>
/// The _cached imaged sizes
/// </summary>
- private readonly ConcurrentDictionary<string, ImageSize> _cachedImagedSizes = new ConcurrentDictionary<string, ImageSize>();
+ private readonly ConcurrentDictionary<Guid, ImageSize> _cachedImagedSizes;
/// <summary>
/// Gets the list of currently registered image processors
@@ -50,21 +50,41 @@ namespace MediaBrowser.Server.Implementations.Drawing
private readonly ILogger _logger;
private readonly IFileSystem _fileSystem;
+ private readonly IJsonSerializer _jsonSerializer;
+ private readonly IServerApplicationPaths _appPaths;
private readonly string _imageSizeCachePath;
private readonly string _croppedWhitespaceImageCachePath;
private readonly string _enhancedImageCachePath;
private readonly string _resizedImageCachePath;
- public ImageProcessor(ILogger logger, IServerApplicationPaths appPaths, IFileSystem fileSystem)
+ public ImageProcessor(ILogger logger, IServerApplicationPaths appPaths, IFileSystem fileSystem, IJsonSerializer jsonSerializer)
{
_logger = logger;
_fileSystem = fileSystem;
+ _jsonSerializer = jsonSerializer;
+ _appPaths = appPaths;
_imageSizeCachePath = Path.Combine(appPaths.ImageCachePath, "image-sizes");
_croppedWhitespaceImageCachePath = Path.Combine(appPaths.ImageCachePath, "cropped-images");
_enhancedImageCachePath = Path.Combine(appPaths.ImageCachePath, "enhanced-images");
_resizedImageCachePath = Path.Combine(appPaths.ImageCachePath, "resized-images");
+
+ _saveImageSizeTimer = new Timer(SaveImageSizeCallback, null, Timeout.Infinite, Timeout.Infinite);
+
+ Dictionary<Guid, ImageSize> sizeDictionary;
+
+ try
+ {
+ sizeDictionary = jsonSerializer.DeserializeFromFile<Dictionary<Guid, ImageSize>>(ImageSizeFile);
+ }
+ catch (IOException)
+ {
+ // No biggie
+ sizeDictionary = new Dictionary<Guid, ImageSize>();
+ }
+
+ _cachedImagedSizes = new ConcurrentDictionary<Guid, ImageSize>(sizeDictionary);
}
public void AddParts(IEnumerable<IImageEnhancer> enhancers)
@@ -85,6 +105,17 @@ namespace MediaBrowser.Server.Implementations.Drawing
}
var originalImagePath = options.OriginalImagePath;
+
+ if (options.HasDefaultOptions())
+ {
+ // Just spit out the original file if all the options are default
+ using (var fileStream = _fileSystem.GetFileStream(originalImagePath, FileMode.Open, FileAccess.Read, FileShare.Read, true))
+ {
+ await fileStream.CopyToAsync(toStream).ConfigureAwait(false);
+ return;
+ }
+ }
+
var dateModified = options.OriginalImageDateModified;
if (options.CropWhiteSpace)
@@ -106,6 +137,16 @@ namespace MediaBrowser.Server.Implementations.Drawing
// Determine the output size based on incoming parameters
var newSize = DrawingUtils.Resize(originalImageSize, options.Width, options.Height, options.MaxWidth, options.MaxHeight);
+ if (options.HasDefaultOptionsWithoutSize() && newSize.Equals(originalImageSize))
+ {
+ // Just spit out the original file the new size equals the old
+ using (var fileStream = _fileSystem.GetFileStream(originalImagePath, FileMode.Open, FileAccess.Read, FileShare.Read, true))
+ {
+ await fileStream.CopyToAsync(toStream).ConfigureAwait(false);
+ return;
+ }
+ }
+
var quality = options.Quality ?? 90;
var cacheFilePath = GetCacheFilePath(originalImagePath, newSize, quality, dateModified, options.OutputFormat, options.AddPlayedIndicator, options.PercentPlayed, options.BackgroundColor);
@@ -465,11 +506,13 @@ namespace MediaBrowser.Server.Implementations.Drawing
ImageSize size;
- if (!_cachedImagedSizes.TryGetValue(name, out size))
+ var cacheHash = name.GetMD5();
+
+ if (!_cachedImagedSizes.TryGetValue(cacheHash, out size))
{
- size = GetImageSizeInternal(name, path);
+ size = GetImageSizeInternal(path);
- _cachedImagedSizes.AddOrUpdate(name, size, (keyName, oldValue) => size);
+ _cachedImagedSizes.AddOrUpdate(cacheHash, size, (keyName, oldValue) => size);
}
return size;
@@ -478,62 +521,47 @@ namespace MediaBrowser.Server.Implementations.Drawing
/// <summary>
/// Gets the image size internal.
/// </summary>
- /// <param name="cacheKey">The cache key.</param>
/// <param name="path">The path.</param>
/// <returns>ImageSize.</returns>
- private ImageSize GetImageSizeInternal(string cacheKey, string path)
+ private ImageSize GetImageSizeInternal(string path)
{
- // Now check the file system cache
- var fullCachePath = GetCachePath(_imageSizeCachePath, cacheKey, ".txt");
+ var size = ImageHeader.GetDimensions(path, _logger, _fileSystem);
- try
- {
- var result = File.ReadAllText(fullCachePath).Split('|');
+ StartSaveImageSizeTimer();
- return new ImageSize
- {
- Width = double.Parse(result[0], UsCulture),
- Height = double.Parse(result[1], UsCulture)
- };
- }
- catch (IOException)
- {
- // Cache file doesn't exist or is currently being written to
- }
+ return new ImageSize { Width = size.Width, Height = size.Height };
+ }
- var syncLock = GetObjectLock(fullCachePath);
+ private readonly Timer _saveImageSizeTimer;
+ private const int SaveImageSizeTimeout = 5000;
+ private readonly object _saveImageSizeLock = new object();
+ private void StartSaveImageSizeTimer()
+ {
+ _saveImageSizeTimer.Change(SaveImageSizeTimeout, Timeout.Infinite);
+ }
- lock (syncLock)
+ private void SaveImageSizeCallback(object state)
+ {
+ lock (_saveImageSizeLock)
{
try
{
- var result = File.ReadAllText(fullCachePath).Split('|');
-
- return new ImageSize
- {
- Width = double.Parse(result[0], UsCulture),
- Height = double.Parse(result[1], UsCulture)
- };
- }
- catch (FileNotFoundException)
- {
- // Cache file doesn't exist no biggie
+ var path = ImageSizeFile;
+ Directory.CreateDirectory(Path.GetDirectoryName(path));
+ _jsonSerializer.SerializeToFile(_cachedImagedSizes, path);
}
- catch (DirectoryNotFoundException)
+ catch (Exception ex)
{
- // Cache file doesn't exist no biggie
+ _logger.ErrorException("Error saving image size file", ex);
}
+ }
+ }
- var size = ImageHeader.GetDimensions(path, _logger, _fileSystem);
-
- var parentPath = Path.GetDirectoryName(fullCachePath);
-
- Directory.CreateDirectory(parentPath);
-
- // Update the file system cache
- File.WriteAllText(fullCachePath, size.Width.ToString(UsCulture) + @"|" + size.Height.ToString(UsCulture));
-
- return new ImageSize { Width = size.Width, Height = size.Height };
+ private string ImageSizeFile
+ {
+ get
+ {
+ return Path.Combine(_appPaths.DataPath, "imagesizes.json");
}
}
@@ -862,5 +890,10 @@ namespace MediaBrowser.Server.Implementations.Drawing
}).ToList();
}
+
+ public void Dispose()
+ {
+ _saveImageSizeTimer.Dispose();
+ }
}
}
diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
index 19e19f8ea..0104196e0 100644
--- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs
+++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
@@ -792,11 +792,15 @@ namespace MediaBrowser.Server.Implementations.Dto
dto.MediaType = item.MediaType;
dto.LocationType = item.LocationType;
- dto.CriticRating = item.CriticRating;
-
- if (fields.Contains(ItemFields.CriticRatingSummary))
+ var hasCriticRating = item as IHasCriticRating;
+ if (hasCriticRating != null)
{
- dto.CriticRatingSummary = item.CriticRatingSummary;
+ dto.CriticRating = hasCriticRating.CriticRating;
+
+ if (fields.Contains(ItemFields.CriticRatingSummary))
+ {
+ dto.CriticRatingSummary = hasCriticRating.CriticRatingSummary;
+ }
}
var localTrailerCount = item.LocalTrailerIds.Count;
diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpServer.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpServer.cs
index 5f354fb0d..7d049549b 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/HttpServer.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/HttpServer.cs
@@ -181,6 +181,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// <param name="dto">The dto.</param>
private void FilterResponse(IHttpRequest req, IHttpResponse res, object dto)
{
+ // Try to prevent compatibility view
+ res.AddHeader("X-UA-Compatible", "IE=Edge");
+
var exception = dto as Exception;
if (exception != null)
diff --git a/MediaBrowser.Server.Implementations/IO/DirectoryWatchers.cs b/MediaBrowser.Server.Implementations/IO/DirectoryWatchers.cs
index 9fc622c21..a8c923bb0 100644
--- a/MediaBrowser.Server.Implementations/IO/DirectoryWatchers.cs
+++ b/MediaBrowser.Server.Implementations/IO/DirectoryWatchers.cs
@@ -363,6 +363,7 @@ namespace MediaBrowser.Server.Implementations.IO
{
if (string.Equals(i, e.FullPath, StringComparison.OrdinalIgnoreCase))
{
+ Logger.Debug("Watcher ignoring change to {0}", e.FullPath);
return true;
}
@@ -370,6 +371,7 @@ namespace MediaBrowser.Server.Implementations.IO
var parent = Path.GetDirectoryName(i);
if (string.Equals(parent, e.FullPath, StringComparison.OrdinalIgnoreCase))
{
+ Logger.Debug("Watcher ignoring change to {0}", e.FullPath);
return true;
}
@@ -379,10 +381,18 @@ namespace MediaBrowser.Server.Implementations.IO
parent = Path.GetDirectoryName(i);
if (string.Equals(parent, e.FullPath, StringComparison.OrdinalIgnoreCase))
{
+ Logger.Debug("Watcher ignoring change to {0}", e.FullPath);
return true;
}
}
+ if (i.StartsWith(e.FullPath, StringComparison.OrdinalIgnoreCase) ||
+ e.FullPath.StartsWith(i, StringComparison.OrdinalIgnoreCase))
+ {
+ Logger.Debug("Watcher ignoring change to {0}", e.FullPath);
+ return true;
+ }
+
return false;
}))
@@ -390,12 +400,6 @@ namespace MediaBrowser.Server.Implementations.IO
return;
}
- if (tempIgnorePaths.Contains(e.FullPath, StringComparer.OrdinalIgnoreCase))
- {
- Logger.Debug("Watcher requested to ignore change to " + e.FullPath);
- return;
- }
-
Logger.Info("Watcher sees change of type " + e.ChangeType + " to " + e.FullPath);
//Since we're watching created, deleted and renamed we always want the parent of the item to be the affected path
diff --git a/MediaBrowser.Server.Implementations/Providers/ImageSaver.cs b/MediaBrowser.Server.Implementations/Providers/ImageSaver.cs
index f46498599..0ed46e761 100644
--- a/MediaBrowser.Server.Implementations/Providers/ImageSaver.cs
+++ b/MediaBrowser.Server.Implementations/Providers/ImageSaver.cs
@@ -1,5 +1,4 @@
-using System.Collections.Generic;
-using MediaBrowser.Common.IO;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
@@ -8,6 +7,7 @@ using MediaBrowser.Controller.IO;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using System;
+using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
@@ -70,6 +70,15 @@ namespace MediaBrowser.Server.Implementations.Providers
throw new ArgumentNullException("mimeType");
}
+ if (type == ImageType.Backdrop && imageIndex == null)
+ {
+ imageIndex = item.BackdropImagePaths.Count;
+ }
+ else if (type == ImageType.Screenshot && imageIndex == null)
+ {
+ imageIndex = item.ScreenshotImagePaths.Count;
+ }
+
var saveLocally = _config.Configuration.SaveLocalMeta && item.Parent != null && !(item is Audio);
if (item is IItemByName || item is User)
diff --git a/MediaBrowser.Server.Implementations/Sorting/CriticRatingComparer.cs b/MediaBrowser.Server.Implementations/Sorting/CriticRatingComparer.cs
index 9484130cb..d01f7ed1b 100644
--- a/MediaBrowser.Server.Implementations/Sorting/CriticRatingComparer.cs
+++ b/MediaBrowser.Server.Implementations/Sorting/CriticRatingComparer.cs
@@ -22,7 +22,9 @@ namespace MediaBrowser.Server.Implementations.Sorting
private float GetValue(BaseItem x)
{
- return x.CriticRating ?? 0;
+ var hasCriticRating = x as IHasCriticRating;
+
+ return hasCriticRating == null ? 0 : hasCriticRating.CriticRating ?? 0;
}
/// <summary>