commit
e0c907cc60
|
@ -33,10 +33,6 @@
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
|
||||||
<None Include="project.json" />
|
|
||||||
<!-- A reference to the entire .NET Framework is automatically included -->
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="BDInfoSettings.cs" />
|
<Compile Include="BDInfoSettings.cs" />
|
||||||
<Compile Include="BDROM.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>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
|
||||||
<None Include="project.json" />
|
|
||||||
<!-- A reference to the entire .NET Framework is automatically included -->
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="BigEndianBinaryReader.cs" />
|
<Compile Include="BigEndianBinaryReader.cs" />
|
||||||
<Compile Include="Ifo\AudioAttributes.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>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
<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>
|
||||||
<Reference Include="ServiceStack.Text, Version=4.5.8.0, Culture=neutral, processorArchitecture=MSIL">
|
<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>
|
<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>
|
<HintPath>..\packages\SharpCompress.0.14.0\lib\net45\SharpCompress.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="SimpleInjector, Version=4.0.7.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
|
<Reference Include="SimpleInjector, Version=4.0.8.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\SimpleInjector.4.0.7\lib\net45\SimpleInjector.dll</HintPath>
|
<HintPath>..\packages\SimpleInjector.4.0.8\lib\net45\SimpleInjector.dll</HintPath>
|
||||||
<Private>True</Private>
|
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
|
|
|
@ -157,6 +157,7 @@ namespace Emby.Common.Implementations.TextEncoding
|
||||||
case "ota":
|
case "ota":
|
||||||
case "tur":
|
case "tur":
|
||||||
return "windows-1254";
|
return "windows-1254";
|
||||||
|
case "bgr":
|
||||||
case "rus":
|
case "rus":
|
||||||
return "windows-1251";
|
return "windows-1251";
|
||||||
case "vie":
|
case "vie":
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<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="ServiceStack.Text" version="4.5.8" targetFramework="net462" />
|
||||||
<package id="SharpCompress" version="0.14.0" 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>
|
</packages>
|
|
@ -70,7 +70,7 @@ namespace Emby.Dlna.Profiles
|
||||||
|
|
||||||
new DirectPlayProfile
|
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
|
Type = DlnaProfileType.Audio
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,42 +31,7 @@ namespace Emby.Dlna.Profiles
|
||||||
{
|
{
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "mp3",
|
Container = "aac,mp3,mpa,wav,wma,mp2,ogg,oga,webma,ape,opus,flac,m4a",
|
||||||
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",
|
|
||||||
Type = DlnaProfileType.Audio
|
Type = DlnaProfileType.Audio
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
<XmlRootAttributes />
|
<XmlRootAttributes />
|
||||||
<DirectPlayProfiles>
|
<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="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>
|
</DirectPlayProfiles>
|
||||||
<TranscodingProfiles>
|
<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" />
|
<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>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<XmlRootAttributes />
|
<XmlRootAttributes />
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="mp3" audioCodec="mp2,mp3" type="Audio" />
|
<DirectPlayProfile container="aac,mp3,mpa,wav,wma,mp2,ogg,oga,webma,ape,opus,flac,m4a" 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" />
|
|
||||||
</DirectPlayProfiles>
|
</DirectPlayProfiles>
|
||||||
<TranscodingProfiles>
|
<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" />
|
<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);
|
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
|
// Even if the caller specified 100, don't use it because it takes forever
|
||||||
quality = Math.Min(quality, 99);
|
quality = Math.Min(quality, 99);
|
||||||
|
|
|
@ -126,11 +126,11 @@ namespace Emby.Drawing.Skia
|
||||||
for (int row = 0; row < bitmap.Height; ++row)
|
for (int row = 0; row < bitmap.Height; ++row)
|
||||||
{
|
{
|
||||||
if (IsAllWhiteRow(bitmap, row))
|
if (IsAllWhiteRow(bitmap, row))
|
||||||
topmost = row;
|
topmost = row + 1;
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bottommost = 0;
|
int bottommost = bitmap.Height;
|
||||||
for (int row = bitmap.Height - 1; row >= 0; --row)
|
for (int row = bitmap.Height - 1; row >= 0; --row)
|
||||||
{
|
{
|
||||||
if (IsAllWhiteRow(bitmap, row))
|
if (IsAllWhiteRow(bitmap, row))
|
||||||
|
@ -138,11 +138,11 @@ namespace Emby.Drawing.Skia
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int leftmost = 0, rightmost = 0;
|
int leftmost = 0, rightmost = bitmap.Width;
|
||||||
for (int col = 0; col < bitmap.Width; ++col)
|
for (int col = 0; col < bitmap.Width; ++col)
|
||||||
{
|
{
|
||||||
if (IsAllWhiteColumn(bitmap, col))
|
if (IsAllWhiteColumn(bitmap, col))
|
||||||
leftmost = col;
|
leftmost = col + 1;
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -162,13 +162,6 @@ namespace Emby.Drawing.Skia
|
||||||
using (var subset = image.Subset(newRect))
|
using (var subset = image.Subset(newRect))
|
||||||
{
|
{
|
||||||
return SKBitmap.FromImage(subset);
|
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 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);
|
var requiresTransparencyHack = TransparentImageTypes.Contains(Path.GetExtension(path) ?? string.Empty);
|
||||||
|
|
||||||
|
@ -206,6 +199,8 @@ namespace Emby.Drawing.Skia
|
||||||
// decode
|
// decode
|
||||||
codec.GetPixels(bitmap.Info, bitmap.GetPixels());
|
codec.GetPixels(bitmap.Info, bitmap.GetPixels());
|
||||||
|
|
||||||
|
origin = codec.Origin;
|
||||||
|
|
||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -214,7 +209,7 @@ namespace Emby.Drawing.Skia
|
||||||
|
|
||||||
if (resultBitmap == null)
|
if (resultBitmap == null)
|
||||||
{
|
{
|
||||||
return Decode(path, true);
|
return Decode(path, true, out origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have to resize these they often end up distorted
|
// If we have to resize these they often end up distorted
|
||||||
|
@ -222,27 +217,128 @@ namespace Emby.Drawing.Skia
|
||||||
{
|
{
|
||||||
using (resultBitmap)
|
using (resultBitmap)
|
||||||
{
|
{
|
||||||
return Decode(path, true);
|
return Decode(path, true, out origin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
origin = SKCodecOrigin.TopLeft;
|
||||||
return resultBitmap;
|
return resultBitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SKBitmap GetBitmap(string path, bool cropWhitespace)
|
private SKBitmap GetBitmap(string path, bool cropWhitespace, bool forceAnalyzeBitmap, out SKCodecOrigin origin)
|
||||||
{
|
{
|
||||||
if (cropWhitespace)
|
if (cropWhitespace)
|
||||||
{
|
{
|
||||||
using (var bitmap = Decode(path))
|
using (var bitmap = Decode(path, forceAnalyzeBitmap, out origin))
|
||||||
{
|
{
|
||||||
return CropWhiteSpace(bitmap);
|
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))
|
if (string.IsNullOrWhiteSpace(inputPath))
|
||||||
{
|
{
|
||||||
|
@ -260,7 +356,7 @@ namespace Emby.Drawing.Skia
|
||||||
var blur = options.Blur ?? 0;
|
var blur = options.Blur ?? 0;
|
||||||
var hasIndicator = options.AddPlayedIndicator || options.UnplayedCount.HasValue || !options.PercentPlayed.Equals(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)
|
if (bitmap == null)
|
||||||
{
|
{
|
||||||
|
@ -272,7 +368,7 @@ namespace Emby.Drawing.Skia
|
||||||
var originalImageSize = new ImageSize(bitmap.Width, bitmap.Height);
|
var originalImageSize = new ImageSize(bitmap.Width, bitmap.Height);
|
||||||
ImageHelper.SaveImageSize(inputPath, dateModified, originalImageSize);
|
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
|
// Just spit out the original file if all the options are default
|
||||||
return inputPath;
|
return inputPath;
|
||||||
|
|
|
@ -217,14 +217,23 @@ namespace Emby.Drawing
|
||||||
dateModified = tuple.Item2;
|
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
|
// Just spit out the original file if all the options are default
|
||||||
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
|
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageSize? originalImageSize = GetSavedImageSize(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
|
// Just spit out the original file if all the options are default
|
||||||
_logger.Info("Returning original image {0}", originalImagePath);
|
_logger.Info("Returning original image {0}", originalImagePath);
|
||||||
|
@ -243,7 +252,6 @@ namespace Emby.Drawing
|
||||||
|
|
||||||
if (!_fileSystem.FileExists(cacheFilePath))
|
if (!_fileSystem.FileExists(cacheFilePath))
|
||||||
{
|
{
|
||||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFilePath));
|
|
||||||
var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(cacheFilePath));
|
var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(cacheFilePath));
|
||||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
|
||||||
|
|
||||||
|
@ -252,13 +260,14 @@ namespace Emby.Drawing
|
||||||
item = _libraryManager().GetItemById(options.ItemId);
|
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))
|
if (string.Equals(resultPath, originalImagePath, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
|
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFilePath));
|
||||||
CopyFile(tmpPath, cacheFilePath);
|
CopyFile(tmpPath, cacheFilePath);
|
||||||
|
|
||||||
return new Tuple<string, string, DateTime>(tmpPath, GetMimeType(outputFormat, cacheFilePath), _fileSystem.GetLastWriteTimeUtc(tmpPath));
|
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[][] {
|
//private static int[][] OPERATIONS = new int[][] {
|
||||||
// TopLeft
|
// TopLeft
|
||||||
//new int[] { 0, NONE},
|
//new int[] { 0, NONE},
|
||||||
|
|
|
@ -32,7 +32,7 @@ namespace Emby.Drawing
|
||||||
throw new NotImplementedException();
|
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();
|
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>
|
<HintPath>..\packages\ServiceStack.Text.4.5.8\lib\net45\ServiceStack.Text.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="SimpleInjector, Version=4.0.7.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
|
<Reference Include="SimpleInjector, Version=4.0.8.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\SimpleInjector.4.0.7\lib\net45\SimpleInjector.dll</HintPath>
|
<HintPath>..\packages\SimpleInjector.4.0.8\lib\net45\SimpleInjector.dll</HintPath>
|
||||||
<Private>True</Private>
|
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Configuration" />
|
<Reference Include="System.Configuration" />
|
||||||
|
|
|
@ -332,7 +332,13 @@ namespace Emby.Server.Core.IO
|
||||||
NotifyFilters.Attributes;
|
NotifyFilters.Attributes;
|
||||||
|
|
||||||
newWatcher.Created += watcher_Changed;
|
newWatcher.Created += watcher_Changed;
|
||||||
newWatcher.Deleted += 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.Renamed += watcher_Changed;
|
||||||
newWatcher.Changed += watcher_Changed;
|
newWatcher.Changed += watcher_Changed;
|
||||||
|
|
||||||
|
|
|
@ -2,5 +2,5 @@
|
||||||
<packages>
|
<packages>
|
||||||
<package id="Microsoft.IO.RecyclableMemoryStream" version="1.2.2" targetFramework="net462" />
|
<package id="Microsoft.IO.RecyclableMemoryStream" version="1.2.2" targetFramework="net462" />
|
||||||
<package id="ServiceStack.Text" version="4.5.8" 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>
|
</packages>
|
|
@ -123,7 +123,7 @@ namespace Emby.Server.Implementations.Activity
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.IsThemeMedia)
|
if (e.Item != null && e.Item.IsThemeMedia)
|
||||||
{
|
{
|
||||||
// Don't report theme song or local trailer playback
|
// Don't report theme song or local trailer playback
|
||||||
return;
|
return;
|
||||||
|
@ -155,7 +155,7 @@ namespace Emby.Server.Implementations.Activity
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.IsThemeMedia)
|
if (e.Item != null && e.Item.IsThemeMedia)
|
||||||
{
|
{
|
||||||
// Don't report theme song or local trailer playback
|
// Don't report theme song or local trailer playback
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -176,7 +176,9 @@ namespace Emby.Server.Implementations.Channels
|
||||||
|
|
||||||
var internalResult = await GetChannelsInternal(query, cancellationToken).ConfigureAwait(false);
|
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))
|
var returnItems = (await _dtoService.GetBaseItemDtos(internalResult.Items, dtoOptions, user).ConfigureAwait(false))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
@ -558,7 +560,10 @@ namespace Emby.Server.Implementations.Channels
|
||||||
totalRecordCount = items.Length;
|
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))
|
var returnItems = (await _dtoService.GetBaseItemDtos(items, dtoOptions, user).ConfigureAwait(false))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
@ -825,7 +830,10 @@ namespace Emby.Server.Implementations.Channels
|
||||||
|
|
||||||
RefreshIfNeeded(internalResult.Items);
|
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))
|
var returnItems = (await _dtoService.GetBaseItemDtos(internalResult.Items, dtoOptions, user).ConfigureAwait(false))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
@ -974,7 +982,10 @@ namespace Emby.Server.Implementations.Channels
|
||||||
|
|
||||||
var internalResult = await GetChannelItemsInternal(query, new Progress<double>(), cancellationToken).ConfigureAwait(false);
|
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))
|
var returnItems = (await _dtoService.GetBaseItemDtos(internalResult.Items, dtoOptions, user).ConfigureAwait(false))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
@ -1378,12 +1389,6 @@ namespace Emby.Server.Implementations.Channels
|
||||||
item.SetImagePath(ImageType.Primary, info.ImageUrl);
|
item.SetImagePath(ImageType.Primary, info.ImageUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.SourceType != SourceType.Channel)
|
|
||||||
{
|
|
||||||
item.SourceType = SourceType.Channel;
|
|
||||||
forceUpdate = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isNew)
|
if (isNew)
|
||||||
{
|
{
|
||||||
await _libraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
|
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", "ParentId", "GUID", existingColumnNames);
|
||||||
AddColumn(db, "TypedBaseItems", "Genres", "Text", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "Genres", "Text", existingColumnNames);
|
||||||
AddColumn(db, "TypedBaseItems", "SortName", "Text", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "SortName", "Text", existingColumnNames);
|
||||||
|
AddColumn(db, "TypedBaseItems", "ForcedSortName", "Text", existingColumnNames);
|
||||||
|
|
||||||
AddColumn(db, "TypedBaseItems", "RunTimeTicks", "BIGINT", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "RunTimeTicks", "BIGINT", existingColumnNames);
|
||||||
|
|
||||||
AddColumn(db, "TypedBaseItems", "HomePageUrl", "Text", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "HomePageUrl", "Text", existingColumnNames);
|
||||||
AddColumn(db, "TypedBaseItems", "VoteCount", "INT", existingColumnNames);
|
|
||||||
AddColumn(db, "TypedBaseItems", "DisplayMediaType", "Text", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "DisplayMediaType", "Text", existingColumnNames);
|
||||||
AddColumn(db, "TypedBaseItems", "DateCreated", "DATETIME", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "DateCreated", "DATETIME", existingColumnNames);
|
||||||
AddColumn(db, "TypedBaseItems", "DateModified", "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", "UnratedType", "Text", existingColumnNames);
|
||||||
AddColumn(db, "TypedBaseItems", "TopParentId", "Text", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "TopParentId", "Text", existingColumnNames);
|
||||||
AddColumn(db, "TypedBaseItems", "IsItemByName", "BIT", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "IsItemByName", "BIT", existingColumnNames);
|
||||||
AddColumn(db, "TypedBaseItems", "SourceType", "Text", existingColumnNames);
|
|
||||||
AddColumn(db, "TypedBaseItems", "TrailerTypes", "Text", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "TrailerTypes", "Text", existingColumnNames);
|
||||||
AddColumn(db, "TypedBaseItems", "CriticRating", "Float", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "CriticRating", "Float", existingColumnNames);
|
||||||
AddColumn(db, "TypedBaseItems", "InheritedTags", "Text", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "InheritedTags", "Text", existingColumnNames);
|
||||||
|
@ -424,9 +424,8 @@ namespace Emby.Server.Implementations.Data
|
||||||
"OfficialRating",
|
"OfficialRating",
|
||||||
"HomePageUrl",
|
"HomePageUrl",
|
||||||
"DisplayMediaType",
|
"DisplayMediaType",
|
||||||
"SortName",
|
"ForcedSortName",
|
||||||
"RunTimeTicks",
|
"RunTimeTicks",
|
||||||
"VoteCount",
|
|
||||||
"DateCreated",
|
"DateCreated",
|
||||||
"DateModified",
|
"DateModified",
|
||||||
"guid",
|
"guid",
|
||||||
|
@ -439,7 +438,6 @@ namespace Emby.Server.Implementations.Data
|
||||||
"LockedFields",
|
"LockedFields",
|
||||||
"Studios",
|
"Studios",
|
||||||
"Tags",
|
"Tags",
|
||||||
"SourceType",
|
|
||||||
"TrailerTypes",
|
"TrailerTypes",
|
||||||
"OriginalTitle",
|
"OriginalTitle",
|
||||||
"PrimaryVersionId",
|
"PrimaryVersionId",
|
||||||
|
@ -541,9 +539,9 @@ namespace Emby.Server.Implementations.Data
|
||||||
"Genres",
|
"Genres",
|
||||||
"InheritedParentalRatingValue",
|
"InheritedParentalRatingValue",
|
||||||
"SortName",
|
"SortName",
|
||||||
|
"ForcedSortName",
|
||||||
"RunTimeTicks",
|
"RunTimeTicks",
|
||||||
"HomePageUrl",
|
"HomePageUrl",
|
||||||
"VoteCount",
|
|
||||||
"DisplayMediaType",
|
"DisplayMediaType",
|
||||||
"DateCreated",
|
"DateCreated",
|
||||||
"DateModified",
|
"DateModified",
|
||||||
|
@ -563,7 +561,6 @@ namespace Emby.Server.Implementations.Data
|
||||||
"UnratedType",
|
"UnratedType",
|
||||||
"TopParentId",
|
"TopParentId",
|
||||||
"IsItemByName",
|
"IsItemByName",
|
||||||
"SourceType",
|
|
||||||
"TrailerTypes",
|
"TrailerTypes",
|
||||||
"CriticRating",
|
"CriticRating",
|
||||||
"InheritedTags",
|
"InheritedTags",
|
||||||
|
@ -815,10 +812,12 @@ namespace Emby.Server.Implementations.Data
|
||||||
saveItemStatement.TryBind("@InheritedParentalRatingValue", item.InheritedParentalRatingValue);
|
saveItemStatement.TryBind("@InheritedParentalRatingValue", item.InheritedParentalRatingValue);
|
||||||
|
|
||||||
saveItemStatement.TryBind("@SortName", item.SortName);
|
saveItemStatement.TryBind("@SortName", item.SortName);
|
||||||
|
|
||||||
|
saveItemStatement.TryBind("@ForcedSortName", item.ForcedSortName);
|
||||||
|
|
||||||
saveItemStatement.TryBind("@RunTimeTicks", item.RunTimeTicks);
|
saveItemStatement.TryBind("@RunTimeTicks", item.RunTimeTicks);
|
||||||
|
|
||||||
saveItemStatement.TryBind("@HomePageUrl", item.HomePageUrl);
|
saveItemStatement.TryBind("@HomePageUrl", item.HomePageUrl);
|
||||||
saveItemStatement.TryBind("@VoteCount", item.VoteCount);
|
|
||||||
saveItemStatement.TryBind("@DisplayMediaType", item.DisplayMediaType);
|
saveItemStatement.TryBind("@DisplayMediaType", item.DisplayMediaType);
|
||||||
saveItemStatement.TryBind("@DateCreated", item.DateCreated);
|
saveItemStatement.TryBind("@DateCreated", item.DateCreated);
|
||||||
saveItemStatement.TryBind("@DateModified", item.DateModified);
|
saveItemStatement.TryBind("@DateModified", item.DateModified);
|
||||||
|
@ -909,7 +908,6 @@ namespace Emby.Server.Implementations.Data
|
||||||
isByName = dualAccess == null || dualAccess.IsAccessedByName;
|
isByName = dualAccess == null || dualAccess.IsAccessedByName;
|
||||||
}
|
}
|
||||||
saveItemStatement.TryBind("@IsItemByName", isByName);
|
saveItemStatement.TryBind("@IsItemByName", isByName);
|
||||||
saveItemStatement.TryBind("@SourceType", item.SourceType.ToString());
|
|
||||||
|
|
||||||
var trailer = item as Trailer;
|
var trailer = item as Trailer;
|
||||||
if (trailer != null && trailer.TrailerTypes.Count > 0)
|
if (trailer != null && trailer.TrailerTypes.Count > 0)
|
||||||
|
@ -1624,7 +1622,7 @@ namespace Emby.Server.Implementations.Data
|
||||||
{
|
{
|
||||||
if (!reader.IsDBNull(index))
|
if (!reader.IsDBNull(index))
|
||||||
{
|
{
|
||||||
item.SortName = reader.GetString(index);
|
item.ForcedSortName = reader.GetString(index);
|
||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
@ -1635,15 +1633,6 @@ namespace Emby.Server.Implementations.Data
|
||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
|
|
||||||
if (HasField(query, ItemFields.VoteCount))
|
|
||||||
{
|
|
||||||
if (!reader.IsDBNull(index))
|
|
||||||
{
|
|
||||||
item.VoteCount = reader.GetInt32(index);
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HasField(query, ItemFields.DateCreated))
|
if (HasField(query, ItemFields.DateCreated))
|
||||||
{
|
{
|
||||||
if (!reader.IsDBNull(index))
|
if (!reader.IsDBNull(index))
|
||||||
|
@ -1733,12 +1722,6 @@ namespace Emby.Server.Implementations.Data
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!reader.IsDBNull(index))
|
|
||||||
{
|
|
||||||
item.SourceType = (SourceType)Enum.Parse(typeof(SourceType), reader.GetString(index), true);
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
|
|
||||||
if (hasTrailerTypes)
|
if (hasTrailerTypes)
|
||||||
{
|
{
|
||||||
var trailer = item as Trailer;
|
var trailer = item as Trailer;
|
||||||
|
@ -2283,7 +2266,7 @@ namespace Emby.Server.Implementations.Data
|
||||||
}
|
}
|
||||||
if (field == ItemFields.SortName)
|
if (field == ItemFields.SortName)
|
||||||
{
|
{
|
||||||
return new[] { "SortName" };
|
return new[] { "ForcedSortName" };
|
||||||
}
|
}
|
||||||
if (field == ItemFields.Taglines)
|
if (field == ItemFields.Taglines)
|
||||||
{
|
{
|
||||||
|
@ -2306,7 +2289,6 @@ namespace Emby.Server.Implementations.Data
|
||||||
case ItemFields.HomePageUrl:
|
case ItemFields.HomePageUrl:
|
||||||
case ItemFields.Keywords:
|
case ItemFields.Keywords:
|
||||||
case ItemFields.DisplayMediaType:
|
case ItemFields.DisplayMediaType:
|
||||||
case ItemFields.VoteCount:
|
|
||||||
case ItemFields.CustomRating:
|
case ItemFields.CustomRating:
|
||||||
case ItemFields.ProductionLocations:
|
case ItemFields.ProductionLocations:
|
||||||
case ItemFields.Settings:
|
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)
|
if (query.TrailerTypes.Length > 0)
|
||||||
{
|
{
|
||||||
var clauses = new List<string>();
|
var clauses = new List<string>();
|
||||||
|
@ -5017,14 +4971,6 @@ namespace Emby.Server.Implementations.Data
|
||||||
statement.TryBind("@NameContains", "%" + query.NameContains + "%");
|
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;
|
return whereClauses;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1058,11 +1058,6 @@ namespace Emby.Server.Implementations.Dto
|
||||||
dto.CommunityRating = item.CommunityRating;
|
dto.CommunityRating = item.CommunityRating;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fields.Contains(ItemFields.VoteCount))
|
|
||||||
{
|
|
||||||
dto.VoteCount = item.VoteCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
//if (item.IsFolder)
|
//if (item.IsFolder)
|
||||||
//{
|
//{
|
||||||
// var folder = (Folder)item;
|
// var folder = (Folder)item;
|
||||||
|
@ -1084,7 +1079,10 @@ namespace Emby.Server.Implementations.Dto
|
||||||
if (audio != null)
|
if (audio != null)
|
||||||
{
|
{
|
||||||
dto.Album = audio.Album;
|
dto.Album = audio.Album;
|
||||||
dto.ExtraType = audio.ExtraType;
|
if (audio.ExtraType.HasValue)
|
||||||
|
{
|
||||||
|
dto.ExtraType = audio.ExtraType.Value.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
var albumParent = audio.AlbumEntity;
|
var albumParent = audio.AlbumEntity;
|
||||||
|
|
||||||
|
@ -1239,7 +1237,10 @@ namespace Emby.Server.Implementations.Dto
|
||||||
dto.Chapters = GetChapterInfoDtos(item);
|
dto.Chapters = GetChapterInfoDtos(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
dto.ExtraType = video.ExtraType;
|
if (video.ExtraType.HasValue)
|
||||||
|
{
|
||||||
|
dto.ExtraType = video.ExtraType.Value.ToString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fields.Contains(ItemFields.MediaStreams))
|
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;
|
series = series ?? season.Series;
|
||||||
if (series != null)
|
if (series != null)
|
||||||
|
@ -1586,7 +1587,7 @@ namespace Emby.Server.Implementations.Dto
|
||||||
{
|
{
|
||||||
var imageInfo = item.GetImageInfo(ImageType.Primary, 0);
|
var imageInfo = item.GetImageInfo(ImageType.Primary, 0);
|
||||||
|
|
||||||
if (imageInfo == null || !imageInfo.IsLocalFile)
|
if (imageInfo == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -1610,6 +1611,11 @@ namespace Emby.Server.Implementations.Dto
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (!imageInfo.IsLocalFile)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
size = _imageProcessor.GetImageSize(imageInfo);
|
size = _imageProcessor.GetImageSize(imageInfo);
|
||||||
|
|
|
@ -31,6 +31,9 @@
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="..\SharedVersion.cs">
|
||||||
|
<Link>Properties\SharedVersion.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="Activity\ActivityLogEntryPoint.cs" />
|
<Compile Include="Activity\ActivityLogEntryPoint.cs" />
|
||||||
<Compile Include="Activity\ActivityManager.cs" />
|
<Compile Include="Activity\ActivityManager.cs" />
|
||||||
<Compile Include="Activity\ActivityRepository.cs" />
|
<Compile Include="Activity\ActivityRepository.cs" />
|
||||||
|
|
|
@ -38,7 +38,10 @@ namespace Emby.Server.Implementations.Library
|
||||||
// Synology
|
// Synology
|
||||||
"@eaDir",
|
"@eaDir",
|
||||||
"eaDir",
|
"eaDir",
|
||||||
"#recycle"
|
"#recycle",
|
||||||
|
|
||||||
|
// Qnap
|
||||||
|
"@Recycle"
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1292,7 +1292,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<BaseItem> GetItemList(InternalItemsQuery query)
|
public IEnumerable<BaseItem> GetItemList(InternalItemsQuery query, bool allowExternalContent)
|
||||||
{
|
{
|
||||||
if (query.Recursive && query.ParentId.HasValue)
|
if (query.Recursive && query.ParentId.HasValue)
|
||||||
{
|
{
|
||||||
|
@ -1305,12 +1305,17 @@ namespace Emby.Server.Implementations.Library
|
||||||
|
|
||||||
if (query.User != null)
|
if (query.User != null)
|
||||||
{
|
{
|
||||||
AddUserToQuery(query, query.User);
|
AddUserToQuery(query, query.User, allowExternalContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ItemRepository.GetItemList(query);
|
return ItemRepository.GetItemList(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<BaseItem> GetItemList(InternalItemsQuery query)
|
||||||
|
{
|
||||||
|
return GetItemList(query, true);
|
||||||
|
}
|
||||||
|
|
||||||
public int GetCount(InternalItemsQuery query)
|
public int GetCount(InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
if (query.Recursive && query.ParentId.HasValue)
|
if (query.Recursive && query.ParentId.HasValue)
|
||||||
|
@ -1548,7 +1553,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
query.Parent = null;
|
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 &&
|
if (query.AncestorIds.Length == 0 &&
|
||||||
!query.ParentId.HasValue &&
|
!query.ParentId.HasValue &&
|
||||||
|
@ -1561,7 +1566,8 @@ namespace Emby.Server.Implementations.Library
|
||||||
var userViews = _userviewManager().GetUserViews(new UserViewQuery
|
var userViews = _userviewManager().GetUserViews(new UserViewQuery
|
||||||
{
|
{
|
||||||
UserId = user.Id.ToString("N"),
|
UserId = user.Id.ToString("N"),
|
||||||
IncludeHidden = true
|
IncludeHidden = true,
|
||||||
|
IncludeExternalContent = allowExternalContent
|
||||||
|
|
||||||
}, CancellationToken.None).Result.ToList();
|
}, CancellationToken.None).Result.ToList();
|
||||||
|
|
||||||
|
|
|
@ -202,8 +202,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
|
|
||||||
private bool IsValidUsernameCharacter(char i)
|
private bool IsValidUsernameCharacter(char i)
|
||||||
{
|
{
|
||||||
return char.IsLetterOrDigit(i) || char.Equals(i, '-') || char.Equals(i, '_') || char.Equals(i, '\'') ||
|
return !char.Equals(i, '<') && !char.Equals(i, '>');
|
||||||
char.Equals(i, '.');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string MakeValidUsername(string username)
|
public string MakeValidUsername(string username)
|
||||||
|
|
|
@ -280,7 +280,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
|
|
||||||
} : new string[] { };
|
} : new string[] { };
|
||||||
|
|
||||||
return _libraryManager.GetItemList(new InternalItemsQuery(user)
|
var query = new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
IncludeItemTypes = includeItemTypes,
|
IncludeItemTypes = includeItemTypes,
|
||||||
SortOrder = SortOrder.Descending,
|
SortOrder = SortOrder.Descending,
|
||||||
|
@ -289,11 +289,16 @@ namespace Emby.Server.Implementations.Library
|
||||||
ExcludeItemTypes = excludeItemTypes,
|
ExcludeItemTypes = excludeItemTypes,
|
||||||
IsVirtualItem = false,
|
IsVirtualItem = false,
|
||||||
Limit = limit * 5,
|
Limit = limit * 5,
|
||||||
SourceTypes = parents.Count == 0 ? new[] { SourceType.Library } : new SourceType[] { },
|
|
||||||
IsPlayed = isPlayed,
|
IsPlayed = isPlayed,
|
||||||
DtoOptions = options
|
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);
|
writer.WriteElementString("studio", studio);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.VoteCount.HasValue)
|
|
||||||
{
|
|
||||||
writer.WriteElementString("votes", item.VoteCount.Value.ToString(CultureInfo.InvariantCulture));
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.WriteEndElement();
|
writer.WriteEndElement();
|
||||||
writer.WriteEndDocument();
|
writer.WriteEndDocument();
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,6 +136,9 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
||||||
var requestBody = "[\"" + string.Join("\", \"", programsID) + "\"]";
|
var requestBody = "[\"" + string.Join("\", \"", programsID) + "\"]";
|
||||||
httpOptions.RequestContent = requestBody;
|
httpOptions.RequestContent = requestBody;
|
||||||
|
|
||||||
|
double wideAspect = 1.77777778;
|
||||||
|
var primaryImageCategory = "Logo";
|
||||||
|
|
||||||
using (var innerResponse = await Post(httpOptions, true, info).ConfigureAwait(false))
|
using (var innerResponse = await Post(httpOptions, true, info).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
StreamReader innerReader = new StreamReader(innerResponse.Content);
|
StreamReader innerReader = new StreamReader(innerResponse.Content);
|
||||||
|
@ -167,13 +170,25 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
||||||
{
|
{
|
||||||
var programEntry = programDict[schedule.programID];
|
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 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) ??
|
double desiredAspect = IsMovie(programEntry) ? 0.666666667 : wideAspect;
|
||||||
GetProgramImage(ApiUrl, allImages, "Logo", true, 600);
|
|
||||||
|
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) ??
|
//programEntry.bannerImage = GetProgramImage(ApiUrl, data, "Banner", false) ??
|
||||||
// GetProgramImage(ApiUrl, data, "Banner-L1", false) ??
|
// GetProgramImage(ApiUrl, data, "Banner-L1", false) ??
|
||||||
// GetProgramImage(ApiUrl, data, "Banner-LO", false) ??
|
// GetProgramImage(ApiUrl, data, "Banner-LO", false) ??
|
||||||
|
@ -220,9 +235,14 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
||||||
return channelNumber;
|
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)
|
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 startAt = GetDate(programInfo.airDateTime);
|
||||||
DateTime endAt = startAt.AddSeconds(programInfo.duration);
|
DateTime endAt = startAt.AddSeconds(programInfo.duration);
|
||||||
ProgramAudio audioType = ProgramAudio.Stereo;
|
ProgramAudio audioType = ProgramAudio.Stereo;
|
||||||
|
@ -276,9 +296,10 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
||||||
IsRepeat = repeat,
|
IsRepeat = repeat,
|
||||||
IsSeries = showType.IndexOf("series", StringComparison.OrdinalIgnoreCase) != -1,
|
IsSeries = showType.IndexOf("series", StringComparison.OrdinalIgnoreCase) != -1,
|
||||||
ImageUrl = details.primaryImage,
|
ImageUrl = details.primaryImage,
|
||||||
|
ThumbImageUrl = details.thumbImage,
|
||||||
IsKids = string.Equals(details.audience, "children", StringComparison.OrdinalIgnoreCase),
|
IsKids = string.Equals(details.audience, "children", StringComparison.OrdinalIgnoreCase),
|
||||||
IsSports = showType.IndexOf("sports", StringComparison.OrdinalIgnoreCase) != -1,
|
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
|
Etag = programInfo.md5
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -378,49 +399,18 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
||||||
return date;
|
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;
|
string url = null;
|
||||||
|
|
||||||
var matches = images
|
var matches = images;
|
||||||
.Where(i => string.Equals(i.category, category, StringComparison.OrdinalIgnoreCase))
|
|
||||||
|
matches = matches
|
||||||
|
.OrderBy(i => Math.Abs(desiredAspect - GetApsectRatio(i)))
|
||||||
|
.ThenByDescending(GetSizeOrder)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
if (matches.Count == 0)
|
var match = matches.FirstOrDefault();
|
||||||
{
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (match == null)
|
if (match == null)
|
||||||
{
|
{
|
||||||
|
@ -444,6 +434,31 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
||||||
return url;
|
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(
|
private async Task<List<ScheduleDirect.ShowImages>> GetImageForPrograms(
|
||||||
ListingsProviderInfo info,
|
ListingsProviderInfo info,
|
||||||
List<string> programIds,
|
List<string> programIds,
|
||||||
|
@ -1188,6 +1203,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
||||||
public bool hasImageArtwork { get; set; }
|
public bool hasImageArtwork { get; set; }
|
||||||
public string primaryImage { get; set; }
|
public string primaryImage { get; set; }
|
||||||
public string thumbImage { get; set; }
|
public string thumbImage { get; set; }
|
||||||
|
public string backdropImage { get; set; }
|
||||||
public string bannerImage { get; set; }
|
public string bannerImage { get; set; }
|
||||||
public string imageID { get; set; }
|
public string imageID { get; set; }
|
||||||
public string md5 { get; set; }
|
public string md5 { get; set; }
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||||
private readonly IMediaEncoder _mediaEncoder;
|
private readonly IMediaEncoder _mediaEncoder;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
const int AnalyzeDurationMs = 2000;
|
const int AnalyzeDurationMs = 1000;
|
||||||
|
|
||||||
public LiveStreamHelper(IMediaEncoder mediaEncoder, ILogger logger)
|
public LiveStreamHelper(IMediaEncoder mediaEncoder, ILogger logger)
|
||||||
{
|
{
|
||||||
|
|
|
@ -679,8 +679,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||||
item.SetImage(new ItemImageInfo
|
item.SetImage(new ItemImageInfo
|
||||||
{
|
{
|
||||||
Path = info.ImagePath,
|
Path = info.ImagePath,
|
||||||
Type = ImageType.Primary,
|
Type = ImageType.Primary
|
||||||
IsPlaceholder = true
|
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
else if (!string.IsNullOrWhiteSpace(info.ImageUrl))
|
else if (!string.IsNullOrWhiteSpace(info.ImageUrl))
|
||||||
|
@ -688,8 +687,46 @@ namespace Emby.Server.Implementations.LiveTv
|
||||||
item.SetImage(new ItemImageInfo
|
item.SetImage(new ItemImageInfo
|
||||||
{
|
{
|
||||||
Path = info.ImageUrl,
|
Path = info.ImageUrl,
|
||||||
Type = ImageType.Primary,
|
Type = ImageType.Primary
|
||||||
IsPlaceholder = true
|
}, 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);
|
}, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -422,6 +422,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
SupportsTranscoding = true,
|
SupportsTranscoding = true,
|
||||||
IsInfiniteStream = true,
|
IsInfiniteStream = true,
|
||||||
IgnoreDts = true,
|
IgnoreDts = true,
|
||||||
|
//SupportsProbing = false,
|
||||||
|
//AnalyzeDurationMs = 2000000
|
||||||
//IgnoreIndex = true,
|
//IgnoreIndex = true,
|
||||||
//ReadAtNativeFramerate = true
|
//ReadAtNativeFramerate = true
|
||||||
};
|
};
|
||||||
|
|
|
@ -117,7 +117,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await _multicastStream.CopyUntilCancelled(response.Content, () => Resolve(openTaskCompletionSource), cancellationToken).ConfigureAwait(false);
|
Resolve(openTaskCompletionSource);
|
||||||
|
|
||||||
|
await _multicastStream.CopyUntilCancelled(response.Content, null, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -235,10 +235,18 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
numberString = Path.GetFileNameWithoutExtension(mediaUrl.Split('/').Last());
|
try
|
||||||
|
|
||||||
if (!IsValidChannelNumber(numberString))
|
|
||||||
{
|
{
|
||||||
|
numberString = Path.GetFileNameWithoutExtension(mediaUrl.Split('/').Last());
|
||||||
|
|
||||||
|
if (!IsValidChannelNumber(numberString))
|
||||||
|
{
|
||||||
|
numberString = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Seeing occasional argument exception here
|
||||||
numberString = null;
|
numberString = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
using MediaBrowser.Model.Threading;
|
using MediaBrowser.Model.Threading;
|
||||||
|
using MediaBrowser.Model.Dto;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.Notifications
|
namespace Emby.Server.Implementations.Notifications
|
||||||
{
|
{
|
||||||
|
@ -260,7 +261,7 @@ namespace Emby.Server.Implementations.Notifications
|
||||||
|
|
||||||
var item = e.MediaInfo;
|
var item = e.MediaInfo;
|
||||||
|
|
||||||
if ( item.IsThemeMedia)
|
if (e.Item != null && e.Item.IsThemeMedia)
|
||||||
{
|
{
|
||||||
// Don't report theme song or local trailer playback
|
// Don't report theme song or local trailer playback
|
||||||
return;
|
return;
|
||||||
|
@ -430,7 +431,7 @@ namespace Emby.Server.Implementations.Notifications
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetItemName(BaseItemInfo item)
|
public static string GetItemName(BaseItemDto item)
|
||||||
{
|
{
|
||||||
var name = item.Name;
|
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
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [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;
|
info.Item.RunTimeTicks = runtimeTicks;
|
||||||
}
|
}
|
||||||
|
@ -813,7 +813,7 @@ namespace Emby.Server.Implementations.Session
|
||||||
mediaSource = await GetMediaSource(hasMediaSources, info.MediaSourceId, info.LiveStreamId).ConfigureAwait(false);
|
mediaSource = await GetMediaSource(hasMediaSources, info.MediaSourceId, info.LiveStreamId).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
info.Item = GetItemInfo(libraryItem, libraryItem, mediaSource);
|
info.Item = GetItemInfo(libraryItem, mediaSource);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1637,165 +1637,65 @@ namespace Emby.Server.Implementations.Session
|
||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DtoOptions _itemInfoDtoOptions;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converts a BaseItem to a BaseItemInfo
|
/// Converts a BaseItem to a BaseItemInfo
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">The item.</param>
|
private BaseItemDto GetItemInfo(BaseItem item, MediaSourceInfo mediaSource)
|
||||||
/// <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)
|
|
||||||
{
|
{
|
||||||
if (item == null)
|
if (item == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException("item");
|
throw new ArgumentNullException("item");
|
||||||
}
|
}
|
||||||
|
|
||||||
var info = new BaseItemInfo
|
var dtoOptions = _itemInfoDtoOptions;
|
||||||
{
|
|
||||||
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
|
|
||||||
};
|
|
||||||
|
|
||||||
info.PrimaryImageTag = GetImageCacheTag(item, ImageType.Primary);
|
if (_itemInfoDtoOptions == null)
|
||||||
if (info.PrimaryImageTag != null)
|
|
||||||
{
|
{
|
||||||
info.PrimaryImageItemId = GetDtoId(item);
|
dtoOptions = new 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;
|
AddProgramRecordingInfo = false
|
||||||
info.SeriesName = recording.Name;
|
};
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(info.Name))
|
dtoOptions.Fields.Remove(ItemFields.BasicSyncInfo);
|
||||||
{
|
dtoOptions.Fields.Remove(ItemFields.SyncInfo);
|
||||||
info.Name = recording.Name;
|
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 audio = item as Audio;
|
var info = _dtoService.GetBaseItemDto(item, dtoOptions);
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mediaSource != null)
|
if (mediaSource != null)
|
||||||
{
|
{
|
||||||
|
@ -1837,7 +1737,7 @@ namespace Emby.Server.Implementations.Session
|
||||||
//ReportNowViewingItem(sessionId, info);
|
//ReportNowViewingItem(sessionId, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReportNowViewingItem(string sessionId, BaseItemInfo item)
|
public void ReportNowViewingItem(string sessionId, BaseItemDto item)
|
||||||
{
|
{
|
||||||
//var session = GetSession(sessionId);
|
//var session = GetSession(sessionId);
|
||||||
|
|
||||||
|
|
|
@ -206,15 +206,16 @@ namespace MediaBrowser.Api
|
||||||
var newLockData = request.LockData ?? false;
|
var newLockData = request.LockData ?? false;
|
||||||
var isLockedChanged = item.IsLocked != newLockData;
|
var isLockedChanged = item.IsLocked != newLockData;
|
||||||
|
|
||||||
UpdateItem(request, item);
|
// Do this first so that metadata savers can pull the updates from the database.
|
||||||
|
|
||||||
await item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (request.People != null)
|
if (request.People != null)
|
||||||
{
|
{
|
||||||
await _libraryManager.UpdatePeople(item, request.People.Select(x => new PersonInfo { Name = x.Name, Role = x.Role, Type = x.Type }).ToList());
|
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)
|
if (isLockedChanged && item.IsFolder)
|
||||||
{
|
{
|
||||||
var folder = (Folder)item;
|
var folder = (Folder)item;
|
||||||
|
@ -243,7 +244,6 @@ namespace MediaBrowser.Api
|
||||||
|
|
||||||
item.DisplayMediaType = request.DisplayMediaType;
|
item.DisplayMediaType = request.DisplayMediaType;
|
||||||
item.CommunityRating = request.CommunityRating;
|
item.CommunityRating = request.CommunityRating;
|
||||||
item.VoteCount = request.VoteCount;
|
|
||||||
item.HomePageUrl = request.HomePageUrl;
|
item.HomePageUrl = request.HomePageUrl;
|
||||||
item.IndexNumber = request.IndexNumber;
|
item.IndexNumber = request.IndexNumber;
|
||||||
item.ParentIndexNumber = request.ParentIndexNumber;
|
item.ParentIndexNumber = request.ParentIndexNumber;
|
||||||
|
|
|
@ -27,6 +27,7 @@ using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.IO;
|
using MediaBrowser.Controller.IO;
|
||||||
using MediaBrowser.Model.Globalization;
|
using MediaBrowser.Model.Globalization;
|
||||||
using MediaBrowser.Model.Services;
|
using MediaBrowser.Model.Services;
|
||||||
|
using MediaBrowser.Common.Extensions;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.Library
|
namespace MediaBrowser.Api.Library
|
||||||
{
|
{
|
||||||
|
@ -675,7 +676,6 @@ namespace MediaBrowser.Api.Library
|
||||||
Limit = 0,
|
Limit = 0,
|
||||||
Recursive = true,
|
Recursive = true,
|
||||||
IsVirtualItem = false,
|
IsVirtualItem = false,
|
||||||
SourceTypes = new[] { SourceType.Library },
|
|
||||||
IsFavorite = request.IsFavorite,
|
IsFavorite = request.IsFavorite,
|
||||||
DtoOptions = new DtoOptions(false)
|
DtoOptions = new DtoOptions(false)
|
||||||
{
|
{
|
||||||
|
@ -831,6 +831,11 @@ namespace MediaBrowser.Api.Library
|
||||||
: (Folder)_libraryManager.RootFolder)
|
: (Folder)_libraryManager.RootFolder)
|
||||||
: _libraryManager.GetItemById(request.Id);
|
: _libraryManager.GetItemById(request.Id);
|
||||||
|
|
||||||
|
if (item == null)
|
||||||
|
{
|
||||||
|
throw new ResourceNotFoundException("Item not found.");
|
||||||
|
}
|
||||||
|
|
||||||
while (item.ThemeSongIds.Count == 0 && request.InheritFromParent && item.GetParent() != null)
|
while (item.ThemeSongIds.Count == 0 && request.InheritFromParent && item.GetParent() != null)
|
||||||
{
|
{
|
||||||
item = item.GetParent();
|
item = item.GetParent();
|
||||||
|
@ -875,6 +880,11 @@ namespace MediaBrowser.Api.Library
|
||||||
: (Folder)_libraryManager.RootFolder)
|
: (Folder)_libraryManager.RootFolder)
|
||||||
: _libraryManager.GetItemById(request.Id);
|
: _libraryManager.GetItemById(request.Id);
|
||||||
|
|
||||||
|
if (item == null)
|
||||||
|
{
|
||||||
|
throw new ResourceNotFoundException("Item not found.");
|
||||||
|
}
|
||||||
|
|
||||||
while (item.ThemeVideoIds.Count == 0 && request.InheritFromParent && item.GetParent() != null)
|
while (item.ThemeVideoIds.Count == 0 && request.InheritFromParent && item.GetParent() != null)
|
||||||
{
|
{
|
||||||
item = item.GetParent();
|
item = item.GetParent();
|
||||||
|
|
|
@ -783,7 +783,6 @@ namespace MediaBrowser.Api.Playback
|
||||||
state.OutputContainer = (container ?? string.Empty).TrimStart('.');
|
state.OutputContainer = (container ?? string.Empty).TrimStart('.');
|
||||||
|
|
||||||
state.OutputAudioBitrate = EncodingHelper.GetAudioBitrateParam(state.Request, state.AudioStream);
|
state.OutputAudioBitrate = EncodingHelper.GetAudioBitrateParam(state.Request, state.AudioStream);
|
||||||
state.OutputAudioSampleRate = request.AudioSampleRate;
|
|
||||||
|
|
||||||
state.OutputAudioCodec = state.Request.AudioCodec;
|
state.OutputAudioCodec = state.Request.AudioCodec;
|
||||||
|
|
||||||
|
|
|
@ -106,6 +106,13 @@ namespace MediaBrowser.Api.Playback
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<object> Post(OpenMediaSource request)
|
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);
|
var authInfo = _authContext.GetAuthorizationInfo(Request);
|
||||||
|
|
||||||
|
@ -137,7 +144,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Post(CloseMediaSource request)
|
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);
|
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;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,6 +357,19 @@ namespace MediaBrowser.Api.Playback
|
||||||
mediaSource.SupportsTranscoding = false;
|
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.SupportsDirectPlay)
|
||||||
{
|
{
|
||||||
if (mediaSource.IsRemote && forceDirectPlayRemoteMediaSource)
|
if (mediaSource.IsRemote && forceDirectPlayRemoteMediaSource)
|
||||||
|
|
|
@ -250,248 +250,6 @@ namespace MediaBrowser.Api.Playback
|
||||||
|
|
||||||
public DeviceProfile DeviceProfile { get; set; }
|
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 TranscodingJob TranscodingJob;
|
||||||
public override void ReportTranscodingProgress(TimeSpan? transcodingPosition, float? framerate, double? percentComplete, long? bytesTranscoded, int? bitRate)
|
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")]
|
[Route("/Sessions/{Id}/Playing/{Command}", "POST", Summary = "Issues a playstate command to a client")]
|
||||||
[Authenticated]
|
[Authenticated]
|
||||||
public class SendPlaystateCommand : IReturnVoid
|
public class SendPlaystateCommand : PlaystateRequest, IReturnVoid
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the id.
|
/// Gets or sets the id.
|
||||||
|
@ -106,19 +106,6 @@ namespace MediaBrowser.Api.Session
|
||||||
/// <value>The id.</value>
|
/// <value>The id.</value>
|
||||||
[ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
|
[ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
|
||||||
public string Id { get; set; }
|
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")]
|
[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)
|
public void Post(SendPlaystateCommand request)
|
||||||
{
|
{
|
||||||
var command = new PlaystateRequest
|
var task = _sessionManager.SendPlaystateCommand(GetSession(_sessionContext).Result.Id, request.Id, request, CancellationToken.None);
|
||||||
{
|
|
||||||
Command = request.Command,
|
|
||||||
SeekPositionTicks = request.SeekPositionTicks
|
|
||||||
};
|
|
||||||
|
|
||||||
var task = _sessionManager.SendPlaystateCommand(GetSession(_sessionContext).Result.Id, request.Id, command, CancellationToken.None);
|
|
||||||
|
|
||||||
Task.WaitAll(task);
|
Task.WaitAll(task);
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,6 @@ namespace MediaBrowser.Api
|
||||||
config.EnableSimpleArtistDetection = true;
|
config.EnableSimpleArtistDetection = true;
|
||||||
config.EnableNormalizedItemByNameIds = true;
|
config.EnableNormalizedItemByNameIds = true;
|
||||||
config.DisableLiveTvChannelUserDataName = true;
|
config.DisableLiveTvChannelUserDataName = true;
|
||||||
config.EnableSimpleSortNameHandling = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Post(UpdateStartupConfiguration request)
|
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>
|
<Name>MediaBrowser.Model</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<None Include="project.json" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup />
|
<ItemGroup />
|
||||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
|
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
|
|
@ -58,7 +58,7 @@ namespace MediaBrowser.Common.Updates
|
||||||
}
|
}
|
||||||
else if (updateLevel == PackageVersionClass.Beta)
|
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)
|
else if (updateLevel == PackageVersionClass.Dev)
|
||||||
{
|
{
|
||||||
|
@ -81,7 +81,7 @@ namespace MediaBrowser.Common.Updates
|
||||||
{
|
{
|
||||||
if (updateLevel == PackageVersionClass.Beta)
|
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)
|
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
|
public override SourceType SourceType
|
||||||
{
|
{
|
||||||
get { return SourceType.Channel; }
|
get { return SourceType.Channel; }
|
||||||
set { }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override QueryResult<BaseItem> GetItemsInternal(InternalItemsQuery query)
|
protected override QueryResult<BaseItem> GetItemsInternal(InternalItemsQuery query)
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace MediaBrowser.Controller.Drawing
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Encodes the image.
|
/// Encodes the image.
|
||||||
/// </summary>
|
/// </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>
|
/// <summary>
|
||||||
/// Creates the image collage.
|
/// Creates the image collage.
|
||||||
|
|
|
@ -87,7 +87,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
private List<Guid> _childrenIds = null;
|
private List<Guid> _childrenIds = null;
|
||||||
private readonly object _childIdsLock = new object();
|
private readonly object _childIdsLock = new object();
|
||||||
protected override IEnumerable<BaseItem> LoadChildren()
|
protected override List<BaseItem> LoadChildren()
|
||||||
{
|
{
|
||||||
lock (_childIdsLock)
|
lock (_childIdsLock)
|
||||||
{
|
{
|
||||||
|
|
|
@ -131,7 +131,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
/// Creates the name of the sort.
|
/// Creates the name of the sort.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
protected override string CreateSortNameInternal()
|
protected override string CreateSortName()
|
||||||
{
|
{
|
||||||
return (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("0000 - ") : "")
|
return (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("0000 - ") : "")
|
||||||
+ (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ") : "") + Name;
|
+ (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ") : "") + Name;
|
||||||
|
|
|
@ -90,7 +90,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
protected override IEnumerable<BaseItem> ActualChildren
|
public override IEnumerable<BaseItem> Children
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
@ -99,7 +99,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
return new List<BaseItem>();
|
return new List<BaseItem>();
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.ActualChildren;
|
return base.Children;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
ImageInfos = new List<ItemImageInfo>();
|
ImageInfos = new List<ItemImageInfo>();
|
||||||
InheritedTags = new List<string>();
|
InheritedTags = new List<string>();
|
||||||
ProductionLocations = new List<string>();
|
ProductionLocations = new List<string>();
|
||||||
SourceType = SourceType.Library;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly char[] SlugReplaceChars = { '?', '/', '&' };
|
public static readonly char[] SlugReplaceChars = { '?', '/', '&' };
|
||||||
|
@ -187,15 +186,10 @@ namespace MediaBrowser.Controller.Entities
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
var isSortNameDefault = IsSortNameDefault(SortName);
|
|
||||||
|
|
||||||
_name = value;
|
_name = value;
|
||||||
|
|
||||||
if (isSortNameDefault)
|
// lazy load this again
|
||||||
{
|
_sortName = null;
|
||||||
// lazy load this again
|
|
||||||
SortName = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,7 +273,18 @@ namespace MediaBrowser.Controller.Entities
|
||||||
public virtual string Path { get; set; }
|
public virtual string Path { get; set; }
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public virtual SourceType SourceType { get; set; }
|
public virtual SourceType SourceType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(ChannelId))
|
||||||
|
{
|
||||||
|
return SourceType.Channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SourceType.Library;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the folder containing the item.
|
/// Returns the folder containing the item.
|
||||||
|
@ -586,6 +591,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string _forcedSortName;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the name of the forced sort.
|
/// Gets or sets the name of the forced sort.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -593,42 +599,8 @@ namespace MediaBrowser.Controller.Entities
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public string ForcedSortName
|
public string ForcedSortName
|
||||||
{
|
{
|
||||||
get
|
get { return _forcedSortName; }
|
||||||
{
|
set { _forcedSortName = value; _sortName = null; }
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private string _sortName;
|
private string _sortName;
|
||||||
|
@ -643,7 +615,15 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
if (_sortName == null)
|
if (_sortName == null)
|
||||||
{
|
{
|
||||||
_sortName = CreateSortName();
|
if (!string.IsNullOrWhiteSpace(ForcedSortName))
|
||||||
|
{
|
||||||
|
// Need the ToLower because that's what CreateSortName does
|
||||||
|
_sortName = ModifySortChunks(ForcedSortName).ToLower();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_sortName = CreateSortName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return _sortName;
|
return _sortName;
|
||||||
}
|
}
|
||||||
|
@ -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()
|
public string GetInternalMetadataPath()
|
||||||
{
|
{
|
||||||
var basePath = ConfigurationManager.ApplicationPaths.InternalMetadataPath;
|
var basePath = ConfigurationManager.ApplicationPaths.InternalMetadataPath;
|
||||||
|
@ -699,22 +654,14 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return System.IO.Path.Combine(basePath, idString.Substring(0, 2), idString);
|
return System.IO.Path.Combine(basePath, idString.Substring(0, 2), idString);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected string CreateSortName()
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(Name))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CreateSortNameInternal();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates the name of the sort.
|
/// Creates the name of the sort.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>System.String.</returns>
|
/// <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)
|
if (!EnableAlphaNumericSorting)
|
||||||
{
|
{
|
||||||
return Name.TrimStart();
|
return Name.TrimStart();
|
||||||
|
@ -951,13 +898,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public float? CommunityRating { get; set; }
|
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>
|
/// <summary>
|
||||||
/// Gets or sets the run time ticks.
|
/// Gets or sets the run time ticks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1367,6 +1307,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
public void AfterMetadataRefresh()
|
public void AfterMetadataRefresh()
|
||||||
{
|
{
|
||||||
|
_sortName = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -2253,6 +2194,8 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual bool BeforeMetadataRefresh()
|
public virtual bool BeforeMetadataRefresh()
|
||||||
{
|
{
|
||||||
|
_sortName = null;
|
||||||
|
|
||||||
var hasChanges = false;
|
var hasChanges = false;
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(Name) && !string.IsNullOrEmpty(Path))
|
if (string.IsNullOrEmpty(Name) && !string.IsNullOrEmpty(Path))
|
||||||
|
|
|
@ -311,12 +311,12 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The actual children.</value>
|
/// <value>The actual children.</value>
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
protected override IEnumerable<BaseItem> ActualChildren
|
public override IEnumerable<BaseItem> Children
|
||||||
{
|
{
|
||||||
get { return GetActualChildren(); }
|
get { return GetActualChildren(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<BaseItem> GetActualChildren()
|
public IEnumerable<BaseItem> GetActualChildren()
|
||||||
{
|
{
|
||||||
return GetPhysicalFolders(true).SelectMany(c => c.Children);
|
return GetPhysicalFolders(true).SelectMany(c => c.Children);
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,7 +185,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
item.Id = LibraryManager.GetNewItemId(item.Path, item.GetType());
|
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));
|
throw new ArgumentException(string.Format("A child with the Id {0} already exists.", item.Id));
|
||||||
}
|
}
|
||||||
|
@ -243,7 +243,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The actual children.</value>
|
/// <value>The actual children.</value>
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
protected virtual IEnumerable<BaseItem> ActualChildren
|
public virtual IEnumerable<BaseItem> Children
|
||||||
{
|
{
|
||||||
get
|
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>
|
/// <summary>
|
||||||
/// thread-safe access to all recursive children of this folder - without regard to user
|
/// thread-safe access to all recursive children of this folder - without regard to user
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -301,7 +291,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// Loads our children. Validation will occur externally.
|
/// Loads our children. Validation will occur externally.
|
||||||
/// We want this sychronous.
|
/// We want this sychronous.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual IEnumerable<BaseItem> LoadChildren()
|
protected virtual List<BaseItem> LoadChildren()
|
||||||
{
|
{
|
||||||
//Logger.Debug("Loading children from {0} {1} {2}", GetType().Name, Id, Path);
|
//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
|
//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>();
|
var dictionary = new Dictionary<Guid, BaseItem>();
|
||||||
|
|
||||||
foreach (var child in ActualChildren)
|
var childrenList = Children.ToList();
|
||||||
|
|
||||||
|
foreach (var child in childrenList)
|
||||||
{
|
{
|
||||||
var id = child.Id;
|
var id = child.Id;
|
||||||
if (dictionary.ContainsKey(id))
|
if (dictionary.ContainsKey(id))
|
||||||
|
@ -466,7 +458,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
if (recursive)
|
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);
|
progress.Report(20);
|
||||||
|
@ -494,7 +486,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
private async Task RefreshMetadataRecursive(MetadataRefreshOptions refreshOptions, bool recursive, IProgress<double> progress, CancellationToken cancellationToken)
|
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 percentages = new Dictionary<Guid, double>(children.Count);
|
||||||
var numComplete = 0;
|
var numComplete = 0;
|
||||||
|
@ -668,7 +660,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// Get our children from the repo - stubbed for now
|
/// Get our children from the repo - stubbed for now
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
/// <returns>IEnumerable{BaseItem}.</returns>
|
||||||
protected IEnumerable<BaseItem> GetCachedChildren()
|
protected List<BaseItem> GetCachedChildren()
|
||||||
{
|
{
|
||||||
return ItemRepository.GetItemList(new InternalItemsQuery
|
return ItemRepository.GetItemList(new InternalItemsQuery
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,7 +26,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// <value>The date last saved.</value>
|
/// <value>The date last saved.</value>
|
||||||
DateTime DateLastSaved { get; set; }
|
DateTime DateLastSaved { get; set; }
|
||||||
|
|
||||||
SourceType SourceType { get; set; }
|
SourceType SourceType { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the date last refreshed.
|
/// Gets or sets the date last refreshed.
|
||||||
|
|
|
@ -148,9 +148,8 @@ namespace MediaBrowser.Controller.Entities
|
||||||
}
|
}
|
||||||
|
|
||||||
public string[] PresetViews { get; set; }
|
public string[] PresetViews { get; set; }
|
||||||
public SourceType[] SourceTypes { get; set; }
|
|
||||||
public SourceType[] ExcludeSourceTypes { get; set; }
|
|
||||||
public TrailerType[] TrailerTypes { get; set; }
|
public TrailerType[] TrailerTypes { get; set; }
|
||||||
|
public SourceType[] SourceTypes { get; set; }
|
||||||
|
|
||||||
public DayOfWeek[] AirDays { get; set; }
|
public DayOfWeek[] AirDays { get; set; }
|
||||||
public SeriesStatus[] SeriesStatuses { get; set; }
|
public SeriesStatus[] SeriesStatuses { get; set; }
|
||||||
|
@ -215,9 +214,8 @@ namespace MediaBrowser.Controller.Entities
|
||||||
ExcludeTags = new string[] { };
|
ExcludeTags = new string[] { };
|
||||||
ExcludeInheritedTags = new string[] { };
|
ExcludeInheritedTags = new string[] { };
|
||||||
PresetViews = new string[] { };
|
PresetViews = new string[] { };
|
||||||
SourceTypes = new SourceType[] { };
|
|
||||||
ExcludeSourceTypes = new SourceType[] { };
|
|
||||||
TrailerTypes = new TrailerType[] { };
|
TrailerTypes = new TrailerType[] { };
|
||||||
|
SourceTypes = new SourceType[] { };
|
||||||
AirDays = new DayOfWeek[] { };
|
AirDays = new DayOfWeek[] { };
|
||||||
SeriesStatuses = new SeriesStatus[] { };
|
SeriesStatuses = new SeriesStatus[] { };
|
||||||
OrderBy = new List<Tuple<string, SortOrder>>();
|
OrderBy = new List<Tuple<string, SortOrder>>();
|
||||||
|
|
|
@ -11,13 +11,11 @@ namespace MediaBrowser.Controller.Entities
|
||||||
public int? MaxListOrder { get; set; }
|
public int? MaxListOrder { get; set; }
|
||||||
public Guid AppearsInItemId { get; set; }
|
public Guid AppearsInItemId { get; set; }
|
||||||
public string NameContains { get; set; }
|
public string NameContains { get; set; }
|
||||||
public SourceType[] SourceTypes { get; set; }
|
|
||||||
|
|
||||||
public InternalPeopleQuery()
|
public InternalPeopleQuery()
|
||||||
{
|
{
|
||||||
PersonTypes = new List<string>();
|
PersonTypes = new List<string>();
|
||||||
ExcludePersonTypes = new List<string>();
|
ExcludePersonTypes = new List<string>();
|
||||||
SourceTypes = new SourceType[] { };
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@ namespace MediaBrowser.Controller.Entities.Movies
|
||||||
return new List<BaseItem>();
|
return new List<BaseItem>();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override IEnumerable<BaseItem> LoadChildren()
|
protected override List<BaseItem> LoadChildren()
|
||||||
{
|
{
|
||||||
if (IsLegacyBoxSet)
|
if (IsLegacyBoxSet)
|
||||||
{
|
{
|
||||||
|
|
|
@ -237,7 +237,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
/// Creates the name of the sort.
|
/// Creates the name of the sort.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
protected override string CreateSortNameInternal()
|
protected override string CreateSortName()
|
||||||
{
|
{
|
||||||
return (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("000 - ") : "")
|
return (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("000 - ") : "")
|
||||||
+ (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ") : "") + Name;
|
+ (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ") : "") + Name;
|
||||||
|
|
|
@ -145,7 +145,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
/// Creates the name of the sort.
|
/// Creates the name of the sort.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
protected override string CreateSortNameInternal()
|
protected override string CreateSortName()
|
||||||
{
|
{
|
||||||
return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name;
|
return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
private List<Guid> _childrenIds = null;
|
private List<Guid> _childrenIds = null;
|
||||||
private readonly object _childIdsLock = new object();
|
private readonly object _childIdsLock = new object();
|
||||||
protected override IEnumerable<BaseItem> LoadChildren()
|
protected override List<BaseItem> LoadChildren()
|
||||||
{
|
{
|
||||||
lock (_childIdsLock)
|
lock (_childIdsLock)
|
||||||
{
|
{
|
||||||
|
|
|
@ -633,14 +633,17 @@ namespace MediaBrowser.Controller.Entities
|
||||||
if (info.Path.StartsWith("Http", StringComparison.OrdinalIgnoreCase))
|
if (info.Path.StartsWith("Http", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
info.Protocol = MediaProtocol.Http;
|
info.Protocol = MediaProtocol.Http;
|
||||||
|
info.SupportsDirectStream = false;
|
||||||
}
|
}
|
||||||
else if (info.Path.StartsWith("Rtmp", StringComparison.OrdinalIgnoreCase))
|
else if (info.Path.StartsWith("Rtmp", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
info.Protocol = MediaProtocol.Rtmp;
|
info.Protocol = MediaProtocol.Rtmp;
|
||||||
|
info.SupportsDirectStream = false;
|
||||||
}
|
}
|
||||||
else if (info.Path.StartsWith("Rtsp", StringComparison.OrdinalIgnoreCase))
|
else if (info.Path.StartsWith("Rtsp", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
info.Protocol = MediaProtocol.Rtsp;
|
info.Protocol = MediaProtocol.Rtsp;
|
||||||
|
info.SupportsDirectStream = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -527,6 +527,8 @@ namespace MediaBrowser.Controller.Library
|
||||||
/// <returns>QueryResult<BaseItem>.</returns>
|
/// <returns>QueryResult<BaseItem>.</returns>
|
||||||
IEnumerable<BaseItem> GetItemList(InternalItemsQuery query);
|
IEnumerable<BaseItem> GetItemList(InternalItemsQuery query);
|
||||||
|
|
||||||
|
IEnumerable<BaseItem> GetItemList(InternalItemsQuery query, bool allowExternalContent);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the items.
|
/// Gets the items.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Dto;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ namespace MediaBrowser.Controller.Library
|
||||||
public List<User> Users { get; set; }
|
public List<User> Users { get; set; }
|
||||||
public long? PlaybackPositionTicks { get; set; }
|
public long? PlaybackPositionTicks { get; set; }
|
||||||
public BaseItem Item { get; set; }
|
public BaseItem Item { get; set; }
|
||||||
public BaseItemInfo MediaInfo { get; set; }
|
public BaseItemDto MediaInfo { get; set; }
|
||||||
public string MediaSourceId { get; set; }
|
public string MediaSourceId { get; set; }
|
||||||
public bool IsPaused { get; set; }
|
public bool IsPaused { get; set; }
|
||||||
public bool IsAutomated { get; set; }
|
public bool IsAutomated { get; set; }
|
||||||
|
|
|
@ -43,7 +43,6 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
public override SourceType SourceType
|
public override SourceType SourceType
|
||||||
{
|
{
|
||||||
get { return SourceType.LiveTV; }
|
get { return SourceType.LiveTV; }
|
||||||
set { }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
|
|
|
@ -55,7 +55,6 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
public override SourceType SourceType
|
public override SourceType SourceType
|
||||||
{
|
{
|
||||||
get { return SourceType.LiveTV; }
|
get { return SourceType.LiveTV; }
|
||||||
set { }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
|
@ -89,7 +88,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string CreateSortNameInternal()
|
protected override string CreateSortName()
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(Number))
|
if (!string.IsNullOrEmpty(Number))
|
||||||
{
|
{
|
||||||
|
|
|
@ -65,7 +65,6 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
public override SourceType SourceType
|
public override SourceType SourceType
|
||||||
{
|
{
|
||||||
get { return SourceType.LiveTV; }
|
get { return SourceType.LiveTV; }
|
||||||
set { }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -42,7 +42,6 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
public override SourceType SourceType
|
public override SourceType SourceType
|
||||||
{
|
{
|
||||||
get { return SourceType.LiveTV; }
|
get { return SourceType.LiveTV; }
|
||||||
set { }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
|
|
|
@ -107,8 +107,12 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
/// <value>The image URL.</value>
|
/// <value>The image URL.</value>
|
||||||
public string ImageUrl { get; set; }
|
public string ImageUrl { get; set; }
|
||||||
|
|
||||||
|
public string ThumbImageUrl { get; set; }
|
||||||
|
|
||||||
public string LogoImageUrl { get; set; }
|
public string LogoImageUrl { get; set; }
|
||||||
|
|
||||||
|
public string BackdropImageUrl { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether this instance has image.
|
/// Gets or sets a value indicating whether this instance has image.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -30,7 +30,6 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
public override SourceType SourceType
|
public override SourceType SourceType
|
||||||
{
|
{
|
||||||
get { return SourceType.LiveTV; }
|
get { return SourceType.LiveTV; }
|
||||||
set { }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,10 +36,6 @@
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<RunPostBuildEvent>Always</RunPostBuildEvent>
|
<RunPostBuildEvent>Always</RunPostBuildEvent>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
|
||||||
<None Include="project.json" />
|
|
||||||
<!-- A reference to the entire .NET Framework is automatically included -->
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="..\SharedVersion.cs">
|
<Compile Include="..\SharedVersion.cs">
|
||||||
<Link>Properties\SharedVersion.cs</Link>
|
<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
|
// 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)
|
foreach (var stream in state.MediaSource.MediaStreams)
|
||||||
{
|
{
|
||||||
|
@ -1806,6 +1806,20 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
break;
|
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
|
// leave blank so ffmpeg will decide
|
||||||
|
|
|
@ -8,6 +8,7 @@ using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using MediaBrowser.Model.MediaInfo;
|
using MediaBrowser.Model.MediaInfo;
|
||||||
|
using MediaBrowser.Model.Drawing;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.MediaEncoding
|
namespace MediaBrowser.Controller.MediaEncoding
|
||||||
{
|
{
|
||||||
|
@ -134,7 +135,6 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
|
|
||||||
public int? OutputAudioBitrate;
|
public int? OutputAudioBitrate;
|
||||||
public int? OutputAudioChannels;
|
public int? OutputAudioChannels;
|
||||||
public int? OutputAudioSampleRate;
|
|
||||||
public bool DeInterlace { get; set; }
|
public bool DeInterlace { get; set; }
|
||||||
public bool IsVideoRequest { get; set; }
|
public bool IsVideoRequest { get; set; }
|
||||||
public TranscodingJobType TranscodingType { get; set; }
|
public TranscodingJobType TranscodingType { get; set; }
|
||||||
|
@ -173,6 +173,97 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
return false;
|
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>
|
/// <summary>
|
||||||
/// Predicts the audio sample rate that will be in the output stream
|
/// Predicts the audio sample rate that will be in the output stream
|
||||||
/// </summary>
|
/// </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()
|
protected void DisposeIsoMount()
|
||||||
{
|
{
|
||||||
if (IsoMount != null)
|
if (IsoMount != null)
|
||||||
|
|
|
@ -74,7 +74,7 @@ namespace MediaBrowser.Controller.Playlists
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override IEnumerable<BaseItem> LoadChildren()
|
protected override List<BaseItem> LoadChildren()
|
||||||
{
|
{
|
||||||
// Save a trip to the database
|
// Save a trip to the database
|
||||||
return new List<BaseItem>();
|
return new List<BaseItem>();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Security;
|
using MediaBrowser.Controller.Security;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Events;
|
using MediaBrowser.Model.Events;
|
||||||
using MediaBrowser.Model.Session;
|
using MediaBrowser.Model.Session;
|
||||||
using MediaBrowser.Model.Users;
|
using MediaBrowser.Model.Users;
|
||||||
|
@ -249,7 +249,7 @@ namespace MediaBrowser.Controller.Session
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sessionId">The session identifier.</param>
|
/// <param name="sessionId">The session identifier.</param>
|
||||||
/// <param name="item">The item.</param>
|
/// <param name="item">The item.</param>
|
||||||
void ReportNowViewingItem(string sessionId, BaseItemInfo item);
|
void ReportNowViewingItem(string sessionId, BaseItemDto item);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Authenticates the new session.
|
/// Authenticates the new session.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Session;
|
using MediaBrowser.Model.Session;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -100,13 +100,13 @@ namespace MediaBrowser.Controller.Session
|
||||||
/// Gets or sets the name of the now viewing item.
|
/// Gets or sets the name of the now viewing item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The name of the now viewing item.</value>
|
/// <value>The name of the now viewing item.</value>
|
||||||
public BaseItemInfo NowViewingItem { get; set; }
|
public BaseItemDto NowViewingItem { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the now playing item.
|
/// Gets or sets the now playing item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The now playing item.</value>
|
/// <value>The now playing item.</value>
|
||||||
public BaseItemInfo NowPlayingItem { get; set; }
|
public BaseItemDto NowPlayingItem { get; set; }
|
||||||
|
|
||||||
public BaseItem FullNowPlayingItem { 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 parentPath = _fileSystem.GetDirectoryName(item.Path);
|
||||||
|
|
||||||
var parentPathFiles = directoryService.GetFileSystemEntries(parentPath)
|
var parentPathFiles = directoryService.GetFiles(parentPath)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var nameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(item.Path);
|
var nameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(item.Path);
|
||||||
|
|
||||||
var files = GetFilesFromParentFolder(nameWithoutExtension, parentPathFiles);
|
return 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>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<LocalImageInfo> GetFilesFromParentFolder(string filenameWithoutExtension, IEnumerable<FileSystemMetadata> parentPathFiles)
|
private List<LocalImageInfo> GetFilesFromParentFolder(string filenameWithoutExtension, IEnumerable<FileSystemMetadata> parentPathFiles)
|
||||||
|
|
|
@ -44,24 +44,15 @@
|
||||||
<Compile Include="Images\LocalImageProvider.cs" />
|
<Compile Include="Images\LocalImageProvider.cs" />
|
||||||
<Compile Include="Parsers\BaseItemXmlParser.cs" />
|
<Compile Include="Parsers\BaseItemXmlParser.cs" />
|
||||||
<Compile Include="Parsers\BoxSetXmlParser.cs" />
|
<Compile Include="Parsers\BoxSetXmlParser.cs" />
|
||||||
<Compile Include="Parsers\EpisodeXmlParser.cs" />
|
|
||||||
<Compile Include="Parsers\GameSystemXmlParser.cs" />
|
<Compile Include="Parsers\GameSystemXmlParser.cs" />
|
||||||
<Compile Include="Parsers\GameXmlParser.cs" />
|
<Compile Include="Parsers\GameXmlParser.cs" />
|
||||||
<Compile Include="Parsers\MovieXmlParser.cs" />
|
|
||||||
<Compile Include="Parsers\MusicVideoXmlParser.cs" />
|
|
||||||
<Compile Include="Parsers\PlaylistXmlParser.cs" />
|
<Compile Include="Parsers\PlaylistXmlParser.cs" />
|
||||||
<Compile Include="Parsers\SeriesXmlParser.cs" />
|
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Providers\BoxSetXmlProvider.cs" />
|
<Compile Include="Providers\BoxSetXmlProvider.cs" />
|
||||||
<Compile Include="Providers\EpisodeXmlProvider.cs" />
|
|
||||||
<Compile Include="Providers\FolderXmlProvider.cs" />
|
<Compile Include="Providers\FolderXmlProvider.cs" />
|
||||||
<Compile Include="Providers\GameSystemXmlProvider.cs" />
|
<Compile Include="Providers\GameSystemXmlProvider.cs" />
|
||||||
<Compile Include="Providers\GameXmlProvider.cs" />
|
<Compile Include="Providers\GameXmlProvider.cs" />
|
||||||
<Compile Include="Providers\MovieXmlProvider.cs" />
|
|
||||||
<Compile Include="Providers\MusicVideoXmlProvider.cs" />
|
|
||||||
<Compile Include="Providers\PlaylistXmlProvider.cs" />
|
<Compile Include="Providers\PlaylistXmlProvider.cs" />
|
||||||
<Compile Include="Providers\SeriesXmlProvider.cs" />
|
|
||||||
<Compile Include="Providers\VideoXmlProvider.cs" />
|
|
||||||
<Compile Include="Savers\BaseXmlSaver.cs" />
|
<Compile Include="Savers\BaseXmlSaver.cs" />
|
||||||
<Compile Include="Savers\BoxSetXmlSaver.cs" />
|
<Compile Include="Savers\BoxSetXmlSaver.cs" />
|
||||||
<Compile Include="Savers\FolderXmlSaver.cs" />
|
<Compile Include="Savers\FolderXmlSaver.cs" />
|
||||||
|
|
|
@ -598,20 +598,6 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
||||||
break;
|
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":
|
case "CollectionNumber":
|
||||||
var tmdbCollection = reader.ReadElementContentAsString();
|
var tmdbCollection = reader.ReadElementContentAsString();
|
||||||
if (!string.IsNullOrWhiteSpace(tmdbCollection))
|
if (!string.IsNullOrWhiteSpace(tmdbCollection))
|
||||||
|
|
|
@ -17,9 +17,16 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
||||||
{
|
{
|
||||||
case "CollectionItems":
|
case "CollectionItems":
|
||||||
|
|
||||||
using (var subReader = reader.ReadSubtree())
|
if (!reader.IsEmptyElement)
|
||||||
{
|
{
|
||||||
FetchFromCollectionItemsNode(subReader, item);
|
using (var subReader = reader.ReadSubtree())
|
||||||
|
{
|
||||||
|
FetchFromCollectionItemsNode(subReader, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -45,15 +52,22 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
||||||
{
|
{
|
||||||
case "CollectionItem":
|
case "CollectionItem":
|
||||||
{
|
{
|
||||||
using (var subReader = reader.ReadSubtree())
|
if (!reader.IsEmptyElement)
|
||||||
{
|
{
|
||||||
var child = GetLinkedChild(subReader);
|
using (var subReader = reader.ReadSubtree())
|
||||||
|
|
||||||
if (child != null)
|
|
||||||
{
|
{
|
||||||
list.Add(child);
|
var child = GetLinkedChild(subReader);
|
||||||
|
|
||||||
|
if (child != null)
|
||||||
|
{
|
||||||
|
list.Add(child);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
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",
|
"TvDbId",
|
||||||
"Type",
|
"Type",
|
||||||
"TVRageId",
|
"TVRageId",
|
||||||
"VoteCount",
|
|
||||||
"Website",
|
"Website",
|
||||||
"Zap2ItId",
|
"Zap2ItId",
|
||||||
"CollectionItems",
|
"CollectionItems",
|
||||||
|
@ -407,10 +406,6 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||||
{
|
{
|
||||||
writer.WriteElementString("Rating", item.CommunityRating.Value.ToString(UsCulture));
|
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))
|
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",
|
"h264_qsv",
|
||||||
"hevc_qsv",
|
"hevc_qsv",
|
||||||
"mpeg2_qsv",
|
"mpeg2_qsv",
|
||||||
"vc1_qsv"
|
"vc1_qsv",
|
||||||
|
"h264_cuvid"
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (var codec in required)
|
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)
|
public override void ReportTranscodingProgress(TimeSpan? transcodingPosition, float? framerate, double? percentComplete, long? bytesTranscoded, int? bitRate)
|
||||||
{
|
{
|
||||||
var ticks = transcodingPosition.HasValue ? transcodingPosition.Value.Ticks : (long?)null;
|
var ticks = transcodingPosition.HasValue ? transcodingPosition.Value.Ticks : (long?)null;
|
||||||
|
|
|
@ -105,7 +105,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
//state.OutputContainer = (container ?? string.Empty).TrimStart('.');
|
//state.OutputContainer = (container ?? string.Empty).TrimStart('.');
|
||||||
|
|
||||||
state.OutputAudioBitrate = encodingHelper.GetAudioBitrateParam(state.Options, state.AudioStream);
|
state.OutputAudioBitrate = encodingHelper.GetAudioBitrateParam(state.Options, state.AudioStream);
|
||||||
state.OutputAudioSampleRate = request.AudioSampleRate;
|
|
||||||
|
|
||||||
state.OutputAudioCodec = state.Options.AudioCodec;
|
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