commit
e0c907cc60
|
@ -33,10 +33,6 @@
|
|||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<None Include="project.json" />
|
||||
<!-- A reference to the entire .NET Framework is automatically included -->
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BDInfoSettings.cs" />
|
||||
<Compile Include="BDROM.cs" />
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"frameworks":{
|
||||
"netstandard1.6":{
|
||||
"dependencies":{
|
||||
"NETStandard.Library":"1.6.0",
|
||||
}
|
||||
},
|
||||
".NETPortable,Version=v4.5,Profile=Profile7":{
|
||||
"buildOptions": {
|
||||
"define": [ ]
|
||||
},
|
||||
"frameworkAssemblies":{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,10 +33,6 @@
|
|||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<None Include="project.json" />
|
||||
<!-- A reference to the entire .NET Framework is automatically included -->
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BigEndianBinaryReader.cs" />
|
||||
<Compile Include="Ifo\AudioAttributes.cs" />
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"frameworks":{
|
||||
"netstandard1.6":{
|
||||
"dependencies":{
|
||||
"NETStandard.Library":"1.6.0",
|
||||
}
|
||||
},
|
||||
".NETPortable,Version=v4.5,Profile=Profile7":{
|
||||
"buildOptions": {
|
||||
"define": [ ]
|
||||
},
|
||||
"frameworkAssemblies":{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -32,7 +32,7 @@
|
|||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.4.4.9\lib\net45\NLog.dll</HintPath>
|
||||
<HintPath>..\packages\NLog.4.4.10\lib\net45\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ServiceStack.Text, Version=4.5.8.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\ServiceStack.Text.4.5.8\lib\net45\ServiceStack.Text.dll</HintPath>
|
||||
|
@ -42,9 +42,8 @@
|
|||
<HintPath>..\packages\SharpCompress.0.14.0\lib\net45\SharpCompress.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="SimpleInjector, Version=4.0.7.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SimpleInjector.4.0.7\lib\net45\SimpleInjector.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="SimpleInjector, Version=4.0.8.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SimpleInjector.4.0.8\lib\net45\SimpleInjector.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
|
|
|
@ -157,6 +157,7 @@ namespace Emby.Common.Implementations.TextEncoding
|
|||
case "ota":
|
||||
case "tur":
|
||||
return "windows-1254";
|
||||
case "bgr":
|
||||
case "rus":
|
||||
return "windows-1251";
|
||||
case "vie":
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="NLog" version="4.4.9" targetFramework="net46" />
|
||||
<package id="NLog" version="4.4.10" targetFramework="net46" />
|
||||
<package id="ServiceStack.Text" version="4.5.8" targetFramework="net462" />
|
||||
<package id="SharpCompress" version="0.14.0" targetFramework="net462" />
|
||||
<package id="SimpleInjector" version="4.0.7" targetFramework="net462" />
|
||||
<package id="SimpleInjector" version="4.0.8" targetFramework="net46" />
|
||||
</packages>
|
|
@ -70,7 +70,7 @@ namespace Emby.Dlna.Profiles
|
|||
|
||||
new DirectPlayProfile
|
||||
{
|
||||
Container = "aac,mp3,mpa,wav,wma,mp2,ogg,oga,webma,ape,opus,flac",
|
||||
Container = "aac,mp3,mpa,wav,wma,mp2,ogg,oga,webma,ape,opus,flac,m4a",
|
||||
Type = DlnaProfileType.Audio
|
||||
}
|
||||
};
|
||||
|
|
|
@ -31,42 +31,7 @@ namespace Emby.Dlna.Profiles
|
|||
{
|
||||
new DirectPlayProfile
|
||||
{
|
||||
Container = "mp3",
|
||||
AudioCodec = "mp2,mp3",
|
||||
Type = DlnaProfileType.Audio
|
||||
},
|
||||
|
||||
new DirectPlayProfile
|
||||
{
|
||||
Container = "mp4",
|
||||
AudioCodec = "mp4",
|
||||
Type = DlnaProfileType.Audio
|
||||
},
|
||||
|
||||
new DirectPlayProfile
|
||||
{
|
||||
Container = "aac,wav",
|
||||
Type = DlnaProfileType.Audio
|
||||
},
|
||||
|
||||
new DirectPlayProfile
|
||||
{
|
||||
Container = "flac",
|
||||
AudioCodec = "flac",
|
||||
Type = DlnaProfileType.Audio
|
||||
},
|
||||
|
||||
new DirectPlayProfile
|
||||
{
|
||||
Container = "asf",
|
||||
AudioCodec = "wmav2,wmapro,wmavoice",
|
||||
Type = DlnaProfileType.Audio
|
||||
},
|
||||
|
||||
new DirectPlayProfile
|
||||
{
|
||||
Container = "ogg",
|
||||
AudioCodec = "vorbis",
|
||||
Container = "aac,mp3,mpa,wav,wma,mp2,ogg,oga,webma,ape,opus,flac,m4a",
|
||||
Type = DlnaProfileType.Audio
|
||||
}
|
||||
};
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
<XmlRootAttributes />
|
||||
<DirectPlayProfiles>
|
||||
<DirectPlayProfile container="m4v,mpegts,ts,3gp,mov,xvid,vob,mkv,wmv,asf,ogm,ogv,m2v,avi,mpg,mpeg,mp4,webm,wtv,m2ts,dvr-ms" type="Video" />
|
||||
<DirectPlayProfile container="aac,mp3,mpa,wav,wma,mp2,ogg,oga,webma,ape,opus,flac" type="Audio" />
|
||||
<DirectPlayProfile container="aac,mp3,mpa,wav,wma,mp2,ogg,oga,webma,ape,opus,flac,m4a" type="Audio" />
|
||||
</DirectPlayProfiles>
|
||||
<TranscodingProfiles>
|
||||
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" minSegments="0" segmentLength="0" breakOnNonKeyFrames="false" />
|
||||
|
|
|
@ -35,12 +35,7 @@
|
|||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||
<XmlRootAttributes />
|
||||
<DirectPlayProfiles>
|
||||
<DirectPlayProfile container="mp3" audioCodec="mp2,mp3" type="Audio" />
|
||||
<DirectPlayProfile container="mp4" audioCodec="mp4" type="Audio" />
|
||||
<DirectPlayProfile container="aac,wav" type="Audio" />
|
||||
<DirectPlayProfile container="flac" audioCodec="flac" type="Audio" />
|
||||
<DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" type="Audio" />
|
||||
<DirectPlayProfile container="ogg" audioCodec="vorbis" type="Audio" />
|
||||
<DirectPlayProfile container="aac,mp3,mpa,wav,wma,mp2,ogg,oga,webma,ape,opus,flac,m4a" type="Audio" />
|
||||
</DirectPlayProfiles>
|
||||
<TranscodingProfiles>
|
||||
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" minSegments="0" segmentLength="0" breakOnNonKeyFrames="false" />
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"frameworks":{
|
||||
"netstandard1.6":{
|
||||
"dependencies":{
|
||||
"NETStandard.Library":"1.6.0",
|
||||
}
|
||||
},
|
||||
".NETPortable,Version=v4.5,Profile=Profile7":{
|
||||
"buildOptions": {
|
||||
"define": [ ]
|
||||
},
|
||||
"frameworkAssemblies":{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -130,7 +130,7 @@ namespace Emby.Drawing.ImageMagick
|
|||
string.Equals(ext, ".webp", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
|
||||
public string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation? orientation, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
|
||||
{
|
||||
// Even if the caller specified 100, don't use it because it takes forever
|
||||
quality = Math.Min(quality, 99);
|
||||
|
|
|
@ -126,11 +126,11 @@ namespace Emby.Drawing.Skia
|
|||
for (int row = 0; row < bitmap.Height; ++row)
|
||||
{
|
||||
if (IsAllWhiteRow(bitmap, row))
|
||||
topmost = row;
|
||||
topmost = row + 1;
|
||||
else break;
|
||||
}
|
||||
|
||||
int bottommost = 0;
|
||||
int bottommost = bitmap.Height;
|
||||
for (int row = bitmap.Height - 1; row >= 0; --row)
|
||||
{
|
||||
if (IsAllWhiteRow(bitmap, row))
|
||||
|
@ -138,11 +138,11 @@ namespace Emby.Drawing.Skia
|
|||
else break;
|
||||
}
|
||||
|
||||
int leftmost = 0, rightmost = 0;
|
||||
int leftmost = 0, rightmost = bitmap.Width;
|
||||
for (int col = 0; col < bitmap.Width; ++col)
|
||||
{
|
||||
if (IsAllWhiteColumn(bitmap, col))
|
||||
leftmost = col;
|
||||
leftmost = col + 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
@ -162,13 +162,6 @@ namespace Emby.Drawing.Skia
|
|||
using (var subset = image.Subset(newRect))
|
||||
{
|
||||
return SKBitmap.FromImage(subset);
|
||||
//using (var data = subset.Encode(StripCollageBuilder.GetEncodedFormat(outputPath), 90))
|
||||
//{
|
||||
// using (var fileStream = _fileSystem.GetFileStream(outputPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
|
||||
// {
|
||||
// data.AsStream().CopyTo(fileStream);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -191,7 +184,7 @@ namespace Emby.Drawing.Skia
|
|||
}
|
||||
|
||||
private string[] TransparentImageTypes = new string[] { ".png", ".gif", ".webp" };
|
||||
private SKBitmap Decode(string path, bool forceCleanBitmap = false)
|
||||
private SKBitmap Decode(string path, bool forceCleanBitmap, out SKCodecOrigin origin)
|
||||
{
|
||||
var requiresTransparencyHack = TransparentImageTypes.Contains(Path.GetExtension(path) ?? string.Empty);
|
||||
|
||||
|
@ -206,6 +199,8 @@ namespace Emby.Drawing.Skia
|
|||
// decode
|
||||
codec.GetPixels(bitmap.Info, bitmap.GetPixels());
|
||||
|
||||
origin = codec.Origin;
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
|
@ -214,7 +209,7 @@ namespace Emby.Drawing.Skia
|
|||
|
||||
if (resultBitmap == null)
|
||||
{
|
||||
return Decode(path, true);
|
||||
return Decode(path, true, out origin);
|
||||
}
|
||||
|
||||
// If we have to resize these they often end up distorted
|
||||
|
@ -222,27 +217,128 @@ namespace Emby.Drawing.Skia
|
|||
{
|
||||
using (resultBitmap)
|
||||
{
|
||||
return Decode(path, true);
|
||||
return Decode(path, true, out origin);
|
||||
}
|
||||
}
|
||||
|
||||
origin = SKCodecOrigin.TopLeft;
|
||||
return resultBitmap;
|
||||
}
|
||||
|
||||
private SKBitmap GetBitmap(string path, bool cropWhitespace)
|
||||
private SKBitmap GetBitmap(string path, bool cropWhitespace, bool forceAnalyzeBitmap, out SKCodecOrigin origin)
|
||||
{
|
||||
if (cropWhitespace)
|
||||
{
|
||||
using (var bitmap = Decode(path))
|
||||
using (var bitmap = Decode(path, forceAnalyzeBitmap, out origin))
|
||||
{
|
||||
return CropWhiteSpace(bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
return Decode(path);
|
||||
return Decode(path, forceAnalyzeBitmap, out origin);
|
||||
}
|
||||
|
||||
public string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
|
||||
private SKBitmap GetBitmap(string path, bool cropWhitespace, bool autoOrient, ImageOrientation? orientation)
|
||||
{
|
||||
SKCodecOrigin origin;
|
||||
|
||||
if (autoOrient)
|
||||
{
|
||||
var bitmap = GetBitmap(path, cropWhitespace, true, out origin);
|
||||
|
||||
if (origin != SKCodecOrigin.TopLeft)
|
||||
{
|
||||
using (bitmap)
|
||||
{
|
||||
return RotateAndFlip(bitmap, origin);
|
||||
}
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
return GetBitmap(path, cropWhitespace, false, out origin);
|
||||
}
|
||||
|
||||
private SKBitmap RotateAndFlip(SKBitmap original, SKCodecOrigin origin)
|
||||
{
|
||||
// these are the origins that represent a 90 degree turn in some fashion
|
||||
var differentOrientations = new SKCodecOrigin[]
|
||||
{
|
||||
SKCodecOrigin.LeftBottom,
|
||||
SKCodecOrigin.LeftTop,
|
||||
SKCodecOrigin.RightBottom,
|
||||
SKCodecOrigin.RightTop
|
||||
};
|
||||
|
||||
// check if we need to turn the image
|
||||
bool isDifferentOrientation = differentOrientations.Any(o => o == origin);
|
||||
|
||||
// define new width/height
|
||||
var width = isDifferentOrientation ? original.Height : original.Width;
|
||||
var height = isDifferentOrientation ? original.Width : original.Height;
|
||||
|
||||
var bitmap = new SKBitmap(width, height, true);
|
||||
|
||||
// todo: the stuff in this switch statement should be rewritten to use pointers
|
||||
switch (origin)
|
||||
{
|
||||
case SKCodecOrigin.LeftBottom:
|
||||
|
||||
for (var x = 0; x < original.Width; x++)
|
||||
for (var y = 0; y < original.Height; y++)
|
||||
bitmap.SetPixel(y, original.Width - 1 - x, original.GetPixel(x, y));
|
||||
break;
|
||||
|
||||
case SKCodecOrigin.RightTop:
|
||||
|
||||
for (var x = 0; x < original.Width; x++)
|
||||
for (var y = 0; y < original.Height; y++)
|
||||
bitmap.SetPixel(original.Height - 1 - y, x, original.GetPixel(x, y));
|
||||
break;
|
||||
|
||||
case SKCodecOrigin.RightBottom:
|
||||
|
||||
for (var x = 0; x < original.Width; x++)
|
||||
for (var y = 0; y < original.Height; y++)
|
||||
bitmap.SetPixel(original.Height - 1 - y, original.Width - 1 - x, original.GetPixel(x, y));
|
||||
|
||||
break;
|
||||
|
||||
case SKCodecOrigin.LeftTop:
|
||||
|
||||
for (var x = 0; x < original.Width; x++)
|
||||
for (var y = 0; y < original.Height; y++)
|
||||
bitmap.SetPixel(y, x, original.GetPixel(x, y));
|
||||
break;
|
||||
|
||||
case SKCodecOrigin.BottomLeft:
|
||||
|
||||
for (var x = 0; x < original.Width; x++)
|
||||
for (var y = 0; y < original.Height; y++)
|
||||
bitmap.SetPixel(x, original.Height - 1 - y, original.GetPixel(x, y));
|
||||
break;
|
||||
|
||||
case SKCodecOrigin.BottomRight:
|
||||
|
||||
for (var x = 0; x < original.Width; x++)
|
||||
for (var y = 0; y < original.Height; y++)
|
||||
bitmap.SetPixel(original.Width - 1 - x, original.Height - 1 - y, original.GetPixel(x, y));
|
||||
break;
|
||||
|
||||
case SKCodecOrigin.TopRight:
|
||||
|
||||
for (var x = 0; x < original.Width; x++)
|
||||
for (var y = 0; y < original.Height; y++)
|
||||
bitmap.SetPixel(original.Width - 1 - x, y, original.GetPixel(x, y));
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation? orientation, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(inputPath))
|
||||
{
|
||||
|
@ -260,7 +356,7 @@ namespace Emby.Drawing.Skia
|
|||
var blur = options.Blur ?? 0;
|
||||
var hasIndicator = options.AddPlayedIndicator || options.UnplayedCount.HasValue || !options.PercentPlayed.Equals(0);
|
||||
|
||||
using (var bitmap = GetBitmap(inputPath, options.CropWhiteSpace))
|
||||
using (var bitmap = GetBitmap(inputPath, options.CropWhiteSpace, autoOrient, orientation))
|
||||
{
|
||||
if (bitmap == null)
|
||||
{
|
||||
|
@ -272,7 +368,7 @@ namespace Emby.Drawing.Skia
|
|||
var originalImageSize = new ImageSize(bitmap.Width, bitmap.Height);
|
||||
ImageHelper.SaveImageSize(inputPath, dateModified, originalImageSize);
|
||||
|
||||
if (!options.CropWhiteSpace && options.HasDefaultOptions(inputPath, originalImageSize))
|
||||
if (!options.CropWhiteSpace && options.HasDefaultOptions(inputPath, originalImageSize) && !autoOrient)
|
||||
{
|
||||
// Just spit out the original file if all the options are default
|
||||
return inputPath;
|
||||
|
|
|
@ -217,14 +217,23 @@ namespace Emby.Drawing
|
|||
dateModified = tuple.Item2;
|
||||
}
|
||||
|
||||
if (options.HasDefaultOptions(originalImagePath))
|
||||
var photo = item as Photo;
|
||||
var autoOrient = false;
|
||||
ImageOrientation? orientation = null;
|
||||
if (photo != null && photo.Orientation.HasValue && photo.Orientation.Value != ImageOrientation.TopLeft)
|
||||
{
|
||||
autoOrient = true;
|
||||
orientation = photo.Orientation;
|
||||
}
|
||||
|
||||
if (options.HasDefaultOptions(originalImagePath) && !autoOrient)
|
||||
{
|
||||
// Just spit out the original file if all the options are default
|
||||
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
|
||||
}
|
||||
|
||||
ImageSize? originalImageSize = GetSavedImageSize(originalImagePath, dateModified);
|
||||
if (originalImageSize.HasValue && options.HasDefaultOptions(originalImagePath, originalImageSize.Value))
|
||||
if (originalImageSize.HasValue && options.HasDefaultOptions(originalImagePath, originalImageSize.Value) && !autoOrient)
|
||||
{
|
||||
// Just spit out the original file if all the options are default
|
||||
_logger.Info("Returning original image {0}", originalImagePath);
|
||||
|
@ -243,7 +252,6 @@ namespace Emby.Drawing
|
|||
|
||||
if (!_fileSystem.FileExists(cacheFilePath))
|
||||
{
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFilePath));
|
||||
var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(cacheFilePath));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
|
||||
|
||||
|
@ -252,13 +260,14 @@ namespace Emby.Drawing
|
|||
item = _libraryManager().GetItemById(options.ItemId);
|
||||
}
|
||||
|
||||
var resultPath =_imageEncoder.EncodeImage(originalImagePath, dateModified, tmpPath, AutoOrient(item), quality, options, outputFormat);
|
||||
var resultPath = _imageEncoder.EncodeImage(originalImagePath, dateModified, tmpPath, autoOrient, orientation, quality, options, outputFormat);
|
||||
|
||||
if (string.Equals(resultPath, originalImagePath, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
|
||||
}
|
||||
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFilePath));
|
||||
CopyFile(tmpPath, cacheFilePath);
|
||||
|
||||
return new Tuple<string, string, DateTime>(tmpPath, GetMimeType(outputFormat, cacheFilePath), _fileSystem.GetLastWriteTimeUtc(tmpPath));
|
||||
|
@ -288,17 +297,6 @@ namespace Emby.Drawing
|
|||
}
|
||||
}
|
||||
|
||||
private bool AutoOrient(IHasImages item)
|
||||
{
|
||||
var photo = item as Photo;
|
||||
if (photo != null && photo.Orientation.HasValue)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//private static int[][] OPERATIONS = new int[][] {
|
||||
// TopLeft
|
||||
//new int[] { 0, NONE},
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace Emby.Drawing
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
|
||||
public string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation? orientation, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"frameworks":{
|
||||
"netstandard1.6":{
|
||||
"dependencies":{
|
||||
"NETStandard.Library":"1.6.0",
|
||||
}
|
||||
},
|
||||
".NETPortable,Version=v4.5,Profile=Profile7":{
|
||||
"buildOptions": {
|
||||
"define": [ ]
|
||||
},
|
||||
"frameworkAssemblies":{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"frameworks":{
|
||||
"netstandard1.6":{
|
||||
"dependencies":{
|
||||
"NETStandard.Library":"1.6.0",
|
||||
}
|
||||
},
|
||||
".NETPortable,Version=v4.5,Profile=Profile7":{
|
||||
"buildOptions": {
|
||||
"define": [ ]
|
||||
},
|
||||
"frameworkAssemblies":{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -41,9 +41,8 @@
|
|||
<HintPath>..\packages\ServiceStack.Text.4.5.8\lib\net45\ServiceStack.Text.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="SimpleInjector, Version=4.0.7.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SimpleInjector.4.0.7\lib\net45\SimpleInjector.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="SimpleInjector, Version=4.0.8.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SimpleInjector.4.0.8\lib\net45\SimpleInjector.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
|
|
|
@ -332,7 +332,13 @@ namespace Emby.Server.Core.IO
|
|||
NotifyFilters.Attributes;
|
||||
|
||||
newWatcher.Created += watcher_Changed;
|
||||
|
||||
// Seeing mono crashes on background threads we can't catch, testing if this might help
|
||||
if (_environmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows)
|
||||
{
|
||||
newWatcher.Deleted += watcher_Changed;
|
||||
}
|
||||
|
||||
newWatcher.Renamed += watcher_Changed;
|
||||
newWatcher.Changed += watcher_Changed;
|
||||
|
||||
|
|
|
@ -2,5 +2,5 @@
|
|||
<packages>
|
||||
<package id="Microsoft.IO.RecyclableMemoryStream" version="1.2.2" targetFramework="net462" />
|
||||
<package id="ServiceStack.Text" version="4.5.8" targetFramework="net462" />
|
||||
<package id="SimpleInjector" version="4.0.7" targetFramework="net462" />
|
||||
<package id="SimpleInjector" version="4.0.8" targetFramework="net46" />
|
||||
</packages>
|
|
@ -123,7 +123,7 @@ namespace Emby.Server.Implementations.Activity
|
|||
return;
|
||||
}
|
||||
|
||||
if (item.IsThemeMedia)
|
||||
if (e.Item != null && e.Item.IsThemeMedia)
|
||||
{
|
||||
// Don't report theme song or local trailer playback
|
||||
return;
|
||||
|
@ -155,7 +155,7 @@ namespace Emby.Server.Implementations.Activity
|
|||
return;
|
||||
}
|
||||
|
||||
if (item.IsThemeMedia)
|
||||
if (e.Item != null && e.Item.IsThemeMedia)
|
||||
{
|
||||
// Don't report theme song or local trailer playback
|
||||
return;
|
||||
|
|
|
@ -176,7 +176,9 @@ namespace Emby.Server.Implementations.Channels
|
|||
|
||||
var internalResult = await GetChannelsInternal(query, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var dtoOptions = new DtoOptions();
|
||||
var dtoOptions = new DtoOptions()
|
||||
{
|
||||
};
|
||||
|
||||
var returnItems = (await _dtoService.GetBaseItemDtos(internalResult.Items, dtoOptions, user).ConfigureAwait(false))
|
||||
.ToArray();
|
||||
|
@ -558,7 +560,10 @@ namespace Emby.Server.Implementations.Channels
|
|||
totalRecordCount = items.Length;
|
||||
}
|
||||
|
||||
var dtoOptions = new DtoOptions();
|
||||
var dtoOptions = new DtoOptions()
|
||||
{
|
||||
Fields = query.Fields.ToList()
|
||||
};
|
||||
|
||||
var returnItems = (await _dtoService.GetBaseItemDtos(items, dtoOptions, user).ConfigureAwait(false))
|
||||
.ToArray();
|
||||
|
@ -825,7 +830,10 @@ namespace Emby.Server.Implementations.Channels
|
|||
|
||||
RefreshIfNeeded(internalResult.Items);
|
||||
|
||||
var dtoOptions = new DtoOptions();
|
||||
var dtoOptions = new DtoOptions()
|
||||
{
|
||||
Fields = query.Fields.ToList()
|
||||
};
|
||||
|
||||
var returnItems = (await _dtoService.GetBaseItemDtos(internalResult.Items, dtoOptions, user).ConfigureAwait(false))
|
||||
.ToArray();
|
||||
|
@ -974,7 +982,10 @@ namespace Emby.Server.Implementations.Channels
|
|||
|
||||
var internalResult = await GetChannelItemsInternal(query, new Progress<double>(), cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var dtoOptions = new DtoOptions();
|
||||
var dtoOptions = new DtoOptions()
|
||||
{
|
||||
Fields = query.Fields.ToList()
|
||||
};
|
||||
|
||||
var returnItems = (await _dtoService.GetBaseItemDtos(internalResult.Items, dtoOptions, user).ConfigureAwait(false))
|
||||
.ToArray();
|
||||
|
@ -1378,12 +1389,6 @@ namespace Emby.Server.Implementations.Channels
|
|||
item.SetImagePath(ImageType.Primary, info.ImageUrl);
|
||||
}
|
||||
|
||||
if (item.SourceType != SourceType.Channel)
|
||||
{
|
||||
item.SourceType = SourceType.Channel;
|
||||
forceUpdate = true;
|
||||
}
|
||||
|
||||
if (isNew)
|
||||
{
|
||||
await _libraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
|
||||
|
|
|
@ -199,10 +199,11 @@ namespace Emby.Server.Implementations.Data
|
|||
AddColumn(db, "TypedBaseItems", "ParentId", "GUID", existingColumnNames);
|
||||
AddColumn(db, "TypedBaseItems", "Genres", "Text", existingColumnNames);
|
||||
AddColumn(db, "TypedBaseItems", "SortName", "Text", existingColumnNames);
|
||||
AddColumn(db, "TypedBaseItems", "ForcedSortName", "Text", existingColumnNames);
|
||||
|
||||
AddColumn(db, "TypedBaseItems", "RunTimeTicks", "BIGINT", existingColumnNames);
|
||||
|
||||
AddColumn(db, "TypedBaseItems", "HomePageUrl", "Text", existingColumnNames);
|
||||
AddColumn(db, "TypedBaseItems", "VoteCount", "INT", existingColumnNames);
|
||||
AddColumn(db, "TypedBaseItems", "DisplayMediaType", "Text", existingColumnNames);
|
||||
AddColumn(db, "TypedBaseItems", "DateCreated", "DATETIME", existingColumnNames);
|
||||
AddColumn(db, "TypedBaseItems", "DateModified", "DATETIME", existingColumnNames);
|
||||
|
@ -233,7 +234,6 @@ namespace Emby.Server.Implementations.Data
|
|||
AddColumn(db, "TypedBaseItems", "UnratedType", "Text", existingColumnNames);
|
||||
AddColumn(db, "TypedBaseItems", "TopParentId", "Text", existingColumnNames);
|
||||
AddColumn(db, "TypedBaseItems", "IsItemByName", "BIT", existingColumnNames);
|
||||
AddColumn(db, "TypedBaseItems", "SourceType", "Text", existingColumnNames);
|
||||
AddColumn(db, "TypedBaseItems", "TrailerTypes", "Text", existingColumnNames);
|
||||
AddColumn(db, "TypedBaseItems", "CriticRating", "Float", existingColumnNames);
|
||||
AddColumn(db, "TypedBaseItems", "InheritedTags", "Text", existingColumnNames);
|
||||
|
@ -424,9 +424,8 @@ namespace Emby.Server.Implementations.Data
|
|||
"OfficialRating",
|
||||
"HomePageUrl",
|
||||
"DisplayMediaType",
|
||||
"SortName",
|
||||
"ForcedSortName",
|
||||
"RunTimeTicks",
|
||||
"VoteCount",
|
||||
"DateCreated",
|
||||
"DateModified",
|
||||
"guid",
|
||||
|
@ -439,7 +438,6 @@ namespace Emby.Server.Implementations.Data
|
|||
"LockedFields",
|
||||
"Studios",
|
||||
"Tags",
|
||||
"SourceType",
|
||||
"TrailerTypes",
|
||||
"OriginalTitle",
|
||||
"PrimaryVersionId",
|
||||
|
@ -541,9 +539,9 @@ namespace Emby.Server.Implementations.Data
|
|||
"Genres",
|
||||
"InheritedParentalRatingValue",
|
||||
"SortName",
|
||||
"ForcedSortName",
|
||||
"RunTimeTicks",
|
||||
"HomePageUrl",
|
||||
"VoteCount",
|
||||
"DisplayMediaType",
|
||||
"DateCreated",
|
||||
"DateModified",
|
||||
|
@ -563,7 +561,6 @@ namespace Emby.Server.Implementations.Data
|
|||
"UnratedType",
|
||||
"TopParentId",
|
||||
"IsItemByName",
|
||||
"SourceType",
|
||||
"TrailerTypes",
|
||||
"CriticRating",
|
||||
"InheritedTags",
|
||||
|
@ -815,10 +812,12 @@ namespace Emby.Server.Implementations.Data
|
|||
saveItemStatement.TryBind("@InheritedParentalRatingValue", item.InheritedParentalRatingValue);
|
||||
|
||||
saveItemStatement.TryBind("@SortName", item.SortName);
|
||||
|
||||
saveItemStatement.TryBind("@ForcedSortName", item.ForcedSortName);
|
||||
|
||||
saveItemStatement.TryBind("@RunTimeTicks", item.RunTimeTicks);
|
||||
|
||||
saveItemStatement.TryBind("@HomePageUrl", item.HomePageUrl);
|
||||
saveItemStatement.TryBind("@VoteCount", item.VoteCount);
|
||||
saveItemStatement.TryBind("@DisplayMediaType", item.DisplayMediaType);
|
||||
saveItemStatement.TryBind("@DateCreated", item.DateCreated);
|
||||
saveItemStatement.TryBind("@DateModified", item.DateModified);
|
||||
|
@ -909,7 +908,6 @@ namespace Emby.Server.Implementations.Data
|
|||
isByName = dualAccess == null || dualAccess.IsAccessedByName;
|
||||
}
|
||||
saveItemStatement.TryBind("@IsItemByName", isByName);
|
||||
saveItemStatement.TryBind("@SourceType", item.SourceType.ToString());
|
||||
|
||||
var trailer = item as Trailer;
|
||||
if (trailer != null && trailer.TrailerTypes.Count > 0)
|
||||
|
@ -1624,7 +1622,7 @@ namespace Emby.Server.Implementations.Data
|
|||
{
|
||||
if (!reader.IsDBNull(index))
|
||||
{
|
||||
item.SortName = reader.GetString(index);
|
||||
item.ForcedSortName = reader.GetString(index);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
@ -1635,15 +1633,6 @@ namespace Emby.Server.Implementations.Data
|
|||
}
|
||||
index++;
|
||||
|
||||
if (HasField(query, ItemFields.VoteCount))
|
||||
{
|
||||
if (!reader.IsDBNull(index))
|
||||
{
|
||||
item.VoteCount = reader.GetInt32(index);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
if (HasField(query, ItemFields.DateCreated))
|
||||
{
|
||||
if (!reader.IsDBNull(index))
|
||||
|
@ -1733,12 +1722,6 @@ namespace Emby.Server.Implementations.Data
|
|||
index++;
|
||||
}
|
||||
|
||||
if (!reader.IsDBNull(index))
|
||||
{
|
||||
item.SourceType = (SourceType)Enum.Parse(typeof(SourceType), reader.GetString(index), true);
|
||||
}
|
||||
index++;
|
||||
|
||||
if (hasTrailerTypes)
|
||||
{
|
||||
var trailer = item as Trailer;
|
||||
|
@ -2283,7 +2266,7 @@ namespace Emby.Server.Implementations.Data
|
|||
}
|
||||
if (field == ItemFields.SortName)
|
||||
{
|
||||
return new[] { "SortName" };
|
||||
return new[] { "ForcedSortName" };
|
||||
}
|
||||
if (field == ItemFields.Taglines)
|
||||
{
|
||||
|
@ -2306,7 +2289,6 @@ namespace Emby.Server.Implementations.Data
|
|||
case ItemFields.HomePageUrl:
|
||||
case ItemFields.Keywords:
|
||||
case ItemFields.DisplayMediaType:
|
||||
case ItemFields.VoteCount:
|
||||
case ItemFields.CustomRating:
|
||||
case ItemFields.ProductionLocations:
|
||||
case ItemFields.Settings:
|
||||
|
@ -3872,34 +3854,6 @@ namespace Emby.Server.Implementations.Data
|
|||
}
|
||||
}
|
||||
|
||||
if (query.SourceTypes.Length == 1)
|
||||
{
|
||||
whereClauses.Add("SourceType=@SourceType");
|
||||
if (statement != null)
|
||||
{
|
||||
statement.TryBind("@SourceType", query.SourceTypes[0].ToString());
|
||||
}
|
||||
}
|
||||
else if (query.SourceTypes.Length > 1)
|
||||
{
|
||||
var inClause = string.Join(",", query.SourceTypes.Select(i => "'" + i + "'").ToArray());
|
||||
whereClauses.Add(string.Format("SourceType in ({0})", inClause));
|
||||
}
|
||||
|
||||
if (query.ExcludeSourceTypes.Length == 1)
|
||||
{
|
||||
whereClauses.Add("SourceType<>@ExcludeSourceTypes");
|
||||
if (statement != null)
|
||||
{
|
||||
statement.TryBind("@ExcludeSourceTypes", query.ExcludeSourceTypes[0].ToString());
|
||||
}
|
||||
}
|
||||
else if (query.ExcludeSourceTypes.Length > 1)
|
||||
{
|
||||
var inClause = string.Join(",", query.ExcludeSourceTypes.Select(i => "'" + i + "'").ToArray());
|
||||
whereClauses.Add(string.Format("SourceType not in ({0})", inClause));
|
||||
}
|
||||
|
||||
if (query.TrailerTypes.Length > 0)
|
||||
{
|
||||
var clauses = new List<string>();
|
||||
|
@ -5017,14 +4971,6 @@ namespace Emby.Server.Implementations.Data
|
|||
statement.TryBind("@NameContains", "%" + query.NameContains + "%");
|
||||
}
|
||||
}
|
||||
if (query.SourceTypes.Length == 1)
|
||||
{
|
||||
whereClauses.Add("(select sourcetype from typedbaseitems where guid=ItemId) = @SourceTypes");
|
||||
if (statement != null)
|
||||
{
|
||||
statement.TryBind("@SourceTypes", query.SourceTypes[0].ToString());
|
||||
}
|
||||
}
|
||||
|
||||
return whereClauses;
|
||||
}
|
||||
|
|
|
@ -1058,11 +1058,6 @@ namespace Emby.Server.Implementations.Dto
|
|||
dto.CommunityRating = item.CommunityRating;
|
||||
}
|
||||
|
||||
if (fields.Contains(ItemFields.VoteCount))
|
||||
{
|
||||
dto.VoteCount = item.VoteCount;
|
||||
}
|
||||
|
||||
//if (item.IsFolder)
|
||||
//{
|
||||
// var folder = (Folder)item;
|
||||
|
@ -1084,7 +1079,10 @@ namespace Emby.Server.Implementations.Dto
|
|||
if (audio != null)
|
||||
{
|
||||
dto.Album = audio.Album;
|
||||
dto.ExtraType = audio.ExtraType;
|
||||
if (audio.ExtraType.HasValue)
|
||||
{
|
||||
dto.ExtraType = audio.ExtraType.Value.ToString();
|
||||
}
|
||||
|
||||
var albumParent = audio.AlbumEntity;
|
||||
|
||||
|
@ -1239,7 +1237,10 @@ namespace Emby.Server.Implementations.Dto
|
|||
dto.Chapters = GetChapterInfoDtos(item);
|
||||
}
|
||||
|
||||
dto.ExtraType = video.ExtraType;
|
||||
if (video.ExtraType.HasValue)
|
||||
{
|
||||
dto.ExtraType = video.ExtraType.Value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
if (fields.Contains(ItemFields.MediaStreams))
|
||||
|
@ -1395,7 +1396,7 @@ namespace Emby.Server.Implementations.Dto
|
|||
}
|
||||
}
|
||||
|
||||
if (fields.Contains(ItemFields.SeriesPrimaryImage))
|
||||
//if (fields.Contains(ItemFields.SeriesPrimaryImage))
|
||||
{
|
||||
series = series ?? season.Series;
|
||||
if (series != null)
|
||||
|
@ -1586,7 +1587,7 @@ namespace Emby.Server.Implementations.Dto
|
|||
{
|
||||
var imageInfo = item.GetImageInfo(ImageType.Primary, 0);
|
||||
|
||||
if (imageInfo == null || !imageInfo.IsLocalFile)
|
||||
if (imageInfo == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
@ -1610,6 +1611,11 @@ namespace Emby.Server.Implementations.Dto
|
|||
}
|
||||
else
|
||||
{
|
||||
if (!imageInfo.IsLocalFile)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
size = _imageProcessor.GetImageSize(imageInfo);
|
||||
|
|
|
@ -31,6 +31,9 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\SharedVersion.cs">
|
||||
<Link>Properties\SharedVersion.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="Activity\ActivityLogEntryPoint.cs" />
|
||||
<Compile Include="Activity\ActivityManager.cs" />
|
||||
<Compile Include="Activity\ActivityRepository.cs" />
|
||||
|
|
|
@ -38,7 +38,10 @@ namespace Emby.Server.Implementations.Library
|
|||
// Synology
|
||||
"@eaDir",
|
||||
"eaDir",
|
||||
"#recycle"
|
||||
"#recycle",
|
||||
|
||||
// Qnap
|
||||
"@Recycle"
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -1292,7 +1292,7 @@ namespace Emby.Server.Implementations.Library
|
|||
return item;
|
||||
}
|
||||
|
||||
public IEnumerable<BaseItem> GetItemList(InternalItemsQuery query)
|
||||
public IEnumerable<BaseItem> GetItemList(InternalItemsQuery query, bool allowExternalContent)
|
||||
{
|
||||
if (query.Recursive && query.ParentId.HasValue)
|
||||
{
|
||||
|
@ -1305,12 +1305,17 @@ namespace Emby.Server.Implementations.Library
|
|||
|
||||
if (query.User != null)
|
||||
{
|
||||
AddUserToQuery(query, query.User);
|
||||
AddUserToQuery(query, query.User, allowExternalContent);
|
||||
}
|
||||
|
||||
return ItemRepository.GetItemList(query);
|
||||
}
|
||||
|
||||
public IEnumerable<BaseItem> GetItemList(InternalItemsQuery query)
|
||||
{
|
||||
return GetItemList(query, true);
|
||||
}
|
||||
|
||||
public int GetCount(InternalItemsQuery query)
|
||||
{
|
||||
if (query.Recursive && query.ParentId.HasValue)
|
||||
|
@ -1548,7 +1553,7 @@ namespace Emby.Server.Implementations.Library
|
|||
query.Parent = null;
|
||||
}
|
||||
|
||||
private void AddUserToQuery(InternalItemsQuery query, User user)
|
||||
private void AddUserToQuery(InternalItemsQuery query, User user, bool allowExternalContent = true)
|
||||
{
|
||||
if (query.AncestorIds.Length == 0 &&
|
||||
!query.ParentId.HasValue &&
|
||||
|
@ -1561,7 +1566,8 @@ namespace Emby.Server.Implementations.Library
|
|||
var userViews = _userviewManager().GetUserViews(new UserViewQuery
|
||||
{
|
||||
UserId = user.Id.ToString("N"),
|
||||
IncludeHidden = true
|
||||
IncludeHidden = true,
|
||||
IncludeExternalContent = allowExternalContent
|
||||
|
||||
}, CancellationToken.None).Result.ToList();
|
||||
|
||||
|
|
|
@ -202,8 +202,7 @@ namespace Emby.Server.Implementations.Library
|
|||
|
||||
private bool IsValidUsernameCharacter(char i)
|
||||
{
|
||||
return char.IsLetterOrDigit(i) || char.Equals(i, '-') || char.Equals(i, '_') || char.Equals(i, '\'') ||
|
||||
char.Equals(i, '.');
|
||||
return !char.Equals(i, '<') && !char.Equals(i, '>');
|
||||
}
|
||||
|
||||
public string MakeValidUsername(string username)
|
||||
|
|
|
@ -280,7 +280,7 @@ namespace Emby.Server.Implementations.Library
|
|||
|
||||
} : new string[] { };
|
||||
|
||||
return _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||
var query = new InternalItemsQuery(user)
|
||||
{
|
||||
IncludeItemTypes = includeItemTypes,
|
||||
SortOrder = SortOrder.Descending,
|
||||
|
@ -289,11 +289,16 @@ namespace Emby.Server.Implementations.Library
|
|||
ExcludeItemTypes = excludeItemTypes,
|
||||
IsVirtualItem = false,
|
||||
Limit = limit * 5,
|
||||
SourceTypes = parents.Count == 0 ? new[] { SourceType.Library } : new SourceType[] { },
|
||||
IsPlayed = isPlayed,
|
||||
DtoOptions = options
|
||||
};
|
||||
|
||||
}, parents);
|
||||
if (parents.Count == 0)
|
||||
{
|
||||
return _libraryManager.GetItemList(query, false);
|
||||
}
|
||||
|
||||
return _libraryManager.GetItemList(query, parents);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2270,11 +2270,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
writer.WriteElementString("studio", studio);
|
||||
}
|
||||
|
||||
if (item.VoteCount.HasValue)
|
||||
{
|
||||
writer.WriteElementString("votes", item.VoteCount.Value.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
writer.WriteEndElement();
|
||||
writer.WriteEndDocument();
|
||||
}
|
||||
|
|
|
@ -136,6 +136,9 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||
var requestBody = "[\"" + string.Join("\", \"", programsID) + "\"]";
|
||||
httpOptions.RequestContent = requestBody;
|
||||
|
||||
double wideAspect = 1.77777778;
|
||||
var primaryImageCategory = "Logo";
|
||||
|
||||
using (var innerResponse = await Post(httpOptions, true, info).ConfigureAwait(false))
|
||||
{
|
||||
StreamReader innerReader = new StreamReader(innerResponse.Content);
|
||||
|
@ -167,13 +170,25 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||
{
|
||||
var programEntry = programDict[schedule.programID];
|
||||
|
||||
var allImages = (images[imageIndex].data ?? new List<ScheduleDirect.ImageData>()).OrderByDescending(GetSizeOrder).ToList();
|
||||
var allImages = (images[imageIndex].data ?? new List<ScheduleDirect.ImageData>()).ToList();
|
||||
var imagesWithText = allImages.Where(i => string.Equals(i.text, "yes", StringComparison.OrdinalIgnoreCase)).ToList();
|
||||
var imagesWithoutText = allImages.Where(i => string.Equals(i.text, "no", StringComparison.OrdinalIgnoreCase)).ToList();
|
||||
|
||||
programEntry.primaryImage = GetProgramImage(ApiUrl, imagesWithText, "Logo", true, 600) ??
|
||||
GetProgramImage(ApiUrl, allImages, "Logo", true, 600);
|
||||
double desiredAspect = IsMovie(programEntry) ? 0.666666667 : wideAspect;
|
||||
|
||||
programEntry.primaryImage = GetProgramImage(ApiUrl, imagesWithText, true, desiredAspect) ??
|
||||
GetProgramImage(ApiUrl, allImages, true, desiredAspect);
|
||||
|
||||
programEntry.thumbImage = GetProgramImage(ApiUrl, imagesWithText, true, wideAspect);
|
||||
|
||||
// Don't supply the same image twice
|
||||
if (string.Equals(programEntry.primaryImage, programEntry.thumbImage, StringComparison.Ordinal))
|
||||
{
|
||||
programEntry.thumbImage = null;
|
||||
}
|
||||
|
||||
programEntry.backdropImage = GetProgramImage(ApiUrl, imagesWithoutText, true, wideAspect);
|
||||
|
||||
//programEntry.thumbImage = GetProgramImage(ApiUrl, data, "Iconic", false);
|
||||
//programEntry.bannerImage = GetProgramImage(ApiUrl, data, "Banner", false) ??
|
||||
// GetProgramImage(ApiUrl, data, "Banner-L1", false) ??
|
||||
// GetProgramImage(ApiUrl, data, "Banner-LO", false) ??
|
||||
|
@ -220,9 +235,14 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||
return channelNumber;
|
||||
}
|
||||
|
||||
private bool IsMovie(ScheduleDirect.ProgramDetails programInfo)
|
||||
{
|
||||
var showType = programInfo.showType ?? string.Empty;
|
||||
return showType.IndexOf("movie", StringComparison.OrdinalIgnoreCase) != -1 || showType.IndexOf("film", StringComparison.OrdinalIgnoreCase) != -1;
|
||||
}
|
||||
|
||||
private ProgramInfo GetProgram(string channelId, ScheduleDirect.Program programInfo, ScheduleDirect.ProgramDetails details)
|
||||
{
|
||||
//_logger.Debug("Show type is: " + (details.showType ?? "No ShowType"));
|
||||
DateTime startAt = GetDate(programInfo.airDateTime);
|
||||
DateTime endAt = startAt.AddSeconds(programInfo.duration);
|
||||
ProgramAudio audioType = ProgramAudio.Stereo;
|
||||
|
@ -276,9 +296,10 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||
IsRepeat = repeat,
|
||||
IsSeries = showType.IndexOf("series", StringComparison.OrdinalIgnoreCase) != -1,
|
||||
ImageUrl = details.primaryImage,
|
||||
ThumbImageUrl = details.thumbImage,
|
||||
IsKids = string.Equals(details.audience, "children", StringComparison.OrdinalIgnoreCase),
|
||||
IsSports = showType.IndexOf("sports", StringComparison.OrdinalIgnoreCase) != -1,
|
||||
IsMovie = showType.IndexOf("movie", StringComparison.OrdinalIgnoreCase) != -1 || showType.IndexOf("film", StringComparison.OrdinalIgnoreCase) != -1,
|
||||
IsMovie = IsMovie(details),
|
||||
Etag = programInfo.md5
|
||||
};
|
||||
|
||||
|
@ -378,49 +399,18 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||
return date;
|
||||
}
|
||||
|
||||
private string GetProgramImage(string apiUrl, List<ScheduleDirect.ImageData> images, string category, bool returnDefaultImage, int desiredWidth)
|
||||
private string GetProgramImage(string apiUrl, List<ScheduleDirect.ImageData> images, bool returnDefaultImage, double desiredAspect)
|
||||
{
|
||||
string url = null;
|
||||
|
||||
var matches = images
|
||||
.Where(i => string.Equals(i.category, category, StringComparison.OrdinalIgnoreCase))
|
||||
var matches = images;
|
||||
|
||||
matches = matches
|
||||
.OrderBy(i => Math.Abs(desiredAspect - GetApsectRatio(i)))
|
||||
.ThenByDescending(GetSizeOrder)
|
||||
.ToList();
|
||||
|
||||
if (matches.Count == 0)
|
||||
{
|
||||
if (!returnDefaultImage)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
matches = images;
|
||||
}
|
||||
|
||||
var match = matches.FirstOrDefault(i =>
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(i.width))
|
||||
{
|
||||
int value;
|
||||
if (int.TryParse(i.width, out value))
|
||||
{
|
||||
return value <= desiredWidth;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
if (match == null)
|
||||
{
|
||||
// Get the second lowest quality image, when possible
|
||||
if (matches.Count > 1)
|
||||
{
|
||||
match = matches[matches.Count - 2];
|
||||
}
|
||||
else
|
||||
{
|
||||
match = matches.FirstOrDefault();
|
||||
}
|
||||
}
|
||||
var match = matches.FirstOrDefault();
|
||||
|
||||
if (match == null)
|
||||
{
|
||||
|
@ -444,6 +434,31 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||
return url;
|
||||
}
|
||||
|
||||
private double GetApsectRatio(ScheduleDirect.ImageData i)
|
||||
{
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(i.width))
|
||||
{
|
||||
int.TryParse(i.width, out width);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(i.height))
|
||||
{
|
||||
int.TryParse(i.height, out height);
|
||||
}
|
||||
|
||||
if (height == 0 || width == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
double result = width;
|
||||
result /= height;
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<List<ScheduleDirect.ShowImages>> GetImageForPrograms(
|
||||
ListingsProviderInfo info,
|
||||
List<string> programIds,
|
||||
|
@ -1188,6 +1203,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||
public bool hasImageArtwork { get; set; }
|
||||
public string primaryImage { get; set; }
|
||||
public string thumbImage { get; set; }
|
||||
public string backdropImage { get; set; }
|
||||
public string bannerImage { get; set; }
|
||||
public string imageID { get; set; }
|
||||
public string md5 { get; set; }
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||
private readonly IMediaEncoder _mediaEncoder;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
const int AnalyzeDurationMs = 2000;
|
||||
const int AnalyzeDurationMs = 1000;
|
||||
|
||||
public LiveStreamHelper(IMediaEncoder mediaEncoder, ILogger logger)
|
||||
{
|
||||
|
|
|
@ -679,8 +679,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||
item.SetImage(new ItemImageInfo
|
||||
{
|
||||
Path = info.ImagePath,
|
||||
Type = ImageType.Primary,
|
||||
IsPlaceholder = true
|
||||
Type = ImageType.Primary
|
||||
}, 0);
|
||||
}
|
||||
else if (!string.IsNullOrWhiteSpace(info.ImageUrl))
|
||||
|
@ -688,8 +687,46 @@ namespace Emby.Server.Implementations.LiveTv
|
|||
item.SetImage(new ItemImageInfo
|
||||
{
|
||||
Path = info.ImageUrl,
|
||||
Type = ImageType.Primary,
|
||||
IsPlaceholder = true
|
||||
Type = ImageType.Primary
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!item.HasImage(ImageType.Thumb))
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(info.ThumbImageUrl))
|
||||
{
|
||||
item.SetImage(new ItemImageInfo
|
||||
{
|
||||
Path = info.ThumbImageUrl,
|
||||
Type = ImageType.Thumb
|
||||
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!item.HasImage(ImageType.Logo))
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(info.LogoImageUrl))
|
||||
{
|
||||
item.SetImage(new ItemImageInfo
|
||||
{
|
||||
Path = info.LogoImageUrl,
|
||||
Type = ImageType.Logo
|
||||
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!item.HasImage(ImageType.Backdrop))
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(info.BackdropImageUrl))
|
||||
{
|
||||
item.SetImage(new ItemImageInfo
|
||||
{
|
||||
Path = info.BackdropImageUrl,
|
||||
Type = ImageType.Backdrop
|
||||
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -422,6 +422,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
|||
SupportsTranscoding = true,
|
||||
IsInfiniteStream = true,
|
||||
IgnoreDts = true,
|
||||
//SupportsProbing = false,
|
||||
//AnalyzeDurationMs = 2000000
|
||||
//IgnoreIndex = true,
|
||||
//ReadAtNativeFramerate = true
|
||||
};
|
||||
|
|
|
@ -117,7 +117,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
|||
}
|
||||
else
|
||||
{
|
||||
await _multicastStream.CopyUntilCancelled(response.Content, () => Resolve(openTaskCompletionSource), cancellationToken).ConfigureAwait(false);
|
||||
Resolve(openTaskCompletionSource);
|
||||
|
||||
await _multicastStream.CopyUntilCancelled(response.Content, null, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -234,6 +234,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||
numberString = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
numberString = Path.GetFileNameWithoutExtension(mediaUrl.Split('/').Last());
|
||||
|
||||
|
@ -242,6 +244,12 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||
numberString = null;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Seeing occasional argument exception here
|
||||
numberString = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return numberString;
|
||||
|
|
|
@ -23,6 +23,7 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Model.Threading;
|
||||
using MediaBrowser.Model.Dto;
|
||||
|
||||
namespace Emby.Server.Implementations.Notifications
|
||||
{
|
||||
|
@ -260,7 +261,7 @@ namespace Emby.Server.Implementations.Notifications
|
|||
|
||||
var item = e.MediaInfo;
|
||||
|
||||
if ( item.IsThemeMedia)
|
||||
if (e.Item != null && e.Item.IsThemeMedia)
|
||||
{
|
||||
// Don't report theme song or local trailer playback
|
||||
return;
|
||||
|
@ -430,7 +431,7 @@ namespace Emby.Server.Implementations.Notifications
|
|||
return name;
|
||||
}
|
||||
|
||||
public static string GetItemName(BaseItemInfo item)
|
||||
public static string GetItemName(BaseItemDto item)
|
||||
{
|
||||
var name = item.Name;
|
||||
|
||||
|
|
|
@ -26,5 +26,3 @@ using System.Runtime.InteropServices;
|
|||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
|
|
@ -338,7 +338,7 @@ namespace Emby.Server.Implementations.Session
|
|||
}
|
||||
}
|
||||
|
||||
info.Item = GetItemInfo(libraryItem, libraryItem, mediaSource);
|
||||
info.Item = GetItemInfo(libraryItem, mediaSource);
|
||||
|
||||
info.Item.RunTimeTicks = runtimeTicks;
|
||||
}
|
||||
|
@ -813,7 +813,7 @@ namespace Emby.Server.Implementations.Session
|
|||
mediaSource = await GetMediaSource(hasMediaSources, info.MediaSourceId, info.LiveStreamId).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
info.Item = GetItemInfo(libraryItem, libraryItem, mediaSource);
|
||||
info.Item = GetItemInfo(libraryItem, mediaSource);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1637,165 +1637,65 @@ namespace Emby.Server.Implementations.Session
|
|||
return dto;
|
||||
}
|
||||
|
||||
private DtoOptions _itemInfoDtoOptions;
|
||||
|
||||
/// <summary>
|
||||
/// Converts a BaseItem to a BaseItemInfo
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="chapterOwner">The chapter owner.</param>
|
||||
/// <param name="mediaSource">The media source.</param>
|
||||
/// <returns>BaseItemInfo.</returns>
|
||||
/// <exception cref="System.ArgumentNullException">item</exception>
|
||||
private BaseItemInfo GetItemInfo(BaseItem item, BaseItem chapterOwner, MediaSourceInfo mediaSource)
|
||||
private BaseItemDto GetItemInfo(BaseItem item, MediaSourceInfo mediaSource)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException("item");
|
||||
}
|
||||
|
||||
var info = new BaseItemInfo
|
||||
var dtoOptions = _itemInfoDtoOptions;
|
||||
|
||||
if (_itemInfoDtoOptions == null)
|
||||
{
|
||||
Id = GetDtoId(item),
|
||||
Name = item.Name,
|
||||
MediaType = item.MediaType,
|
||||
Type = item.GetClientTypeName(),
|
||||
RunTimeTicks = item.RunTimeTicks,
|
||||
IndexNumber = item.IndexNumber,
|
||||
ParentIndexNumber = item.ParentIndexNumber,
|
||||
PremiereDate = item.PremiereDate,
|
||||
ProductionYear = item.ProductionYear,
|
||||
IsThemeMedia = item.IsThemeMedia
|
||||
dtoOptions = new DtoOptions
|
||||
{
|
||||
AddProgramRecordingInfo = false
|
||||
};
|
||||
|
||||
info.PrimaryImageTag = GetImageCacheTag(item, ImageType.Primary);
|
||||
if (info.PrimaryImageTag != null)
|
||||
{
|
||||
info.PrimaryImageItemId = GetDtoId(item);
|
||||
dtoOptions.Fields.Remove(ItemFields.BasicSyncInfo);
|
||||
dtoOptions.Fields.Remove(ItemFields.SyncInfo);
|
||||
dtoOptions.Fields.Remove(ItemFields.CanDelete);
|
||||
dtoOptions.Fields.Remove(ItemFields.CanDownload);
|
||||
dtoOptions.Fields.Remove(ItemFields.ChildCount);
|
||||
dtoOptions.Fields.Remove(ItemFields.CustomRating);
|
||||
dtoOptions.Fields.Remove(ItemFields.DateLastMediaAdded);
|
||||
dtoOptions.Fields.Remove(ItemFields.DateLastRefreshed);
|
||||
dtoOptions.Fields.Remove(ItemFields.DateLastSaved);
|
||||
dtoOptions.Fields.Remove(ItemFields.DisplayMediaType);
|
||||
dtoOptions.Fields.Remove(ItemFields.DisplayPreferencesId);
|
||||
dtoOptions.Fields.Remove(ItemFields.Etag);
|
||||
dtoOptions.Fields.Remove(ItemFields.ExternalEtag);
|
||||
dtoOptions.Fields.Remove(ItemFields.IndexOptions);
|
||||
dtoOptions.Fields.Remove(ItemFields.InheritedParentalRatingValue);
|
||||
dtoOptions.Fields.Remove(ItemFields.ItemCounts);
|
||||
dtoOptions.Fields.Remove(ItemFields.Keywords);
|
||||
dtoOptions.Fields.Remove(ItemFields.MediaSourceCount);
|
||||
dtoOptions.Fields.Remove(ItemFields.MediaStreams);
|
||||
dtoOptions.Fields.Remove(ItemFields.MediaSources);
|
||||
dtoOptions.Fields.Remove(ItemFields.People);
|
||||
dtoOptions.Fields.Remove(ItemFields.PlayAccess);
|
||||
dtoOptions.Fields.Remove(ItemFields.People);
|
||||
dtoOptions.Fields.Remove(ItemFields.ProductionLocations);
|
||||
dtoOptions.Fields.Remove(ItemFields.RecursiveItemCount);
|
||||
dtoOptions.Fields.Remove(ItemFields.RemoteTrailers);
|
||||
dtoOptions.Fields.Remove(ItemFields.SeasonUserData);
|
||||
dtoOptions.Fields.Remove(ItemFields.SeriesGenres);
|
||||
dtoOptions.Fields.Remove(ItemFields.Settings);
|
||||
dtoOptions.Fields.Remove(ItemFields.SortName);
|
||||
dtoOptions.Fields.Remove(ItemFields.Tags);
|
||||
dtoOptions.Fields.Remove(ItemFields.ThemeSongIds);
|
||||
dtoOptions.Fields.Remove(ItemFields.ThemeVideoIds);
|
||||
|
||||
_itemInfoDtoOptions = dtoOptions;
|
||||
}
|
||||
|
||||
var episode = item as Episode;
|
||||
if (episode != null)
|
||||
{
|
||||
info.IndexNumberEnd = episode.IndexNumberEnd;
|
||||
}
|
||||
|
||||
var hasSeries = item as IHasSeries;
|
||||
if (hasSeries != null)
|
||||
{
|
||||
info.SeriesName = hasSeries.SeriesName;
|
||||
}
|
||||
|
||||
var recording = item as ILiveTvRecording;
|
||||
if (recording != null)
|
||||
{
|
||||
if (recording.IsSeries)
|
||||
{
|
||||
info.Name = recording.EpisodeTitle;
|
||||
info.SeriesName = recording.Name;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(info.Name))
|
||||
{
|
||||
info.Name = recording.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var audio = item as Audio;
|
||||
if (audio != null)
|
||||
{
|
||||
info.Album = audio.Album;
|
||||
info.Artists = audio.Artists;
|
||||
|
||||
if (info.PrimaryImageTag == null)
|
||||
{
|
||||
var album = audio.AlbumEntity;
|
||||
|
||||
if (album != null && album.HasImage(ImageType.Primary))
|
||||
{
|
||||
info.PrimaryImageTag = GetImageCacheTag(album, ImageType.Primary);
|
||||
if (info.PrimaryImageTag != null)
|
||||
{
|
||||
info.PrimaryImageItemId = GetDtoId(album);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var musicVideo = item as MusicVideo;
|
||||
if (musicVideo != null)
|
||||
{
|
||||
info.Album = musicVideo.Album;
|
||||
info.Artists = musicVideo.Artists.ToList();
|
||||
}
|
||||
|
||||
var backropItem = item.HasImage(ImageType.Backdrop) ? item : null;
|
||||
var thumbItem = item.HasImage(ImageType.Thumb) ? item : null;
|
||||
var logoItem = item.HasImage(ImageType.Logo) ? item : null;
|
||||
|
||||
if (thumbItem == null)
|
||||
{
|
||||
if (episode != null)
|
||||
{
|
||||
var series = episode.Series;
|
||||
|
||||
if (series != null && series.HasImage(ImageType.Thumb))
|
||||
{
|
||||
thumbItem = series;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (backropItem == null)
|
||||
{
|
||||
if (episode != null)
|
||||
{
|
||||
var series = episode.Series;
|
||||
|
||||
if (series != null && series.HasImage(ImageType.Backdrop))
|
||||
{
|
||||
backropItem = series;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (backropItem == null)
|
||||
{
|
||||
backropItem = item.GetParents().FirstOrDefault(i => i.HasImage(ImageType.Backdrop));
|
||||
}
|
||||
|
||||
if (thumbItem == null)
|
||||
{
|
||||
thumbItem = item.GetParents().FirstOrDefault(i => i.HasImage(ImageType.Thumb));
|
||||
}
|
||||
|
||||
if (logoItem == null)
|
||||
{
|
||||
logoItem = item.GetParents().FirstOrDefault(i => i.HasImage(ImageType.Logo));
|
||||
}
|
||||
|
||||
if (thumbItem != null)
|
||||
{
|
||||
info.ThumbImageTag = GetImageCacheTag(thumbItem, ImageType.Thumb);
|
||||
info.ThumbItemId = GetDtoId(thumbItem);
|
||||
}
|
||||
|
||||
if (backropItem != null)
|
||||
{
|
||||
info.BackdropImageTag = GetImageCacheTag(backropItem, ImageType.Backdrop);
|
||||
info.BackdropItemId = GetDtoId(backropItem);
|
||||
}
|
||||
|
||||
if (logoItem != null)
|
||||
{
|
||||
info.LogoImageTag = GetImageCacheTag(logoItem, ImageType.Logo);
|
||||
info.LogoItemId = GetDtoId(logoItem);
|
||||
}
|
||||
|
||||
if (chapterOwner != null)
|
||||
{
|
||||
info.ChapterImagesItemId = chapterOwner.Id.ToString("N");
|
||||
|
||||
info.Chapters = _dtoService.GetChapterInfoDtos(chapterOwner).ToList();
|
||||
}
|
||||
var info = _dtoService.GetBaseItemDto(item, dtoOptions);
|
||||
|
||||
if (mediaSource != null)
|
||||
{
|
||||
|
@ -1837,7 +1737,7 @@ namespace Emby.Server.Implementations.Session
|
|||
//ReportNowViewingItem(sessionId, info);
|
||||
}
|
||||
|
||||
public void ReportNowViewingItem(string sessionId, BaseItemInfo item)
|
||||
public void ReportNowViewingItem(string sessionId, BaseItemDto item)
|
||||
{
|
||||
//var session = GetSession(sessionId);
|
||||
|
||||
|
|
|
@ -206,15 +206,16 @@ namespace MediaBrowser.Api
|
|||
var newLockData = request.LockData ?? false;
|
||||
var isLockedChanged = item.IsLocked != newLockData;
|
||||
|
||||
UpdateItem(request, item);
|
||||
|
||||
await item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
// Do this first so that metadata savers can pull the updates from the database.
|
||||
if (request.People != null)
|
||||
{
|
||||
await _libraryManager.UpdatePeople(item, request.People.Select(x => new PersonInfo { Name = x.Name, Role = x.Role, Type = x.Type }).ToList());
|
||||
}
|
||||
|
||||
UpdateItem(request, item);
|
||||
|
||||
await item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
if (isLockedChanged && item.IsFolder)
|
||||
{
|
||||
var folder = (Folder)item;
|
||||
|
@ -243,7 +244,6 @@ namespace MediaBrowser.Api
|
|||
|
||||
item.DisplayMediaType = request.DisplayMediaType;
|
||||
item.CommunityRating = request.CommunityRating;
|
||||
item.VoteCount = request.VoteCount;
|
||||
item.HomePageUrl = request.HomePageUrl;
|
||||
item.IndexNumber = request.IndexNumber;
|
||||
item.ParentIndexNumber = request.ParentIndexNumber;
|
||||
|
|
|
@ -27,6 +27,7 @@ using MediaBrowser.Controller.Configuration;
|
|||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Model.Globalization;
|
||||
using MediaBrowser.Model.Services;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
|
||||
namespace MediaBrowser.Api.Library
|
||||
{
|
||||
|
@ -675,7 +676,6 @@ namespace MediaBrowser.Api.Library
|
|||
Limit = 0,
|
||||
Recursive = true,
|
||||
IsVirtualItem = false,
|
||||
SourceTypes = new[] { SourceType.Library },
|
||||
IsFavorite = request.IsFavorite,
|
||||
DtoOptions = new DtoOptions(false)
|
||||
{
|
||||
|
@ -831,6 +831,11 @@ namespace MediaBrowser.Api.Library
|
|||
: (Folder)_libraryManager.RootFolder)
|
||||
: _libraryManager.GetItemById(request.Id);
|
||||
|
||||
if (item == null)
|
||||
{
|
||||
throw new ResourceNotFoundException("Item not found.");
|
||||
}
|
||||
|
||||
while (item.ThemeSongIds.Count == 0 && request.InheritFromParent && item.GetParent() != null)
|
||||
{
|
||||
item = item.GetParent();
|
||||
|
@ -875,6 +880,11 @@ namespace MediaBrowser.Api.Library
|
|||
: (Folder)_libraryManager.RootFolder)
|
||||
: _libraryManager.GetItemById(request.Id);
|
||||
|
||||
if (item == null)
|
||||
{
|
||||
throw new ResourceNotFoundException("Item not found.");
|
||||
}
|
||||
|
||||
while (item.ThemeVideoIds.Count == 0 && request.InheritFromParent && item.GetParent() != null)
|
||||
{
|
||||
item = item.GetParent();
|
||||
|
|
|
@ -783,7 +783,6 @@ namespace MediaBrowser.Api.Playback
|
|||
state.OutputContainer = (container ?? string.Empty).TrimStart('.');
|
||||
|
||||
state.OutputAudioBitrate = EncodingHelper.GetAudioBitrateParam(state.Request, state.AudioStream);
|
||||
state.OutputAudioSampleRate = request.AudioSampleRate;
|
||||
|
||||
state.OutputAudioCodec = state.Request.AudioCodec;
|
||||
|
||||
|
|
|
@ -106,6 +106,13 @@ namespace MediaBrowser.Api.Playback
|
|||
}
|
||||
|
||||
public async Task<object> Post(OpenMediaSource request)
|
||||
{
|
||||
var result = await OpenMediaSource(request).ConfigureAwait(false);
|
||||
|
||||
return ToOptimizedResult(result);
|
||||
}
|
||||
|
||||
private async Task<LiveStreamResponse> OpenMediaSource(OpenMediaSource request)
|
||||
{
|
||||
var authInfo = _authContext.GetAuthorizationInfo(Request);
|
||||
|
||||
|
@ -137,7 +144,7 @@ namespace MediaBrowser.Api.Playback
|
|||
}
|
||||
}
|
||||
|
||||
return ToOptimizedResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void Post(CloseMediaSource request)
|
||||
|
@ -172,6 +179,34 @@ namespace MediaBrowser.Api.Playback
|
|||
SetDeviceSpecificData(request.Id, info, profile, authInfo, request.MaxStreamingBitrate ?? profile.MaxStreamingBitrate, request.StartTimeTicks ?? 0, mediaSourceId, request.AudioStreamIndex, request.SubtitleStreamIndex, request.MaxAudioChannels, request.UserId, request.EnableDirectPlay, request.ForceDirectPlayRemoteMediaSource, request.EnableDirectStream, request.EnableTranscoding, request.AllowVideoStreamCopy, request.AllowAudioStreamCopy);
|
||||
}
|
||||
|
||||
if (request.AutoOpenLiveStream)
|
||||
{
|
||||
var mediaSource = string.IsNullOrWhiteSpace(request.MediaSourceId) ? info.MediaSources.FirstOrDefault() : info.MediaSources.FirstOrDefault(i => string.Equals(i.Id, request.MediaSourceId, StringComparison.Ordinal));
|
||||
|
||||
if (mediaSource != null && mediaSource.RequiresOpening && string.IsNullOrWhiteSpace(mediaSource.LiveStreamId))
|
||||
{
|
||||
var openStreamResult = await OpenMediaSource(new OpenMediaSource
|
||||
{
|
||||
AudioStreamIndex = request.AudioStreamIndex,
|
||||
DeviceProfile = request.DeviceProfile,
|
||||
EnableDirectPlay = request.EnableDirectPlay,
|
||||
EnableDirectStream = request.EnableDirectStream,
|
||||
ForceDirectPlayRemoteMediaSource = request.ForceDirectPlayRemoteMediaSource,
|
||||
ItemId = request.Id,
|
||||
MaxAudioChannels = request.MaxAudioChannels,
|
||||
MaxStreamingBitrate = request.MaxStreamingBitrate,
|
||||
PlaySessionId = info.PlaySessionId,
|
||||
StartTimeTicks = request.StartTimeTicks,
|
||||
SubtitleStreamIndex = request.SubtitleStreamIndex,
|
||||
UserId = request.UserId,
|
||||
OpenToken = mediaSource.OpenToken
|
||||
|
||||
}).ConfigureAwait(false);
|
||||
|
||||
info.MediaSources = new List<MediaSourceInfo> { openStreamResult.MediaSource };
|
||||
}
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
|
@ -322,6 +357,19 @@ namespace MediaBrowser.Api.Playback
|
|||
mediaSource.SupportsTranscoding = false;
|
||||
}
|
||||
|
||||
if (item is Audio)
|
||||
{
|
||||
Logger.Info("User policy for {0}. EnableAudioPlaybackTranscoding: {1}", user.Name, user.Policy.EnableAudioPlaybackTranscoding);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Info("User policy for {0}. EnablePlaybackRemuxing: {1} EnableVideoPlaybackTranscoding: {2} EnableAudioPlaybackTranscoding: {3}",
|
||||
user.Name,
|
||||
user.Policy.EnablePlaybackRemuxing,
|
||||
user.Policy.EnableVideoPlaybackTranscoding,
|
||||
user.Policy.EnableAudioPlaybackTranscoding);
|
||||
}
|
||||
|
||||
if (mediaSource.SupportsDirectPlay)
|
||||
{
|
||||
if (mediaSource.IsRemote && forceDirectPlayRemoteMediaSource)
|
||||
|
|
|
@ -250,248 +250,6 @@ namespace MediaBrowser.Api.Playback
|
|||
|
||||
public DeviceProfile DeviceProfile { get; set; }
|
||||
|
||||
public int? TotalOutputBitrate
|
||||
{
|
||||
get
|
||||
{
|
||||
return (OutputAudioBitrate ?? 0) + (OutputVideoBitrate ?? 0);
|
||||
}
|
||||
}
|
||||
|
||||
public int? OutputWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
if (VideoStream != null && VideoStream.Width.HasValue && VideoStream.Height.HasValue)
|
||||
{
|
||||
var size = new ImageSize
|
||||
{
|
||||
Width = VideoStream.Width.Value,
|
||||
Height = VideoStream.Height.Value
|
||||
};
|
||||
|
||||
var newSize = DrawingUtils.Resize(size,
|
||||
VideoRequest.Width,
|
||||
VideoRequest.Height,
|
||||
VideoRequest.MaxWidth,
|
||||
VideoRequest.MaxHeight);
|
||||
|
||||
return Convert.ToInt32(newSize.Width);
|
||||
}
|
||||
|
||||
if (VideoRequest == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return VideoRequest.MaxWidth ?? VideoRequest.Width;
|
||||
}
|
||||
}
|
||||
|
||||
public int? OutputHeight
|
||||
{
|
||||
get
|
||||
{
|
||||
if (VideoStream != null && VideoStream.Width.HasValue && VideoStream.Height.HasValue)
|
||||
{
|
||||
var size = new ImageSize
|
||||
{
|
||||
Width = VideoStream.Width.Value,
|
||||
Height = VideoStream.Height.Value
|
||||
};
|
||||
|
||||
var newSize = DrawingUtils.Resize(size,
|
||||
VideoRequest.Width,
|
||||
VideoRequest.Height,
|
||||
VideoRequest.MaxWidth,
|
||||
VideoRequest.MaxHeight);
|
||||
|
||||
return Convert.ToInt32(newSize.Height);
|
||||
}
|
||||
|
||||
if (VideoRequest == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return VideoRequest.MaxHeight ?? VideoRequest.Height;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Predicts the audio sample rate that will be in the output stream
|
||||
/// </summary>
|
||||
public int? TargetVideoBitDepth
|
||||
{
|
||||
get
|
||||
{
|
||||
var stream = VideoStream;
|
||||
return stream == null || !Request.Static ? null : stream.BitDepth;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the target reference frames.
|
||||
/// </summary>
|
||||
/// <value>The target reference frames.</value>
|
||||
public int? TargetRefFrames
|
||||
{
|
||||
get
|
||||
{
|
||||
var stream = VideoStream;
|
||||
return stream == null || !Request.Static ? null : stream.RefFrames;
|
||||
}
|
||||
}
|
||||
|
||||
public int? TargetVideoStreamCount
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Request.Static)
|
||||
{
|
||||
return GetMediaStreamCount(MediaStreamType.Video, int.MaxValue);
|
||||
}
|
||||
return GetMediaStreamCount(MediaStreamType.Video, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public int? TargetAudioStreamCount
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Request.Static)
|
||||
{
|
||||
return GetMediaStreamCount(MediaStreamType.Audio, int.MaxValue);
|
||||
}
|
||||
return GetMediaStreamCount(MediaStreamType.Audio, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public bool? IsTargetAnamorphic
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Request.Static)
|
||||
{
|
||||
return VideoStream == null ? null : VideoStream.IsAnamorphic;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool? IsTargetInterlaced
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Request.Static)
|
||||
{
|
||||
return VideoStream == null ? (bool?)null : VideoStream.IsInterlaced;
|
||||
}
|
||||
|
||||
if (DeInterlace)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return VideoStream == null ? (bool?)null : VideoStream.IsInterlaced;
|
||||
}
|
||||
}
|
||||
|
||||
private int? GetMediaStreamCount(MediaStreamType type, int limit)
|
||||
{
|
||||
var count = MediaSource.GetStreamCount(type);
|
||||
|
||||
if (count.HasValue)
|
||||
{
|
||||
count = Math.Min(count.Value, limit);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Predicts the audio sample rate that will be in the output stream
|
||||
/// </summary>
|
||||
public float? TargetFramerate
|
||||
{
|
||||
get
|
||||
{
|
||||
var stream = VideoStream;
|
||||
var requestedFramerate = VideoRequest.MaxFramerate ?? VideoRequest.Framerate;
|
||||
|
||||
return requestedFramerate.HasValue && !Request.Static
|
||||
? requestedFramerate
|
||||
: stream == null ? null : stream.AverageFrameRate ?? stream.RealFrameRate;
|
||||
}
|
||||
}
|
||||
|
||||
public TransportStreamTimestamp TargetTimestamp
|
||||
{
|
||||
get
|
||||
{
|
||||
var defaultValue = string.Equals(OutputContainer, "m2ts", StringComparison.OrdinalIgnoreCase) ?
|
||||
TransportStreamTimestamp.Valid :
|
||||
TransportStreamTimestamp.None;
|
||||
|
||||
return !Request.Static
|
||||
? defaultValue
|
||||
: InputTimestamp;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Predicts the audio sample rate that will be in the output stream
|
||||
/// </summary>
|
||||
public int? TargetPacketLength
|
||||
{
|
||||
get
|
||||
{
|
||||
var stream = VideoStream;
|
||||
return !Request.Static
|
||||
? null
|
||||
: stream == null ? null : stream.PacketLength;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Predicts the audio sample rate that will be in the output stream
|
||||
/// </summary>
|
||||
public string TargetVideoProfile
|
||||
{
|
||||
get
|
||||
{
|
||||
var stream = VideoStream;
|
||||
return !string.IsNullOrEmpty(VideoRequest.Profile) && !Request.Static
|
||||
? VideoRequest.Profile
|
||||
: stream == null ? null : stream.Profile;
|
||||
}
|
||||
}
|
||||
|
||||
public string TargetVideoCodecTag
|
||||
{
|
||||
get
|
||||
{
|
||||
var stream = VideoStream;
|
||||
return !Request.Static
|
||||
? null
|
||||
: stream == null ? null : stream.CodecTag;
|
||||
}
|
||||
}
|
||||
|
||||
public bool? IsTargetAVC
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Request.Static)
|
||||
{
|
||||
return VideoStream == null ? null : VideoStream.IsAVC;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public TranscodingJob TranscodingJob;
|
||||
public override void ReportTranscodingProgress(TimeSpan? transcodingPosition, float? framerate, double? percentComplete, long? bytesTranscoded, int? bitRate)
|
||||
{
|
||||
|
|
|
@ -98,7 +98,7 @@ namespace MediaBrowser.Api.Session
|
|||
|
||||
[Route("/Sessions/{Id}/Playing/{Command}", "POST", Summary = "Issues a playstate command to a client")]
|
||||
[Authenticated]
|
||||
public class SendPlaystateCommand : IReturnVoid
|
||||
public class SendPlaystateCommand : PlaystateRequest, IReturnVoid
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the id.
|
||||
|
@ -106,19 +106,6 @@ namespace MediaBrowser.Api.Session
|
|||
/// <value>The id.</value>
|
||||
[ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the position to seek to
|
||||
/// </summary>
|
||||
[ApiMember(Name = "SeekPositionTicks", Description = "The position to seek to.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
|
||||
public long? SeekPositionTicks { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the play command.
|
||||
/// </summary>
|
||||
/// <value>The play command.</value>
|
||||
[ApiMember(Name = "Command", Description = "The command to send - stop, pause, unpause, nexttrack, previoustrack, seek, fullscreen.", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
|
||||
public PlaystateCommand Command { get; set; }
|
||||
}
|
||||
|
||||
[Route("/Sessions/{Id}/System/{Command}", "POST", Summary = "Issues a system command to a client")]
|
||||
|
@ -414,13 +401,7 @@ namespace MediaBrowser.Api.Session
|
|||
|
||||
public void Post(SendPlaystateCommand request)
|
||||
{
|
||||
var command = new PlaystateRequest
|
||||
{
|
||||
Command = request.Command,
|
||||
SeekPositionTicks = request.SeekPositionTicks
|
||||
};
|
||||
|
||||
var task = _sessionManager.SendPlaystateCommand(GetSession(_sessionContext).Result.Id, request.Id, command, CancellationToken.None);
|
||||
var task = _sessionManager.SendPlaystateCommand(GetSession(_sessionContext).Result.Id, request.Id, request, CancellationToken.None);
|
||||
|
||||
Task.WaitAll(task);
|
||||
}
|
||||
|
|
|
@ -100,7 +100,6 @@ namespace MediaBrowser.Api
|
|||
config.EnableSimpleArtistDetection = true;
|
||||
config.EnableNormalizedItemByNameIds = true;
|
||||
config.DisableLiveTvChannelUserDataName = true;
|
||||
config.EnableSimpleSortNameHandling = true;
|
||||
}
|
||||
|
||||
public void Post(UpdateStartupConfiguration request)
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"frameworks":{
|
||||
"netstandard1.6":{
|
||||
"dependencies":{
|
||||
"NETStandard.Library":"1.6.0",
|
||||
}
|
||||
},
|
||||
".NETPortable,Version=v4.5,Profile=Profile7":{
|
||||
"buildOptions": {
|
||||
"define": [ ]
|
||||
},
|
||||
"frameworkAssemblies":{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -72,9 +72,6 @@
|
|||
<Name>MediaBrowser.Model</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="project.json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
|
|
|
@ -58,7 +58,7 @@ namespace MediaBrowser.Common.Updates
|
|||
}
|
||||
else if (updateLevel == PackageVersionClass.Beta)
|
||||
{
|
||||
obj = obj.Where(i => !i.prerelease || i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||
obj = obj.Where(i => i.prerelease && i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||
}
|
||||
else if (updateLevel == PackageVersionClass.Dev)
|
||||
{
|
||||
|
@ -81,7 +81,7 @@ namespace MediaBrowser.Common.Updates
|
|||
{
|
||||
if (updateLevel == PackageVersionClass.Beta)
|
||||
{
|
||||
return !i.prerelease || i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase);
|
||||
return i.prerelease && i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
if (updateLevel == PackageVersionClass.Dev)
|
||||
{
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"frameworks":{
|
||||
"netstandard1.6":{
|
||||
"dependencies":{
|
||||
"NETStandard.Library":"1.6.0",
|
||||
}
|
||||
},
|
||||
".NETPortable,Version=v4.5,Profile=Profile7":{
|
||||
"buildOptions": {
|
||||
"define": [ ]
|
||||
},
|
||||
"frameworkAssemblies":{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -35,7 +35,6 @@ namespace MediaBrowser.Controller.Channels
|
|||
public override SourceType SourceType
|
||||
{
|
||||
get { return SourceType.Channel; }
|
||||
set { }
|
||||
}
|
||||
|
||||
protected override QueryResult<BaseItem> GetItemsInternal(InternalItemsQuery query)
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace MediaBrowser.Controller.Drawing
|
|||
/// <summary>
|
||||
/// Encodes the image.
|
||||
/// </summary>
|
||||
string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, int quality, ImageProcessingOptions options, ImageFormat outputFormat);
|
||||
string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation? orientation, int quality, ImageProcessingOptions options, ImageFormat outputFormat);
|
||||
|
||||
/// <summary>
|
||||
/// Creates the image collage.
|
||||
|
|
|
@ -87,7 +87,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
private List<Guid> _childrenIds = null;
|
||||
private readonly object _childIdsLock = new object();
|
||||
protected override IEnumerable<BaseItem> LoadChildren()
|
||||
protected override List<BaseItem> LoadChildren()
|
||||
{
|
||||
lock (_childIdsLock)
|
||||
{
|
||||
|
|
|
@ -131,7 +131,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||
/// Creates the name of the sort.
|
||||
/// </summary>
|
||||
/// <returns>System.String.</returns>
|
||||
protected override string CreateSortNameInternal()
|
||||
protected override string CreateSortName()
|
||||
{
|
||||
return (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("0000 - ") : "")
|
||||
+ (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ") : "") + Name;
|
||||
|
|
|
@ -90,7 +90,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
protected override IEnumerable<BaseItem> ActualChildren
|
||||
public override IEnumerable<BaseItem> Children
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -99,7 +99,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||
return new List<BaseItem>();
|
||||
}
|
||||
|
||||
return base.ActualChildren;
|
||||
return base.Children;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
ImageInfos = new List<ItemImageInfo>();
|
||||
InheritedTags = new List<string>();
|
||||
ProductionLocations = new List<string>();
|
||||
SourceType = SourceType.Library;
|
||||
}
|
||||
|
||||
public static readonly char[] SlugReplaceChars = { '?', '/', '&' };
|
||||
|
@ -187,15 +186,10 @@ namespace MediaBrowser.Controller.Entities
|
|||
}
|
||||
set
|
||||
{
|
||||
var isSortNameDefault = IsSortNameDefault(SortName);
|
||||
|
||||
_name = value;
|
||||
|
||||
if (isSortNameDefault)
|
||||
{
|
||||
// lazy load this again
|
||||
SortName = null;
|
||||
}
|
||||
_sortName = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -279,7 +273,18 @@ namespace MediaBrowser.Controller.Entities
|
|||
public virtual string Path { get; set; }
|
||||
|
||||
[IgnoreDataMember]
|
||||
public virtual SourceType SourceType { get; set; }
|
||||
public virtual SourceType SourceType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(ChannelId))
|
||||
{
|
||||
return SourceType.Channel;
|
||||
}
|
||||
|
||||
return SourceType.Library;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the folder containing the item.
|
||||
|
@ -586,6 +591,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
}
|
||||
}
|
||||
|
||||
private string _forcedSortName;
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the forced sort.
|
||||
/// </summary>
|
||||
|
@ -593,42 +599,8 @@ namespace MediaBrowser.Controller.Entities
|
|||
[IgnoreDataMember]
|
||||
public string ForcedSortName
|
||||
{
|
||||
get
|
||||
{
|
||||
var sortName = SortName;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(sortName))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (string.Equals(sortName, CreateSortName(), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return sortName;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
SortName = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
var newValue = CreateSortNameFromCustomValue(value);
|
||||
|
||||
if (string.Equals(newValue, CreateSortName(), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
SortName = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
SortName = newValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
get { return _forcedSortName; }
|
||||
set { _forcedSortName = value; _sortName = null; }
|
||||
}
|
||||
|
||||
private string _sortName;
|
||||
|
@ -642,9 +614,17 @@ namespace MediaBrowser.Controller.Entities
|
|||
get
|
||||
{
|
||||
if (_sortName == null)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(ForcedSortName))
|
||||
{
|
||||
// Need the ToLower because that's what CreateSortName does
|
||||
_sortName = ModifySortChunks(ForcedSortName).ToLower();
|
||||
}
|
||||
else
|
||||
{
|
||||
_sortName = CreateSortName();
|
||||
}
|
||||
}
|
||||
return _sortName;
|
||||
}
|
||||
set
|
||||
|
@ -653,31 +633,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
}
|
||||
}
|
||||
|
||||
private string CreateSortNameFromCustomValue(string value)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(value) ? null : NormalizeCustomSortName(value);
|
||||
}
|
||||
|
||||
protected virtual string NormalizeCustomSortName(string value)
|
||||
{
|
||||
if (ConfigurationManager.Configuration.EnableSimpleSortNameHandling)
|
||||
{
|
||||
return value.RemoveDiacritics().ToLower();
|
||||
}
|
||||
|
||||
return ModifySortChunks(value).ToLower();
|
||||
}
|
||||
|
||||
public bool IsSortNameDefault(string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return string.Equals(CreateSortNameFromCustomValue(value), CreateSortName(), StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public string GetInternalMetadataPath()
|
||||
{
|
||||
var basePath = ConfigurationManager.ApplicationPaths.InternalMetadataPath;
|
||||
|
@ -699,22 +654,14 @@ namespace MediaBrowser.Controller.Entities
|
|||
return System.IO.Path.Combine(basePath, idString.Substring(0, 2), idString);
|
||||
}
|
||||
|
||||
protected string CreateSortName()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Name))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return CreateSortNameInternal();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the name of the sort.
|
||||
/// </summary>
|
||||
/// <returns>System.String.</returns>
|
||||
protected virtual string CreateSortNameInternal()
|
||||
protected virtual string CreateSortName()
|
||||
{
|
||||
if (Name == null) return null; //some items may not have name filled in properly
|
||||
|
||||
if (!EnableAlphaNumericSorting)
|
||||
{
|
||||
return Name.TrimStart();
|
||||
|
@ -951,13 +898,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
[IgnoreDataMember]
|
||||
public float? CommunityRating { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the community rating vote count.
|
||||
/// </summary>
|
||||
/// <value>The community rating vote count.</value>
|
||||
[IgnoreDataMember]
|
||||
public int? VoteCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the run time ticks.
|
||||
/// </summary>
|
||||
|
@ -1367,6 +1307,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
public void AfterMetadataRefresh()
|
||||
{
|
||||
_sortName = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -2253,6 +2194,8 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// </summary>
|
||||
public virtual bool BeforeMetadataRefresh()
|
||||
{
|
||||
_sortName = null;
|
||||
|
||||
var hasChanges = false;
|
||||
|
||||
if (string.IsNullOrEmpty(Name) && !string.IsNullOrEmpty(Path))
|
||||
|
|
|
@ -311,12 +311,12 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// </summary>
|
||||
/// <value>The actual children.</value>
|
||||
[IgnoreDataMember]
|
||||
protected override IEnumerable<BaseItem> ActualChildren
|
||||
public override IEnumerable<BaseItem> Children
|
||||
{
|
||||
get { return GetActualChildren(); }
|
||||
}
|
||||
|
||||
private IEnumerable<BaseItem> GetActualChildren()
|
||||
public IEnumerable<BaseItem> GetActualChildren()
|
||||
{
|
||||
return GetPhysicalFolders(true).SelectMany(c => c.Children);
|
||||
}
|
||||
|
|
|
@ -185,7 +185,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
item.Id = LibraryManager.GetNewItemId(item.Path, item.GetType());
|
||||
}
|
||||
|
||||
if (ActualChildren.Any(i => i.Id == item.Id))
|
||||
if (Children.Any(i => i.Id == item.Id))
|
||||
{
|
||||
throw new ArgumentException(string.Format("A child with the Id {0} already exists.", item.Id));
|
||||
}
|
||||
|
@ -243,7 +243,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// </summary>
|
||||
/// <value>The actual children.</value>
|
||||
[IgnoreDataMember]
|
||||
protected virtual IEnumerable<BaseItem> ActualChildren
|
||||
public virtual IEnumerable<BaseItem> Children
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -251,16 +251,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// thread-safe access to the actual children of this folder - without regard to user
|
||||
/// </summary>
|
||||
/// <value>The children.</value>
|
||||
[IgnoreDataMember]
|
||||
public IEnumerable<BaseItem> Children
|
||||
{
|
||||
get { return ActualChildren.ToList(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// thread-safe access to all recursive children of this folder - without regard to user
|
||||
/// </summary>
|
||||
|
@ -301,7 +291,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// Loads our children. Validation will occur externally.
|
||||
/// We want this sychronous.
|
||||
/// </summary>
|
||||
protected virtual IEnumerable<BaseItem> LoadChildren()
|
||||
protected virtual List<BaseItem> LoadChildren()
|
||||
{
|
||||
//Logger.Debug("Loading children from {0} {1} {2}", GetType().Name, Id, Path);
|
||||
//just load our children from the repo - the library will be validated and maintained in other processes
|
||||
|
@ -330,7 +320,9 @@ namespace MediaBrowser.Controller.Entities
|
|||
{
|
||||
var dictionary = new Dictionary<Guid, BaseItem>();
|
||||
|
||||
foreach (var child in ActualChildren)
|
||||
var childrenList = Children.ToList();
|
||||
|
||||
foreach (var child in childrenList)
|
||||
{
|
||||
var id = child.Id;
|
||||
if (dictionary.ContainsKey(id))
|
||||
|
@ -466,7 +458,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
if (recursive)
|
||||
{
|
||||
await ValidateSubFolders(ActualChildren.OfType<Folder>().ToList(), directoryService, progress, cancellationToken).ConfigureAwait(false);
|
||||
await ValidateSubFolders(Children.ToList().OfType<Folder>().ToList(), directoryService, progress, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
progress.Report(20);
|
||||
|
@ -494,7 +486,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
private async Task RefreshMetadataRecursive(MetadataRefreshOptions refreshOptions, bool recursive, IProgress<double> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
var children = ActualChildren.ToList();
|
||||
var children = Children.ToList();
|
||||
|
||||
var percentages = new Dictionary<Guid, double>(children.Count);
|
||||
var numComplete = 0;
|
||||
|
@ -668,7 +660,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// Get our children from the repo - stubbed for now
|
||||
/// </summary>
|
||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
||||
protected IEnumerable<BaseItem> GetCachedChildren()
|
||||
protected List<BaseItem> GetCachedChildren()
|
||||
{
|
||||
return ItemRepository.GetItemList(new InternalItemsQuery
|
||||
{
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// <value>The date last saved.</value>
|
||||
DateTime DateLastSaved { get; set; }
|
||||
|
||||
SourceType SourceType { get; set; }
|
||||
SourceType SourceType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the date last refreshed.
|
||||
|
|
|
@ -148,9 +148,8 @@ namespace MediaBrowser.Controller.Entities
|
|||
}
|
||||
|
||||
public string[] PresetViews { get; set; }
|
||||
public SourceType[] SourceTypes { get; set; }
|
||||
public SourceType[] ExcludeSourceTypes { get; set; }
|
||||
public TrailerType[] TrailerTypes { get; set; }
|
||||
public SourceType[] SourceTypes { get; set; }
|
||||
|
||||
public DayOfWeek[] AirDays { get; set; }
|
||||
public SeriesStatus[] SeriesStatuses { get; set; }
|
||||
|
@ -215,9 +214,8 @@ namespace MediaBrowser.Controller.Entities
|
|||
ExcludeTags = new string[] { };
|
||||
ExcludeInheritedTags = new string[] { };
|
||||
PresetViews = new string[] { };
|
||||
SourceTypes = new SourceType[] { };
|
||||
ExcludeSourceTypes = new SourceType[] { };
|
||||
TrailerTypes = new TrailerType[] { };
|
||||
SourceTypes = new SourceType[] { };
|
||||
AirDays = new DayOfWeek[] { };
|
||||
SeriesStatuses = new SeriesStatus[] { };
|
||||
OrderBy = new List<Tuple<string, SortOrder>>();
|
||||
|
|
|
@ -11,13 +11,11 @@ namespace MediaBrowser.Controller.Entities
|
|||
public int? MaxListOrder { get; set; }
|
||||
public Guid AppearsInItemId { get; set; }
|
||||
public string NameContains { get; set; }
|
||||
public SourceType[] SourceTypes { get; set; }
|
||||
|
||||
public InternalPeopleQuery()
|
||||
{
|
||||
PersonTypes = new List<string>();
|
||||
ExcludePersonTypes = new List<string>();
|
||||
SourceTypes = new SourceType[] { };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ namespace MediaBrowser.Controller.Entities.Movies
|
|||
return new List<BaseItem>();
|
||||
}
|
||||
|
||||
protected override IEnumerable<BaseItem> LoadChildren()
|
||||
protected override List<BaseItem> LoadChildren()
|
||||
{
|
||||
if (IsLegacyBoxSet)
|
||||
{
|
||||
|
|
|
@ -237,7 +237,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
/// Creates the name of the sort.
|
||||
/// </summary>
|
||||
/// <returns>System.String.</returns>
|
||||
protected override string CreateSortNameInternal()
|
||||
protected override string CreateSortName()
|
||||
{
|
||||
return (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("000 - ") : "")
|
||||
+ (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ") : "") + Name;
|
||||
|
|
|
@ -145,7 +145,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
/// Creates the name of the sort.
|
||||
/// </summary>
|
||||
/// <returns>System.String.</returns>
|
||||
protected override string CreateSortNameInternal()
|
||||
protected override string CreateSortName()
|
||||
{
|
||||
return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
{
|
||||
private List<Guid> _childrenIds = null;
|
||||
private readonly object _childIdsLock = new object();
|
||||
protected override IEnumerable<BaseItem> LoadChildren()
|
||||
protected override List<BaseItem> LoadChildren()
|
||||
{
|
||||
lock (_childIdsLock)
|
||||
{
|
||||
|
|
|
@ -633,14 +633,17 @@ namespace MediaBrowser.Controller.Entities
|
|||
if (info.Path.StartsWith("Http", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
info.Protocol = MediaProtocol.Http;
|
||||
info.SupportsDirectStream = false;
|
||||
}
|
||||
else if (info.Path.StartsWith("Rtmp", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
info.Protocol = MediaProtocol.Rtmp;
|
||||
info.SupportsDirectStream = false;
|
||||
}
|
||||
else if (info.Path.StartsWith("Rtsp", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
info.Protocol = MediaProtocol.Rtsp;
|
||||
info.SupportsDirectStream = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -527,6 +527,8 @@ namespace MediaBrowser.Controller.Library
|
|||
/// <returns>QueryResult<BaseItem>.</returns>
|
||||
IEnumerable<BaseItem> GetItemList(InternalItemsQuery query);
|
||||
|
||||
IEnumerable<BaseItem> GetItemList(InternalItemsQuery query, bool allowExternalContent);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the items.
|
||||
/// </summary>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
@ -13,7 +13,7 @@ namespace MediaBrowser.Controller.Library
|
|||
public List<User> Users { get; set; }
|
||||
public long? PlaybackPositionTicks { get; set; }
|
||||
public BaseItem Item { get; set; }
|
||||
public BaseItemInfo MediaInfo { get; set; }
|
||||
public BaseItemDto MediaInfo { get; set; }
|
||||
public string MediaSourceId { get; set; }
|
||||
public bool IsPaused { get; set; }
|
||||
public bool IsAutomated { get; set; }
|
||||
|
|
|
@ -43,7 +43,6 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
public override SourceType SourceType
|
||||
{
|
||||
get { return SourceType.LiveTV; }
|
||||
set { }
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
|
|
|
@ -55,7 +55,6 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
public override SourceType SourceType
|
||||
{
|
||||
get { return SourceType.LiveTV; }
|
||||
set { }
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
|
@ -89,7 +88,7 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
}
|
||||
}
|
||||
|
||||
protected override string CreateSortNameInternal()
|
||||
protected override string CreateSortName()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Number))
|
||||
{
|
||||
|
|
|
@ -65,7 +65,6 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
public override SourceType SourceType
|
||||
{
|
||||
get { return SourceType.LiveTV; }
|
||||
set { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -42,7 +42,6 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
public override SourceType SourceType
|
||||
{
|
||||
get { return SourceType.LiveTV; }
|
||||
set { }
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
|
|
|
@ -107,8 +107,12 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
/// <value>The image URL.</value>
|
||||
public string ImageUrl { get; set; }
|
||||
|
||||
public string ThumbImageUrl { get; set; }
|
||||
|
||||
public string LogoImageUrl { get; set; }
|
||||
|
||||
public string BackdropImageUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance has image.
|
||||
/// </summary>
|
||||
|
|
|
@ -30,7 +30,6 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
public override SourceType SourceType
|
||||
{
|
||||
get { return SourceType.LiveTV; }
|
||||
set { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,10 +36,6 @@
|
|||
<PropertyGroup>
|
||||
<RunPostBuildEvent>Always</RunPostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<None Include="project.json" />
|
||||
<!-- A reference to the entire .NET Framework is automatically included -->
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\SharedVersion.cs">
|
||||
<Link>Properties\SharedVersion.cs</Link>
|
||||
|
|
|
@ -1604,7 +1604,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
}
|
||||
|
||||
// Only do this for video files due to sometimes unpredictable codec names coming from BDInfo
|
||||
if (state.RunTimeTicks.HasValue && state.VideoType == VideoType.VideoFile && string.IsNullOrWhiteSpace(encodingOptions.HardwareAccelerationType))
|
||||
if (state.VideoType == VideoType.VideoFile && state.RunTimeTicks.HasValue && string.IsNullOrWhiteSpace(encodingOptions.HardwareAccelerationType))
|
||||
{
|
||||
foreach (var stream in state.MediaSource.MediaStreams)
|
||||
{
|
||||
|
@ -1806,6 +1806,20 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
else if (string.Equals(encodingOptions.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
switch (state.MediaSource.VideoStream.Codec.ToLower())
|
||||
{
|
||||
case "avc":
|
||||
case "h264":
|
||||
if (_mediaEncoder.SupportsDecoder("h264_cuvid"))
|
||||
{
|
||||
return "-c:v h264_cuvid ";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// leave blank so ffmpeg will decide
|
||||
|
|
|
@ -8,6 +8,7 @@ using MediaBrowser.Model.Entities;
|
|||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Model.MediaInfo;
|
||||
using MediaBrowser.Model.Drawing;
|
||||
|
||||
namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
|
@ -134,7 +135,6 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
|
||||
public int? OutputAudioBitrate;
|
||||
public int? OutputAudioChannels;
|
||||
public int? OutputAudioSampleRate;
|
||||
public bool DeInterlace { get; set; }
|
||||
public bool IsVideoRequest { get; set; }
|
||||
public TranscodingJobType TranscodingType { get; set; }
|
||||
|
@ -173,6 +173,97 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
return false;
|
||||
}
|
||||
|
||||
public int? TotalOutputBitrate
|
||||
{
|
||||
get
|
||||
{
|
||||
return (OutputAudioBitrate ?? 0) + (OutputVideoBitrate ?? 0);
|
||||
}
|
||||
}
|
||||
|
||||
public int? OutputWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
if (VideoStream != null && VideoStream.Width.HasValue && VideoStream.Height.HasValue)
|
||||
{
|
||||
var size = new ImageSize
|
||||
{
|
||||
Width = VideoStream.Width.Value,
|
||||
Height = VideoStream.Height.Value
|
||||
};
|
||||
|
||||
var newSize = DrawingUtils.Resize(size,
|
||||
BaseRequest.Width,
|
||||
BaseRequest.Height,
|
||||
BaseRequest.MaxWidth,
|
||||
BaseRequest.MaxHeight);
|
||||
|
||||
return Convert.ToInt32(newSize.Width);
|
||||
}
|
||||
|
||||
if (!IsVideoRequest)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return BaseRequest.MaxWidth ?? BaseRequest.Width;
|
||||
}
|
||||
}
|
||||
|
||||
public int? OutputHeight
|
||||
{
|
||||
get
|
||||
{
|
||||
if (VideoStream != null && VideoStream.Width.HasValue && VideoStream.Height.HasValue)
|
||||
{
|
||||
var size = new ImageSize
|
||||
{
|
||||
Width = VideoStream.Width.Value,
|
||||
Height = VideoStream.Height.Value
|
||||
};
|
||||
|
||||
var newSize = DrawingUtils.Resize(size,
|
||||
BaseRequest.Width,
|
||||
BaseRequest.Height,
|
||||
BaseRequest.MaxWidth,
|
||||
BaseRequest.MaxHeight);
|
||||
|
||||
return Convert.ToInt32(newSize.Height);
|
||||
}
|
||||
|
||||
if (!IsVideoRequest)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return BaseRequest.MaxHeight ?? BaseRequest.Height;
|
||||
}
|
||||
}
|
||||
|
||||
public int? OutputAudioSampleRate
|
||||
{
|
||||
get
|
||||
{
|
||||
if (BaseRequest.Static || string.Equals(OutputAudioCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (AudioStream != null)
|
||||
{
|
||||
return AudioStream.SampleRate;
|
||||
}
|
||||
}
|
||||
|
||||
else if (BaseRequest.AudioSampleRate.HasValue)
|
||||
{
|
||||
// Don't exceed what the encoder supports
|
||||
// Seeing issues of attempting to encode to 88200
|
||||
return Math.Min(44100, BaseRequest.AudioSampleRate.Value);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Predicts the audio sample rate that will be in the output stream
|
||||
/// </summary>
|
||||
|
@ -189,6 +280,180 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Predicts the audio sample rate that will be in the output stream
|
||||
/// </summary>
|
||||
public int? TargetVideoBitDepth
|
||||
{
|
||||
get
|
||||
{
|
||||
var stream = VideoStream;
|
||||
return stream == null || !BaseRequest.Static ? null : stream.BitDepth;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the target reference frames.
|
||||
/// </summary>
|
||||
/// <value>The target reference frames.</value>
|
||||
public int? TargetRefFrames
|
||||
{
|
||||
get
|
||||
{
|
||||
var stream = VideoStream;
|
||||
return stream == null || !BaseRequest.Static ? null : stream.RefFrames;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Predicts the audio sample rate that will be in the output stream
|
||||
/// </summary>
|
||||
public float? TargetFramerate
|
||||
{
|
||||
get
|
||||
{
|
||||
var stream = VideoStream;
|
||||
var requestedFramerate = BaseRequest.MaxFramerate ?? BaseRequest.Framerate;
|
||||
|
||||
return requestedFramerate.HasValue && !BaseRequest.Static
|
||||
? requestedFramerate
|
||||
: stream == null ? null : stream.AverageFrameRate ?? stream.RealFrameRate;
|
||||
}
|
||||
}
|
||||
|
||||
public TransportStreamTimestamp TargetTimestamp
|
||||
{
|
||||
get
|
||||
{
|
||||
var defaultValue = string.Equals(OutputContainer, "m2ts", StringComparison.OrdinalIgnoreCase) ?
|
||||
TransportStreamTimestamp.Valid :
|
||||
TransportStreamTimestamp.None;
|
||||
|
||||
return !BaseRequest.Static
|
||||
? defaultValue
|
||||
: InputTimestamp;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Predicts the audio sample rate that will be in the output stream
|
||||
/// </summary>
|
||||
public int? TargetPacketLength
|
||||
{
|
||||
get
|
||||
{
|
||||
var stream = VideoStream;
|
||||
return !BaseRequest.Static
|
||||
? null
|
||||
: stream == null ? null : stream.PacketLength;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Predicts the audio sample rate that will be in the output stream
|
||||
/// </summary>
|
||||
public string TargetVideoProfile
|
||||
{
|
||||
get
|
||||
{
|
||||
var stream = VideoStream;
|
||||
return !string.IsNullOrEmpty(BaseRequest.Profile) && !BaseRequest.Static
|
||||
? BaseRequest.Profile
|
||||
: stream == null ? null : stream.Profile;
|
||||
}
|
||||
}
|
||||
|
||||
public string TargetVideoCodecTag
|
||||
{
|
||||
get
|
||||
{
|
||||
var stream = VideoStream;
|
||||
return !BaseRequest.Static
|
||||
? null
|
||||
: stream == null ? null : stream.CodecTag;
|
||||
}
|
||||
}
|
||||
|
||||
public bool? IsTargetAnamorphic
|
||||
{
|
||||
get
|
||||
{
|
||||
if (BaseRequest.Static)
|
||||
{
|
||||
return VideoStream == null ? null : VideoStream.IsAnamorphic;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool? IsTargetInterlaced
|
||||
{
|
||||
get
|
||||
{
|
||||
if (BaseRequest.Static)
|
||||
{
|
||||
return VideoStream == null ? (bool?)null : VideoStream.IsInterlaced;
|
||||
}
|
||||
|
||||
if (DeInterlace)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return VideoStream == null ? (bool?)null : VideoStream.IsInterlaced;
|
||||
}
|
||||
}
|
||||
|
||||
public bool? IsTargetAVC
|
||||
{
|
||||
get
|
||||
{
|
||||
if (BaseRequest.Static)
|
||||
{
|
||||
return VideoStream == null ? null : VideoStream.IsAVC;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int? TargetVideoStreamCount
|
||||
{
|
||||
get
|
||||
{
|
||||
if (BaseRequest.Static)
|
||||
{
|
||||
return GetMediaStreamCount(MediaStreamType.Video, int.MaxValue);
|
||||
}
|
||||
return GetMediaStreamCount(MediaStreamType.Video, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public int? TargetAudioStreamCount
|
||||
{
|
||||
get
|
||||
{
|
||||
if (BaseRequest.Static)
|
||||
{
|
||||
return GetMediaStreamCount(MediaStreamType.Audio, int.MaxValue);
|
||||
}
|
||||
return GetMediaStreamCount(MediaStreamType.Audio, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private int? GetMediaStreamCount(MediaStreamType type, int limit)
|
||||
{
|
||||
var count = MediaSource.GetStreamCount(type);
|
||||
|
||||
if (count.HasValue)
|
||||
{
|
||||
count = Math.Min(count.Value, limit);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
protected void DisposeIsoMount()
|
||||
{
|
||||
if (IsoMount != null)
|
||||
|
|
|
@ -74,7 +74,7 @@ namespace MediaBrowser.Controller.Playlists
|
|||
return true;
|
||||
}
|
||||
|
||||
protected override IEnumerable<BaseItem> LoadChildren()
|
||||
protected override List<BaseItem> LoadChildren()
|
||||
{
|
||||
// Save a trip to the database
|
||||
return new List<BaseItem>();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Security;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Events;
|
||||
using MediaBrowser.Model.Session;
|
||||
using MediaBrowser.Model.Users;
|
||||
|
@ -249,7 +249,7 @@ namespace MediaBrowser.Controller.Session
|
|||
/// </summary>
|
||||
/// <param name="sessionId">The session identifier.</param>
|
||||
/// <param name="item">The item.</param>
|
||||
void ReportNowViewingItem(string sessionId, BaseItemInfo item);
|
||||
void ReportNowViewingItem(string sessionId, BaseItemDto item);
|
||||
|
||||
/// <summary>
|
||||
/// Authenticates the new session.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Session;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -100,13 +100,13 @@ namespace MediaBrowser.Controller.Session
|
|||
/// Gets or sets the name of the now viewing item.
|
||||
/// </summary>
|
||||
/// <value>The name of the now viewing item.</value>
|
||||
public BaseItemInfo NowViewingItem { get; set; }
|
||||
public BaseItemDto NowViewingItem { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the now playing item.
|
||||
/// </summary>
|
||||
/// <value>The now playing item.</value>
|
||||
public BaseItemInfo NowPlayingItem { get; set; }
|
||||
public BaseItemDto NowPlayingItem { get; set; }
|
||||
|
||||
public BaseItem FullNowPlayingItem { get; set; }
|
||||
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"frameworks":{
|
||||
"netstandard1.6":{
|
||||
"dependencies":{
|
||||
"NETStandard.Library":"1.6.0",
|
||||
}
|
||||
},
|
||||
".NETPortable,Version=v4.5,Profile=Profile7":{
|
||||
"buildOptions": {
|
||||
"define": [ ]
|
||||
},
|
||||
"frameworkAssemblies":{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -40,27 +40,12 @@ namespace MediaBrowser.LocalMetadata.Images
|
|||
{
|
||||
var parentPath = _fileSystem.GetDirectoryName(item.Path);
|
||||
|
||||
var parentPathFiles = directoryService.GetFileSystemEntries(parentPath)
|
||||
var parentPathFiles = directoryService.GetFiles(parentPath)
|
||||
.ToList();
|
||||
|
||||
var nameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(item.Path);
|
||||
|
||||
var files = GetFilesFromParentFolder(nameWithoutExtension, parentPathFiles);
|
||||
|
||||
if (files.Count > 0)
|
||||
{
|
||||
return files;
|
||||
}
|
||||
|
||||
var metadataPath = Path.Combine(parentPath, "metadata");
|
||||
|
||||
if (parentPathFiles.Any(i => string.Equals(i.FullName, metadataPath, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
var filesInMetadataFolder = _fileSystem.GetFiles(metadataPath, BaseItem.SupportedImageExtensions, false, false);
|
||||
return GetFilesFromParentFolder(nameWithoutExtension, filesInMetadataFolder);
|
||||
}
|
||||
|
||||
return new List<LocalImageInfo>();
|
||||
return GetFilesFromParentFolder(nameWithoutExtension, parentPathFiles);
|
||||
}
|
||||
|
||||
private List<LocalImageInfo> GetFilesFromParentFolder(string filenameWithoutExtension, IEnumerable<FileSystemMetadata> parentPathFiles)
|
||||
|
|
|
@ -44,24 +44,15 @@
|
|||
<Compile Include="Images\LocalImageProvider.cs" />
|
||||
<Compile Include="Parsers\BaseItemXmlParser.cs" />
|
||||
<Compile Include="Parsers\BoxSetXmlParser.cs" />
|
||||
<Compile Include="Parsers\EpisodeXmlParser.cs" />
|
||||
<Compile Include="Parsers\GameSystemXmlParser.cs" />
|
||||
<Compile Include="Parsers\GameXmlParser.cs" />
|
||||
<Compile Include="Parsers\MovieXmlParser.cs" />
|
||||
<Compile Include="Parsers\MusicVideoXmlParser.cs" />
|
||||
<Compile Include="Parsers\PlaylistXmlParser.cs" />
|
||||
<Compile Include="Parsers\SeriesXmlParser.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Providers\BoxSetXmlProvider.cs" />
|
||||
<Compile Include="Providers\EpisodeXmlProvider.cs" />
|
||||
<Compile Include="Providers\FolderXmlProvider.cs" />
|
||||
<Compile Include="Providers\GameSystemXmlProvider.cs" />
|
||||
<Compile Include="Providers\GameXmlProvider.cs" />
|
||||
<Compile Include="Providers\MovieXmlProvider.cs" />
|
||||
<Compile Include="Providers\MusicVideoXmlProvider.cs" />
|
||||
<Compile Include="Providers\PlaylistXmlProvider.cs" />
|
||||
<Compile Include="Providers\SeriesXmlProvider.cs" />
|
||||
<Compile Include="Providers\VideoXmlProvider.cs" />
|
||||
<Compile Include="Savers\BaseXmlSaver.cs" />
|
||||
<Compile Include="Savers\BoxSetXmlSaver.cs" />
|
||||
<Compile Include="Savers\FolderXmlSaver.cs" />
|
||||
|
|
|
@ -598,20 +598,6 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
|||
break;
|
||||
}
|
||||
|
||||
case "VoteCount":
|
||||
{
|
||||
var val = reader.ReadElementContentAsString();
|
||||
if (!string.IsNullOrWhiteSpace(val))
|
||||
{
|
||||
int num;
|
||||
|
||||
if (int.TryParse(val, NumberStyles.Integer, _usCulture, out num))
|
||||
{
|
||||
item.VoteCount = num;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "CollectionNumber":
|
||||
var tmdbCollection = reader.ReadElementContentAsString();
|
||||
if (!string.IsNullOrWhiteSpace(tmdbCollection))
|
||||
|
|
|
@ -17,10 +17,17 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
|||
{
|
||||
case "CollectionItems":
|
||||
|
||||
if (!reader.IsEmptyElement)
|
||||
{
|
||||
using (var subReader = reader.ReadSubtree())
|
||||
{
|
||||
FetchFromCollectionItemsNode(subReader, item);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
reader.Read();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -44,6 +51,8 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
|||
switch (reader.Name)
|
||||
{
|
||||
case "CollectionItem":
|
||||
{
|
||||
if (!reader.IsEmptyElement)
|
||||
{
|
||||
using (var subReader = reader.ReadSubtree())
|
||||
{
|
||||
|
@ -54,6 +63,11 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
|||
list.Add(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
reader.Read();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1,271 +0,0 @@
|
|||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Xml;
|
||||
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Xml;
|
||||
|
||||
namespace MediaBrowser.LocalMetadata.Parsers
|
||||
{
|
||||
/// <summary>
|
||||
/// Class EpisodeXmlParser
|
||||
/// </summary>
|
||||
public class EpisodeXmlParser : BaseItemXmlParser<Episode>
|
||||
{
|
||||
private List<LocalImageInfo> _imagesFound;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
|
||||
public EpisodeXmlParser(ILogger logger, IFileSystem fileSystem, IProviderManager providerManager, IXmlReaderSettingsFactory xmlSettings)
|
||||
: base(logger, providerManager, xmlSettings, fileSystem)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
|
||||
private string _xmlPath;
|
||||
|
||||
public void Fetch(MetadataResult<Episode> item,
|
||||
List<LocalImageInfo> images,
|
||||
string metadataFile,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
_imagesFound = images;
|
||||
_xmlPath = metadataFile;
|
||||
|
||||
Fetch(item, metadataFile, cancellationToken);
|
||||
}
|
||||
|
||||
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
||||
|
||||
/// <summary>
|
||||
/// Fetches the data from XML node.
|
||||
/// </summary>
|
||||
/// <param name="reader">The reader.</param>
|
||||
/// <param name="result">The result.</param>
|
||||
protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult<Episode> result)
|
||||
{
|
||||
var item = result.Item;
|
||||
|
||||
switch (reader.Name)
|
||||
{
|
||||
case "Episode":
|
||||
|
||||
//MB generated metadata is within an "Episode" node
|
||||
using (var subTree = reader.ReadSubtree())
|
||||
{
|
||||
subTree.MoveToContent();
|
||||
|
||||
// Loop through each element
|
||||
while (subTree.Read())
|
||||
{
|
||||
if (subTree.NodeType == XmlNodeType.Element)
|
||||
{
|
||||
FetchDataFromXmlNode(subTree, result);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case "filename":
|
||||
{
|
||||
var filename = reader.ReadElementContentAsString();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(filename))
|
||||
{
|
||||
// Strip off everything but the filename. Some metadata tools like MetaBrowser v1.0 will have an 'episodes' prefix
|
||||
// even though it's actually using the metadata folder.
|
||||
filename = Path.GetFileName(filename);
|
||||
|
||||
var parentFolder = _fileSystem.GetDirectoryName(_xmlPath);
|
||||
filename = Path.Combine(parentFolder, filename);
|
||||
var file = _fileSystem.GetFileInfo(filename);
|
||||
|
||||
if (file.Exists)
|
||||
{
|
||||
_imagesFound.Add(new LocalImageInfo
|
||||
{
|
||||
Type = ImageType.Primary,
|
||||
FileInfo = file
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "SeasonNumber":
|
||||
{
|
||||
var number = reader.ReadElementContentAsString();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(number))
|
||||
{
|
||||
int num;
|
||||
|
||||
if (int.TryParse(number, out num))
|
||||
{
|
||||
item.ParentIndexNumber = num;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "EpisodeNumber":
|
||||
{
|
||||
var number = reader.ReadElementContentAsString();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(number))
|
||||
{
|
||||
int num;
|
||||
|
||||
if (int.TryParse(number, out num))
|
||||
{
|
||||
item.IndexNumber = num;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "EpisodeNumberEnd":
|
||||
{
|
||||
var number = reader.ReadElementContentAsString();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(number))
|
||||
{
|
||||
int num;
|
||||
|
||||
if (int.TryParse(number, out num))
|
||||
{
|
||||
item.IndexNumberEnd = num;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "absolute_number":
|
||||
{
|
||||
var val = reader.ReadElementContentAsString();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(val))
|
||||
{
|
||||
int rval;
|
||||
|
||||
// int.TryParse is local aware, so it can be probamatic, force us culture
|
||||
if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval))
|
||||
{
|
||||
item.AbsoluteEpisodeNumber = rval;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case "DVD_episodenumber":
|
||||
{
|
||||
var number = reader.ReadElementContentAsString();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(number))
|
||||
{
|
||||
float num;
|
||||
|
||||
if (float.TryParse(number, NumberStyles.Any, UsCulture, out num))
|
||||
{
|
||||
item.DvdEpisodeNumber = num;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "DVD_season":
|
||||
{
|
||||
var number = reader.ReadElementContentAsString();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(number))
|
||||
{
|
||||
float num;
|
||||
|
||||
if (float.TryParse(number, NumberStyles.Any, UsCulture, out num))
|
||||
{
|
||||
item.DvdSeasonNumber = Convert.ToInt32(num);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "airsbefore_episode":
|
||||
{
|
||||
var val = reader.ReadElementContentAsString();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(val))
|
||||
{
|
||||
int rval;
|
||||
|
||||
// int.TryParse is local aware, so it can be probamatic, force us culture
|
||||
if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval))
|
||||
{
|
||||
item.AirsBeforeEpisodeNumber = rval;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "airsafter_season":
|
||||
{
|
||||
var val = reader.ReadElementContentAsString();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(val))
|
||||
{
|
||||
int rval;
|
||||
|
||||
// int.TryParse is local aware, so it can be probamatic, force us culture
|
||||
if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval))
|
||||
{
|
||||
item.AirsAfterSeasonNumber = rval;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "airsbefore_season":
|
||||
{
|
||||
var val = reader.ReadElementContentAsString();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(val))
|
||||
{
|
||||
int rval;
|
||||
|
||||
// int.TryParse is local aware, so it can be probamatic, force us culture
|
||||
if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval))
|
||||
{
|
||||
item.AirsBeforeSeasonNumber = rval;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "EpisodeName":
|
||||
{
|
||||
var name = reader.ReadElementContentAsString();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
item.Name = name;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
base.FetchDataFromXmlNode(reader, result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Movies;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using System.Xml;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Xml;
|
||||
|
||||
namespace MediaBrowser.LocalMetadata.Parsers
|
||||
{
|
||||
/// <summary>
|
||||
/// Class EpisodeXmlParser
|
||||
/// </summary>
|
||||
public class BaseVideoXmlParser<T> : BaseItemXmlParser<T>
|
||||
where T : Video
|
||||
{
|
||||
/// <summary>
|
||||
/// Fetches the data from XML node.
|
||||
/// </summary>
|
||||
/// <param name="reader">The reader.</param>
|
||||
/// <param name="result">The result.</param>
|
||||
protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult<T> result)
|
||||
{
|
||||
var item = result.Item;
|
||||
|
||||
switch (reader.Name)
|
||||
{
|
||||
case "TmdbCollectionName":
|
||||
{
|
||||
var val = reader.ReadElementContentAsString();
|
||||
var movie = item as Movie;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(val) && movie != null)
|
||||
{
|
||||
movie.CollectionName = val;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
base.FetchDataFromXmlNode(reader, result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public BaseVideoXmlParser(ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory, IFileSystem fileSystem) : base(logger, providerManager, xmlReaderSettingsFactory, fileSystem)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class MovieXmlParser : BaseVideoXmlParser<Movie>
|
||||
{
|
||||
public MovieXmlParser(ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory, IFileSystem fileSystem) : base(logger, providerManager, xmlReaderSettingsFactory, fileSystem)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class VideoXmlParser : BaseVideoXmlParser<Video>
|
||||
{
|
||||
public VideoXmlParser(ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory, IFileSystem fileSystem) : base(logger, providerManager, xmlReaderSettingsFactory, fileSystem)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using System;
|
||||
using System.Xml;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Xml;
|
||||
|
||||
namespace MediaBrowser.LocalMetadata.Parsers
|
||||
{
|
||||
public class MusicVideoXmlParser : BaseVideoXmlParser<MusicVideo>
|
||||
{
|
||||
/// <summary>
|
||||
/// Fetches the data from XML node.
|
||||
/// </summary>
|
||||
/// <param name="reader">The reader.</param>
|
||||
/// <param name="result">The result.</param>
|
||||
protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult<MusicVideo> result)
|
||||
{
|
||||
var item = result.Item;
|
||||
|
||||
switch (reader.Name)
|
||||
{
|
||||
case "Artist":
|
||||
{
|
||||
var val = reader.ReadElementContentAsString();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(val))
|
||||
{
|
||||
var artists = val.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
item.Artists.AddRange(artists);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "Album":
|
||||
item.Album = reader.ReadElementContentAsString();
|
||||
break;
|
||||
|
||||
default:
|
||||
base.FetchDataFromXmlNode(reader, result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public MusicVideoXmlParser(ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory, IFileSystem fileSystem) : base(logger, providerManager, xmlReaderSettingsFactory, fileSystem)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
using System;
|
||||
using System.Xml;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Model.Xml;
|
||||
|
||||
namespace MediaBrowser.LocalMetadata.Parsers
|
||||
{
|
||||
/// <summary>
|
||||
/// Class SeriesXmlParser
|
||||
/// </summary>
|
||||
public class SeriesXmlParser : BaseItemXmlParser<Series>
|
||||
{
|
||||
/// <summary>
|
||||
/// Fetches the data from XML node.
|
||||
/// </summary>
|
||||
/// <param name="reader">The reader.</param>
|
||||
/// <param name="result">The result.</param>
|
||||
protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult<Series> result)
|
||||
{
|
||||
var item = result.Item;
|
||||
|
||||
switch (reader.Name)
|
||||
{
|
||||
case "Series":
|
||||
//MB generated metadata is within a "Series" node
|
||||
using (var subTree = reader.ReadSubtree())
|
||||
{
|
||||
subTree.MoveToContent();
|
||||
|
||||
// Loop through each element
|
||||
while (subTree.Read())
|
||||
{
|
||||
if (subTree.NodeType == XmlNodeType.Element)
|
||||
{
|
||||
FetchDataFromXmlNode(subTree, result);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case "id":
|
||||
string id = reader.ReadElementContentAsString();
|
||||
if (!string.IsNullOrWhiteSpace(id))
|
||||
{
|
||||
item.SetProviderId(MetadataProviders.Tvdb, id);
|
||||
}
|
||||
break;
|
||||
|
||||
case "Airs_DayOfWeek":
|
||||
{
|
||||
item.AirDays = TVUtils.GetAirDays(reader.ReadElementContentAsString());
|
||||
break;
|
||||
}
|
||||
|
||||
case "Airs_Time":
|
||||
{
|
||||
var val = reader.ReadElementContentAsString();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(val))
|
||||
{
|
||||
item.AirTime = val;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "Status":
|
||||
{
|
||||
var status = reader.ReadElementContentAsString();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(status))
|
||||
{
|
||||
SeriesStatus seriesStatus;
|
||||
if (Enum.TryParse(status, true, out seriesStatus))
|
||||
{
|
||||
item.Status = seriesStatus;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Info("Unrecognized series status: " + status);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
base.FetchDataFromXmlNode(reader, result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public SeriesXmlParser(ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory, IFileSystem fileSystem) : base(logger, providerManager, xmlReaderSettingsFactory, fileSystem)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.LocalMetadata.Parsers;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Xml;
|
||||
|
||||
namespace MediaBrowser.LocalMetadata.Providers
|
||||
{
|
||||
public class EpisodeXmlProvider : BaseXmlProvider<Episode>
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly IProviderManager _providerManager;
|
||||
private readonly IXmlReaderSettingsFactory _xmlSettings;
|
||||
|
||||
public EpisodeXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlSettings)
|
||||
: base(fileSystem)
|
||||
{
|
||||
_logger = logger;
|
||||
_providerManager = providerManager;
|
||||
_xmlSettings = xmlSettings;
|
||||
}
|
||||
|
||||
protected override void Fetch(MetadataResult<Episode> result, string path, CancellationToken cancellationToken)
|
||||
{
|
||||
var images = new List<LocalImageInfo>();
|
||||
var chapters = new List<ChapterInfo>();
|
||||
|
||||
new EpisodeXmlParser(_logger, FileSystem, _providerManager, _xmlSettings).Fetch(result, images, path, cancellationToken);
|
||||
|
||||
result.Images = images;
|
||||
}
|
||||
|
||||
protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService)
|
||||
{
|
||||
var metadataPath = FileSystem.GetDirectoryName(info.Path);
|
||||
metadataPath = Path.Combine(metadataPath, "metadata");
|
||||
|
||||
var metadataFile = Path.Combine(metadataPath, Path.ChangeExtension(Path.GetFileName(info.Path), ".xml"));
|
||||
|
||||
return directoryService.GetFile(metadataFile);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
using MediaBrowser.Controller.Entities.Movies;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.LocalMetadata.Parsers;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Xml;
|
||||
|
||||
namespace MediaBrowser.LocalMetadata.Providers
|
||||
{
|
||||
public class MovieXmlProvider : BaseXmlProvider<Movie>
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly IProviderManager _providerManager;
|
||||
protected IXmlReaderSettingsFactory XmlReaderSettingsFactory { get; private set; }
|
||||
|
||||
public MovieXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory)
|
||||
: base(fileSystem)
|
||||
{
|
||||
_logger = logger;
|
||||
_providerManager = providerManager;
|
||||
XmlReaderSettingsFactory = xmlReaderSettingsFactory;
|
||||
}
|
||||
|
||||
protected override void Fetch(MetadataResult<Movie> result, string path, CancellationToken cancellationToken)
|
||||
{
|
||||
new MovieXmlParser(_logger, _providerManager, XmlReaderSettingsFactory, FileSystem).Fetch(result, path, cancellationToken);
|
||||
}
|
||||
|
||||
protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService)
|
||||
{
|
||||
return GetXmlFileInfo(info, FileSystem);
|
||||
}
|
||||
|
||||
public static FileSystemMetadata GetXmlFileInfo(ItemInfo info, IFileSystem fileSystem)
|
||||
{
|
||||
var fileInfo = fileSystem.GetFileSystemInfo(info.Path);
|
||||
|
||||
var directoryInfo = fileInfo.IsDirectory ? fileInfo : fileSystem.GetDirectoryInfo(fileSystem.GetDirectoryName(info.Path));
|
||||
|
||||
var directoryPath = directoryInfo.FullName;
|
||||
|
||||
var specificFile = Path.Combine(directoryPath, fileSystem.GetFileNameWithoutExtension(info.Path) + ".xml");
|
||||
|
||||
var file = fileSystem.GetFileInfo(specificFile);
|
||||
|
||||
// In a mixed folder, only {moviename}.xml is supported
|
||||
if (info.IsInMixedFolder)
|
||||
{
|
||||
return file;
|
||||
}
|
||||
|
||||
// If in it's own folder, prefer movie.xml, but allow the specific file as well
|
||||
var movieFile = fileSystem.GetFileInfo(Path.Combine(directoryPath, "movie.xml"));
|
||||
|
||||
return movieFile.Exists ? movieFile : file;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
using System.Threading;
|
||||
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.LocalMetadata.Parsers;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Model.Xml;
|
||||
|
||||
namespace MediaBrowser.LocalMetadata.Providers
|
||||
{
|
||||
class MusicVideoXmlProvider : BaseXmlProvider<MusicVideo>
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly IProviderManager _providerManager;
|
||||
protected IXmlReaderSettingsFactory XmlReaderSettingsFactory { get; private set; }
|
||||
|
||||
public MusicVideoXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory)
|
||||
: base(fileSystem)
|
||||
{
|
||||
_logger = logger;
|
||||
_providerManager = providerManager;
|
||||
XmlReaderSettingsFactory = xmlReaderSettingsFactory;
|
||||
}
|
||||
|
||||
protected override void Fetch(MetadataResult<MusicVideo> result, string path, CancellationToken cancellationToken)
|
||||
{
|
||||
new MusicVideoXmlParser(_logger, _providerManager, XmlReaderSettingsFactory, FileSystem).Fetch(result, path, cancellationToken);
|
||||
}
|
||||
|
||||
protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService)
|
||||
{
|
||||
return MovieXmlProvider.GetXmlFileInfo(info, FileSystem);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.LocalMetadata.Parsers;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Model.Xml;
|
||||
|
||||
namespace MediaBrowser.LocalMetadata.Providers
|
||||
{
|
||||
/// <summary>
|
||||
/// Class SeriesProviderFromXml
|
||||
/// </summary>
|
||||
public class SeriesXmlProvider : BaseXmlProvider<Series>, IHasOrder
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly IProviderManager _providerManager;
|
||||
protected IXmlReaderSettingsFactory XmlReaderSettingsFactory { get; private set; }
|
||||
|
||||
public SeriesXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory)
|
||||
: base(fileSystem)
|
||||
{
|
||||
_logger = logger;
|
||||
_providerManager = providerManager;
|
||||
XmlReaderSettingsFactory = xmlReaderSettingsFactory;
|
||||
}
|
||||
|
||||
protected override void Fetch(MetadataResult<Series> result, string path, CancellationToken cancellationToken)
|
||||
{
|
||||
new SeriesXmlParser(_logger, _providerManager, XmlReaderSettingsFactory, FileSystem).Fetch(result, path, cancellationToken);
|
||||
}
|
||||
|
||||
protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService)
|
||||
{
|
||||
return directoryService.GetFile(Path.Combine(info.Path, "series.xml"));
|
||||
}
|
||||
|
||||
public override int Order
|
||||
{
|
||||
get
|
||||
{
|
||||
// After Xbmc
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.LocalMetadata.Parsers;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using System.Threading;
|
||||
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Xml;
|
||||
|
||||
namespace MediaBrowser.LocalMetadata.Providers
|
||||
{
|
||||
class VideoXmlProvider : BaseXmlProvider<Video>
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly IProviderManager _providerManager;
|
||||
protected IXmlReaderSettingsFactory XmlReaderSettingsFactory { get; private set; }
|
||||
|
||||
public VideoXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory)
|
||||
: base(fileSystem)
|
||||
{
|
||||
_logger = logger;
|
||||
_providerManager = providerManager;
|
||||
XmlReaderSettingsFactory = xmlReaderSettingsFactory;
|
||||
}
|
||||
|
||||
protected override void Fetch(MetadataResult<Video> result, string path, CancellationToken cancellationToken)
|
||||
{
|
||||
new VideoXmlParser(_logger, _providerManager, XmlReaderSettingsFactory, FileSystem).Fetch(result, path, cancellationToken);
|
||||
}
|
||||
|
||||
protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService)
|
||||
{
|
||||
return MovieXmlProvider.GetXmlFileInfo(info, FileSystem);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -109,7 +109,6 @@ namespace MediaBrowser.LocalMetadata.Savers
|
|||
"TvDbId",
|
||||
"Type",
|
||||
"TVRageId",
|
||||
"VoteCount",
|
||||
"Website",
|
||||
"Zap2ItId",
|
||||
"CollectionItems",
|
||||
|
@ -407,10 +406,6 @@ namespace MediaBrowser.LocalMetadata.Savers
|
|||
{
|
||||
writer.WriteElementString("Rating", item.CommunityRating.Value.ToString(UsCulture));
|
||||
}
|
||||
if (item.VoteCount.HasValue)
|
||||
{
|
||||
writer.WriteElementString("VoteCount", item.VoteCount.Value.ToString(UsCulture));
|
||||
}
|
||||
|
||||
if (item.ProductionYear.HasValue && !(item is Person))
|
||||
{
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"frameworks":{
|
||||
"netstandard1.6":{
|
||||
"dependencies":{
|
||||
"NETStandard.Library":"1.6.0",
|
||||
}
|
||||
},
|
||||
".NETPortable,Version=v4.5,Profile=Profile7":{
|
||||
"buildOptions": {
|
||||
"define": [ ]
|
||||
},
|
||||
"frameworkAssemblies":{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -90,7 +90,8 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||
"h264_qsv",
|
||||
"hevc_qsv",
|
||||
"mpeg2_qsv",
|
||||
"vc1_qsv"
|
||||
"vc1_qsv",
|
||||
"h264_cuvid"
|
||||
};
|
||||
|
||||
foreach (var codec in required)
|
||||
|
|
|
@ -150,248 +150,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||
}
|
||||
}
|
||||
|
||||
public int? TotalOutputBitrate
|
||||
{
|
||||
get
|
||||
{
|
||||
return (OutputAudioBitrate ?? 0) + (OutputVideoBitrate ?? 0);
|
||||
}
|
||||
}
|
||||
|
||||
public int? OutputWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
if (VideoStream != null && VideoStream.Width.HasValue && VideoStream.Height.HasValue)
|
||||
{
|
||||
var size = new ImageSize
|
||||
{
|
||||
Width = VideoStream.Width.Value,
|
||||
Height = VideoStream.Height.Value
|
||||
};
|
||||
|
||||
var newSize = DrawingUtils.Resize(size,
|
||||
Options.Width,
|
||||
Options.Height,
|
||||
Options.MaxWidth,
|
||||
Options.MaxHeight);
|
||||
|
||||
return Convert.ToInt32(newSize.Width);
|
||||
}
|
||||
|
||||
if (!IsVideoRequest)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return Options.MaxWidth ?? Options.Width;
|
||||
}
|
||||
}
|
||||
|
||||
public int? OutputHeight
|
||||
{
|
||||
get
|
||||
{
|
||||
if (VideoStream != null && VideoStream.Width.HasValue && VideoStream.Height.HasValue)
|
||||
{
|
||||
var size = new ImageSize
|
||||
{
|
||||
Width = VideoStream.Width.Value,
|
||||
Height = VideoStream.Height.Value
|
||||
};
|
||||
|
||||
var newSize = DrawingUtils.Resize(size,
|
||||
Options.Width,
|
||||
Options.Height,
|
||||
Options.MaxWidth,
|
||||
Options.MaxHeight);
|
||||
|
||||
return Convert.ToInt32(newSize.Height);
|
||||
}
|
||||
|
||||
if (!IsVideoRequest)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return Options.MaxHeight ?? Options.Height;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Predicts the audio sample rate that will be in the output stream
|
||||
/// </summary>
|
||||
public int? TargetVideoBitDepth
|
||||
{
|
||||
get
|
||||
{
|
||||
var stream = VideoStream;
|
||||
return stream == null || !Options.Static ? null : stream.BitDepth;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the target reference frames.
|
||||
/// </summary>
|
||||
/// <value>The target reference frames.</value>
|
||||
public int? TargetRefFrames
|
||||
{
|
||||
get
|
||||
{
|
||||
var stream = VideoStream;
|
||||
return stream == null || !Options.Static ? null : stream.RefFrames;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Predicts the audio sample rate that will be in the output stream
|
||||
/// </summary>
|
||||
public float? TargetFramerate
|
||||
{
|
||||
get
|
||||
{
|
||||
var stream = VideoStream;
|
||||
var requestedFramerate = Options.MaxFramerate ?? Options.Framerate;
|
||||
|
||||
return requestedFramerate.HasValue && !Options.Static
|
||||
? requestedFramerate
|
||||
: stream == null ? null : stream.AverageFrameRate ?? stream.RealFrameRate;
|
||||
}
|
||||
}
|
||||
|
||||
public TransportStreamTimestamp TargetTimestamp
|
||||
{
|
||||
get
|
||||
{
|
||||
var defaultValue = string.Equals(OutputContainer, "m2ts", StringComparison.OrdinalIgnoreCase) ?
|
||||
TransportStreamTimestamp.Valid :
|
||||
TransportStreamTimestamp.None;
|
||||
|
||||
return !Options.Static
|
||||
? defaultValue
|
||||
: InputTimestamp;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Predicts the audio sample rate that will be in the output stream
|
||||
/// </summary>
|
||||
public int? TargetPacketLength
|
||||
{
|
||||
get
|
||||
{
|
||||
var stream = VideoStream;
|
||||
return !Options.Static
|
||||
? null
|
||||
: stream == null ? null : stream.PacketLength;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Predicts the audio sample rate that will be in the output stream
|
||||
/// </summary>
|
||||
public string TargetVideoProfile
|
||||
{
|
||||
get
|
||||
{
|
||||
var stream = VideoStream;
|
||||
return !string.IsNullOrEmpty(Options.Profile) && !Options.Static
|
||||
? Options.Profile
|
||||
: stream == null ? null : stream.Profile;
|
||||
}
|
||||
}
|
||||
|
||||
public string TargetVideoCodecTag
|
||||
{
|
||||
get
|
||||
{
|
||||
var stream = VideoStream;
|
||||
return !Options.Static
|
||||
? null
|
||||
: stream == null ? null : stream.CodecTag;
|
||||
}
|
||||
}
|
||||
|
||||
public bool? IsTargetAnamorphic
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Options.Static)
|
||||
{
|
||||
return VideoStream == null ? null : VideoStream.IsAnamorphic;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool? IsTargetInterlaced
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Options.Static)
|
||||
{
|
||||
return VideoStream == null ? (bool?)null : VideoStream.IsInterlaced;
|
||||
}
|
||||
|
||||
if (DeInterlace)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return VideoStream == null ? (bool?)null : VideoStream.IsInterlaced;
|
||||
}
|
||||
}
|
||||
|
||||
public bool? IsTargetAVC
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Options.Static)
|
||||
{
|
||||
return VideoStream == null ? null : VideoStream.IsAVC;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int? TargetVideoStreamCount
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Options.Static)
|
||||
{
|
||||
return GetMediaStreamCount(MediaStreamType.Video, int.MaxValue);
|
||||
}
|
||||
return GetMediaStreamCount(MediaStreamType.Video, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public int? TargetAudioStreamCount
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Options.Static)
|
||||
{
|
||||
return GetMediaStreamCount(MediaStreamType.Audio, int.MaxValue);
|
||||
}
|
||||
return GetMediaStreamCount(MediaStreamType.Audio, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private int? GetMediaStreamCount(MediaStreamType type, int limit)
|
||||
{
|
||||
var count = MediaSource.GetStreamCount(type);
|
||||
|
||||
if (count.HasValue)
|
||||
{
|
||||
count = Math.Min(count.Value, limit);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public override void ReportTranscodingProgress(TimeSpan? transcodingPosition, float? framerate, double? percentComplete, long? bytesTranscoded, int? bitRate)
|
||||
{
|
||||
var ticks = transcodingPosition.HasValue ? transcodingPosition.Value.Ticks : (long?)null;
|
||||
|
|
|
@ -105,7 +105,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||
//state.OutputContainer = (container ?? string.Empty).TrimStart('.');
|
||||
|
||||
state.OutputAudioBitrate = encodingHelper.GetAudioBitrateParam(state.Options, state.AudioStream);
|
||||
state.OutputAudioSampleRate = request.AudioSampleRate;
|
||||
|
||||
state.OutputAudioCodec = state.Options.AudioCodec;
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user