aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Emby.Common.Implementations/IO/ManagedFileSystem.cs58
-rw-r--r--Emby.Common.Implementations/IO/SharpCifsFileSystem.cs25
-rw-r--r--Emby.Drawing.Skia/StripCollageBuilder.cs44
-rw-r--r--Emby.Drawing/ImageProcessor.cs49
-rw-r--r--Emby.Drawing/NullImageEncoder.cs5
-rw-r--r--Emby.Server.Core/IO/LibraryMonitor.cs2
-rw-r--r--Emby.Server.Implementations/IO/FileRefresher.cs10
-rw-r--r--MediaBrowser.Api/MediaBrowser.Api.csproj4
-rw-r--r--MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs12
-rw-r--r--MediaBrowser.Api/Playback/Hls/VideoHlsService.cs2
-rw-r--r--MediaBrowser.Api/Reports/Common/HeaderMetadata.cs3
-rw-r--r--MediaBrowser.Api/Reports/Common/ReportBuilderBase.cs5
-rw-r--r--MediaBrowser.Api/Reports/Data/ReportBuilder.cs13
-rw-r--r--MediaBrowser.Api/Reports/Stat/ReportStatBuilder.cs256
-rw-r--r--MediaBrowser.Api/Reports/Stat/ReportStatGroup.cs33
-rw-r--r--MediaBrowser.Api/Reports/Stat/ReportStatItem.cs23
-rw-r--r--MediaBrowser.Api/Reports/Stat/ReportStatResult.cs24
-rw-r--r--MediaBrowser.Controller/Drawing/IImageEncoder.cs2
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs37
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs46
-rw-r--r--MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs6
-rw-r--r--MediaBrowser.Model/IO/IFileSystem.cs3
-rw-r--r--MediaBrowser.Providers/Manager/ImageSaver.cs27
-rw-r--r--MediaBrowser.Providers/Omdb/OmdbItemProvider.cs19
-rw-r--r--MediaBrowser.Providers/Omdb/OmdbProvider.cs17
-rw-r--r--MediaBrowser.Server.Mac/Emby.Server.Mac.csproj4
-rw-r--r--MediaBrowser.ServerApplication/ImageEncoderHelper.cs4
-rw-r--r--MediaBrowser.ServerApplication/MainStartup.cs108
-rw-r--r--MediaBrowser.ServerApplication/Native/LoopUtil.cs21
-rw-r--r--MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs7
-rw-r--r--SharedVersion.cs2
31 files changed, 353 insertions, 518 deletions
diff --git a/Emby.Common.Implementations/IO/ManagedFileSystem.cs b/Emby.Common.Implementations/IO/ManagedFileSystem.cs
index 6cbf39758..7d14e521f 100644
--- a/Emby.Common.Implementations/IO/ManagedFileSystem.cs
+++ b/Emby.Common.Implementations/IO/ManagedFileSystem.cs
@@ -518,6 +518,49 @@ namespace Emby.Common.Implementations.IO
}
}
+ public void SetAttributes(string path, bool isHidden, bool isReadOnly)
+ {
+ if (_sharpCifsFileSystem.IsEnabledForPath(path))
+ {
+ _sharpCifsFileSystem.SetAttributes(path, isHidden, isReadOnly);
+ return;
+ }
+
+ var info = GetFileInfo(path);
+
+ if (!info.Exists)
+ {
+ return;
+ }
+
+ if (info.IsReadOnly == isReadOnly && info.IsHidden == isHidden)
+ {
+ return;
+ }
+
+ var attributes = File.GetAttributes(path);
+
+ if (isReadOnly)
+ {
+ attributes = attributes | FileAttributes.ReadOnly;
+ }
+ else
+ {
+ attributes = RemoveAttribute(attributes, FileAttributes.ReadOnly);
+ }
+
+ if (isHidden)
+ {
+ attributes = attributes | FileAttributes.Hidden;
+ }
+ else
+ {
+ attributes = RemoveAttribute(attributes, FileAttributes.Hidden);
+ }
+
+ File.SetAttributes(path, attributes);
+ }
+
private static FileAttributes RemoveAttribute(FileAttributes attributes, FileAttributes attributesToRemove)
{
return attributes & ~attributesToRemove;
@@ -690,20 +733,7 @@ namespace Emby.Common.Implementations.IO
return;
}
- var fileInfo = GetFileInfo(path);
-
- if (fileInfo.Exists)
- {
- if (fileInfo.IsHidden)
- {
- SetHidden(path, false);
- }
- if (fileInfo.IsReadOnly)
- {
- SetReadOnly(path, false);
- }
- }
-
+ SetAttributes(path, false, false);
File.Delete(path);
}
diff --git a/Emby.Common.Implementations/IO/SharpCifsFileSystem.cs b/Emby.Common.Implementations/IO/SharpCifsFileSystem.cs
index 283bcdef0..64cac7623 100644
--- a/Emby.Common.Implementations/IO/SharpCifsFileSystem.cs
+++ b/Emby.Common.Implementations/IO/SharpCifsFileSystem.cs
@@ -166,23 +166,38 @@ namespace Emby.Common.Implementations.IO
public void SetHidden(string path, bool isHidden)
{
var file = CreateSmbFile(path);
+ SetHidden(file, isHidden);
+ }
+
+ public void SetReadOnly(string path, bool isReadOnly)
+ {
+ var file = CreateSmbFile(path);
+ SetReadOnly(file, isReadOnly);
+ }
+
+ public void SetAttributes(string path, bool isHidden, bool isReadOnly)
+ {
+ var file = CreateSmbFile(path);
+ SetHidden(file, isHidden);
+ SetReadOnly(file, isReadOnly);
+ }
+ private void SetHidden(SmbFile file, bool isHidden)
+ {
var isCurrentlyHidden = file.IsHidden();
if (isCurrentlyHidden && !isHidden)
{
- file.SetAttributes(file.GetAttributes() & ~SmbFile.AttrReadonly);
+ file.SetAttributes(file.GetAttributes() & ~SmbFile.AttrHidden);
}
else if (!isCurrentlyHidden && isHidden)
{
- file.SetAttributes(file.GetAttributes() | SmbFile.AttrReadonly);
+ file.SetAttributes(file.GetAttributes() | SmbFile.AttrHidden);
}
}
- public void SetReadOnly(string path, bool isReadOnly)
+ private void SetReadOnly(SmbFile file, bool isReadOnly)
{
- var file = CreateSmbFile(path);
-
var isCurrentlyReadOnly = !file.CanWrite();
if (isCurrentlyReadOnly && !isReadOnly)
diff --git a/Emby.Drawing.Skia/StripCollageBuilder.cs b/Emby.Drawing.Skia/StripCollageBuilder.cs
index 7f3700769..605677aab 100644
--- a/Emby.Drawing.Skia/StripCollageBuilder.cs
+++ b/Emby.Drawing.Skia/StripCollageBuilder.cs
@@ -72,7 +72,8 @@ namespace Emby.Drawing.Skia
{
canvas.Clear(SKColors.Black);
- var iSlice = Convert.ToInt32(width * 0.24125);
+ // determine sizes for each image that will composited into the final image
+ var iSlice = Convert.ToInt32(width * 0.23475);
int iTrans = Convert.ToInt32(height * .25);
int iHeight = Convert.ToInt32(height * .70);
var horizontalImagePadding = Convert.ToInt32(width * 0.0125);
@@ -83,29 +84,54 @@ namespace Emby.Drawing.Skia
{
using (var currentBitmap = SKBitmap.Decode(paths[imageIndex]))
{
+ // resize to the same aspect as the original
int iWidth = (int)Math.Abs(iHeight * currentBitmap.Width / currentBitmap.Height);
using (var resizeBitmap = new SKBitmap(iWidth, iHeight, currentBitmap.ColorType, currentBitmap.AlphaType))
{
currentBitmap.Resize(resizeBitmap, SKBitmapResizeMethod.Lanczos3);
+ // determine how much to crop
int ix = (int)Math.Abs((iWidth - iSlice) / 2);
using (var image = SKImage.FromBitmap(resizeBitmap))
{
+ // crop image
using (var subset = image.Subset(SKRectI.Create(ix, 0, iSlice, iHeight)))
{
- canvas.DrawImage(subset, (horizontalImagePadding * (i + 1)) + (iSlice * i), 0);
+ // draw image onto canvas
+ canvas.DrawImage(subset, (horizontalImagePadding * (i + 1)) + (iSlice * i), verticalSpacing);
using (var croppedBitmap = SKBitmap.FromImage(subset))
{
- using (var flipped = new SKBitmap(croppedBitmap.Width, croppedBitmap.Height / 2, croppedBitmap.ColorType, croppedBitmap.AlphaType))
+ // create reflection of image below the drawn image
+ using (var reflectionBitmap = new SKBitmap(croppedBitmap.Width, croppedBitmap.Height / 2, croppedBitmap.ColorType, croppedBitmap.AlphaType))
{
- croppedBitmap.Resize(flipped, SKBitmapResizeMethod.Lanczos3);
+ // resize to half height
+ croppedBitmap.Resize(reflectionBitmap, SKBitmapResizeMethod.Lanczos3);
- using (var gradient = new SKPaint())
+ using (var flippedBitmap = new SKBitmap(reflectionBitmap.Width, reflectionBitmap.Height, reflectionBitmap.ColorType, reflectionBitmap.AlphaType))
{
- var matrix = SKMatrix.MakeScale(1, -1);
- matrix.SetScaleTranslate(1, -1, 0, flipped.Height);
- gradient.Shader = SKShader.CreateLinearGradient(new SKPoint(0, 0), new SKPoint(0, flipped.Height), new[] { new SKColor(0, 0, 0, 0), SKColors.Black }, null, SKShaderTileMode.Clamp, matrix);
- canvas.DrawBitmap(flipped, (horizontalImagePadding * (i + 1)) + (iSlice * i), iHeight + verticalSpacing, gradient);
+ using (var flippedCanvas = new SKCanvas(flippedBitmap))
+ {
+ // flip image vertically
+ var matrix = SKMatrix.MakeScale(1, -1);
+ matrix.SetScaleTranslate(1, -1, 0, flippedBitmap.Height);
+ flippedCanvas.SetMatrix(matrix);
+ flippedCanvas.DrawBitmap(reflectionBitmap, 0, 0);
+ flippedCanvas.ResetMatrix();
+
+ // create gradient to make image appear as a reflection
+ var remainingHeight = height - (iHeight + (2 * verticalSpacing));
+ flippedCanvas.ClipRect(SKRect.Create(reflectionBitmap.Width, remainingHeight));
+ using (var gradient = new SKPaint())
+ {
+ gradient.IsAntialias = true;
+ gradient.BlendMode = SKBlendMode.SrcOver;
+ gradient.Shader = SKShader.CreateLinearGradient(new SKPoint(0, 0), new SKPoint(0, remainingHeight), new[] { new SKColor(0, 0, 0, 128), new SKColor(0, 0, 0, 208), new SKColor(0, 0, 0, 240), new SKColor(0, 0, 0, 255) }, null, SKShaderTileMode.Clamp);
+ flippedCanvas.DrawPaint(gradient);
+ }
+
+ // finally draw reflection onto canvas
+ canvas.DrawBitmap(flippedBitmap, (horizontalImagePadding * (i + 1)) + (iSlice * i), iHeight + (2 * verticalSpacing));
+ }
}
}
}
diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs
index 9dc5f75ee..030291def 100644
--- a/Emby.Drawing/ImageProcessor.cs
+++ b/Emby.Drawing/ImageProcessor.cs
@@ -198,7 +198,7 @@ namespace Emby.Drawing
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
}
- ImageSize? originalImageSize;
+ ImageSize? originalImageSize = null;
try
{
originalImageSize = GetImageSize(originalImagePath, dateModified, true);
@@ -333,7 +333,7 @@ namespace Emby.Drawing
return new ImageSize(options.Width.Value, options.Height.Value);
}
- var aspect = GetEstimatedAspectRatio(options.Image.Type);
+ var aspect = GetEstimatedAspectRatio(options.Image.Type, options.Item);
var width = options.Width ?? options.MaxWidth;
@@ -348,7 +348,7 @@ namespace Emby.Drawing
return new ImageSize(widthValue, height);
}
- private double GetEstimatedAspectRatio(ImageType type)
+ private double GetEstimatedAspectRatio(ImageType type, IHasImages item)
{
switch (type)
{
@@ -368,7 +368,7 @@ namespace Emby.Drawing
case ImageType.Logo:
return 2.58;
case ImageType.Primary:
- return .667;
+ return item.GetDefaultPrimaryImageAspectRatio() ?? .667;
default:
return 1;
}
@@ -499,26 +499,39 @@ namespace Emby.Drawing
/// <returns>ImageSize.</returns>
private ImageSize GetImageSizeInternal(string path, bool allowSlowMethod)
{
+ // Can't use taglib because it keeps a lock on the file
+ //try
+ //{
+ // using (var file = TagLib.File.Create(new StreamFileAbstraction(Path.GetFileName(path), _fileSystem.OpenRead(path), null)))
+ // {
+ // var image = file as TagLib.Image.File;
+
+ // var properties = image.Properties;
+
+ // return new ImageSize
+ // {
+ // Height = properties.PhotoHeight,
+ // Width = properties.PhotoWidth
+ // };
+ // }
+ //}
+ //catch
+ //{
+ //}
+
try
{
- using (var file = TagLib.File.Create(new StreamFileAbstraction(Path.GetFileName(path), _fileSystem.OpenRead(path), null)))
- {
- var image = file as TagLib.Image.File;
-
- var properties = image.Properties;
-
- return new ImageSize
- {
- Height = properties.PhotoHeight,
- Width = properties.PhotoWidth
- };
- }
+ return ImageHeader.GetDimensions(path, _logger, _fileSystem);
}
catch
{
- }
+ if (allowSlowMethod)
+ {
+ return _imageEncoder.GetImageSize(path);
+ }
- return ImageHeader.GetDimensions(path, _logger, _fileSystem);
+ throw;
+ }
}
private readonly ITimer _saveImageSizeTimer;
diff --git a/Emby.Drawing/NullImageEncoder.cs b/Emby.Drawing/NullImageEncoder.cs
index 4fa18ce55..c7d365fb2 100644
--- a/Emby.Drawing/NullImageEncoder.cs
+++ b/Emby.Drawing/NullImageEncoder.cs
@@ -57,6 +57,11 @@ namespace Emby.Drawing
get { return false; }
}
+ public ImageSize GetImageSize(string path)
+ {
+ throw new NotImplementedException();
+ }
+
public void Dispose()
{
}
diff --git a/Emby.Server.Core/IO/LibraryMonitor.cs b/Emby.Server.Core/IO/LibraryMonitor.cs
index 8af826c88..0f0640a38 100644
--- a/Emby.Server.Core/IO/LibraryMonitor.cs
+++ b/Emby.Server.Core/IO/LibraryMonitor.cs
@@ -537,7 +537,7 @@ namespace Emby.Server.Core.IO
}
}
- var newRefresher = new FileRefresher(path, _fileSystem, ConfigurationManager, LibraryManager, TaskManager, Logger, _timerFactory, _environmentInfo);
+ var newRefresher = new FileRefresher(path, _fileSystem, ConfigurationManager, LibraryManager, TaskManager, Logger, _timerFactory, _environmentInfo, LibraryManager);
newRefresher.Completed += NewRefresher_Completed;
_activeRefreshers.Add(newRefresher);
}
diff --git a/Emby.Server.Implementations/IO/FileRefresher.cs b/Emby.Server.Implementations/IO/FileRefresher.cs
index 033cbd8b0..edff25156 100644
--- a/Emby.Server.Implementations/IO/FileRefresher.cs
+++ b/Emby.Server.Implementations/IO/FileRefresher.cs
@@ -34,8 +34,9 @@ namespace Emby.Server.Implementations.IO
public event EventHandler<EventArgs> Completed;
private readonly IEnvironmentInfo _environmentInfo;
+ private readonly ILibraryManager _libraryManager;
- public FileRefresher(string path, IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, ITaskManager taskManager, ILogger logger, ITimerFactory timerFactory, IEnvironmentInfo environmentInfo)
+ public FileRefresher(string path, IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, ITaskManager taskManager, ILogger logger, ITimerFactory timerFactory, IEnvironmentInfo environmentInfo, ILibraryManager libraryManager1)
{
logger.Debug("New file refresher created for {0}", path);
Path = path;
@@ -47,6 +48,7 @@ namespace Emby.Server.Implementations.IO
Logger = logger;
_timerFactory = timerFactory;
_environmentInfo = environmentInfo;
+ _libraryManager = libraryManager1;
AddPath(path);
}
@@ -235,6 +237,12 @@ namespace Emby.Server.Implementations.IO
return false;
}
+ // Only try to open video files
+ if (!_libraryManager.IsVideoFile(path))
+ {
+ return false;
+ }
+
try
{
var data = _fileSystem.GetFileSystemInfo(path);
diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj
index 0785b904a..ff7749795 100644
--- a/MediaBrowser.Api/MediaBrowser.Api.csproj
+++ b/MediaBrowser.Api/MediaBrowser.Api.csproj
@@ -82,10 +82,6 @@
<Compile Include="Reports\Model\ReportRow.cs" />
<Compile Include="Reports\ReportRequests.cs" />
<Compile Include="Reports\ReportsService.cs" />
- <Compile Include="Reports\Stat\ReportStatBuilder.cs" />
- <Compile Include="Reports\Stat\ReportStatGroup.cs" />
- <Compile Include="Reports\Stat\ReportStatItem.cs" />
- <Compile Include="Reports\Stat\ReportStatResult.cs" />
<Compile Include="Social\SharingService.cs" />
<Compile Include="StartupWizardService.cs" />
<Compile Include="Subtitles\SubtitleService.cs" />
diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
index 0fe1e533d..d64c009a0 100644
--- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
@@ -879,7 +879,7 @@ namespace MediaBrowser.Api.Playback.Hls
// Add resolution params, if specified
if (!hasGraphicalSubs)
{
- args += EncodingHelper.GetOutputSizeParam(state, codec, EnableCopyTs(state));
+ args += EncodingHelper.GetOutputSizeParam(state, codec, true);
}
// This is for internal graphical subs
@@ -891,7 +891,7 @@ namespace MediaBrowser.Api.Playback.Hls
//args += " -flags -global_header";
}
- if (EnableCopyTs(state) && args.IndexOf("-copyts", StringComparison.OrdinalIgnoreCase) == -1)
+ if (args.IndexOf("-copyts", StringComparison.OrdinalIgnoreCase) == -1)
{
args += " -copyts";
}
@@ -901,13 +901,9 @@ namespace MediaBrowser.Api.Playback.Hls
args += " -vsync " + state.OutputVideoSync;
}
- return args;
- }
+ args += EncodingHelper.GetOutputFFlags(state);
- private bool EnableCopyTs(StreamState state)
- {
- //return state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode;
- return true;
+ return args;
}
protected override string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding)
diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
index 22c6202e4..e32970be5 100644
--- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
@@ -124,6 +124,8 @@ namespace MediaBrowser.Api.Playback.Hls
args += " -vsync " + state.OutputVideoSync;
}
+ args += EncodingHelper.GetOutputFFlags(state);
+
return args;
}
diff --git a/MediaBrowser.Api/Reports/Common/HeaderMetadata.cs b/MediaBrowser.Api/Reports/Common/HeaderMetadata.cs
index b25123df8..e25e78802 100644
--- a/MediaBrowser.Api/Reports/Common/HeaderMetadata.cs
+++ b/MediaBrowser.Api/Reports/Common/HeaderMetadata.cs
@@ -35,7 +35,8 @@ namespace MediaBrowser.Api.Reports
Tracks,
EpisodeSeries,
EpisodeSeason,
- AudioAlbumArtist,
+ EpisodeNumber,
+ AudioAlbumArtist,
MusicArtist,
AudioAlbum,
Locked,
diff --git a/MediaBrowser.Api/Reports/Common/ReportBuilderBase.cs b/MediaBrowser.Api/Reports/Common/ReportBuilderBase.cs
index 39b2610d5..6d5a180fb 100644
--- a/MediaBrowser.Api/Reports/Common/ReportBuilderBase.cs
+++ b/MediaBrowser.Api/Reports/Common/ReportBuilderBase.cs
@@ -148,6 +148,11 @@ namespace MediaBrowser.Api.Reports
/// <returns> The localized header. </returns>
protected static string GetLocalizedHeader(HeaderMetadata internalHeader)
{
+ if (internalHeader == HeaderMetadata.EpisodeNumber)
+ {
+ return "Episode";
+ }
+
string headerName = "";
if (internalHeader != HeaderMetadata.None)
{
diff --git a/MediaBrowser.Api/Reports/Data/ReportBuilder.cs b/MediaBrowser.Api/Reports/Data/ReportBuilder.cs
index c9c63847c..9c3dde6a4 100644
--- a/MediaBrowser.Api/Reports/Data/ReportBuilder.cs
+++ b/MediaBrowser.Api/Reports/Data/ReportBuilder.cs
@@ -102,7 +102,7 @@ namespace MediaBrowser.Api.Reports
HeaderMetadata.Series,
HeaderMetadata.Season,
HeaderMetadata.SeasonNumber,
- HeaderMetadata.DateAdded,
+ HeaderMetadata.DateAdded,
HeaderMetadata.Year,
HeaderMetadata.Genres
};
@@ -269,10 +269,11 @@ namespace MediaBrowser.Api.Reports
HeaderMetadata.ImagePrimary,
HeaderMetadata.ImageBackdrop,
HeaderMetadata.ImageLogo,
- HeaderMetadata.Name,
+ HeaderMetadata.Name,
HeaderMetadata.EpisodeSeries,
HeaderMetadata.Season,
- HeaderMetadata.DateAdded,
+ HeaderMetadata.EpisodeNumber,
+ HeaderMetadata.DateAdded,
HeaderMetadata.ReleaseDate,
HeaderMetadata.Year,
HeaderMetadata.Genres,
@@ -450,6 +451,12 @@ namespace MediaBrowser.Api.Reports
internalHeader = HeaderMetadata.Season;
break;
+ case HeaderMetadata.EpisodeNumber:
+ option.Column = (i, r) => this.GetObject<BaseItem, string>(i, (x) => x.IndexNumber == null ? "" : x.IndexNumber.ToString());
+ //option.Header.SortField = "IndexNumber";
+ //option.Header.HeaderFieldType = ReportFieldType.Int;
+ break;
+
case HeaderMetadata.Network:
option.Column = (i, r) => this.GetListAsString(i.Studios);
option.ItemID = (i) => this.GetStudioID(i.Studios.FirstOrDefault());
diff --git a/MediaBrowser.Api/Reports/Stat/ReportStatBuilder.cs b/MediaBrowser.Api/Reports/Stat/ReportStatBuilder.cs
deleted file mode 100644
index 52b095dee..000000000
--- a/MediaBrowser.Api/Reports/Stat/ReportStatBuilder.cs
+++ /dev/null
@@ -1,256 +0,0 @@
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace MediaBrowser.Api.Reports
-{
- /// <summary> A report stat builder. </summary>
- /// <seealso cref="T:MediaBrowser.Api.Reports.ReportBuilderBase"/>
- public class ReportStatBuilder : ReportBuilderBase
- {
- #region [Constructors]
-
- /// <summary>
- /// Initializes a new instance of the MediaBrowser.Api.Reports.ReportStatBuilder class. </summary>
- /// <param name="libraryManager"> Manager for library. </param>
- public ReportStatBuilder(ILibraryManager libraryManager)
- : base(libraryManager)
- {
- }
-
- #endregion
-
- #region [Public Methods]
-
- /// <summary> Gets report stat result. </summary>
- /// <param name="items"> The items. </param>
- /// <param name="reportIncludeItemTypes"> List of types of the report include items. </param>
- /// <param name="topItem"> The top item. </param>
- /// <returns> The report stat result. </returns>
- public ReportStatResult GetResult(BaseItem[] items, ReportIncludeItemTypes reportIncludeItemTypes, int topItem = 5)
- {
- ReportStatResult result = new ReportStatResult();
- result = this.GetResultGenres(result, items, topItem);
- result = this.GetResultStudios(result, items, topItem);
- result = this.GetResultPersons(result, items, topItem);
- result = this.GetResultProductionYears(result, items, topItem);
- result = this.GetResultCommunityRatings(result, items, topItem);
- result = this.GetResultParentalRatings(result, items, topItem);
-
- switch (reportIncludeItemTypes)
- {
- case ReportIncludeItemTypes.Season:
- case ReportIncludeItemTypes.Series:
- case ReportIncludeItemTypes.MusicAlbum:
- case ReportIncludeItemTypes.MusicArtist:
- case ReportIncludeItemTypes.Game:
- break;
- case ReportIncludeItemTypes.Movie:
- case ReportIncludeItemTypes.BoxSet:
-
- break;
- case ReportIncludeItemTypes.Book:
- case ReportIncludeItemTypes.Episode:
- case ReportIncludeItemTypes.Video:
- case ReportIncludeItemTypes.MusicVideo:
- case ReportIncludeItemTypes.Trailer:
- case ReportIncludeItemTypes.Audio:
- case ReportIncludeItemTypes.BaseItem:
- default:
- break;
- }
-
- result.Groups = result.Groups.OrderByDescending(n => n.Items.Count()).ToList();
-
- return result;
- }
-
- #endregion
-
- #region [Protected Internal Methods]
- /// <summary> Gets the headers. </summary>
- /// <typeparam name="H"> Type of the header. </typeparam>
- /// <param name="request"> The request. </param>
- /// <returns> The headers. </returns>
- /// <seealso cref="M:MediaBrowser.Api.Reports.ReportBuilderBase.GetHeaders{H}(H)"/>
- protected internal override List<ReportHeader> GetHeaders<H>(H request)
- {
- throw new NotImplementedException();
- }
-
- #endregion
-
- #region [Private Methods]
-
- /// <summary> Gets the groups. </summary>
- /// <param name="result"> The result. </param>
- /// <param name="header"> The header. </param>
- /// <param name="topItem"> The top item. </param>
- /// <param name="top"> The top. </param>
- private void GetGroups(ReportStatResult result, string header, int topItem, IEnumerable<ReportStatItem> top)
- {
- if (top != null && top.Count() > 0)
- {
- var group = new ReportStatGroup { Header = ReportStatGroup.FormatedHeader(header, topItem) };
- group.Items.AddRange(top);
- result.Groups.Add(group);
- }
- }
-
- /// <summary> Gets result community ratings. </summary>
- /// <param name="result"> The result. </param>
- /// <param name="items"> The items. </param>
- /// <param name="topItem"> The top item. </param>
- /// <returns> The result community ratings. </returns>
- private ReportStatResult GetResultCommunityRatings(ReportStatResult result, BaseItem[] items, int topItem = 5)
- {
- this.GetGroups(result, GetLocalizedHeader(HeaderMetadata.CommunityRating), topItem,
- items.Where(x => x.CommunityRating != null && x.CommunityRating > 0)
- .GroupBy(x => x.CommunityRating)
- .OrderByDescending(x => x.Count())
- .Take(topItem)
- .Select(x => new ReportStatItem
- {
- Name = x.Key.ToString(),
- Value = x.Count().ToString()
- })
- );
-
- return result;
- }
-
- /// <summary> Gets result genres. </summary>
- /// <param name="result"> The result. </param>
- /// <param name="items"> The items. </param>
- /// <param name="topItem"> The top item. </param>
- /// <returns> The result genres. </returns>
- private ReportStatResult GetResultGenres(ReportStatResult result, BaseItem[] items, int topItem = 5)
- {
- this.GetGroups(result, GetLocalizedHeader(HeaderMetadata.Genres), topItem,
- items.SelectMany(x => x.Genres)
- .GroupBy(x => x)
- .OrderByDescending(x => x.Count())
- .Take(topItem)
- .Select(x => new ReportStatItem
- {
- Name = x.Key,
- Value = x.Count().ToString(),
- Id = GetGenreID(x.Key)
- }));
- return result;
-
- }
-
- /// <summary> Gets result parental ratings. </summary>
- /// <param name="result"> The result. </param>
- /// <param name="items"> The items. </param>
- /// <param name="topItem"> The top item. </param>
- /// <returns> The result parental ratings. </returns>
- private ReportStatResult GetResultParentalRatings(ReportStatResult result, BaseItem[] items, int topItem = 5)
- {
- this.GetGroups(result, GetLocalizedHeader(HeaderMetadata.ParentalRatings), topItem,
- items.Where(x => x.OfficialRating != null)
- .GroupBy(x => x.OfficialRating)
- .OrderByDescending(x => x.Count())
- .Take(topItem)
- .Select(x => new ReportStatItem
- {
- Name = x.Key.ToString(),
- Value = x.Count().ToString()
- })
- );
-
- return result;
- }
-
- /// <summary> Gets result persons. </summary>
- /// <param name="result"> The result. </param>
- /// <param name="items"> The items. </param>
- /// <param name="topItem"> The top item. </param>
- /// <returns> The result persons. </returns>
- private ReportStatResult GetResultPersons(ReportStatResult result, BaseItem[] items, int topItem = 5)
- {
- List<HeaderMetadata> t = new List<HeaderMetadata>
- {
- HeaderMetadata.Actor,
- HeaderMetadata.Composer,
- HeaderMetadata.Director,
- HeaderMetadata.GuestStar,
- HeaderMetadata.Producer,
- HeaderMetadata.Writer,
- HeaderMetadata.Artist,
- HeaderMetadata.AlbumArtist
- };
- foreach (var item in t)
- {
- var ps = items.SelectMany(x => _libraryManager.GetPeople(x))
- .Where(n => n.Type == item.ToString())
- .GroupBy(x => x.Name)
- .OrderByDescending(x => x.Count())
- .Take(topItem);
- if (ps != null && ps.Count() > 0)
- this.GetGroups(result, GetLocalizedHeader(item), topItem,
- ps.Select(x => new ReportStatItem
- {
- Name = x.Key,
- Value = x.Count().ToString(),
- Id = GetPersonID(x.Key)
- })
- );
- }
-
- return result;
- }
-
- /// <summary> Gets result production years. </summary>
- /// <param name="result"> The result. </param>
- /// <param name="items"> The items. </param>
- /// <param name="topItem"> The top item. </param>
- /// <returns> The result production years. </returns>
- private ReportStatResult GetResultProductionYears(ReportStatResult result, BaseItem[] items, int topItem = 5)
- {
- this.GetGroups(result, GetLocalizedHeader(HeaderMetadata.Year), topItem,
- items.Where(x => x.ProductionYear != null && x.ProductionYear > 0)
- .GroupBy(x => x.ProductionYear)
- .OrderByDescending(x => x.Count())
- .Take(topItem)
- .Select(x => new ReportStatItem
- {
- Name = x.Key.ToString(),
- Value = x.Count().ToString()
- })
- );
-
- return result;
- }
-
- /// <summary> Gets result studios. </summary>
- /// <param name="result"> The result. </param>
- /// <param name="items"> The items. </param>
- /// <param name="topItem"> The top item. </param>
- /// <returns> The result studios. </returns>
- private ReportStatResult GetResultStudios(ReportStatResult result, BaseItem[] items, int topItem = 5)
- {
- this.GetGroups(result, GetLocalizedHeader(HeaderMetadata.Studios), topItem,
- items.SelectMany(x => x.Studios)
- .GroupBy(x => x)
- .OrderByDescending(x => x.Count())
- .Take(topItem)
- .Select(x => new ReportStatItem
- {
- Name = x.Key,
- Value = x.Count().ToString(),
- Id = GetStudioID(x.Key)
- })
- );
-
- return result;
-
- }
-
- #endregion
-
- }
-}
diff --git a/MediaBrowser.Api/Reports/Stat/ReportStatGroup.cs b/MediaBrowser.Api/Reports/Stat/ReportStatGroup.cs
deleted file mode 100644
index f901b5417..000000000
--- a/MediaBrowser.Api/Reports/Stat/ReportStatGroup.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System.Collections.Generic;
-
-namespace MediaBrowser.Api.Reports
-{
- /// <summary> A report stat group. </summary>
- public class ReportStatGroup
- {
- /// <summary>
- /// Initializes a new instance of the MediaBrowser.Api.Reports.ReportStatGroup class. </summary>
- public ReportStatGroup()
- {
- Items = new List<ReportStatItem>();
- TotalRecordCount = 0;
- }
-
- /// <summary> Gets or sets the header. </summary>
- /// <value> The header. </value>
- public string Header { get; set; }
-
- /// <summary> Gets or sets the items. </summary>
- /// <value> The items. </value>
- public List<ReportStatItem> Items { get; set; }
-
- /// <summary> Gets or sets the number of total records. </summary>
- /// <value> The total number of record count. </value>
- public int TotalRecordCount { get; set; }
-
- internal static string FormatedHeader(string header, int topItem)
- {
- return string.Format("Top {0} {1}", topItem, header);
- }
- }
-}
diff --git a/MediaBrowser.Api/Reports/Stat/ReportStatItem.cs b/MediaBrowser.Api/Reports/Stat/ReportStatItem.cs
deleted file mode 100644
index c93ba15af..000000000
--- a/MediaBrowser.Api/Reports/Stat/ReportStatItem.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-namespace MediaBrowser.Api.Reports
-{
- /// <summary> A report stat item. </summary>
- public class ReportStatItem
- {
- /// <summary> Gets or sets the name. </summary>
- /// <value> The name. </value>
- public string Name { get; set; }
-
- /// <summary> Gets or sets the image. </summary>
- /// <value> The image. </value>
- public string Image { get; set; }
-
- /// <summary> Gets or sets the value. </summary>
- /// <value> The value. </value>
- public string Value { get; set; }
-
- /// <summary> Gets or sets the identifier. </summary>
- /// <value> The identifier. </value>
- public string Id { get; set; }
-
- }
-}
diff --git a/MediaBrowser.Api/Reports/Stat/ReportStatResult.cs b/MediaBrowser.Api/Reports/Stat/ReportStatResult.cs
deleted file mode 100644
index fbf98fc17..000000000
--- a/MediaBrowser.Api/Reports/Stat/ReportStatResult.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using System.Collections.Generic;
-
-namespace MediaBrowser.Api.Reports
-{
- /// <summary> Encapsulates the result of a report stat. </summary>
- public class ReportStatResult
- {
- /// <summary>
- /// Initializes a new instance of the MediaBrowser.Api.Reports.ReportStatResult class. </summary>
- public ReportStatResult()
- {
- Groups = new List<ReportStatGroup>();
- TotalRecordCount = 0;
- }
-
- /// <summary> Gets or sets the groups. </summary>
- /// <value> The groups. </value>
- public List<ReportStatGroup> Groups { get; set; }
-
- /// <summary> Gets or sets the number of total records. </summary>
- /// <value> The total number of record count. </value>
- public int TotalRecordCount { get; set; }
- }
-}
diff --git a/MediaBrowser.Controller/Drawing/IImageEncoder.cs b/MediaBrowser.Controller/Drawing/IImageEncoder.cs
index ecc99caf9..830093fcf 100644
--- a/MediaBrowser.Controller/Drawing/IImageEncoder.cs
+++ b/MediaBrowser.Controller/Drawing/IImageEncoder.cs
@@ -50,5 +50,7 @@ namespace MediaBrowser.Controller.Drawing
/// </summary>
/// <value><c>true</c> if [supports image encoding]; otherwise, <c>false</c>.</value>
bool SupportsImageEncoding { get; }
+
+ ImageSize GetImageSize(string path);
}
}
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
index ca0b97a9f..11311905c 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
@@ -1306,7 +1306,8 @@ namespace MediaBrowser.Controller.MediaEncoding
filters.Add("format=nv12|vaapi");
filters.Add("hwupload");
}
- else if (state.DeInterlace && !string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
+
+ if (state.DeInterlace && !string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
{
filters.Add("yadif=0:-1:0");
}
@@ -1533,14 +1534,26 @@ namespace MediaBrowser.Controller.MediaEncoding
}
var flags = new List<string>();
- if (state.IgnoreDts)
+ if (state.IgnoreInputDts)
{
flags.Add("+igndts");
}
- if (state.IgnoreIndex)
+ if (state.IgnoreInputIndex)
{
flags.Add("+ignidx");
}
+ if (state.GenPtsInput)
+ {
+ flags.Add("+genpts");
+ }
+ if (state.DiscardCorruptFramesInput)
+ {
+ flags.Add("+discardcorrupt");
+ }
+ if (state.EnableFastSeekInput)
+ {
+ flags.Add("+fastseek");
+ }
if (flags.Count > 0)
{
@@ -1864,6 +1877,22 @@ namespace MediaBrowser.Controller.MediaEncoding
).Trim();
}
+ public string GetOutputFFlags(EncodingJobInfo state)
+ {
+ var flags = new List<string>();
+ if (state.GenPtsOutput)
+ {
+ flags.Add("+genpts");
+ }
+
+ if (flags.Count > 0)
+ {
+ return " -fflags " + string.Join("", flags.ToArray());
+ }
+
+ return string.Empty;
+ }
+
public string GetProgressiveVideoArguments(EncodingJobInfo state, EncodingOptions encodingOptions, string videoCodec, string defaultH264Preset)
{
var args = "-codec:v:0 " + videoCodec;
@@ -1943,6 +1972,8 @@ namespace MediaBrowser.Controller.MediaEncoding
args += " -vsync " + state.OutputVideoSync;
}
+ args += GetOutputFFlags(state);
+
return args;
}
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs
index 28ada9dae..409dec482 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs
@@ -39,14 +39,52 @@ namespace MediaBrowser.Controller.MediaEncoding
public bool ReadInputAtNativeFramerate { get; set; }
- public bool IgnoreDts
+ public bool IgnoreInputDts
{
- get { return MediaSource.IgnoreDts; }
+ get
+ {
+ return MediaSource.IgnoreDts;
+ }
+ }
+
+ public bool IgnoreInputIndex
+ {
+ get
+ {
+ return MediaSource.IgnoreIndex;
+ }
+ }
+
+ public bool GenPtsInput
+ {
+ get
+ {
+ return false;
+ }
}
- public bool IgnoreIndex
+ public bool DiscardCorruptFramesInput
{
- get { return MediaSource.IgnoreIndex; }
+ get
+ {
+ return false;
+ }
+ }
+
+ public bool EnableFastSeekInput
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public bool GenPtsOutput
+ {
+ get
+ {
+ return false;
+ }
}
public string OutputContainer { get; set; }
diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs
index a3a55176c..57e2ec450 100644
--- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs
@@ -218,13 +218,9 @@ namespace MediaBrowser.LocalMetadata.Savers
{
if (file.IsHidden)
{
- FileSystem.SetHidden(path, false);
wasHidden = true;
}
- if (file.IsReadOnly)
- {
- FileSystem.SetReadOnly(path, false);
- }
+ FileSystem.SetAttributes(path, false, false);
}
using (var filestream = FileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
diff --git a/MediaBrowser.Model/IO/IFileSystem.cs b/MediaBrowser.Model/IO/IFileSystem.cs
index 92112f4ae..ea6b04824 100644
--- a/MediaBrowser.Model/IO/IFileSystem.cs
+++ b/MediaBrowser.Model/IO/IFileSystem.cs
@@ -313,7 +313,8 @@ namespace MediaBrowser.Model.IO
IEnumerable<string> GetFileSystemEntryPaths(string path, bool recursive = false);
void SetHidden(string path, bool isHidden);
- void SetReadOnly(string path, bool isHidden);
+ void SetReadOnly(string path, bool readOnly);
+ void SetAttributes(string path, bool isHidden, bool readOnly);
char DirectorySeparatorChar { get; }
diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs
index 1d8275c26..4bd504409 100644
--- a/MediaBrowser.Providers/Manager/ImageSaver.cs
+++ b/MediaBrowser.Providers/Manager/ImageSaver.cs
@@ -166,7 +166,7 @@ namespace MediaBrowser.Providers.Manager
{
var currentPath = currentImagePath;
- _logger.Debug("Deleting previous image {0}", currentPath);
+ _logger.Info("Deleting previous image {0}", currentPath);
_libraryMonitor.ReportFileSystemChangeBeginning(currentPath);
@@ -236,7 +236,7 @@ namespace MediaBrowser.Providers.Manager
/// <returns>Task.</returns>
private async Task SaveImageToLocation(Stream source, string path, CancellationToken cancellationToken)
{
- _logger.Debug("Saving image to {0}", path);
+ _logger.Info("Saving image to {0}", path);
var parentFolder = _fileSystem.GetDirectoryName(path);
@@ -249,31 +249,16 @@ namespace MediaBrowser.Providers.Manager
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
- // If the file is currently hidden we'll have to remove that or the save will fail
- var file = _fileSystem.GetFileInfo(path);
+ _fileSystem.SetAttributes(path, false, false);
- // This will fail if the file is hidden
- if (file.Exists)
+ using (var fs = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, FileOpenOptions.Asynchronous))
{
- if (file.IsHidden)
- {
- _fileSystem.SetHidden(file.FullName, false);
- }
- if (file.IsReadOnly)
- {
- _fileSystem.SetReadOnly(path, false);
- }
- }
-
- using (var fs = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
- {
- await source.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, cancellationToken)
- .ConfigureAwait(false);
+ await source.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, cancellationToken).ConfigureAwait(false);
}
if (_config.Configuration.SaveMetadataHidden)
{
- _fileSystem.SetHidden(file.FullName, true);
+ _fileSystem.SetHidden(path, true);
}
}
finally
diff --git a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs
index 477543d5e..f9d19b6be 100644
--- a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs
+++ b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs
@@ -72,8 +72,7 @@ namespace MediaBrowser.Providers.Omdb
var imdbId = searchInfo.GetProviderId(MetadataProviders.Imdb);
- var baseUrl = await OmdbProvider.GetOmdbBaseUrl(cancellationToken).ConfigureAwait(false);
- var url = baseUrl + "/?plot=full&r=json";
+ var urlQuery = "plot=full&r=json";
if (type == "episode" && episodeSearchInfo != null)
{
episodeSearchInfo.SeriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out imdbId);
@@ -94,23 +93,23 @@ namespace MediaBrowser.Providers.Omdb
{
if (year.HasValue)
{
- url += "&y=" + year.Value.ToString(CultureInfo.InvariantCulture);
+ urlQuery += "&y=" + year.Value.ToString(CultureInfo.InvariantCulture);
}
// &s means search and returns a list of results as opposed to t
if (isSearch)
{
- url += "&s=" + WebUtility.UrlEncode(name);
+ urlQuery += "&s=" + WebUtility.UrlEncode(name);
}
else
{
- url += "&t=" + WebUtility.UrlEncode(name);
+ urlQuery += "&t=" + WebUtility.UrlEncode(name);
}
- url += "&type=" + type;
+ urlQuery += "&type=" + type;
}
else
{
- url += "&i=" + imdbId;
+ urlQuery += "&i=" + imdbId;
isSearch = false;
}
@@ -118,14 +117,16 @@ namespace MediaBrowser.Providers.Omdb
{
if (searchInfo.IndexNumber.HasValue)
{
- url += string.Format(CultureInfo.InvariantCulture, "&Episode={0}", searchInfo.IndexNumber);
+ urlQuery += string.Format(CultureInfo.InvariantCulture, "&Episode={0}", searchInfo.IndexNumber);
}
if (searchInfo.ParentIndexNumber.HasValue)
{
- url += string.Format(CultureInfo.InvariantCulture, "&Season={0}", searchInfo.ParentIndexNumber);
+ urlQuery += string.Format(CultureInfo.InvariantCulture, "&Season={0}", searchInfo.ParentIndexNumber);
}
}
+ var url = await OmdbProvider.GetOmdbUrl(urlQuery, cancellationToken).ConfigureAwait(false);
+
using (var stream = await OmdbProvider.GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false))
{
var resultList = new List<SearchResult>();
diff --git a/MediaBrowser.Providers/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Omdb/OmdbProvider.cs
index d1c3b2214..b89105376 100644
--- a/MediaBrowser.Providers/Omdb/OmdbProvider.cs
+++ b/MediaBrowser.Providers/Omdb/OmdbProvider.cs
@@ -265,9 +265,16 @@ namespace MediaBrowser.Providers.Omdb
return false;
}
- public static async Task<string> GetOmdbBaseUrl(CancellationToken cancellationToken)
+ public static async Task<string> GetOmdbUrl(string query, CancellationToken cancellationToken)
{
- return "https://www.omdbapi.com";
+ var url = "https://www.omdbapi.com?apikey=fe53f97e";
+
+ if (!string.IsNullOrWhiteSpace(query))
+ {
+ url += "&" + query;
+ }
+
+ return url;
}
private async Task<string> EnsureItemInfo(string imdbId, CancellationToken cancellationToken)
@@ -292,8 +299,7 @@ namespace MediaBrowser.Providers.Omdb
}
}
- var baseUrl = await GetOmdbBaseUrl(cancellationToken).ConfigureAwait(false);
- var url = string.Format(baseUrl + "/?i={0}&plot=full&tomatoes=true&r=json", imdbParam);
+ var url = await GetOmdbUrl(string.Format("i={0}&plot=full&tomatoes=true&r=json", imdbParam), cancellationToken).ConfigureAwait(false);
using (var stream = await GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false))
{
@@ -327,8 +333,7 @@ namespace MediaBrowser.Providers.Omdb
}
}
- var baseUrl = await GetOmdbBaseUrl(cancellationToken).ConfigureAwait(false);
- var url = string.Format(baseUrl + "/?i={0}&season={1}&detail=full", imdbParam, seasonId);
+ var url = await GetOmdbUrl(string.Format("i={0}&season={1}&detail=full", imdbParam, seasonId), cancellationToken).ConfigureAwait(false);
using (var stream = await GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false))
{
diff --git a/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj b/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj
index 8133efafb..73626328a 100644
--- a/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj
+++ b/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj
@@ -122,10 +122,10 @@
<HintPath>..\ThirdParty\taglib\TagLib.Portable.dll</HintPath>
</Reference>
<Reference Include="SQLitePCLRaw.core">
- <HintPath>..\packages\SQLitePCLRaw.core.1.1.2\lib\net45\SQLitePCLRaw.core.dll</HintPath>
+ <HintPath>..\packages\SQLitePCLRaw.core.1.1.5\lib\net45\SQLitePCLRaw.core.dll</HintPath>
</Reference>
<Reference Include="SQLitePCLRaw.provider.sqlite3">
- <HintPath>..\packages\SQLitePCLRaw.provider.sqlite3.net45.1.1.2\lib\net45\SQLitePCLRaw.provider.sqlite3.dll</HintPath>
+ <HintPath>..\packages\SQLitePCLRaw.provider.sqlite3.net45.1.1.5\lib\net45\SQLitePCLRaw.provider.sqlite3.dll</HintPath>
</Reference>
<Reference Include="Emby.Server.Connect">
<HintPath>..\ThirdParty\emby\Emby.Server.Connect.dll</HintPath>
diff --git a/MediaBrowser.ServerApplication/ImageEncoderHelper.cs b/MediaBrowser.ServerApplication/ImageEncoderHelper.cs
index 8c3d8d213..b8fa097d6 100644
--- a/MediaBrowser.ServerApplication/ImageEncoderHelper.cs
+++ b/MediaBrowser.ServerApplication/ImageEncoderHelper.cs
@@ -26,11 +26,11 @@ namespace MediaBrowser.Server.Startup.Common
{
try
{
- return new SkiaEncoder(logManager.GetLogger("ImageMagick"), appPaths, httpClient, fileSystem);
+ return new SkiaEncoder(logManager.GetLogger("Skia"), appPaths, httpClient, fileSystem);
}
catch
{
- logger.Error("Error loading ImageMagick. Will revert to GDI.");
+ logger.Error("Error loading Skia. Will revert to ImageMagick.");
}
try
diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs
index 8e38c9a98..a4bbd65d0 100644
--- a/MediaBrowser.ServerApplication/MainStartup.cs
+++ b/MediaBrowser.ServerApplication/MainStartup.cs
@@ -380,6 +380,9 @@ namespace MediaBrowser.ServerApplication
task = InstallVcredist2013IfNeeded(_appHost, _logger);
Task.WaitAll(task);
+ task = InstallVcredist2015IfNeeded(_appHost, _logger);
+ Task.WaitAll(task);
+
Microsoft.Win32.SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
HideSplashScreen();
@@ -736,32 +739,61 @@ namespace MediaBrowser.ServerApplication
Process.Start(startInfo);
}
- private static bool CanRestartWindowsService()
+ private static async Task InstallVcredist2013IfNeeded(ApplicationHost appHost, ILogger logger)
{
- var startInfo = new ProcessStartInfo
- {
- FileName = "cmd.exe",
- CreateNoWindow = true,
- WindowStyle = ProcessWindowStyle.Hidden,
- Verb = "runas",
- ErrorDialog = false,
- Arguments = String.Format("/c sc query {0}", BackgroundService.GetExistingServiceName())
- };
- using (var process = Process.Start(startInfo))
+ // Reference
+ // http://stackoverflow.com/questions/12206314/detect-if-visual-c-redistributable-for-visual-studio-2012-is-installed
+
+ try
{
- process.WaitForExit();
- if (process.ExitCode == 0)
- {
- return true;
- }
- else
+ var subkey = Environment.Is64BitProcess
+ ? "SOFTWARE\\WOW6432Node\\Microsoft\\VisualStudio\\12.0\\VC\\Runtimes\\x64"
+ : "SOFTWARE\\Microsoft\\VisualStudio\\12.0\\VC\\Runtimes\\x86";
+
+ using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default)
+ .OpenSubKey(subkey))
{
- return false;
+ if (ndpKey != null && ndpKey.GetValue("Version") != null)
+ {
+ var installedVersion = ((string)ndpKey.GetValue("Version")).TrimStart('v');
+ if (installedVersion.StartsWith("12", StringComparison.OrdinalIgnoreCase))
+ {
+ return;
+ }
+ }
}
}
+ catch (Exception ex)
+ {
+ logger.ErrorException("Error getting .NET Framework version", ex);
+ return;
+ }
+
+ MessageBox.Show("The Visual C++ 2013 Runtime will now be installed.", "Install Visual C++ Runtime", MessageBoxButtons.OK, MessageBoxIcon.Information);
+
+ try
+ {
+ await InstallVcredist(GetVcredist2013Url()).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ logger.ErrorException("Error installing Visual Studio C++ runtime", ex);
+ }
}
- private static async Task InstallVcredist2013IfNeeded(ApplicationHost appHost, ILogger logger)
+ private static string GetVcredist2013Url()
+ {
+ if (Environment.Is64BitProcess)
+ {
+ return "https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2013/vcredist_x64.exe";
+ }
+
+ // TODO: ARM url - https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2013/vcredist_arm.exe
+
+ return "https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2013/vcredist_x86.exe";
+ }
+
+ private static async Task InstallVcredist2015IfNeeded(ApplicationHost appHost, ILogger logger)
{
// Reference
// http://stackoverflow.com/questions/12206314/detect-if-visual-c-redistributable-for-visual-studio-2012-is-installed
@@ -769,8 +801,8 @@ namespace MediaBrowser.ServerApplication
try
{
var subkey = Environment.Is64BitProcess
- ? "SOFTWARE\\WOW6432Node\\Microsoft\\VisualStudio\\12.0\\VC\\Runtimes\\x64"
- : "SOFTWARE\\Microsoft\\VisualStudio\\12.0\\VC\\Runtimes\\x86";
+ ? "SOFTWARE\\WOW6432Node\\Microsoft\\VisualStudio\\14.0\\VC\\Runtimes\\x64"
+ : "SOFTWARE\\Microsoft\\VisualStudio\\14.0\\VC\\Runtimes\\x86";
using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default)
.OpenSubKey(subkey))
@@ -778,7 +810,7 @@ namespace MediaBrowser.ServerApplication
if (ndpKey != null && ndpKey.GetValue("Version") != null)
{
var installedVersion = ((string)ndpKey.GetValue("Version")).TrimStart('v');
- if (installedVersion.StartsWith("12", StringComparison.OrdinalIgnoreCase))
+ if (installedVersion.StartsWith("14", StringComparison.OrdinalIgnoreCase))
{
return;
}
@@ -791,9 +823,11 @@ namespace MediaBrowser.ServerApplication
return;
}
+ MessageBox.Show("The Visual C++ 2015 Runtime will now be installed.", "Install Visual C++ Runtime", MessageBoxButtons.OK, MessageBoxIcon.Information);
+
try
{
- await InstallVcredist2013().ConfigureAwait(false);
+ await InstallVcredist(GetVcredist2015Url()).ConfigureAwait(false);
}
catch (Exception ex)
{
@@ -801,13 +835,25 @@ namespace MediaBrowser.ServerApplication
}
}
- private async static Task InstallVcredist2013()
+ private static string GetVcredist2015Url()
+ {
+ if (Environment.Is64BitProcess)
+ {
+ return "https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2015/vc_redist.x64.exe";
+ }
+
+ // TODO: ARM url - https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2015/vcredist_arm.exe
+
+ return "https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2015/vc_redist.x86.exe";
+ }
+
+ private async static Task InstallVcredist(string url)
{
var httpClient = _appHost.HttpClient;
var tmp = await httpClient.GetTempFile(new HttpRequestOptions
{
- Url = GetVcredist2013Url(),
+ Url = url,
Progress = new Progress<double>()
}).ConfigureAwait(false);
@@ -833,18 +879,6 @@ namespace MediaBrowser.ServerApplication
}
}
- private static string GetVcredist2013Url()
- {
- if (Environment.Is64BitProcess)
- {
- return "https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2013/vcredist_x64.exe";
- }
-
- // TODO: ARM url - https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2013/vcredist_arm.exe
-
- return "https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2013/vcredist_x86.exe";
- }
-
/// <summary>
/// Sets the error mode.
/// </summary>
diff --git a/MediaBrowser.ServerApplication/Native/LoopUtil.cs b/MediaBrowser.ServerApplication/Native/LoopUtil.cs
index 9a96f5518..7c7471231 100644
--- a/MediaBrowser.ServerApplication/Native/LoopUtil.cs
+++ b/MediaBrowser.ServerApplication/Native/LoopUtil.cs
@@ -57,10 +57,6 @@ namespace MediaBrowser.ServerApplication.Native
}
- // Call this API to free the memory returned by the Enumeration API
- [DllImport("FirewallAPI.dll")]
- internal static extern void NetworkIsolationFreeAppContainers(IntPtr pACs);
-
// Call this API to load the current list of LoopUtil-enabled AppContainers
[DllImport("FirewallAPI.dll")]
internal static extern uint NetworkIsolationGetAppContainerConfig(out uint pdwCntACs, out IntPtr appContainerSids);
@@ -69,23 +65,13 @@ namespace MediaBrowser.ServerApplication.Native
[DllImport("FirewallAPI.dll")]
private static extern uint NetworkIsolationSetAppContainerConfig(uint pdwCntACs, SID_AND_ATTRIBUTES[] appContainerSids);
-
// Use this API to convert a string SID into an actual SID
[DllImport("advapi32.dll", SetLastError = true)]
internal static extern bool ConvertStringSidToSid(string strSid, out IntPtr pSid);
[DllImport("advapi32", /*CharSet = CharSet.Auto,*/ SetLastError = true)]
- static extern bool ConvertSidToStringSid(
- [MarshalAs(UnmanagedType.LPArray)] byte[] pSID,
- out IntPtr ptrSid);
-
- [DllImport("advapi32", /*CharSet = CharSet.Auto,*/ SetLastError = true)]
static extern bool ConvertSidToStringSid(IntPtr pSid, out string strSid);
- // Use this API to convert a string reference (e.g. "@{blah.pri?ms-resource://whatever}") into a plain string
- [DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
- internal static extern int SHLoadIndirectString(string pszSource, StringBuilder pszOutBuf);
-
// Call this API to enumerate all of the AppContainers on the system
[DllImport("FirewallAPI.dll")]
internal static extern uint NetworkIsolationEnumAppContainers(uint Flags, out uint pdwCntPublicACs, out IntPtr ppACs);
@@ -196,7 +182,6 @@ namespace MediaBrowser.ServerApplication.Native
{
util.SaveLoopbackState();
}
- util.SaveLoopbackState();
}
private static List<SID_AND_ATTRIBUTES> PI_NetworkIsolationGetAppContainerConfig()
@@ -305,11 +290,5 @@ namespace MediaBrowser.ServerApplication.Native
}
return count;
}
-
- public void FreeResources()
- {
- NetworkIsolationFreeAppContainers(_pACs);
- }
-
}
}
diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs
index 623b109f7..ae2492802 100644
--- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs
+++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs
@@ -220,14 +220,9 @@ namespace MediaBrowser.XbmcMetadata.Savers
{
if (file.IsHidden)
{
- FileSystem.SetHidden(path, false);
-
wasHidden = true;
}
- if (file.IsReadOnly)
- {
- FileSystem.SetReadOnly(path, false);
- }
+ FileSystem.SetAttributes(path, false, false);
}
using (var filestream = FileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
diff --git a/SharedVersion.cs b/SharedVersion.cs
index 42c165086..1ef530ece 100644
--- a/SharedVersion.cs
+++ b/SharedVersion.cs
@@ -1,3 +1,3 @@
using System.Reflection;
-[assembly: AssemblyVersion("3.2.15.4")]
+[assembly: AssemblyVersion("3.2.15.5")]