diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj
index dc410c321e..aa7dc5a153 100644
--- a/Emby.Drawing/Emby.Drawing.csproj
+++ b/Emby.Drawing/Emby.Drawing.csproj
@@ -80,7 +80,6 @@
-
diff --git a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs
index cb60d1123e..3dbe7239dd 100644
--- a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs
+++ b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs
@@ -111,7 +111,6 @@ namespace Emby.Drawing.ImageMagick
wand.CurrentImage.TrimImage(10);
wand.SaveImage(outputPath);
}
- SaveDelay();
}
public ImageSize GetImageSize(string path)
@@ -189,7 +188,6 @@ namespace Emby.Drawing.ImageMagick
}
}
}
- SaveDelay();
}
private void AddForegroundLayer(MagickWand wand, ImageProcessingOptions options)
@@ -284,25 +282,16 @@ namespace Emby.Drawing.ImageMagick
if (ratio >= 1.4)
{
- new StripCollageBuilder(_appPaths, _fileSystem).BuildThumbCollage(options.InputPaths.ToList(), options.OutputPath, options.Width, options.Height, options.Text);
+ new StripCollageBuilder(_appPaths, _fileSystem).BuildThumbCollage(options.InputPaths.ToList(), options.OutputPath, options.Width, options.Height);
}
else if (ratio >= .9)
{
- new StripCollageBuilder(_appPaths, _fileSystem).BuildSquareCollage(options.InputPaths.ToList(), options.OutputPath, options.Width, options.Height, options.Text);
+ new StripCollageBuilder(_appPaths, _fileSystem).BuildSquareCollage(options.InputPaths.ToList(), options.OutputPath, options.Width, options.Height);
}
else
{
- new StripCollageBuilder(_appPaths, _fileSystem).BuildPosterCollage(options.InputPaths.ToList(), options.OutputPath, options.Width, options.Height, options.Text);
+ new StripCollageBuilder(_appPaths, _fileSystem).BuildPosterCollage(options.InputPaths.ToList(), options.OutputPath, options.Width, options.Height);
}
-
- SaveDelay();
- }
-
- private void SaveDelay()
- {
- // For some reason the images are not always getting released right away
- //var task = Task.Delay(300);
- //Task.WaitAll(task);
}
public string Name
diff --git a/Emby.Drawing/ImageMagick/StripCollageBuilder.cs b/Emby.Drawing/ImageMagick/StripCollageBuilder.cs
index 8c50fb5eb9..7bc144c11d 100644
--- a/Emby.Drawing/ImageMagick/StripCollageBuilder.cs
+++ b/Emby.Drawing/ImageMagick/StripCollageBuilder.cs
@@ -9,140 +9,35 @@ namespace Emby.Drawing.ImageMagick
public class StripCollageBuilder
{
private readonly IApplicationPaths _appPaths;
- private readonly IFileSystem _fileSystem;
+ private readonly IFileSystem _fileSystem;
- public StripCollageBuilder(IApplicationPaths appPaths, IFileSystem fileSystem)
+ public StripCollageBuilder(IApplicationPaths appPaths, IFileSystem fileSystem)
{
_appPaths = appPaths;
- _fileSystem = fileSystem;
+ _fileSystem = fileSystem;
}
- public void BuildPosterCollage(List paths, string outputPath, int width, int height, string text)
+ public void BuildPosterCollage(List paths, string outputPath, int width, int height)
{
- if (!string.IsNullOrWhiteSpace(text))
+ using (var wand = BuildPosterCollageWand(paths, width, height))
{
- using (var wand = BuildPosterCollageWandWithText(paths, text, width, height))
- {
- wand.SaveImage(outputPath);
- }
- }
- else
- {
- using (var wand = BuildPosterCollageWand(paths, width, height))
- {
- wand.SaveImage(outputPath);
- }
+ wand.SaveImage(outputPath);
}
}
- public void BuildSquareCollage(List paths, string outputPath, int width, int height, string text)
+ public void BuildSquareCollage(List paths, string outputPath, int width, int height)
{
- if (!string.IsNullOrWhiteSpace(text))
+ using (var wand = BuildSquareCollageWand(paths, width, height))
{
- using (var wand = BuildSquareCollageWandWithText(paths, text, width, height))
- {
- wand.SaveImage(outputPath);
- }
- }
- else
- {
- using (var wand = BuildSquareCollageWand(paths, width, height))
- {
- wand.SaveImage(outputPath);
- }
+ wand.SaveImage(outputPath);
}
}
- public void BuildThumbCollage(List paths, string outputPath, int width, int height, string text)
+ public void BuildThumbCollage(List paths, string outputPath, int width, int height)
{
- if (!string.IsNullOrWhiteSpace(text))
+ using (var wand = BuildThumbCollageWand(paths, width, height))
{
- using (var wand = BuildThumbCollageWandWithText(paths, text, width, height))
- {
- wand.SaveImage(outputPath);
- }
- }
- else
- {
- using (var wand = BuildThumbCollageWand(paths, width, height))
- {
- wand.SaveImage(outputPath);
- }
- }
- }
-
- private MagickWand BuildThumbCollageWandWithText(List paths, string text, int width, int height)
- {
- var inputPaths = ImageHelpers.ProjectPaths(paths, 8);
- using (var wandImages = new MagickWand(inputPaths.ToArray()))
- {
- var wand = new MagickWand(width, height);
- wand.OpenImage("gradient:#111111-#111111");
- using (var draw = new DrawingWand())
- {
- using (var fcolor = new PixelWand(ColorName.White))
- {
- draw.FillColor = fcolor;
- draw.Font = MontserratLightFont;
- draw.FontSize = 60;
- draw.FontWeight = FontWeightType.LightStyle;
- draw.TextAntialias = true;
- }
-
- var fontMetrics = wand.QueryFontMetrics(draw, text);
- var textContainerY = Convert.ToInt32(height * .165);
- wand.CurrentImage.AnnotateImage(draw, (width - fontMetrics.TextWidth) / 2, textContainerY, 0.0, text);
-
- var iSlice = Convert.ToInt32(width * .1166666667);
- int iTrans = Convert.ToInt32(height * 0.2);
- int iHeight = Convert.ToInt32(height * 0.46296296296296296296296296296296);
- var horizontalImagePadding = Convert.ToInt32(width * 0.0125);
-
- foreach (var element in wandImages.ImageList)
- {
- int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height);
- element.Gravity = GravityType.CenterGravity;
- element.BackgroundColor = new PixelWand("none", 1);
- element.ResizeImage(iWidth, iHeight, FilterTypes.LanczosFilter);
- int ix = (int)Math.Abs((iWidth - iSlice) / 2);
- element.CropImage(iSlice, iHeight, ix, 0);
-
- element.ExtentImage(iSlice, iHeight, 0 - horizontalImagePadding, 0);
- }
-
- wandImages.SetFirstIterator();
- using (var wandList = wandImages.AppendImages())
- {
- wandList.CurrentImage.TrimImage(1);
- using (var mwr = wandList.CloneMagickWand())
- {
- using (var blackPixelWand = new PixelWand(ColorName.Black))
- {
- using (var greyPixelWand = new PixelWand(ColorName.Grey70))
- {
- mwr.CurrentImage.ResizeImage(wandList.CurrentImage.Width, (wandList.CurrentImage.Height / 2), FilterTypes.LanczosFilter, 1);
- mwr.CurrentImage.FlipImage();
-
- mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel;
- mwr.CurrentImage.ColorizeImage(blackPixelWand, greyPixelWand);
-
- using (var mwg = new MagickWand(wandList.CurrentImage.Width, iTrans))
- {
- mwg.OpenImage("gradient:black-none");
- var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111);
- mwr.CurrentImage.CompositeImage(mwg, CompositeOperator.DstInCompositeOp, 0, verticalSpacing);
-
- wandList.AddImage(mwr);
- int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2;
- wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * 0.26851851851851851851851851851852));
- }
- }
- }
- }
- }
- }
-
- return wand;
+ wand.SaveImage(outputPath);
}
}
@@ -211,81 +106,6 @@ namespace Emby.Drawing.ImageMagick
}
}
- private MagickWand BuildPosterCollageWandWithText(List paths, string label, int width, int height)
- {
- var inputPaths = ImageHelpers.ProjectPaths(paths, 4);
- using (var wandImages = new MagickWand(inputPaths.ToArray()))
- {
- var wand = new MagickWand(width, height);
- wand.OpenImage("gradient:#111111-#111111");
- using (var draw = new DrawingWand())
- {
- using (var fcolor = new PixelWand(ColorName.White))
- {
- draw.FillColor = fcolor;
- draw.Font = MontserratLightFont;
- draw.FontSize = 60;
- draw.FontWeight = FontWeightType.LightStyle;
- draw.TextAntialias = true;
- }
-
- var fontMetrics = wand.QueryFontMetrics(draw, label);
- var textContainerY = Convert.ToInt32(height * .165);
- wand.CurrentImage.AnnotateImage(draw, (width - fontMetrics.TextWidth) / 2, textContainerY, 0.0, label);
-
- var iSlice = Convert.ToInt32(width * 0.225);
- int iTrans = Convert.ToInt32(height * 0.2);
- int iHeight = Convert.ToInt32(height * 0.46296296296296296296296296296296);
- var horizontalImagePadding = Convert.ToInt32(width * 0.0275);
-
- foreach (var element in wandImages.ImageList)
- {
- int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height);
- element.Gravity = GravityType.CenterGravity;
- element.BackgroundColor = new PixelWand("none", 1);
- element.ResizeImage(iWidth, iHeight, FilterTypes.LanczosFilter);
- int ix = (int)Math.Abs((iWidth - iSlice) / 2);
- element.CropImage(iSlice, iHeight, ix, 0);
-
- element.ExtentImage(iSlice, iHeight, 0 - horizontalImagePadding, 0);
- }
-
- wandImages.SetFirstIterator();
- using (var wandList = wandImages.AppendImages())
- {
- wandList.CurrentImage.TrimImage(1);
- using (var mwr = wandList.CloneMagickWand())
- {
- using (var blackPixelWand = new PixelWand(ColorName.Black))
- {
- using (var greyPixelWand = new PixelWand(ColorName.Grey70))
- {
- mwr.CurrentImage.ResizeImage(wandList.CurrentImage.Width, (wandList.CurrentImage.Height / 2), FilterTypes.LanczosFilter, 1);
- mwr.CurrentImage.FlipImage();
-
- mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel;
- mwr.CurrentImage.ColorizeImage(blackPixelWand, greyPixelWand);
-
- using (var mwg = new MagickWand(wandList.CurrentImage.Width, iTrans))
- {
- mwg.OpenImage("gradient:black-none");
- var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111);
- mwr.CurrentImage.CompositeImage(mwg, CompositeOperator.DstInCompositeOp, 0, verticalSpacing);
-
- wandList.AddImage(mwr);
- int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2;
- wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * 0.26851851851851851851851851851852));
- }
- }
- }
- }
- }
- }
-
- return wand;
- }
- }
-
private MagickWand BuildThumbCollageWand(List paths, int width, int height)
{
var inputPaths = ImageHelpers.ProjectPaths(paths, 4);
@@ -295,9 +115,9 @@ namespace Emby.Drawing.ImageMagick
wand.OpenImage("gradient:#111111-#111111");
using (var draw = new DrawingWand())
{
- var iSlice = Convert.ToInt32(width * .1166666667 * 2);
+ var iSlice = Convert.ToInt32(width * 0.24125);
int iTrans = Convert.ToInt32(height * .25);
- int iHeight = Convert.ToInt32(height * .62);
+ int iHeight = Convert.ToInt32(height * .70);
var horizontalImagePadding = Convert.ToInt32(width * 0.0125);
foreach (var element in wandImages.ImageList)
@@ -339,7 +159,7 @@ namespace Emby.Drawing.ImageMagick
wandList.AddImage(mwr);
int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2;
- wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * .085));
+ wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * .045));
}
}
}
@@ -352,148 +172,29 @@ namespace Emby.Drawing.ImageMagick
}
private MagickWand BuildSquareCollageWand(List paths, int width, int height)
- {
- 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 * .3);
- int iTrans = Convert.ToInt32(height * .25);
- int iHeight = Convert.ToInt32(height * .63);
- var horizontalImagePadding = Convert.ToInt32(width * 0.02);
-
- foreach (var element in wandImages.ImageList)
- {
- using (var blackPixelWand = new PixelWand(ColorName.Black))
- {
- int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height);
- element.Gravity = GravityType.CenterGravity;
- element.BackgroundColor = blackPixelWand;
- element.ResizeImage(iWidth, iHeight, FilterTypes.LanczosFilter);
- int ix = (int)Math.Abs((iWidth - iSlice) / 2);
- element.CropImage(iSlice, iHeight, ix, 0);
-
- element.ExtentImage(iSlice, iHeight, 0 - horizontalImagePadding, 0);
- }
- }
-
- wandImages.SetFirstIterator();
- using (var wandList = wandImages.AppendImages())
- {
- wandList.CurrentImage.TrimImage(1);
- using (var mwr = wandList.CloneMagickWand())
- {
- using (var blackPixelWand = new PixelWand(ColorName.Black))
- {
- using (var greyPixelWand = new PixelWand(ColorName.Grey70))
- {
- mwr.CurrentImage.ResizeImage(wandList.CurrentImage.Width, (wandList.CurrentImage.Height / 2), FilterTypes.LanczosFilter, 1);
- mwr.CurrentImage.FlipImage();
-
- mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel;
- mwr.CurrentImage.ColorizeImage(blackPixelWand, greyPixelWand);
-
- using (var mwg = new MagickWand(wandList.CurrentImage.Width, iTrans))
- {
- mwg.OpenImage("gradient:black-none");
- var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111);
- mwr.CurrentImage.CompositeImage(mwg, CompositeOperator.CopyOpacityCompositeOp, 0, verticalSpacing);
-
- wandList.AddImage(mwr);
- int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2;
- wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * .07));
- }
- }
- }
- }
- }
- }
-
- return wand;
- }
- }
-
- private MagickWand BuildSquareCollageWandWithText(List paths, string label, int width, int height)
{
var inputPaths = ImageHelpers.ProjectPaths(paths, 4);
- using (var wandImages = new MagickWand(inputPaths.ToArray()))
+ var outputWand = new MagickWand(width, height, new PixelWand("none", 1));
+ var imageIndex = 0;
+ var cellWidth = width/2;
+ var cellHeight = height/2;
+ for (var x = 0; x < 2; x++)
{
- var wand = new MagickWand(width, height);
- wand.OpenImage("gradient:#111111-#111111");
- using (var draw = new DrawingWand())
+ for (var y = 0; y < 2; y++)
{
- using (var fcolor = new PixelWand(ColorName.White))
+ using (var temp = new MagickWand(inputPaths[imageIndex]))
{
- draw.FillColor = fcolor;
- draw.Font = MontserratLightFont;
- draw.FontSize = 60;
- draw.FontWeight = FontWeightType.LightStyle;
- draw.TextAntialias = true;
- }
-
- var fontMetrics = wand.QueryFontMetrics(draw, label);
- var textContainerY = Convert.ToInt32(height * .165);
- wand.CurrentImage.AnnotateImage(draw, (width - fontMetrics.TextWidth) / 2, textContainerY, 0.0, label);
-
- var iSlice = Convert.ToInt32(width * .225);
- int iTrans = Convert.ToInt32(height * 0.2);
- int iHeight = Convert.ToInt32(height * 0.46296296296296296296296296296296);
- var horizontalImagePadding = Convert.ToInt32(width * 0.02);
-
- foreach (var element in wandImages.ImageList)
- {
- int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height);
- element.Gravity = GravityType.CenterGravity;
- element.BackgroundColor = new PixelWand("none", 1);
- element.ResizeImage(iWidth, iHeight, FilterTypes.LanczosFilter);
- int ix = (int)Math.Abs((iWidth - iSlice) / 2);
- element.CropImage(iSlice, iHeight, ix, 0);
-
- element.ExtentImage(iSlice, iHeight, 0 - horizontalImagePadding, 0);
- }
-
- wandImages.SetFirstIterator();
- using (var wandList = wandImages.AppendImages())
- {
- wandList.CurrentImage.TrimImage(1);
- using (var mwr = wandList.CloneMagickWand())
- {
- using (var blackPixelWand = new PixelWand(ColorName.Black))
- {
- using (var greyPixelWand = new PixelWand(ColorName.Grey70))
- {
- mwr.CurrentImage.ResizeImage(wandList.CurrentImage.Width, (wandList.CurrentImage.Height / 2), FilterTypes.LanczosFilter, 1);
- mwr.CurrentImage.FlipImage();
-
- mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel;
- mwr.CurrentImage.ColorizeImage(blackPixelWand, greyPixelWand);
-
- using (var mwg = new MagickWand(wandList.CurrentImage.Width, iTrans))
- {
- mwg.OpenImage("gradient:black-none");
- var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111);
- mwr.CurrentImage.CompositeImage(mwg, CompositeOperator.DstInCompositeOp, 0, verticalSpacing);
-
- wandList.AddImage(mwr);
- int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2;
- wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * 0.26851851851851851851851851851852));
- }
- }
- }
- }
+ temp.CurrentImage.ScaleImage(cellWidth, cellHeight);
+ // draw this image into the strip at the next position
+ var xPos = x*cellWidth;
+ var yPos = y*cellHeight;
+ outputWand.CurrentImage.CompositeImage(temp, CompositeOperator.OverCompositeOp, xPos, yPos);
}
+ imageIndex++;
}
-
- return wand;
}
- }
- private string MontserratLightFont
- {
- get { return PlayedIndicatorDrawer.ExtractFont("MontserratLight.otf", _appPaths, _fileSystem); }
+ return outputWand;
}
}
}
diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs
index dc93cb7304..80ebbb7190 100644
--- a/Emby.Drawing/ImageProcessor.cs
+++ b/Emby.Drawing/ImageProcessor.cs
@@ -163,7 +163,7 @@ namespace Emby.Drawing
return _imageEncoder.SupportedOutputFormats;
}
- public async Task> ProcessImage(ImageProcessingOptions options)
+ public async Task> ProcessImage(ImageProcessingOptions options)
{
if (options == null)
{
@@ -178,14 +178,13 @@ namespace Emby.Drawing
}
var originalImagePath = originalImage.Path;
+ var dateModified = originalImage.DateModified;
if (!_imageEncoder.SupportsImageEncoding)
{
- return new Tuple(originalImagePath, MimeTypes.GetMimeType(originalImagePath));
+ return new Tuple(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
}
- var dateModified = originalImage.DateModified;
-
if (options.CropWhiteSpace && _imageEncoder.SupportsImageEncoding)
{
var tuple = await GetWhitespaceCroppedImage(originalImagePath, dateModified).ConfigureAwait(false);
@@ -211,7 +210,7 @@ namespace Emby.Drawing
if (options.HasDefaultOptions(originalImagePath))
{
// Just spit out the original file if all the options are default
- return new Tuple(originalImagePath, MimeTypes.GetMimeType(originalImagePath));
+ return new Tuple(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
}
ImageSize? originalImageSize;
@@ -221,7 +220,7 @@ namespace Emby.Drawing
if (options.HasDefaultOptions(originalImagePath, originalImageSize.Value))
{
// Just spit out the original file if all the options are default
- return new Tuple(originalImagePath, MimeTypes.GetMimeType(originalImagePath));
+ return new Tuple(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
}
}
catch
@@ -235,10 +234,6 @@ namespace Emby.Drawing
var outputFormat = GetOutputFormat(options.SupportedOutputFormats[0]);
var cacheFilePath = GetCacheFilePath(originalImagePath, newSize, quality, dateModified, outputFormat, options.AddPlayedIndicator, options.PercentPlayed, options.UnplayedCount, options.BackgroundColor, options.ForegroundLayer);
- var semaphore = GetLock(cacheFilePath);
-
- await semaphore.WaitAsync().ConfigureAwait(false);
-
var imageProcessingLockTaken = false;
try
@@ -251,15 +246,20 @@ namespace Emby.Drawing
var newHeight = Convert.ToInt32(newSize.Height);
_fileSystem.CreateDirectory(Path.GetDirectoryName(cacheFilePath));
+ var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(cacheFilePath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(tmpPath));
await _imageProcessingSemaphore.WaitAsync().ConfigureAwait(false);
imageProcessingLockTaken = true;
- _imageEncoder.EncodeImage(originalImagePath, cacheFilePath, AutoOrient(options.Item), newWidth, newHeight, quality, options, outputFormat);
+ _imageEncoder.EncodeImage(originalImagePath, tmpPath, AutoOrient(options.Item), newWidth, newHeight, quality, options, outputFormat);
+ CopyFile(tmpPath, cacheFilePath);
+
+ return new Tuple(tmpPath, GetMimeType(outputFormat, cacheFilePath), _fileSystem.GetLastWriteTimeUtc(tmpPath));
}
- return new Tuple(cacheFilePath, GetMimeType(outputFormat, cacheFilePath));
+ return new Tuple(cacheFilePath, GetMimeType(outputFormat, cacheFilePath), _fileSystem.GetLastWriteTimeUtc(cacheFilePath));
}
catch (Exception ex)
{
@@ -267,7 +267,7 @@ namespace Emby.Drawing
_logger.ErrorException("Error encoding image", ex);
// Just spit out the original file if all the options are default
- return new Tuple(originalImagePath, MimeTypes.GetMimeType(originalImagePath));
+ return new Tuple(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
}
finally
{
@@ -275,8 +275,18 @@ namespace Emby.Drawing
{
_imageProcessingSemaphore.Release();
}
+ }
+ }
+
+ private void CopyFile(string src, string destination)
+ {
+ try
+ {
+ File.Copy(src, destination, true);
+ }
+ catch
+ {
- semaphore.Release();
}
}
@@ -412,14 +422,9 @@ namespace Emby.Drawing
var croppedImagePath = GetCachePath(CroppedWhitespaceImageCachePath, name, Path.GetExtension(originalImagePath));
- var semaphore = GetLock(croppedImagePath);
-
- await semaphore.WaitAsync().ConfigureAwait(false);
-
// Check again in case of contention
if (_fileSystem.FileExists(croppedImagePath))
{
- semaphore.Release();
return GetResult(croppedImagePath);
}
@@ -428,11 +433,15 @@ namespace Emby.Drawing
try
{
_fileSystem.CreateDirectory(Path.GetDirectoryName(croppedImagePath));
+ var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(croppedImagePath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(tmpPath));
await _imageProcessingSemaphore.WaitAsync().ConfigureAwait(false);
imageProcessingLockTaken = true;
- _imageEncoder.CropWhiteSpace(originalImagePath, croppedImagePath);
+ _imageEncoder.CropWhiteSpace(originalImagePath, tmpPath);
+ CopyFile(tmpPath, croppedImagePath);
+ return GetResult(tmpPath);
}
catch (NotImplementedException)
{
@@ -452,11 +461,7 @@ namespace Emby.Drawing
{
_imageProcessingSemaphore.Release();
}
-
- semaphore.Release();
}
-
- return GetResult(croppedImagePath);
}
private Tuple GetResult(string path)
diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs
index 8233717abf..dc811812ae 100644
--- a/MediaBrowser.Api/ApiEntryPoint.cs
+++ b/MediaBrowser.Api/ApiEntryPoint.cs
@@ -237,9 +237,12 @@ namespace MediaBrowser.Api
{
lock (_activeTranscodingJobs)
{
- var job = _activeTranscodingJobs.First(j => j.Type == type && string.Equals(j.Path, path, StringComparison.OrdinalIgnoreCase));
+ var job = _activeTranscodingJobs.FirstOrDefault(j => j.Type == type && string.Equals(j.Path, path, StringComparison.OrdinalIgnoreCase));
- _activeTranscodingJobs.Remove(job);
+ if (job != null)
+ {
+ _activeTranscodingJobs.Remove(job);
+ }
}
if (!string.IsNullOrWhiteSpace(state.Request.DeviceId))
@@ -349,7 +352,7 @@ namespace MediaBrowser.Api
if (job.Type != TranscodingJobType.Progressive)
{
- timerDuration = 1800000;
+ timerDuration = 60000;
}
job.PingTimeout = timerDuration;
@@ -488,13 +491,17 @@ namespace MediaBrowser.Api
{
try
{
- Logger.Info("Killing ffmpeg process for {0}", job.Path);
+ Logger.Info("Stopping ffmpeg process with q command for {0}", job.Path);
//process.Kill();
process.StandardInput.WriteLine("q");
// Need to wait because killing is asynchronous
- process.WaitForExit(5000);
+ if (!process.WaitForExit(5000))
+ {
+ Logger.Info("Killing ffmpeg process for {0}", job.Path);
+ process.Kill();
+ }
}
catch (Exception ex)
{
diff --git a/MediaBrowser.Api/BaseApiService.cs b/MediaBrowser.Api/BaseApiService.cs
index 30750b3741..44a367be09 100644
--- a/MediaBrowser.Api/BaseApiService.cs
+++ b/MediaBrowser.Api/BaseApiService.cs
@@ -79,7 +79,7 @@ namespace MediaBrowser.Api
}
}
}
-
+
///
/// To the optimized serialized result using cache.
///
@@ -115,12 +115,9 @@ namespace MediaBrowser.Api
/// System.Object.
protected object ToStaticFileResult(string path)
{
- return ResultFactory.GetStaticFileResult(Request, path);
+ return ResultFactory.GetStaticFileResult(Request, path).Result;
}
- private readonly char[] _dashReplaceChars = { '?', '/', '&' };
- private const char SlugChar = '-';
-
protected DtoOptions GetDtoOptions(object request)
{
var options = new DtoOptions();
@@ -154,152 +151,122 @@ namespace MediaBrowser.Api
protected MusicArtist GetArtist(string name, ILibraryManager libraryManager)
{
- return libraryManager.GetArtist(DeSlugArtistName(name, libraryManager));
+ if (name.IndexOf(BaseItem.SlugChar) != -1)
+ {
+ var result = libraryManager.GetItemList(new InternalItemsQuery
+ {
+ SlugName = name,
+ IncludeItemTypes = new[] { typeof(MusicArtist).Name }
+
+ }).OfType().FirstOrDefault();
+
+ if (result != null)
+ {
+ return result;
+ }
+ }
+
+ return libraryManager.GetArtist(name);
}
protected Studio GetStudio(string name, ILibraryManager libraryManager)
{
- return libraryManager.GetStudio(DeSlugStudioName(name, libraryManager));
+ if (name.IndexOf(BaseItem.SlugChar) != -1)
+ {
+ var result = libraryManager.GetItemList(new InternalItemsQuery
+ {
+ SlugName = name,
+ IncludeItemTypes = new[] { typeof(Studio).Name }
+
+ }).OfType().FirstOrDefault();
+
+ if (result != null)
+ {
+ return result;
+ }
+ }
+
+ return libraryManager.GetStudio(name);
}
protected Genre GetGenre(string name, ILibraryManager libraryManager)
{
- return libraryManager.GetGenre(DeSlugGenreName(name, libraryManager));
+ if (name.IndexOf(BaseItem.SlugChar) != -1)
+ {
+ var result = libraryManager.GetItemList(new InternalItemsQuery
+ {
+ SlugName = name,
+ IncludeItemTypes = new[] { typeof(Genre).Name }
+
+ }).OfType().FirstOrDefault();
+
+ if (result != null)
+ {
+ return result;
+ }
+ }
+
+ return libraryManager.GetGenre(name);
}
protected MusicGenre GetMusicGenre(string name, ILibraryManager libraryManager)
{
- return libraryManager.GetMusicGenre(DeSlugGenreName(name, libraryManager));
+ if (name.IndexOf(BaseItem.SlugChar) != -1)
+ {
+ var result = libraryManager.GetItemList(new InternalItemsQuery
+ {
+ SlugName = name,
+ IncludeItemTypes = new[] { typeof(MusicGenre).Name }
+
+ }).OfType().FirstOrDefault();
+
+ if (result != null)
+ {
+ return result;
+ }
+ }
+
+ return libraryManager.GetMusicGenre(name);
}
protected GameGenre GetGameGenre(string name, ILibraryManager libraryManager)
{
- return libraryManager.GetGameGenre(DeSlugGameGenreName(name, libraryManager));
+ if (name.IndexOf(BaseItem.SlugChar) != -1)
+ {
+ var result = libraryManager.GetItemList(new InternalItemsQuery
+ {
+ SlugName = name,
+ IncludeItemTypes = new[] { typeof(GameGenre).Name }
+
+ }).OfType().FirstOrDefault();
+
+ if (result != null)
+ {
+ return result;
+ }
+ }
+
+ return libraryManager.GetGameGenre(name);
}
protected Person GetPerson(string name, ILibraryManager libraryManager)
{
- return libraryManager.GetPerson(DeSlugPersonName(name, libraryManager));
- }
-
- ///
- /// Deslugs an artist name by finding the correct entry in the library
- ///
- ///
- ///
- ///
- protected string DeSlugArtistName(string name, ILibraryManager libraryManager)
- {
- if (name.IndexOf(SlugChar) == -1)
+ if (name.IndexOf(BaseItem.SlugChar) != -1)
{
- return name;
+ var result = libraryManager.GetItemList(new InternalItemsQuery
+ {
+ SlugName = name,
+ IncludeItemTypes = new[] { typeof(Person).Name }
+
+ }).OfType().FirstOrDefault();
+
+ if (result != null)
+ {
+ return result;
+ }
}
- var items = libraryManager.GetItemList(new InternalItemsQuery
- {
- IncludeItemTypes = new[] { typeof(Audio).Name, typeof(MusicVideo).Name, typeof(MusicAlbum).Name }
- });
-
- return items
- .OfType()
- .SelectMany(i => i.AllArtists)
- .DistinctNames()
- .FirstOrDefault(i =>
- {
- i = _dashReplaceChars.Aggregate(i, (current, c) => current.Replace(c, SlugChar));
-
- return string.Equals(i, name, StringComparison.OrdinalIgnoreCase);
-
- }) ?? name;
- }
-
- ///
- /// Deslugs a genre name by finding the correct entry in the library
- ///
- protected string DeSlugGenreName(string name, ILibraryManager libraryManager)
- {
- if (name.IndexOf(SlugChar) == -1)
- {
- return name;
- }
-
- return libraryManager.RootFolder.GetRecursiveChildren()
- .SelectMany(i => i.Genres)
- .DistinctNames()
- .FirstOrDefault(i =>
- {
- i = _dashReplaceChars.Aggregate(i, (current, c) => current.Replace(c, SlugChar));
-
- return string.Equals(i, name, StringComparison.OrdinalIgnoreCase);
-
- }) ?? name;
- }
-
- protected string DeSlugGameGenreName(string name, ILibraryManager libraryManager)
- {
- if (name.IndexOf(SlugChar) == -1)
- {
- return name;
- }
-
- var items = libraryManager.GetItemList(new InternalItemsQuery
- {
- IncludeItemTypes = new[] { typeof(Game).Name }
- });
-
- return items
- .SelectMany(i => i.Genres)
- .DistinctNames()
- .FirstOrDefault(i =>
- {
- i = _dashReplaceChars.Aggregate(i, (current, c) => current.Replace(c, SlugChar));
-
- return string.Equals(i, name, StringComparison.OrdinalIgnoreCase);
-
- }) ?? name;
- }
-
- ///
- /// Deslugs a studio name by finding the correct entry in the library
- ///
- protected string DeSlugStudioName(string name, ILibraryManager libraryManager)
- {
- if (name.IndexOf(SlugChar) == -1)
- {
- return name;
- }
-
- return libraryManager.RootFolder
- .GetRecursiveChildren()
- .SelectMany(i => i.Studios)
- .DistinctNames()
- .FirstOrDefault(i =>
- {
- i = _dashReplaceChars.Aggregate(i, (current, c) => current.Replace(c, SlugChar));
-
- return string.Equals(i, name, StringComparison.OrdinalIgnoreCase);
-
- }) ?? name;
- }
-
- ///
- /// Deslugs a person name by finding the correct entry in the library
- ///
- protected string DeSlugPersonName(string name, ILibraryManager libraryManager)
- {
- if (name.IndexOf(SlugChar) == -1)
- {
- return name;
- }
-
- return libraryManager.GetPeopleNames(new InternalPeopleQuery())
- .FirstOrDefault(i =>
- {
- i = _dashReplaceChars.Aggregate(i, (current, c) => current.Replace(c, SlugChar));
-
- return string.Equals(i, name, StringComparison.OrdinalIgnoreCase);
-
- }) ?? name;
+ return libraryManager.GetPerson(name);
}
protected string GetPathValue(int index)
diff --git a/MediaBrowser.Api/BrandingService.cs b/MediaBrowser.Api/BrandingService.cs
index c900e4d069..e991565ad2 100644
--- a/MediaBrowser.Api/BrandingService.cs
+++ b/MediaBrowser.Api/BrandingService.cs
@@ -10,6 +10,7 @@ namespace MediaBrowser.Api
}
[Route("/Branding/Css", "GET", Summary = "Gets custom css")]
+ [Route("/Branding/Css.css", "GET", Summary = "Gets custom css")]
public class GetBrandingCss
{
}
diff --git a/MediaBrowser.Api/ConfigurationService.cs b/MediaBrowser.Api/ConfigurationService.cs
index 446415fbb5..2e5c252d63 100644
--- a/MediaBrowser.Api/ConfigurationService.cs
+++ b/MediaBrowser.Api/ConfigurationService.cs
@@ -9,7 +9,9 @@ using ServiceStack.Web;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Threading.Tasks;
using CommonIO;
+using MediaBrowser.Controller.MediaEncoding;
namespace MediaBrowser.Api
{
@@ -71,6 +73,16 @@ namespace MediaBrowser.Api
}
+ [Route("/System/MediaEncoder/Path", "POST", Summary = "Updates the path to the media encoder")]
+ [Authenticated(Roles = "Admin", AllowBeforeStartupWizard = true)]
+ public class UpdateMediaEncoderPath : IReturnVoid
+ {
+ [ApiMember(Name = "Path", Description = "Path", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+ public string Path { get; set; }
+ [ApiMember(Name = "PathType", Description = "PathType", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+ public string PathType { get; set; }
+ }
+
public class ConfigurationService : BaseApiService
{
///
@@ -86,14 +98,22 @@ namespace MediaBrowser.Api
private readonly IFileSystem _fileSystem;
private readonly IProviderManager _providerManager;
private readonly ILibraryManager _libraryManager;
+ private readonly IMediaEncoder _mediaEncoder;
- public ConfigurationService(IJsonSerializer jsonSerializer, IServerConfigurationManager configurationManager, IFileSystem fileSystem, IProviderManager providerManager, ILibraryManager libraryManager)
+ public ConfigurationService(IJsonSerializer jsonSerializer, IServerConfigurationManager configurationManager, IFileSystem fileSystem, IProviderManager providerManager, ILibraryManager libraryManager, IMediaEncoder mediaEncoder)
{
_jsonSerializer = jsonSerializer;
_configurationManager = configurationManager;
_fileSystem = fileSystem;
_providerManager = providerManager;
_libraryManager = libraryManager;
+ _mediaEncoder = mediaEncoder;
+ }
+
+ public void Post(UpdateMediaEncoderPath request)
+ {
+ var task = _mediaEncoder.UpdateEncoderPath(request.Path, request.PathType);
+ Task.WaitAll(task);
}
///
diff --git a/MediaBrowser.Api/Dlna/DlnaService.cs b/MediaBrowser.Api/Dlna/DlnaService.cs
index b6c4f5dfba..dd4b59b920 100644
--- a/MediaBrowser.Api/Dlna/DlnaService.cs
+++ b/MediaBrowser.Api/Dlna/DlnaService.cs
@@ -31,11 +31,9 @@ namespace MediaBrowser.Api.Dlna
public string Id { get; set; }
}
- [Route("/Dlna/Profiles/{ProfileId}", "POST", Summary = "Updates a profile")]
+ [Route("/Dlna/Profiles/{Id}", "POST", Summary = "Updates a profile")]
public class UpdateProfile : DeviceProfile, IReturnVoid
{
- [ApiMember(Name = "ProfileId", Description = "Profile Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string ProfileId { get; set; }
}
[Route("/Dlna/Profiles", "POST", Summary = "Creates a profile")]
@@ -89,4 +87,4 @@ namespace MediaBrowser.Api.Dlna
_dlnaManager.CreateProfile(request);
}
}
-}
+}
\ No newline at end of file
diff --git a/MediaBrowser.Api/EnvironmentService.cs b/MediaBrowser.Api/EnvironmentService.cs
index 4e88e946f4..b354cb26c2 100644
--- a/MediaBrowser.Api/EnvironmentService.cs
+++ b/MediaBrowser.Api/EnvironmentService.cs
@@ -90,6 +90,17 @@ namespace MediaBrowser.Api
public string Path { get; set; }
}
+ public class DefaultDirectoryBrowserInfo
+ {
+ public string Path { get; set; }
+ }
+
+ [Route("/Environment/DefaultDirectoryBrowser", "GET", Summary = "Gets the parent path of a given path")]
+ public class GetDefaultDirectoryBrowser : IReturn
+ {
+
+ }
+
///
/// Class EnvironmentService
///
@@ -108,7 +119,6 @@ namespace MediaBrowser.Api
/// Initializes a new instance of the class.
///
/// The network manager.
- /// networkManager
public EnvironmentService(INetworkManager networkManager, IFileSystem fileSystem)
{
if (networkManager == null)
@@ -120,6 +130,29 @@ namespace MediaBrowser.Api
_fileSystem = fileSystem;
}
+ public object Get(GetDefaultDirectoryBrowser request)
+ {
+ var result = new DefaultDirectoryBrowserInfo();
+
+ if (Environment.OSVersion.Platform == PlatformID.Unix)
+ {
+ try
+ {
+ var qnap = "/share/CACHEDEV1_DATA";
+ if (Directory.Exists(qnap))
+ {
+ result.Path = qnap;
+ }
+ }
+ catch
+ {
+
+ }
+ }
+
+ return ToOptimizedResult(result);
+ }
+
///
/// Gets the specified request.
///
diff --git a/MediaBrowser.Api/FilterService.cs b/MediaBrowser.Api/FilterService.cs
index 6d1c5d868d..b3b75359aa 100644
--- a/MediaBrowser.Api/FilterService.cs
+++ b/MediaBrowser.Api/FilterService.cs
@@ -80,7 +80,7 @@ namespace MediaBrowser.Api
.OrderBy(i => i)
.ToArray();
- result.Tags = items.OfType()
+ result.Tags = items
.SelectMany(i => i.Tags)
.Distinct(StringComparer.OrdinalIgnoreCase)
.OrderBy(i => i)
@@ -103,7 +103,8 @@ namespace MediaBrowser.Api
User = user,
MediaTypes = request.GetMediaTypes(),
IncludeItemTypes = request.GetIncludeItemTypes(),
- Recursive = true
+ Recursive = true,
+ EnableTotalRecordCount = false
};
return query;
diff --git a/MediaBrowser.Api/GamesService.cs b/MediaBrowser.Api/GamesService.cs
index 040872fcc8..0953b95e62 100644
--- a/MediaBrowser.Api/GamesService.cs
+++ b/MediaBrowser.Api/GamesService.cs
@@ -10,6 +10,8 @@ using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
+using System.Threading.Tasks;
+using MediaBrowser.Model.Querying;
namespace MediaBrowser.Api
{
@@ -107,8 +109,7 @@ namespace MediaBrowser.Api
{
IncludeItemTypes = new[] { typeof(GameSystem).Name }
};
- var parentIds = new string[] { } ;
- var gameSystems = _libraryManager.GetItemList(query, parentIds)
+ var gameSystems = _libraryManager.GetItemList(query)
.Cast()
.ToList();
@@ -128,8 +129,7 @@ namespace MediaBrowser.Api
{
IncludeItemTypes = new[] { typeof(Game).Name }
};
- var parentIds = new string[] { };
- var games = _libraryManager.GetItemList(query, parentIds)
+ var games = _libraryManager.GetItemList(query)
.Cast()
.ToList();
@@ -162,7 +162,10 @@ namespace MediaBrowser.Api
var items = user == null ?
system.GetRecursiveChildren(i => i is Game) :
- system.GetRecursiveChildren(user, i => i is Game);
+ system.GetRecursiveChildren(user, new InternalItemsQuery(user)
+ {
+ IncludeItemTypes = new[] { typeof(Game).Name }
+ });
var games = items.Cast().ToList();
@@ -182,20 +185,42 @@ namespace MediaBrowser.Api
///
/// The request.
/// System.Object.
- public object Get(GetSimilarGames request)
+ public async Task