Merge pull request #2630 from MediaBrowser/dev

Dev
pull/1154/head
Luke 8 years ago committed by GitHub
commit 275fe66220

@ -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) private static FileAttributes RemoveAttribute(FileAttributes attributes, FileAttributes attributesToRemove)
{ {
return attributes & ~attributesToRemove; return attributes & ~attributesToRemove;
@ -690,20 +733,7 @@ namespace Emby.Common.Implementations.IO
return; return;
} }
var fileInfo = GetFileInfo(path); SetAttributes(path, false, false);
if (fileInfo.Exists)
{
if (fileInfo.IsHidden)
{
SetHidden(path, false);
}
if (fileInfo.IsReadOnly)
{
SetReadOnly(path, false);
}
}
File.Delete(path); File.Delete(path);
} }

@ -166,23 +166,38 @@ namespace Emby.Common.Implementations.IO
public void SetHidden(string path, bool isHidden) public void SetHidden(string path, bool isHidden)
{ {
var file = CreateSmbFile(path); 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(); var isCurrentlyHidden = file.IsHidden();
if (isCurrentlyHidden && !isHidden) if (isCurrentlyHidden && !isHidden)
{ {
file.SetAttributes(file.GetAttributes() & ~SmbFile.AttrReadonly); file.SetAttributes(file.GetAttributes() & ~SmbFile.AttrHidden);
} }
else if (!isCurrentlyHidden && isHidden) 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(); var isCurrentlyReadOnly = !file.CanWrite();
if (isCurrentlyReadOnly && !isReadOnly) if (isCurrentlyReadOnly && !isReadOnly)

@ -72,7 +72,8 @@ namespace Emby.Drawing.Skia
{ {
canvas.Clear(SKColors.Black); 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 iTrans = Convert.ToInt32(height * .25);
int iHeight = Convert.ToInt32(height * .70); int iHeight = Convert.ToInt32(height * .70);
var horizontalImagePadding = Convert.ToInt32(width * 0.0125); var horizontalImagePadding = Convert.ToInt32(width * 0.0125);
@ -83,29 +84,54 @@ namespace Emby.Drawing.Skia
{ {
using (var currentBitmap = SKBitmap.Decode(paths[imageIndex])) 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); int iWidth = (int)Math.Abs(iHeight * currentBitmap.Width / currentBitmap.Height);
using (var resizeBitmap = new SKBitmap(iWidth, iHeight, currentBitmap.ColorType, currentBitmap.AlphaType)) using (var resizeBitmap = new SKBitmap(iWidth, iHeight, currentBitmap.ColorType, currentBitmap.AlphaType))
{ {
currentBitmap.Resize(resizeBitmap, SKBitmapResizeMethod.Lanczos3); currentBitmap.Resize(resizeBitmap, SKBitmapResizeMethod.Lanczos3);
// determine how much to crop
int ix = (int)Math.Abs((iWidth - iSlice) / 2); int ix = (int)Math.Abs((iWidth - iSlice) / 2);
using (var image = SKImage.FromBitmap(resizeBitmap)) using (var image = SKImage.FromBitmap(resizeBitmap))
{ {
// crop image
using (var subset = image.Subset(SKRectI.Create(ix, 0, iSlice, iHeight))) 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 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); using (var flippedCanvas = new SKCanvas(flippedBitmap))
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); // flip image vertically
canvas.DrawBitmap(flipped, (horizontalImagePadding * (i + 1)) + (iSlice * i), iHeight + verticalSpacing, gradient); 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));
}
} }
} }
} }

@ -198,7 +198,7 @@ namespace Emby.Drawing
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified); return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
} }
ImageSize? originalImageSize; ImageSize? originalImageSize = null;
try try
{ {
originalImageSize = GetImageSize(originalImagePath, dateModified, true); originalImageSize = GetImageSize(originalImagePath, dateModified, true);
@ -333,7 +333,7 @@ namespace Emby.Drawing
return new ImageSize(options.Width.Value, options.Height.Value); 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; var width = options.Width ?? options.MaxWidth;
@ -348,7 +348,7 @@ namespace Emby.Drawing
return new ImageSize(widthValue, height); return new ImageSize(widthValue, height);
} }
private double GetEstimatedAspectRatio(ImageType type) private double GetEstimatedAspectRatio(ImageType type, IHasImages item)
{ {
switch (type) switch (type)
{ {
@ -368,7 +368,7 @@ namespace Emby.Drawing
case ImageType.Logo: case ImageType.Logo:
return 2.58; return 2.58;
case ImageType.Primary: case ImageType.Primary:
return .667; return item.GetDefaultPrimaryImageAspectRatio() ?? .667;
default: default:
return 1; return 1;
} }
@ -499,26 +499,39 @@ namespace Emby.Drawing
/// <returns>ImageSize.</returns> /// <returns>ImageSize.</returns>
private ImageSize GetImageSizeInternal(string path, bool allowSlowMethod) 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 try
{ {
using (var file = TagLib.File.Create(new StreamFileAbstraction(Path.GetFileName(path), _fileSystem.OpenRead(path), null))) return ImageHeader.GetDimensions(path, _logger, _fileSystem);
{
var image = file as TagLib.Image.File;
var properties = image.Properties;
return new ImageSize
{
Height = properties.PhotoHeight,
Width = properties.PhotoWidth
};
}
} }
catch catch
{ {
} if (allowSlowMethod)
{
return _imageEncoder.GetImageSize(path);
}
return ImageHeader.GetDimensions(path, _logger, _fileSystem); throw;
}
} }
private readonly ITimer _saveImageSizeTimer; private readonly ITimer _saveImageSizeTimer;

@ -57,6 +57,11 @@ namespace Emby.Drawing
get { return false; } get { return false; }
} }
public ImageSize GetImageSize(string path)
{
throw new NotImplementedException();
}
public void Dispose() public void Dispose()
{ {
} }

@ -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; newRefresher.Completed += NewRefresher_Completed;
_activeRefreshers.Add(newRefresher); _activeRefreshers.Add(newRefresher);
} }

@ -34,8 +34,9 @@ namespace Emby.Server.Implementations.IO
public event EventHandler<EventArgs> Completed; public event EventHandler<EventArgs> Completed;
private readonly IEnvironmentInfo _environmentInfo; 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); logger.Debug("New file refresher created for {0}", path);
Path = path; Path = path;
@ -47,6 +48,7 @@ namespace Emby.Server.Implementations.IO
Logger = logger; Logger = logger;
_timerFactory = timerFactory; _timerFactory = timerFactory;
_environmentInfo = environmentInfo; _environmentInfo = environmentInfo;
_libraryManager = libraryManager1;
AddPath(path); AddPath(path);
} }
@ -235,6 +237,12 @@ namespace Emby.Server.Implementations.IO
return false; return false;
} }
// Only try to open video files
if (!_libraryManager.IsVideoFile(path))
{
return false;
}
try try
{ {
var data = _fileSystem.GetFileSystemInfo(path); var data = _fileSystem.GetFileSystemInfo(path);

@ -82,10 +82,6 @@
<Compile Include="Reports\Model\ReportRow.cs" /> <Compile Include="Reports\Model\ReportRow.cs" />
<Compile Include="Reports\ReportRequests.cs" /> <Compile Include="Reports\ReportRequests.cs" />
<Compile Include="Reports\ReportsService.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="Social\SharingService.cs" />
<Compile Include="StartupWizardService.cs" /> <Compile Include="StartupWizardService.cs" />
<Compile Include="Subtitles\SubtitleService.cs" /> <Compile Include="Subtitles\SubtitleService.cs" />

@ -879,7 +879,7 @@ namespace MediaBrowser.Api.Playback.Hls
// Add resolution params, if specified // Add resolution params, if specified
if (!hasGraphicalSubs) if (!hasGraphicalSubs)
{ {
args += EncodingHelper.GetOutputSizeParam(state, codec, EnableCopyTs(state)); args += EncodingHelper.GetOutputSizeParam(state, codec, true);
} }
// This is for internal graphical subs // This is for internal graphical subs
@ -891,7 +891,7 @@ namespace MediaBrowser.Api.Playback.Hls
//args += " -flags -global_header"; //args += " -flags -global_header";
} }
if (EnableCopyTs(state) && args.IndexOf("-copyts", StringComparison.OrdinalIgnoreCase) == -1) if (args.IndexOf("-copyts", StringComparison.OrdinalIgnoreCase) == -1)
{ {
args += " -copyts"; args += " -copyts";
} }
@ -901,13 +901,9 @@ namespace MediaBrowser.Api.Playback.Hls
args += " -vsync " + state.OutputVideoSync; args += " -vsync " + state.OutputVideoSync;
} }
return args; args += EncodingHelper.GetOutputFFlags(state);
}
private bool EnableCopyTs(StreamState state) return args;
{
//return state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode;
return true;
} }
protected override string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding) protected override string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding)

@ -124,6 +124,8 @@ namespace MediaBrowser.Api.Playback.Hls
args += " -vsync " + state.OutputVideoSync; args += " -vsync " + state.OutputVideoSync;
} }
args += EncodingHelper.GetOutputFFlags(state);
return args; return args;
} }

@ -35,7 +35,8 @@ namespace MediaBrowser.Api.Reports
Tracks, Tracks,
EpisodeSeries, EpisodeSeries,
EpisodeSeason, EpisodeSeason,
AudioAlbumArtist, EpisodeNumber,
AudioAlbumArtist,
MusicArtist, MusicArtist,
AudioAlbum, AudioAlbum,
Locked, Locked,

@ -148,6 +148,11 @@ namespace MediaBrowser.Api.Reports
/// <returns> The localized header. </returns> /// <returns> The localized header. </returns>
protected static string GetLocalizedHeader(HeaderMetadata internalHeader) protected static string GetLocalizedHeader(HeaderMetadata internalHeader)
{ {
if (internalHeader == HeaderMetadata.EpisodeNumber)
{
return "Episode";
}
string headerName = ""; string headerName = "";
if (internalHeader != HeaderMetadata.None) if (internalHeader != HeaderMetadata.None)
{ {

@ -102,7 +102,7 @@ namespace MediaBrowser.Api.Reports
HeaderMetadata.Series, HeaderMetadata.Series,
HeaderMetadata.Season, HeaderMetadata.Season,
HeaderMetadata.SeasonNumber, HeaderMetadata.SeasonNumber,
HeaderMetadata.DateAdded, HeaderMetadata.DateAdded,
HeaderMetadata.Year, HeaderMetadata.Year,
HeaderMetadata.Genres HeaderMetadata.Genres
}; };
@ -269,10 +269,11 @@ namespace MediaBrowser.Api.Reports
HeaderMetadata.ImagePrimary, HeaderMetadata.ImagePrimary,
HeaderMetadata.ImageBackdrop, HeaderMetadata.ImageBackdrop,
HeaderMetadata.ImageLogo, HeaderMetadata.ImageLogo,
HeaderMetadata.Name, HeaderMetadata.Name,
HeaderMetadata.EpisodeSeries, HeaderMetadata.EpisodeSeries,
HeaderMetadata.Season, HeaderMetadata.Season,
HeaderMetadata.DateAdded, HeaderMetadata.EpisodeNumber,
HeaderMetadata.DateAdded,
HeaderMetadata.ReleaseDate, HeaderMetadata.ReleaseDate,
HeaderMetadata.Year, HeaderMetadata.Year,
HeaderMetadata.Genres, HeaderMetadata.Genres,
@ -450,6 +451,12 @@ namespace MediaBrowser.Api.Reports
internalHeader = HeaderMetadata.Season; internalHeader = HeaderMetadata.Season;
break; 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: case HeaderMetadata.Network:
option.Column = (i, r) => this.GetListAsString(i.Studios); option.Column = (i, r) => this.GetListAsString(i.Studios);
option.ItemID = (i) => this.GetStudioID(i.Studios.FirstOrDefault()); option.ItemID = (i) => this.GetStudioID(i.Studios.FirstOrDefault());

@ -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
}
}

@ -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);
}
}
}

@ -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; }
}
}

@ -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; }
}
}

@ -50,5 +50,7 @@ namespace MediaBrowser.Controller.Drawing
/// </summary> /// </summary>
/// <value><c>true</c> if [supports image encoding]; otherwise, <c>false</c>.</value> /// <value><c>true</c> if [supports image encoding]; otherwise, <c>false</c>.</value>
bool SupportsImageEncoding { get; } bool SupportsImageEncoding { get; }
ImageSize GetImageSize(string path);
} }
} }

@ -1306,7 +1306,8 @@ namespace MediaBrowser.Controller.MediaEncoding
filters.Add("format=nv12|vaapi"); filters.Add("format=nv12|vaapi");
filters.Add("hwupload"); 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"); filters.Add("yadif=0:-1:0");
} }
@ -1533,14 +1534,26 @@ namespace MediaBrowser.Controller.MediaEncoding
} }
var flags = new List<string>(); var flags = new List<string>();
if (state.IgnoreDts) if (state.IgnoreInputDts)
{ {
flags.Add("+igndts"); flags.Add("+igndts");
} }
if (state.IgnoreIndex) if (state.IgnoreInputIndex)
{ {
flags.Add("+ignidx"); 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) if (flags.Count > 0)
{ {
@ -1864,6 +1877,22 @@ namespace MediaBrowser.Controller.MediaEncoding
).Trim(); ).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) public string GetProgressiveVideoArguments(EncodingJobInfo state, EncodingOptions encodingOptions, string videoCodec, string defaultH264Preset)
{ {
var args = "-codec:v:0 " + videoCodec; var args = "-codec:v:0 " + videoCodec;
@ -1943,6 +1972,8 @@ namespace MediaBrowser.Controller.MediaEncoding
args += " -vsync " + state.OutputVideoSync; args += " -vsync " + state.OutputVideoSync;
} }
args += GetOutputFFlags(state);
return args; return args;
} }

@ -39,14 +39,52 @@ namespace MediaBrowser.Controller.MediaEncoding
public bool ReadInputAtNativeFramerate { get; set; } 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; } public string OutputContainer { get; set; }

@ -218,13 +218,9 @@ namespace MediaBrowser.LocalMetadata.Savers
{ {
if (file.IsHidden) if (file.IsHidden)
{ {
FileSystem.SetHidden(path, false);
wasHidden = true; wasHidden = true;
} }
if (file.IsReadOnly) FileSystem.SetAttributes(path, false, false);
{
FileSystem.SetReadOnly(path, false);
}
} }
using (var filestream = FileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read)) using (var filestream = FileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))

@ -313,7 +313,8 @@ namespace MediaBrowser.Model.IO
IEnumerable<string> GetFileSystemEntryPaths(string path, bool recursive = false); IEnumerable<string> GetFileSystemEntryPaths(string path, bool recursive = false);
void SetHidden(string path, bool isHidden); 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; } char DirectorySeparatorChar { get; }

@ -166,7 +166,7 @@ namespace MediaBrowser.Providers.Manager
{ {
var currentPath = currentImagePath; var currentPath = currentImagePath;
_logger.Debug("Deleting previous image {0}", currentPath); _logger.Info("Deleting previous image {0}", currentPath);
_libraryMonitor.ReportFileSystemChangeBeginning(currentPath); _libraryMonitor.ReportFileSystemChangeBeginning(currentPath);
@ -236,7 +236,7 @@ namespace MediaBrowser.Providers.Manager
/// <returns>Task.</returns> /// <returns>Task.</returns>
private async Task SaveImageToLocation(Stream source, string path, CancellationToken cancellationToken) 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); var parentFolder = _fileSystem.GetDirectoryName(path);
@ -249,31 +249,16 @@ namespace MediaBrowser.Providers.Manager
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
// If the file is currently hidden we'll have to remove that or the save will fail _fileSystem.SetAttributes(path, false, false);
var file = _fileSystem.GetFileInfo(path);
// This will fail if the file is hidden using (var fs = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, FileOpenOptions.Asynchronous))
if (file.Exists)
{ {
if (file.IsHidden) await source.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, cancellationToken).ConfigureAwait(false);
{
_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);
} }
if (_config.Configuration.SaveMetadataHidden) if (_config.Configuration.SaveMetadataHidden)
{ {
_fileSystem.SetHidden(file.FullName, true); _fileSystem.SetHidden(path, true);
} }
} }
finally finally

@ -72,8 +72,7 @@ namespace MediaBrowser.Providers.Omdb
var imdbId = searchInfo.GetProviderId(MetadataProviders.Imdb); var imdbId = searchInfo.GetProviderId(MetadataProviders.Imdb);
var baseUrl = await OmdbProvider.GetOmdbBaseUrl(cancellationToken).ConfigureAwait(false); var urlQuery = "plot=full&r=json";
var url = baseUrl + "/?plot=full&r=json";
if (type == "episode" && episodeSearchInfo != null) if (type == "episode" && episodeSearchInfo != null)
{ {
episodeSearchInfo.SeriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out imdbId); episodeSearchInfo.SeriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out imdbId);
@ -94,23 +93,23 @@ namespace MediaBrowser.Providers.Omdb
{ {
if (year.HasValue) 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 // &s means search and returns a list of results as opposed to t
if (isSearch) if (isSearch)
{ {
url += "&s=" + WebUtility.UrlEncode(name); urlQuery += "&s=" + WebUtility.UrlEncode(name);
} }
else else
{ {
url += "&t=" + WebUtility.UrlEncode(name); urlQuery += "&t=" + WebUtility.UrlEncode(name);
} }
url += "&type=" + type; urlQuery += "&type=" + type;
} }
else else
{ {
url += "&i=" + imdbId; urlQuery += "&i=" + imdbId;
isSearch = false; isSearch = false;
} }
@ -118,14 +117,16 @@ namespace MediaBrowser.Providers.Omdb
{ {
if (searchInfo.IndexNumber.HasValue) 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) 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)) using (var stream = await OmdbProvider.GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false))
{ {
var resultList = new List<SearchResult>(); var resultList = new List<SearchResult>();

@ -265,9 +265,16 @@ namespace MediaBrowser.Providers.Omdb
return false; 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) 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 = await GetOmdbUrl(string.Format("i={0}&plot=full&tomatoes=true&r=json", imdbParam), cancellationToken).ConfigureAwait(false);
var url = string.Format(baseUrl + "/?i={0}&plot=full&tomatoes=true&r=json", imdbParam);
using (var stream = await GetOmdbResponse(_httpClient, url, 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 = await GetOmdbUrl(string.Format("i={0}&season={1}&detail=full", imdbParam, seasonId), cancellationToken).ConfigureAwait(false);
var url = string.Format(baseUrl + "/?i={0}&season={1}&detail=full", imdbParam, seasonId);
using (var stream = await GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false)) using (var stream = await GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false))
{ {

@ -122,10 +122,10 @@
<HintPath>..\ThirdParty\taglib\TagLib.Portable.dll</HintPath> <HintPath>..\ThirdParty\taglib\TagLib.Portable.dll</HintPath>
</Reference> </Reference>
<Reference Include="SQLitePCLRaw.core"> <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>
<Reference Include="SQLitePCLRaw.provider.sqlite3"> <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>
<Reference Include="Emby.Server.Connect"> <Reference Include="Emby.Server.Connect">
<HintPath>..\ThirdParty\emby\Emby.Server.Connect.dll</HintPath> <HintPath>..\ThirdParty\emby\Emby.Server.Connect.dll</HintPath>

@ -26,11 +26,11 @@ namespace MediaBrowser.Server.Startup.Common
{ {
try try
{ {
return new SkiaEncoder(logManager.GetLogger("ImageMagick"), appPaths, httpClient, fileSystem); return new SkiaEncoder(logManager.GetLogger("Skia"), appPaths, httpClient, fileSystem);
} }
catch catch
{ {
logger.Error("Error loading ImageMagick. Will revert to GDI."); logger.Error("Error loading Skia. Will revert to ImageMagick.");
} }
try try

@ -380,6 +380,9 @@ namespace MediaBrowser.ServerApplication
task = InstallVcredist2013IfNeeded(_appHost, _logger); task = InstallVcredist2013IfNeeded(_appHost, _logger);
Task.WaitAll(task); Task.WaitAll(task);
task = InstallVcredist2015IfNeeded(_appHost, _logger);
Task.WaitAll(task);
Microsoft.Win32.SystemEvents.SessionSwitch += SystemEvents_SessionSwitch; Microsoft.Win32.SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
HideSplashScreen(); HideSplashScreen();
@ -736,32 +739,61 @@ namespace MediaBrowser.ServerApplication
Process.Start(startInfo); Process.Start(startInfo);
} }
private static bool CanRestartWindowsService() private static async Task InstallVcredist2013IfNeeded(ApplicationHost appHost, ILogger logger)
{ {
var startInfo = new ProcessStartInfo // Reference
{ // http://stackoverflow.com/questions/12206314/detect-if-visual-c-redistributable-for-visual-studio-2012-is-installed
FileName = "cmd.exe",
CreateNoWindow = true, try
WindowStyle = ProcessWindowStyle.Hidden,
Verb = "runas",
ErrorDialog = false,
Arguments = String.Format("/c sc query {0}", BackgroundService.GetExistingServiceName())
};
using (var process = Process.Start(startInfo))
{ {
process.WaitForExit(); var subkey = Environment.Is64BitProcess
if (process.ExitCode == 0) ? "SOFTWARE\\WOW6432Node\\Microsoft\\VisualStudio\\12.0\\VC\\Runtimes\\x64"
{ : "SOFTWARE\\Microsoft\\VisualStudio\\12.0\\VC\\Runtimes\\x86";
return true;
} using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default)
else .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 // Reference
// http://stackoverflow.com/questions/12206314/detect-if-visual-c-redistributable-for-visual-studio-2012-is-installed // http://stackoverflow.com/questions/12206314/detect-if-visual-c-redistributable-for-visual-studio-2012-is-installed
@ -769,8 +801,8 @@ namespace MediaBrowser.ServerApplication
try try
{ {
var subkey = Environment.Is64BitProcess var subkey = Environment.Is64BitProcess
? "SOFTWARE\\WOW6432Node\\Microsoft\\VisualStudio\\12.0\\VC\\Runtimes\\x64" ? "SOFTWARE\\WOW6432Node\\Microsoft\\VisualStudio\\14.0\\VC\\Runtimes\\x64"
: "SOFTWARE\\Microsoft\\VisualStudio\\12.0\\VC\\Runtimes\\x86"; : "SOFTWARE\\Microsoft\\VisualStudio\\14.0\\VC\\Runtimes\\x86";
using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default) using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default)
.OpenSubKey(subkey)) .OpenSubKey(subkey))
@ -778,7 +810,7 @@ namespace MediaBrowser.ServerApplication
if (ndpKey != null && ndpKey.GetValue("Version") != null) if (ndpKey != null && ndpKey.GetValue("Version") != null)
{ {
var installedVersion = ((string)ndpKey.GetValue("Version")).TrimStart('v'); var installedVersion = ((string)ndpKey.GetValue("Version")).TrimStart('v');
if (installedVersion.StartsWith("12", StringComparison.OrdinalIgnoreCase)) if (installedVersion.StartsWith("14", StringComparison.OrdinalIgnoreCase))
{ {
return; return;
} }
@ -791,9 +823,11 @@ namespace MediaBrowser.ServerApplication
return; return;
} }
MessageBox.Show("The Visual C++ 2015 Runtime will now be installed.", "Install Visual C++ Runtime", MessageBoxButtons.OK, MessageBoxIcon.Information);
try try
{ {
await InstallVcredist2013().ConfigureAwait(false); await InstallVcredist(GetVcredist2015Url()).ConfigureAwait(false);
} }
catch (Exception ex) 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 httpClient = _appHost.HttpClient;
var tmp = await httpClient.GetTempFile(new HttpRequestOptions var tmp = await httpClient.GetTempFile(new HttpRequestOptions
{ {
Url = GetVcredist2013Url(), Url = url,
Progress = new Progress<double>() Progress = new Progress<double>()
}).ConfigureAwait(false); }).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> /// <summary>
/// Sets the error mode. /// Sets the error mode.
/// </summary> /// </summary>

@ -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 // Call this API to load the current list of LoopUtil-enabled AppContainers
[DllImport("FirewallAPI.dll")] [DllImport("FirewallAPI.dll")]
internal static extern uint NetworkIsolationGetAppContainerConfig(out uint pdwCntACs, out IntPtr appContainerSids); internal static extern uint NetworkIsolationGetAppContainerConfig(out uint pdwCntACs, out IntPtr appContainerSids);
@ -69,23 +65,13 @@ namespace MediaBrowser.ServerApplication.Native
[DllImport("FirewallAPI.dll")] [DllImport("FirewallAPI.dll")]
private static extern uint NetworkIsolationSetAppContainerConfig(uint pdwCntACs, SID_AND_ATTRIBUTES[] appContainerSids); private static extern uint NetworkIsolationSetAppContainerConfig(uint pdwCntACs, SID_AND_ATTRIBUTES[] appContainerSids);
// Use this API to convert a string SID into an actual SID // Use this API to convert a string SID into an actual SID
[DllImport("advapi32.dll", SetLastError = true)] [DllImport("advapi32.dll", SetLastError = true)]
internal static extern bool ConvertStringSidToSid(string strSid, out IntPtr pSid); 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)] [DllImport("advapi32", /*CharSet = CharSet.Auto,*/ SetLastError = true)]
static extern bool ConvertSidToStringSid(IntPtr pSid, out string strSid); 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 // Call this API to enumerate all of the AppContainers on the system
[DllImport("FirewallAPI.dll")] [DllImport("FirewallAPI.dll")]
internal static extern uint NetworkIsolationEnumAppContainers(uint Flags, out uint pdwCntPublicACs, out IntPtr ppACs); 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();
} }
util.SaveLoopbackState();
} }
private static List<SID_AND_ATTRIBUTES> PI_NetworkIsolationGetAppContainerConfig() private static List<SID_AND_ATTRIBUTES> PI_NetworkIsolationGetAppContainerConfig()
@ -305,11 +290,5 @@ namespace MediaBrowser.ServerApplication.Native
} }
return count; return count;
} }
public void FreeResources()
{
NetworkIsolationFreeAppContainers(_pACs);
}
} }
} }

@ -220,14 +220,9 @@ namespace MediaBrowser.XbmcMetadata.Savers
{ {
if (file.IsHidden) if (file.IsHidden)
{ {
FileSystem.SetHidden(path, false);
wasHidden = true; wasHidden = true;
} }
if (file.IsReadOnly) FileSystem.SetAttributes(path, false, false);
{
FileSystem.SetReadOnly(path, false);
}
} }
using (var filestream = FileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read)) using (var filestream = FileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))

@ -1,3 +1,3 @@
using System.Reflection; using System.Reflection;
[assembly: AssemblyVersion("3.2.15.4")] [assembly: AssemblyVersion("3.2.15.5")]

Loading…
Cancel
Save