diff --git a/Emby.Common.Implementations/IO/ManagedFileSystem.cs b/Emby.Common.Implementations/IO/ManagedFileSystem.cs index 6cbf397585..7d14e521f3 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 283bcdef05..64cac76230 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); - - var isCurrentlyHidden = file.IsHidden(); - - if (isCurrentlyHidden && !isHidden) - { - file.SetAttributes(file.GetAttributes() & ~SmbFile.AttrReadonly); - } - else if (!isCurrentlyHidden && isHidden) - { - file.SetAttributes(file.GetAttributes() | SmbFile.AttrReadonly); - } + 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.AttrHidden); + } + else if (!isCurrentlyHidden && isHidden) + { + file.SetAttributes(file.GetAttributes() | SmbFile.AttrHidden); + } + } + + private void SetReadOnly(SmbFile file, bool isReadOnly) + { var isCurrentlyReadOnly = !file.CanWrite(); if (isCurrentlyReadOnly && !isReadOnly) diff --git a/Emby.Drawing.Skia/StripCollageBuilder.cs b/Emby.Drawing.Skia/StripCollageBuilder.cs index 7f37007697..605677aaba 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 9dc5f75ee2..030291def2 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -198,7 +198,7 @@ namespace Emby.Drawing return new Tuple(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 /// ImageSize. 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 4fa18ce553..c7d365fb2c 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 8af826c881..0f0640a383 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 033cbd8b01..edff251563 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 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 0785b904ae..ff77497954 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -82,10 +82,6 @@ - - - - diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 0fe1e533d4..d64c009a07 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 22c6202e4f..e32970be53 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 b25123df8a..e25e78802c 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 39b2610d5c..6d5a180fb9 100644 --- a/MediaBrowser.Api/Reports/Common/ReportBuilderBase.cs +++ b/MediaBrowser.Api/Reports/Common/ReportBuilderBase.cs @@ -148,6 +148,11 @@ namespace MediaBrowser.Api.Reports /// The localized header. 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 c9c63847c9..9c3dde6a46 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(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 52b095dee3..0000000000 --- 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 -{ - /// A report stat builder. - /// - public class ReportStatBuilder : ReportBuilderBase - { - #region [Constructors] - - /// - /// Initializes a new instance of the MediaBrowser.Api.Reports.ReportStatBuilder class. - /// Manager for library. - public ReportStatBuilder(ILibraryManager libraryManager) - : base(libraryManager) - { - } - - #endregion - - #region [Public Methods] - - /// Gets report stat result. - /// The items. - /// List of types of the report include items. - /// The top item. - /// The report stat result. - 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] - /// Gets the headers. - /// Type of the header. - /// The request. - /// The headers. - /// - protected internal override List GetHeaders(H request) - { - throw new NotImplementedException(); - } - - #endregion - - #region [Private Methods] - - /// Gets the groups. - /// The result. - /// The header. - /// The top item. - /// The top. - private void GetGroups(ReportStatResult result, string header, int topItem, IEnumerable top) - { - if (top != null && top.Count() > 0) - { - var group = new ReportStatGroup { Header = ReportStatGroup.FormatedHeader(header, topItem) }; - group.Items.AddRange(top); - result.Groups.Add(group); - } - } - - /// Gets result community ratings. - /// The result. - /// The items. - /// The top item. - /// The result community ratings. - 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; - } - - /// Gets result genres. - /// The result. - /// The items. - /// The top item. - /// The result genres. - 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; - - } - - /// Gets result parental ratings. - /// The result. - /// The items. - /// The top item. - /// The result parental ratings. - 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; - } - - /// Gets result persons. - /// The result. - /// The items. - /// The top item. - /// The result persons. - private ReportStatResult GetResultPersons(ReportStatResult result, BaseItem[] items, int topItem = 5) - { - List t = new List - { - 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; - } - - /// Gets result production years. - /// The result. - /// The items. - /// The top item. - /// The result production years. - 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; - } - - /// Gets result studios. - /// The result. - /// The items. - /// The top item. - /// The result studios. - 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 f901b54173..0000000000 --- a/MediaBrowser.Api/Reports/Stat/ReportStatGroup.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Collections.Generic; - -namespace MediaBrowser.Api.Reports -{ - /// A report stat group. - public class ReportStatGroup - { - /// - /// Initializes a new instance of the MediaBrowser.Api.Reports.ReportStatGroup class. - public ReportStatGroup() - { - Items = new List(); - TotalRecordCount = 0; - } - - /// Gets or sets the header. - /// The header. - public string Header { get; set; } - - /// Gets or sets the items. - /// The items. - public List Items { get; set; } - - /// Gets or sets the number of total records. - /// The total number of record count. - 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 c93ba15af9..0000000000 --- a/MediaBrowser.Api/Reports/Stat/ReportStatItem.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace MediaBrowser.Api.Reports -{ - /// A report stat item. - public class ReportStatItem - { - /// Gets or sets the name. - /// The name. - public string Name { get; set; } - - /// Gets or sets the image. - /// The image. - public string Image { get; set; } - - /// Gets or sets the value. - /// The value. - public string Value { get; set; } - - /// Gets or sets the identifier. - /// The identifier. - 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 fbf98fc17e..0000000000 --- a/MediaBrowser.Api/Reports/Stat/ReportStatResult.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Collections.Generic; - -namespace MediaBrowser.Api.Reports -{ - /// Encapsulates the result of a report stat. - public class ReportStatResult - { - /// - /// Initializes a new instance of the MediaBrowser.Api.Reports.ReportStatResult class. - public ReportStatResult() - { - Groups = new List(); - TotalRecordCount = 0; - } - - /// Gets or sets the groups. - /// The groups. - public List Groups { get; set; } - - /// Gets or sets the number of total records. - /// The total number of record count. - public int TotalRecordCount { get; set; } - } -} diff --git a/MediaBrowser.Controller/Drawing/IImageEncoder.cs b/MediaBrowser.Controller/Drawing/IImageEncoder.cs index ecc99caf94..830093fcf2 100644 --- a/MediaBrowser.Controller/Drawing/IImageEncoder.cs +++ b/MediaBrowser.Controller/Drawing/IImageEncoder.cs @@ -50,5 +50,7 @@ namespace MediaBrowser.Controller.Drawing /// /// true if [supports image encoding]; otherwise, false. bool SupportsImageEncoding { get; } + + ImageSize GetImageSize(string path); } } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index ca0b97a9f6..11311905c2 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(); - 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(); + 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 28ada9daeb..409dec482c 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 IgnoreIndex + public bool IgnoreInputIndex { - get { return MediaSource.IgnoreIndex; } + get + { + return MediaSource.IgnoreIndex; + } + } + + public bool GenPtsInput + { + get + { + return false; + } + } + + public bool DiscardCorruptFramesInput + { + 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 a3a55176cd..57e2ec450d 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 92112f4ae3..ea6b048248 100644 --- a/MediaBrowser.Model/IO/IFileSystem.cs +++ b/MediaBrowser.Model/IO/IFileSystem.cs @@ -313,7 +313,8 @@ namespace MediaBrowser.Model.IO IEnumerable 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 1d8275c26f..4bd5044094 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 /// Task. 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 477543d5e2..f9d19b6be5 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(); diff --git a/MediaBrowser.Providers/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Omdb/OmdbProvider.cs index d1c3b22142..b89105376a 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 GetOmdbBaseUrl(CancellationToken cancellationToken) + public static async Task 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 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 8133efafb8..73626328a2 100644 --- a/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj +++ b/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj @@ -122,10 +122,10 @@ ..\ThirdParty\taglib\TagLib.Portable.dll - ..\packages\SQLitePCLRaw.core.1.1.2\lib\net45\SQLitePCLRaw.core.dll + ..\packages\SQLitePCLRaw.core.1.1.5\lib\net45\SQLitePCLRaw.core.dll - ..\packages\SQLitePCLRaw.provider.sqlite3.net45.1.1.2\lib\net45\SQLitePCLRaw.provider.sqlite3.dll + ..\packages\SQLitePCLRaw.provider.sqlite3.net45.1.1.5\lib\net45\SQLitePCLRaw.provider.sqlite3.dll ..\ThirdParty\emby\Emby.Server.Connect.dll diff --git a/MediaBrowser.ServerApplication/ImageEncoderHelper.cs b/MediaBrowser.ServerApplication/ImageEncoderHelper.cs index 8c3d8d2130..b8fa097d64 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 8e38c9a987..a4bbd65d0c 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,31 +739,6 @@ namespace MediaBrowser.ServerApplication Process.Start(startInfo); } - private static bool CanRestartWindowsService() - { - 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)) - { - process.WaitForExit(); - if (process.ExitCode == 0) - { - return true; - } - else - { - return false; - } - } - } - private static async Task InstallVcredist2013IfNeeded(ApplicationHost appHost, ILogger logger) { // Reference @@ -791,9 +769,11 @@ namespace MediaBrowser.ServerApplication return; } + MessageBox.Show("The Visual C++ 2013 Runtime will now be installed.", "Install Visual C++ Runtime", MessageBoxButtons.OK, MessageBoxIcon.Information); + try { - await InstallVcredist2013().ConfigureAwait(false); + await InstallVcredist(GetVcredist2013Url()).ConfigureAwait(false); } catch (Exception ex) { @@ -801,13 +781,79 @@ namespace MediaBrowser.ServerApplication } } - private async static Task InstallVcredist2013() + 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 + + try + { + var subkey = Environment.Is64BitProcess + ? "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)) + { + if (ndpKey != null && ndpKey.GetValue("Version") != null) + { + var installedVersion = ((string)ndpKey.GetValue("Version")).TrimStart('v'); + if (installedVersion.StartsWith("14", StringComparison.OrdinalIgnoreCase)) + { + return; + } + } + } + } + catch (Exception ex) + { + logger.ErrorException("Error getting .NET Framework version", ex); + return; + } + + MessageBox.Show("The Visual C++ 2015 Runtime will now be installed.", "Install Visual C++ Runtime", MessageBoxButtons.OK, MessageBoxIcon.Information); + + try + { + await InstallVcredist(GetVcredist2015Url()).ConfigureAwait(false); + } + catch (Exception ex) + { + logger.ErrorException("Error installing Visual Studio C++ runtime", ex); + } + } + + 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() }).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"; - } - /// /// Sets the error mode. /// diff --git a/MediaBrowser.ServerApplication/Native/LoopUtil.cs b/MediaBrowser.ServerApplication/Native/LoopUtil.cs index 9a96f5518e..7c74712312 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 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 623b109f76..ae24928028 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 42c165086b..1ef530ece0 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")]