Merge pull request #2630 from MediaBrowser/dev

Dev
This commit is contained in:
Luke 2017-05-12 01:09:16 -04:00 committed by GitHub
commit 275fe66220
31 changed files with 362 additions and 527 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -82,10 +82,6 @@
<Compile Include="Reports\Model\ReportRow.cs" />
<Compile Include="Reports\ReportRequests.cs" />
<Compile Include="Reports\ReportsService.cs" />
<Compile Include="Reports\Stat\ReportStatBuilder.cs" />
<Compile Include="Reports\Stat\ReportStatGroup.cs" />
<Compile Include="Reports\Stat\ReportStatItem.cs" />
<Compile Include="Reports\Stat\ReportStatResult.cs" />
<Compile Include="Social\SharingService.cs" />
<Compile Include="StartupWizardService.cs" />
<Compile Include="Subtitles\SubtitleService.cs" />

View file

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

View file

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

View file

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

View file

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

View file

@ -102,7 +102,7 @@ namespace MediaBrowser.Api.Reports
HeaderMetadata.Series,
HeaderMetadata.Season,
HeaderMetadata.SeasonNumber,
HeaderMetadata.DateAdded,
HeaderMetadata.DateAdded,
HeaderMetadata.Year,
HeaderMetadata.Genres
};
@ -269,10 +269,11 @@ namespace MediaBrowser.Api.Reports
HeaderMetadata.ImagePrimary,
HeaderMetadata.ImageBackdrop,
HeaderMetadata.ImageLogo,
HeaderMetadata.Name,
HeaderMetadata.Name,
HeaderMetadata.EpisodeSeries,
HeaderMetadata.Season,
HeaderMetadata.DateAdded,
HeaderMetadata.EpisodeNumber,
HeaderMetadata.DateAdded,
HeaderMetadata.ReleaseDate,
HeaderMetadata.Year,
HeaderMetadata.Genres,
@ -450,6 +451,12 @@ namespace MediaBrowser.Api.Reports
internalHeader = HeaderMetadata.Season;
break;
case HeaderMetadata.EpisodeNumber:
option.Column = (i, r) => this.GetObject<BaseItem, string>(i, (x) => x.IndexNumber == null ? "" : x.IndexNumber.ToString());
//option.Header.SortField = "IndexNumber";
//option.Header.HeaderFieldType = ReportFieldType.Int;
break;
case HeaderMetadata.Network:
option.Column = (i, r) => this.GetListAsString(i.Studios);
option.ItemID = (i) => this.GetStudioID(i.Studios.FirstOrDefault());

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1306,7 +1306,8 @@ namespace MediaBrowser.Controller.MediaEncoding
filters.Add("format=nv12|vaapi");
filters.Add("hwupload");
}
else if (state.DeInterlace && !string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
if (state.DeInterlace && !string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
{
filters.Add("yadif=0:-1:0");
}
@ -1533,14 +1534,26 @@ namespace MediaBrowser.Controller.MediaEncoding
}
var flags = new List<string>();
if (state.IgnoreDts)
if (state.IgnoreInputDts)
{
flags.Add("+igndts");
}
if (state.IgnoreIndex)
if (state.IgnoreInputIndex)
{
flags.Add("+ignidx");
}
if (state.GenPtsInput)
{
flags.Add("+genpts");
}
if (state.DiscardCorruptFramesInput)
{
flags.Add("+discardcorrupt");
}
if (state.EnableFastSeekInput)
{
flags.Add("+fastseek");
}
if (flags.Count > 0)
{
@ -1864,6 +1877,22 @@ namespace MediaBrowser.Controller.MediaEncoding
).Trim();
}
public string GetOutputFFlags(EncodingJobInfo state)
{
var flags = new List<string>();
if (state.GenPtsOutput)
{
flags.Add("+genpts");
}
if (flags.Count > 0)
{
return " -fflags " + string.Join("", flags.ToArray());
}
return string.Empty;
}
public string GetProgressiveVideoArguments(EncodingJobInfo state, EncodingOptions encodingOptions, string videoCodec, string defaultH264Preset)
{
var args = "-codec:v:0 " + videoCodec;
@ -1943,6 +1972,8 @@ namespace MediaBrowser.Controller.MediaEncoding
args += " -vsync " + state.OutputVideoSync;
}
args += GetOutputFFlags(state);
return args;
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -265,9 +265,16 @@ namespace MediaBrowser.Providers.Omdb
return false;
}
public static async Task<string> GetOmdbBaseUrl(CancellationToken cancellationToken)
public static async Task<string> GetOmdbUrl(string query, CancellationToken cancellationToken)
{
return "https://www.omdbapi.com";
var url = "https://www.omdbapi.com?apikey=fe53f97e";
if (!string.IsNullOrWhiteSpace(query))
{
url += "&" + query;
}
return url;
}
private async Task<string> EnsureItemInfo(string imdbId, CancellationToken cancellationToken)
@ -292,8 +299,7 @@ namespace MediaBrowser.Providers.Omdb
}
}
var baseUrl = await GetOmdbBaseUrl(cancellationToken).ConfigureAwait(false);
var url = string.Format(baseUrl + "/?i={0}&plot=full&tomatoes=true&r=json", imdbParam);
var url = await GetOmdbUrl(string.Format("i={0}&plot=full&tomatoes=true&r=json", imdbParam), cancellationToken).ConfigureAwait(false);
using (var stream = await GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false))
{
@ -327,8 +333,7 @@ namespace MediaBrowser.Providers.Omdb
}
}
var baseUrl = await GetOmdbBaseUrl(cancellationToken).ConfigureAwait(false);
var url = string.Format(baseUrl + "/?i={0}&season={1}&detail=full", imdbParam, seasonId);
var url = await GetOmdbUrl(string.Format("i={0}&season={1}&detail=full", imdbParam, seasonId), cancellationToken).ConfigureAwait(false);
using (var stream = await GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false))
{

View file

@ -122,10 +122,10 @@
<HintPath>..\ThirdParty\taglib\TagLib.Portable.dll</HintPath>
</Reference>
<Reference Include="SQLitePCLRaw.core">
<HintPath>..\packages\SQLitePCLRaw.core.1.1.2\lib\net45\SQLitePCLRaw.core.dll</HintPath>
<HintPath>..\packages\SQLitePCLRaw.core.1.1.5\lib\net45\SQLitePCLRaw.core.dll</HintPath>
</Reference>
<Reference Include="SQLitePCLRaw.provider.sqlite3">
<HintPath>..\packages\SQLitePCLRaw.provider.sqlite3.net45.1.1.2\lib\net45\SQLitePCLRaw.provider.sqlite3.dll</HintPath>
<HintPath>..\packages\SQLitePCLRaw.provider.sqlite3.net45.1.1.5\lib\net45\SQLitePCLRaw.provider.sqlite3.dll</HintPath>
</Reference>
<Reference Include="Emby.Server.Connect">
<HintPath>..\ThirdParty\emby\Emby.Server.Connect.dll</HintPath>

View file

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

View file

@ -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<double>()
}).ConfigureAwait(false);
@ -833,18 +879,6 @@ namespace MediaBrowser.ServerApplication
}
}
private static string GetVcredist2013Url()
{
if (Environment.Is64BitProcess)
{
return "https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2013/vcredist_x64.exe";
}
// TODO: ARM url - https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2013/vcredist_arm.exe
return "https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2013/vcredist_x86.exe";
}
/// <summary>
/// Sets the error mode.
/// </summary>

View file

@ -57,10 +57,6 @@ namespace MediaBrowser.ServerApplication.Native
}
// Call this API to free the memory returned by the Enumeration API
[DllImport("FirewallAPI.dll")]
internal static extern void NetworkIsolationFreeAppContainers(IntPtr pACs);
// Call this API to load the current list of LoopUtil-enabled AppContainers
[DllImport("FirewallAPI.dll")]
internal static extern uint NetworkIsolationGetAppContainerConfig(out uint pdwCntACs, out IntPtr appContainerSids);
@ -69,23 +65,13 @@ namespace MediaBrowser.ServerApplication.Native
[DllImport("FirewallAPI.dll")]
private static extern uint NetworkIsolationSetAppContainerConfig(uint pdwCntACs, SID_AND_ATTRIBUTES[] appContainerSids);
// Use this API to convert a string SID into an actual SID
[DllImport("advapi32.dll", SetLastError = true)]
internal static extern bool ConvertStringSidToSid(string strSid, out IntPtr pSid);
[DllImport("advapi32", /*CharSet = CharSet.Auto,*/ SetLastError = true)]
static extern bool ConvertSidToStringSid(
[MarshalAs(UnmanagedType.LPArray)] byte[] pSID,
out IntPtr ptrSid);
[DllImport("advapi32", /*CharSet = CharSet.Auto,*/ SetLastError = true)]
static extern bool ConvertSidToStringSid(IntPtr pSid, out string strSid);
// Use this API to convert a string reference (e.g. "@{blah.pri?ms-resource://whatever}") into a plain string
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
internal static extern int SHLoadIndirectString(string pszSource, StringBuilder pszOutBuf);
// Call this API to enumerate all of the AppContainers on the system
[DllImport("FirewallAPI.dll")]
internal static extern uint NetworkIsolationEnumAppContainers(uint Flags, out uint pdwCntPublicACs, out IntPtr ppACs);
@ -196,7 +182,6 @@ namespace MediaBrowser.ServerApplication.Native
{
util.SaveLoopbackState();
}
util.SaveLoopbackState();
}
private static List<SID_AND_ATTRIBUTES> PI_NetworkIsolationGetAppContainerConfig()
@ -305,11 +290,5 @@ namespace MediaBrowser.ServerApplication.Native
}
return count;
}
public void FreeResources()
{
NetworkIsolationFreeAppContainers(_pACs);
}
}
}

View file

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

View file

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