mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-11-16 18:42:52 -07:00
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -57,6 +57,11 @@ namespace Emby.Drawing
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public ImageSize GetImageSize(string path)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
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;
|
||||
_activeRefreshers.Add(newRefresher);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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" />
|
||||
|
@ -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)
|
||||
|
@ -124,6 +124,8 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||
args += " -vsync " + state.OutputVideoSync;
|
||||
}
|
||||
|
||||
args += EncodingHelper.GetOutputFFlags(state);
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,8 @@ namespace MediaBrowser.Api.Reports
|
||||
Tracks,
|
||||
EpisodeSeries,
|
||||
EpisodeSeason,
|
||||
AudioAlbumArtist,
|
||||
EpisodeNumber,
|
||||
AudioAlbumArtist,
|
||||
MusicArtist,
|
||||
AudioAlbum,
|
||||
Locked,
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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());
|
||||
|
@ -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>
|
||||
/// <value><c>true</c> if [supports image encoding]; otherwise, <c>false</c>.</value>
|
||||
bool SupportsImageEncoding { get; }
|
||||
|
||||
ImageSize GetImageSize(string path);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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; }
|
||||
|
@ -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))
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -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
|
||||
|
@ -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>();
|
||||
|
@ -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))
|
||||
{
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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))
|
||||
|
@ -1,3 +1,3 @@
|
||||
using System.Reflection;
|
||||
|
||||
[assembly: AssemblyVersion("3.2.15.4")]
|
||||
[assembly: AssemblyVersion("3.2.15.5")]
|
||||
|
Loading…
Reference in New Issue
Block a user