mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-11-17 10:58:58 -07:00
commit
2708df6cc2
@ -80,7 +80,6 @@
|
|||||||
<Compile Include="ImageMagick\UnplayedCountIndicator.cs" />
|
<Compile Include="ImageMagick\UnplayedCountIndicator.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="ImageMagick\fonts\MontserratLight.otf" />
|
|
||||||
<EmbeddedResource Include="ImageMagick\fonts\robotoregular.ttf" />
|
<EmbeddedResource Include="ImageMagick\fonts\robotoregular.ttf" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -111,7 +111,6 @@ namespace Emby.Drawing.ImageMagick
|
|||||||
wand.CurrentImage.TrimImage(10);
|
wand.CurrentImage.TrimImage(10);
|
||||||
wand.SaveImage(outputPath);
|
wand.SaveImage(outputPath);
|
||||||
}
|
}
|
||||||
SaveDelay();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImageSize GetImageSize(string path)
|
public ImageSize GetImageSize(string path)
|
||||||
@ -189,7 +188,6 @@ namespace Emby.Drawing.ImageMagick
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SaveDelay();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddForegroundLayer(MagickWand wand, ImageProcessingOptions options)
|
private void AddForegroundLayer(MagickWand wand, ImageProcessingOptions options)
|
||||||
@ -284,25 +282,16 @@ namespace Emby.Drawing.ImageMagick
|
|||||||
|
|
||||||
if (ratio >= 1.4)
|
if (ratio >= 1.4)
|
||||||
{
|
{
|
||||||
new StripCollageBuilder(_appPaths, _fileSystem).BuildThumbCollage(options.InputPaths.ToList(), options.OutputPath, options.Width, options.Height, options.Text);
|
new StripCollageBuilder(_appPaths, _fileSystem).BuildThumbCollage(options.InputPaths.ToList(), options.OutputPath, options.Width, options.Height);
|
||||||
}
|
}
|
||||||
else if (ratio >= .9)
|
else if (ratio >= .9)
|
||||||
{
|
{
|
||||||
new StripCollageBuilder(_appPaths, _fileSystem).BuildSquareCollage(options.InputPaths.ToList(), options.OutputPath, options.Width, options.Height, options.Text);
|
new StripCollageBuilder(_appPaths, _fileSystem).BuildSquareCollage(options.InputPaths.ToList(), options.OutputPath, options.Width, options.Height);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
new StripCollageBuilder(_appPaths, _fileSystem).BuildPosterCollage(options.InputPaths.ToList(), options.OutputPath, options.Width, options.Height, options.Text);
|
new StripCollageBuilder(_appPaths, _fileSystem).BuildPosterCollage(options.InputPaths.ToList(), options.OutputPath, options.Width, options.Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
SaveDelay();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SaveDelay()
|
|
||||||
{
|
|
||||||
// For some reason the images are not always getting released right away
|
|
||||||
//var task = Task.Delay(300);
|
|
||||||
//Task.WaitAll(task);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
|
@ -9,140 +9,35 @@ namespace Emby.Drawing.ImageMagick
|
|||||||
public class StripCollageBuilder
|
public class StripCollageBuilder
|
||||||
{
|
{
|
||||||
private readonly IApplicationPaths _appPaths;
|
private readonly IApplicationPaths _appPaths;
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
|
|
||||||
public StripCollageBuilder(IApplicationPaths appPaths, IFileSystem fileSystem)
|
public StripCollageBuilder(IApplicationPaths appPaths, IFileSystem fileSystem)
|
||||||
{
|
{
|
||||||
_appPaths = appPaths;
|
_appPaths = appPaths;
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BuildPosterCollage(List<string> paths, string outputPath, int width, int height, string text)
|
public void BuildPosterCollage(List<string> paths, string outputPath, int width, int height)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(text))
|
using (var wand = BuildPosterCollageWand(paths, width, height))
|
||||||
{
|
{
|
||||||
using (var wand = BuildPosterCollageWandWithText(paths, text, width, height))
|
wand.SaveImage(outputPath);
|
||||||
{
|
|
||||||
wand.SaveImage(outputPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
using (var wand = BuildPosterCollageWand(paths, width, height))
|
|
||||||
{
|
|
||||||
wand.SaveImage(outputPath);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BuildSquareCollage(List<string> paths, string outputPath, int width, int height, string text)
|
public void BuildSquareCollage(List<string> paths, string outputPath, int width, int height)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(text))
|
using (var wand = BuildSquareCollageWand(paths, width, height))
|
||||||
{
|
{
|
||||||
using (var wand = BuildSquareCollageWandWithText(paths, text, width, height))
|
wand.SaveImage(outputPath);
|
||||||
{
|
|
||||||
wand.SaveImage(outputPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
using (var wand = BuildSquareCollageWand(paths, width, height))
|
|
||||||
{
|
|
||||||
wand.SaveImage(outputPath);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BuildThumbCollage(List<string> paths, string outputPath, int width, int height, string text)
|
public void BuildThumbCollage(List<string> paths, string outputPath, int width, int height)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(text))
|
using (var wand = BuildThumbCollageWand(paths, width, height))
|
||||||
{
|
{
|
||||||
using (var wand = BuildThumbCollageWandWithText(paths, text, width, height))
|
wand.SaveImage(outputPath);
|
||||||
{
|
|
||||||
wand.SaveImage(outputPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
using (var wand = BuildThumbCollageWand(paths, width, height))
|
|
||||||
{
|
|
||||||
wand.SaveImage(outputPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private MagickWand BuildThumbCollageWandWithText(List<string> paths, string text, int width, int height)
|
|
||||||
{
|
|
||||||
var inputPaths = ImageHelpers.ProjectPaths(paths, 8);
|
|
||||||
using (var wandImages = new MagickWand(inputPaths.ToArray()))
|
|
||||||
{
|
|
||||||
var wand = new MagickWand(width, height);
|
|
||||||
wand.OpenImage("gradient:#111111-#111111");
|
|
||||||
using (var draw = new DrawingWand())
|
|
||||||
{
|
|
||||||
using (var fcolor = new PixelWand(ColorName.White))
|
|
||||||
{
|
|
||||||
draw.FillColor = fcolor;
|
|
||||||
draw.Font = MontserratLightFont;
|
|
||||||
draw.FontSize = 60;
|
|
||||||
draw.FontWeight = FontWeightType.LightStyle;
|
|
||||||
draw.TextAntialias = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var fontMetrics = wand.QueryFontMetrics(draw, text);
|
|
||||||
var textContainerY = Convert.ToInt32(height * .165);
|
|
||||||
wand.CurrentImage.AnnotateImage(draw, (width - fontMetrics.TextWidth) / 2, textContainerY, 0.0, text);
|
|
||||||
|
|
||||||
var iSlice = Convert.ToInt32(width * .1166666667);
|
|
||||||
int iTrans = Convert.ToInt32(height * 0.2);
|
|
||||||
int iHeight = Convert.ToInt32(height * 0.46296296296296296296296296296296);
|
|
||||||
var horizontalImagePadding = Convert.ToInt32(width * 0.0125);
|
|
||||||
|
|
||||||
foreach (var element in wandImages.ImageList)
|
|
||||||
{
|
|
||||||
int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height);
|
|
||||||
element.Gravity = GravityType.CenterGravity;
|
|
||||||
element.BackgroundColor = new PixelWand("none", 1);
|
|
||||||
element.ResizeImage(iWidth, iHeight, FilterTypes.LanczosFilter);
|
|
||||||
int ix = (int)Math.Abs((iWidth - iSlice) / 2);
|
|
||||||
element.CropImage(iSlice, iHeight, ix, 0);
|
|
||||||
|
|
||||||
element.ExtentImage(iSlice, iHeight, 0 - horizontalImagePadding, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
wandImages.SetFirstIterator();
|
|
||||||
using (var wandList = wandImages.AppendImages())
|
|
||||||
{
|
|
||||||
wandList.CurrentImage.TrimImage(1);
|
|
||||||
using (var mwr = wandList.CloneMagickWand())
|
|
||||||
{
|
|
||||||
using (var blackPixelWand = new PixelWand(ColorName.Black))
|
|
||||||
{
|
|
||||||
using (var greyPixelWand = new PixelWand(ColorName.Grey70))
|
|
||||||
{
|
|
||||||
mwr.CurrentImage.ResizeImage(wandList.CurrentImage.Width, (wandList.CurrentImage.Height / 2), FilterTypes.LanczosFilter, 1);
|
|
||||||
mwr.CurrentImage.FlipImage();
|
|
||||||
|
|
||||||
mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel;
|
|
||||||
mwr.CurrentImage.ColorizeImage(blackPixelWand, greyPixelWand);
|
|
||||||
|
|
||||||
using (var mwg = new MagickWand(wandList.CurrentImage.Width, iTrans))
|
|
||||||
{
|
|
||||||
mwg.OpenImage("gradient:black-none");
|
|
||||||
var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111);
|
|
||||||
mwr.CurrentImage.CompositeImage(mwg, CompositeOperator.DstInCompositeOp, 0, verticalSpacing);
|
|
||||||
|
|
||||||
wandList.AddImage(mwr);
|
|
||||||
int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2;
|
|
||||||
wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * 0.26851851851851851851851851851852));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return wand;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,81 +106,6 @@ namespace Emby.Drawing.ImageMagick
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private MagickWand BuildPosterCollageWandWithText(List<string> paths, string label, int width, int height)
|
|
||||||
{
|
|
||||||
var inputPaths = ImageHelpers.ProjectPaths(paths, 4);
|
|
||||||
using (var wandImages = new MagickWand(inputPaths.ToArray()))
|
|
||||||
{
|
|
||||||
var wand = new MagickWand(width, height);
|
|
||||||
wand.OpenImage("gradient:#111111-#111111");
|
|
||||||
using (var draw = new DrawingWand())
|
|
||||||
{
|
|
||||||
using (var fcolor = new PixelWand(ColorName.White))
|
|
||||||
{
|
|
||||||
draw.FillColor = fcolor;
|
|
||||||
draw.Font = MontserratLightFont;
|
|
||||||
draw.FontSize = 60;
|
|
||||||
draw.FontWeight = FontWeightType.LightStyle;
|
|
||||||
draw.TextAntialias = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var fontMetrics = wand.QueryFontMetrics(draw, label);
|
|
||||||
var textContainerY = Convert.ToInt32(height * .165);
|
|
||||||
wand.CurrentImage.AnnotateImage(draw, (width - fontMetrics.TextWidth) / 2, textContainerY, 0.0, label);
|
|
||||||
|
|
||||||
var iSlice = Convert.ToInt32(width * 0.225);
|
|
||||||
int iTrans = Convert.ToInt32(height * 0.2);
|
|
||||||
int iHeight = Convert.ToInt32(height * 0.46296296296296296296296296296296);
|
|
||||||
var horizontalImagePadding = Convert.ToInt32(width * 0.0275);
|
|
||||||
|
|
||||||
foreach (var element in wandImages.ImageList)
|
|
||||||
{
|
|
||||||
int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height);
|
|
||||||
element.Gravity = GravityType.CenterGravity;
|
|
||||||
element.BackgroundColor = new PixelWand("none", 1);
|
|
||||||
element.ResizeImage(iWidth, iHeight, FilterTypes.LanczosFilter);
|
|
||||||
int ix = (int)Math.Abs((iWidth - iSlice) / 2);
|
|
||||||
element.CropImage(iSlice, iHeight, ix, 0);
|
|
||||||
|
|
||||||
element.ExtentImage(iSlice, iHeight, 0 - horizontalImagePadding, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
wandImages.SetFirstIterator();
|
|
||||||
using (var wandList = wandImages.AppendImages())
|
|
||||||
{
|
|
||||||
wandList.CurrentImage.TrimImage(1);
|
|
||||||
using (var mwr = wandList.CloneMagickWand())
|
|
||||||
{
|
|
||||||
using (var blackPixelWand = new PixelWand(ColorName.Black))
|
|
||||||
{
|
|
||||||
using (var greyPixelWand = new PixelWand(ColorName.Grey70))
|
|
||||||
{
|
|
||||||
mwr.CurrentImage.ResizeImage(wandList.CurrentImage.Width, (wandList.CurrentImage.Height / 2), FilterTypes.LanczosFilter, 1);
|
|
||||||
mwr.CurrentImage.FlipImage();
|
|
||||||
|
|
||||||
mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel;
|
|
||||||
mwr.CurrentImage.ColorizeImage(blackPixelWand, greyPixelWand);
|
|
||||||
|
|
||||||
using (var mwg = new MagickWand(wandList.CurrentImage.Width, iTrans))
|
|
||||||
{
|
|
||||||
mwg.OpenImage("gradient:black-none");
|
|
||||||
var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111);
|
|
||||||
mwr.CurrentImage.CompositeImage(mwg, CompositeOperator.DstInCompositeOp, 0, verticalSpacing);
|
|
||||||
|
|
||||||
wandList.AddImage(mwr);
|
|
||||||
int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2;
|
|
||||||
wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * 0.26851851851851851851851851851852));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return wand;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private MagickWand BuildThumbCollageWand(List<string> paths, int width, int height)
|
private MagickWand BuildThumbCollageWand(List<string> paths, int width, int height)
|
||||||
{
|
{
|
||||||
var inputPaths = ImageHelpers.ProjectPaths(paths, 4);
|
var inputPaths = ImageHelpers.ProjectPaths(paths, 4);
|
||||||
@ -352,148 +172,29 @@ namespace Emby.Drawing.ImageMagick
|
|||||||
}
|
}
|
||||||
|
|
||||||
private MagickWand BuildSquareCollageWand(List<string> paths, int width, int height)
|
private MagickWand BuildSquareCollageWand(List<string> paths, int width, int height)
|
||||||
{
|
|
||||||
var inputPaths = ImageHelpers.ProjectPaths(paths, 3);
|
|
||||||
using (var wandImages = new MagickWand(inputPaths.ToArray()))
|
|
||||||
{
|
|
||||||
var wand = new MagickWand(width, height);
|
|
||||||
wand.OpenImage("gradient:#111111-#111111");
|
|
||||||
using (var draw = new DrawingWand())
|
|
||||||
{
|
|
||||||
var iSlice = Convert.ToInt32(width * .32);
|
|
||||||
int iTrans = Convert.ToInt32(height * .25);
|
|
||||||
int iHeight = Convert.ToInt32(height * .68);
|
|
||||||
var horizontalImagePadding = Convert.ToInt32(width * 0.02);
|
|
||||||
|
|
||||||
foreach (var element in wandImages.ImageList)
|
|
||||||
{
|
|
||||||
using (var blackPixelWand = new PixelWand(ColorName.Black))
|
|
||||||
{
|
|
||||||
int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height);
|
|
||||||
element.Gravity = GravityType.CenterGravity;
|
|
||||||
element.BackgroundColor = blackPixelWand;
|
|
||||||
element.ResizeImage(iWidth, iHeight, FilterTypes.LanczosFilter);
|
|
||||||
int ix = (int)Math.Abs((iWidth - iSlice) / 2);
|
|
||||||
element.CropImage(iSlice, iHeight, ix, 0);
|
|
||||||
|
|
||||||
element.ExtentImage(iSlice, iHeight, 0 - horizontalImagePadding, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wandImages.SetFirstIterator();
|
|
||||||
using (var wandList = wandImages.AppendImages())
|
|
||||||
{
|
|
||||||
wandList.CurrentImage.TrimImage(1);
|
|
||||||
using (var mwr = wandList.CloneMagickWand())
|
|
||||||
{
|
|
||||||
using (var blackPixelWand = new PixelWand(ColorName.Black))
|
|
||||||
{
|
|
||||||
using (var greyPixelWand = new PixelWand(ColorName.Grey70))
|
|
||||||
{
|
|
||||||
mwr.CurrentImage.ResizeImage(wandList.CurrentImage.Width, (wandList.CurrentImage.Height / 2), FilterTypes.LanczosFilter, 1);
|
|
||||||
mwr.CurrentImage.FlipImage();
|
|
||||||
|
|
||||||
mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel;
|
|
||||||
mwr.CurrentImage.ColorizeImage(blackPixelWand, greyPixelWand);
|
|
||||||
|
|
||||||
using (var mwg = new MagickWand(wandList.CurrentImage.Width, iTrans))
|
|
||||||
{
|
|
||||||
mwg.OpenImage("gradient:black-none");
|
|
||||||
var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111);
|
|
||||||
mwr.CurrentImage.CompositeImage(mwg, CompositeOperator.CopyOpacityCompositeOp, 0, verticalSpacing);
|
|
||||||
|
|
||||||
wandList.AddImage(mwr);
|
|
||||||
int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2;
|
|
||||||
wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * .03));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return wand;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private MagickWand BuildSquareCollageWandWithText(List<string> paths, string label, int width, int height)
|
|
||||||
{
|
{
|
||||||
var inputPaths = ImageHelpers.ProjectPaths(paths, 4);
|
var inputPaths = ImageHelpers.ProjectPaths(paths, 4);
|
||||||
using (var wandImages = new MagickWand(inputPaths.ToArray()))
|
var outputWand = new MagickWand(width, height, new PixelWand("none", 1));
|
||||||
|
var imageIndex = 0;
|
||||||
|
var cellWidth = width/2;
|
||||||
|
var cellHeight = height/2;
|
||||||
|
for (var x = 0; x < 2; x++)
|
||||||
{
|
{
|
||||||
var wand = new MagickWand(width, height);
|
for (var y = 0; y < 2; y++)
|
||||||
wand.OpenImage("gradient:#111111-#111111");
|
|
||||||
using (var draw = new DrawingWand())
|
|
||||||
{
|
{
|
||||||
using (var fcolor = new PixelWand(ColorName.White))
|
using (var temp = new MagickWand(inputPaths[imageIndex]))
|
||||||
{
|
{
|
||||||
draw.FillColor = fcolor;
|
temp.CurrentImage.ScaleImage(cellWidth, cellHeight);
|
||||||
draw.Font = MontserratLightFont;
|
// draw this image into the strip at the next position
|
||||||
draw.FontSize = 60;
|
var xPos = x*cellWidth;
|
||||||
draw.FontWeight = FontWeightType.LightStyle;
|
var yPos = y*cellHeight;
|
||||||
draw.TextAntialias = true;
|
outputWand.CurrentImage.CompositeImage(temp, CompositeOperator.OverCompositeOp, xPos, yPos);
|
||||||
}
|
|
||||||
|
|
||||||
var fontMetrics = wand.QueryFontMetrics(draw, label);
|
|
||||||
var textContainerY = Convert.ToInt32(height * .165);
|
|
||||||
wand.CurrentImage.AnnotateImage(draw, (width - fontMetrics.TextWidth) / 2, textContainerY, 0.0, label);
|
|
||||||
|
|
||||||
var iSlice = Convert.ToInt32(width * .225);
|
|
||||||
int iTrans = Convert.ToInt32(height * 0.2);
|
|
||||||
int iHeight = Convert.ToInt32(height * 0.46296296296296296296296296296296);
|
|
||||||
var horizontalImagePadding = Convert.ToInt32(width * 0.02);
|
|
||||||
|
|
||||||
foreach (var element in wandImages.ImageList)
|
|
||||||
{
|
|
||||||
int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height);
|
|
||||||
element.Gravity = GravityType.CenterGravity;
|
|
||||||
element.BackgroundColor = new PixelWand("none", 1);
|
|
||||||
element.ResizeImage(iWidth, iHeight, FilterTypes.LanczosFilter);
|
|
||||||
int ix = (int)Math.Abs((iWidth - iSlice) / 2);
|
|
||||||
element.CropImage(iSlice, iHeight, ix, 0);
|
|
||||||
|
|
||||||
element.ExtentImage(iSlice, iHeight, 0 - horizontalImagePadding, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
wandImages.SetFirstIterator();
|
|
||||||
using (var wandList = wandImages.AppendImages())
|
|
||||||
{
|
|
||||||
wandList.CurrentImage.TrimImage(1);
|
|
||||||
using (var mwr = wandList.CloneMagickWand())
|
|
||||||
{
|
|
||||||
using (var blackPixelWand = new PixelWand(ColorName.Black))
|
|
||||||
{
|
|
||||||
using (var greyPixelWand = new PixelWand(ColorName.Grey70))
|
|
||||||
{
|
|
||||||
mwr.CurrentImage.ResizeImage(wandList.CurrentImage.Width, (wandList.CurrentImage.Height / 2), FilterTypes.LanczosFilter, 1);
|
|
||||||
mwr.CurrentImage.FlipImage();
|
|
||||||
|
|
||||||
mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel;
|
|
||||||
mwr.CurrentImage.ColorizeImage(blackPixelWand, greyPixelWand);
|
|
||||||
|
|
||||||
using (var mwg = new MagickWand(wandList.CurrentImage.Width, iTrans))
|
|
||||||
{
|
|
||||||
mwg.OpenImage("gradient:black-none");
|
|
||||||
var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111);
|
|
||||||
mwr.CurrentImage.CompositeImage(mwg, CompositeOperator.DstInCompositeOp, 0, verticalSpacing);
|
|
||||||
|
|
||||||
wandList.AddImage(mwr);
|
|
||||||
int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2;
|
|
||||||
wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * 0.26851851851851851851851851851852));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
imageIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wand;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private string MontserratLightFont
|
return outputWand;
|
||||||
{
|
|
||||||
get { return PlayedIndicatorDrawer.ExtractFont("MontserratLight.otf", _appPaths, _fileSystem); }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ namespace MediaBrowser.Api
|
|||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
protected object ToStaticFileResult(string path)
|
protected object ToStaticFileResult(string path)
|
||||||
{
|
{
|
||||||
return ResultFactory.GetStaticFileResult(Request, path);
|
return ResultFactory.GetStaticFileResult(Request, path).Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected DtoOptions GetDtoOptions(object request)
|
protected DtoOptions GetDtoOptions(object request)
|
||||||
|
@ -9,7 +9,9 @@ using ServiceStack.Web;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using CommonIO;
|
using CommonIO;
|
||||||
|
using MediaBrowser.Controller.MediaEncoding;
|
||||||
|
|
||||||
namespace MediaBrowser.Api
|
namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
@ -71,6 +73,16 @@ namespace MediaBrowser.Api
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Route("/System/MediaEncoder/Path", "POST", Summary = "Updates the path to the media encoder")]
|
||||||
|
[Authenticated(Roles = "Admin", AllowBeforeStartupWizard = true)]
|
||||||
|
public class UpdateMediaEncoderPath : IReturnVoid
|
||||||
|
{
|
||||||
|
[ApiMember(Name = "Path", Description = "Path", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||||
|
public string Path { get; set; }
|
||||||
|
[ApiMember(Name = "PathType", Description = "PathType", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||||
|
public string PathType { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public class ConfigurationService : BaseApiService
|
public class ConfigurationService : BaseApiService
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -86,14 +98,22 @@ namespace MediaBrowser.Api
|
|||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
private readonly IProviderManager _providerManager;
|
private readonly IProviderManager _providerManager;
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
|
private readonly IMediaEncoder _mediaEncoder;
|
||||||
|
|
||||||
public ConfigurationService(IJsonSerializer jsonSerializer, IServerConfigurationManager configurationManager, IFileSystem fileSystem, IProviderManager providerManager, ILibraryManager libraryManager)
|
public ConfigurationService(IJsonSerializer jsonSerializer, IServerConfigurationManager configurationManager, IFileSystem fileSystem, IProviderManager providerManager, ILibraryManager libraryManager, IMediaEncoder mediaEncoder)
|
||||||
{
|
{
|
||||||
_jsonSerializer = jsonSerializer;
|
_jsonSerializer = jsonSerializer;
|
||||||
_configurationManager = configurationManager;
|
_configurationManager = configurationManager;
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
_providerManager = providerManager;
|
_providerManager = providerManager;
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
|
_mediaEncoder = mediaEncoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Post(UpdateMediaEncoderPath request)
|
||||||
|
{
|
||||||
|
var task = _mediaEncoder.UpdateEncoderPath(request.Path, request.PathType);
|
||||||
|
Task.WaitAll(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -80,7 +80,7 @@ namespace MediaBrowser.Api
|
|||||||
.OrderBy(i => i)
|
.OrderBy(i => i)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
result.Tags = items.OfType<IHasTags>()
|
result.Tags = items
|
||||||
.SelectMany(i => i.Tags)
|
.SelectMany(i => i.Tags)
|
||||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||||
.OrderBy(i => i)
|
.OrderBy(i => i)
|
||||||
|
@ -10,6 +10,8 @@ using System.Collections.Generic;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Model.Querying;
|
||||||
|
|
||||||
namespace MediaBrowser.Api
|
namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
@ -107,8 +109,7 @@ namespace MediaBrowser.Api
|
|||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(GameSystem).Name }
|
IncludeItemTypes = new[] { typeof(GameSystem).Name }
|
||||||
};
|
};
|
||||||
var parentIds = new string[] { } ;
|
var gameSystems = _libraryManager.GetItemList(query)
|
||||||
var gameSystems = _libraryManager.GetItemList(query, parentIds)
|
|
||||||
.Cast<GameSystem>()
|
.Cast<GameSystem>()
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
@ -128,8 +129,7 @@ namespace MediaBrowser.Api
|
|||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(Game).Name }
|
IncludeItemTypes = new[] { typeof(Game).Name }
|
||||||
};
|
};
|
||||||
var parentIds = new string[] { };
|
var games = _libraryManager.GetItemList(query)
|
||||||
var games = _libraryManager.GetItemList(query, parentIds)
|
|
||||||
.Cast<Game>()
|
.Cast<Game>()
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
@ -185,20 +185,42 @@ namespace MediaBrowser.Api
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetSimilarGames request)
|
public async Task<object> Get(GetSimilarGames request)
|
||||||
{
|
{
|
||||||
var dtoOptions = GetDtoOptions(request);
|
var result = await GetSimilarItemsResult(request).ConfigureAwait(false);
|
||||||
|
|
||||||
var result = SimilarItemsHelper.GetSimilarItemsResult(dtoOptions, _userManager,
|
|
||||||
_itemRepo,
|
|
||||||
_libraryManager,
|
|
||||||
_userDataRepository,
|
|
||||||
_dtoService,
|
|
||||||
Logger,
|
|
||||||
request, new[] { typeof(Game) },
|
|
||||||
SimilarItemsHelper.GetSimiliarityScore);
|
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<QueryResult<BaseItemDto>> GetSimilarItemsResult(BaseGetSimilarItemsFromItem request)
|
||||||
|
{
|
||||||
|
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
|
||||||
|
|
||||||
|
var item = string.IsNullOrEmpty(request.Id) ?
|
||||||
|
(!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder :
|
||||||
|
_libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
|
||||||
|
|
||||||
|
var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
|
{
|
||||||
|
Limit = request.Limit,
|
||||||
|
IncludeItemTypes = new[]
|
||||||
|
{
|
||||||
|
typeof(Game).Name
|
||||||
|
},
|
||||||
|
SimilarTo = item
|
||||||
|
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
|
var result = new QueryResult<BaseItemDto>
|
||||||
|
{
|
||||||
|
Items = (await _dtoService.GetBaseItemDtos(itemsResult, dtoOptions, user).ConfigureAwait(false)).ToArray(),
|
||||||
|
|
||||||
|
TotalRecordCount = itemsResult.Count
|
||||||
|
};
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -514,7 +514,7 @@ namespace MediaBrowser.Api.Images
|
|||||||
/// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param>
|
/// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param>
|
||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
/// <exception cref="ResourceNotFoundException"></exception>
|
/// <exception cref="ResourceNotFoundException"></exception>
|
||||||
public object GetImage(ImageRequest request, IHasImages item, bool isHeadRequest)
|
public Task<object> GetImage(ImageRequest request, IHasImages item, bool isHeadRequest)
|
||||||
{
|
{
|
||||||
if (request.PercentPlayed.HasValue)
|
if (request.PercentPlayed.HasValue)
|
||||||
{
|
{
|
||||||
@ -594,8 +594,7 @@ namespace MediaBrowser.Api.Images
|
|||||||
supportedImageEnhancers,
|
supportedImageEnhancers,
|
||||||
cacheDuration,
|
cacheDuration,
|
||||||
responseHeaders,
|
responseHeaders,
|
||||||
isHeadRequest)
|
isHeadRequest);
|
||||||
.Result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<object> GetImageResult(IHasImages item,
|
private async Task<object> GetImageResult(IHasImages item,
|
||||||
@ -632,7 +631,7 @@ namespace MediaBrowser.Api.Images
|
|||||||
|
|
||||||
headers["Vary"] = "Accept";
|
headers["Vary"] = "Accept";
|
||||||
|
|
||||||
return ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions
|
return await ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions
|
||||||
{
|
{
|
||||||
CacheDuration = cacheDuration,
|
CacheDuration = cacheDuration,
|
||||||
ResponseHeaders = headers,
|
ResponseHeaders = headers,
|
||||||
@ -643,7 +642,8 @@ namespace MediaBrowser.Api.Images
|
|||||||
// Sometimes imagemagick keeps a hold on the file briefly even after it's done writing to it.
|
// Sometimes imagemagick keeps a hold on the file briefly even after it's done writing to it.
|
||||||
// I'd rather do this than add a delay after saving the file
|
// I'd rather do this than add a delay after saving the file
|
||||||
FileShare = FileShare.ReadWrite
|
FileShare = FileShare.ReadWrite
|
||||||
});
|
|
||||||
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ImageFormat> GetOutputFormats(ImageRequest request, ItemImageInfo image, bool cropwhitespace, List<IImageEnhancer> enhancers)
|
private List<ImageFormat> GetOutputFormats(ImageRequest request, ItemImageInfo image, bool cropwhitespace, List<IImageEnhancer> enhancers)
|
||||||
|
@ -238,9 +238,9 @@ namespace MediaBrowser.Api.Images
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_fileSystem.FileExists(contentPath))
|
if (_fileSystem.FileExists(contentPath))
|
||||||
{
|
{
|
||||||
return ToStaticFileResult(contentPath);
|
return await ResultFactory.GetStaticFileResult(Request, contentPath).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (DirectoryNotFoundException)
|
catch (DirectoryNotFoundException)
|
||||||
{
|
{
|
||||||
@ -259,9 +259,9 @@ namespace MediaBrowser.Api.Images
|
|||||||
contentPath = await reader.ReadToEndAsync().ConfigureAwait(false);
|
contentPath = await reader.ReadToEndAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ToStaticFileResult(contentPath);
|
return await ResultFactory.GetStaticFileResult(Request, contentPath).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Downloads the image.
|
/// Downloads the image.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -38,6 +38,12 @@ namespace MediaBrowser.Api
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Route("/Items/RemoteSearch/Trailer", "POST")]
|
||||||
|
[Authenticated]
|
||||||
|
public class GetTrailerRemoteSearchResults : RemoteSearchQuery<TrailerInfo>, IReturn<List<RemoteSearchResult>>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
[Route("/Items/RemoteSearch/AdultVideo", "POST")]
|
[Route("/Items/RemoteSearch/AdultVideo", "POST")]
|
||||||
[Authenticated]
|
[Authenticated]
|
||||||
public class GetAdultVideoRemoteSearchResults : RemoteSearchQuery<ItemLookupInfo>, IReturn<List<RemoteSearchResult>>
|
public class GetAdultVideoRemoteSearchResults : RemoteSearchQuery<ItemLookupInfo>, IReturn<List<RemoteSearchResult>>
|
||||||
@ -132,60 +138,65 @@ namespace MediaBrowser.Api
|
|||||||
return ToOptimizedResult(infos);
|
return ToOptimizedResult(infos);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Post(GetMovieRemoteSearchResults request)
|
public async Task<object> Post(GetTrailerRemoteSearchResults request)
|
||||||
{
|
{
|
||||||
var result = _providerManager.GetRemoteSearchResults<Movie, MovieInfo>(request, CancellationToken.None).Result;
|
var result = await _providerManager.GetRemoteSearchResults<Trailer, TrailerInfo>(request, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Post(GetSeriesRemoteSearchResults request)
|
public async Task<object> Post(GetMovieRemoteSearchResults request)
|
||||||
{
|
{
|
||||||
var result = _providerManager.GetRemoteSearchResults<Series, SeriesInfo>(request, CancellationToken.None).Result;
|
var result = await _providerManager.GetRemoteSearchResults<Movie, MovieInfo>(request, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Post(GetGameRemoteSearchResults request)
|
public async Task<object> Post(GetSeriesRemoteSearchResults request)
|
||||||
{
|
{
|
||||||
var result = _providerManager.GetRemoteSearchResults<Game, GameInfo>(request, CancellationToken.None).Result;
|
var result = await _providerManager.GetRemoteSearchResults<Series, SeriesInfo>(request, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Post(GetBoxSetRemoteSearchResults request)
|
public async Task<object> Post(GetGameRemoteSearchResults request)
|
||||||
{
|
{
|
||||||
var result = _providerManager.GetRemoteSearchResults<BoxSet, BoxSetInfo>(request, CancellationToken.None).Result;
|
var result = await _providerManager.GetRemoteSearchResults<Game, GameInfo>(request, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Post(GetPersonRemoteSearchResults request)
|
public async Task<object> Post(GetBoxSetRemoteSearchResults request)
|
||||||
{
|
{
|
||||||
var result = _providerManager.GetRemoteSearchResults<Person, PersonLookupInfo>(request, CancellationToken.None).Result;
|
var result = await _providerManager.GetRemoteSearchResults<BoxSet, BoxSetInfo>(request, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Post(GetMusicAlbumRemoteSearchResults request)
|
public async Task<object> Post(GetPersonRemoteSearchResults request)
|
||||||
{
|
{
|
||||||
var result = _providerManager.GetRemoteSearchResults<MusicAlbum, AlbumInfo>(request, CancellationToken.None).Result;
|
var result = await _providerManager.GetRemoteSearchResults<Person, PersonLookupInfo>(request, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Post(GetMusicArtistRemoteSearchResults request)
|
public async Task<object> Post(GetMusicAlbumRemoteSearchResults request)
|
||||||
{
|
{
|
||||||
var result = _providerManager.GetRemoteSearchResults<MusicArtist, ArtistInfo>(request, CancellationToken.None).Result;
|
var result = await _providerManager.GetRemoteSearchResults<MusicAlbum, AlbumInfo>(request, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetRemoteSearchImage request)
|
public async Task<object> Post(GetMusicArtistRemoteSearchResults request)
|
||||||
{
|
{
|
||||||
var result = GetRemoteImage(request).Result;
|
var result = await _providerManager.GetRemoteSearchResults<MusicArtist, ArtistInfo>(request, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
return result;
|
return ToOptimizedResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<object> Get(GetRemoteSearchImage request)
|
||||||
|
{
|
||||||
|
return GetRemoteImage(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Post(ApplySearchCriteria request)
|
public void Post(ApplySearchCriteria request)
|
||||||
@ -241,7 +252,7 @@ namespace MediaBrowser.Api
|
|||||||
|
|
||||||
if (_fileSystem.FileExists(contentPath))
|
if (_fileSystem.FileExists(contentPath))
|
||||||
{
|
{
|
||||||
return ToStaticFileResult(contentPath);
|
return await ResultFactory.GetStaticFileResult(Request, contentPath).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (DirectoryNotFoundException)
|
catch (DirectoryNotFoundException)
|
||||||
@ -261,7 +272,7 @@ namespace MediaBrowser.Api
|
|||||||
contentPath = await reader.ReadToEndAsync().ConfigureAwait(false);
|
contentPath = await reader.ReadToEndAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ToStaticFileResult(contentPath);
|
return await ResultFactory.GetStaticFileResult(Request, contentPath).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -70,26 +70,21 @@ namespace MediaBrowser.Api
|
|||||||
Cultures = _localizationManager.GetCultures().ToList()
|
Cultures = _localizationManager.GetCultures().ToList()
|
||||||
};
|
};
|
||||||
|
|
||||||
var locationType = item.LocationType;
|
if (!item.IsVirtualItem && !(item is ICollectionFolder) && !(item is UserView) && !(item is AggregateFolder) && !(item is LiveTvChannel) && !(item is IItemByName))
|
||||||
if (locationType == LocationType.FileSystem ||
|
|
||||||
locationType == LocationType.Offline)
|
|
||||||
{
|
{
|
||||||
if (!(item is ICollectionFolder) && !(item is UserView) && !(item is AggregateFolder) && !(item is LiveTvChannel) && !(item is IItemByName))
|
var inheritedContentType = _libraryManager.GetInheritedContentType(item);
|
||||||
|
var configuredContentType = _libraryManager.GetConfiguredContentType(item);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(inheritedContentType) || string.Equals(inheritedContentType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase) || !string.IsNullOrWhiteSpace(configuredContentType))
|
||||||
{
|
{
|
||||||
var inheritedContentType = _libraryManager.GetInheritedContentType(item);
|
info.ContentTypeOptions = GetContentTypeOptions(true);
|
||||||
var configuredContentType = _libraryManager.GetConfiguredContentType(item);
|
info.ContentType = configuredContentType;
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(inheritedContentType) || string.Equals(inheritedContentType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase) || !string.IsNullOrWhiteSpace(configuredContentType))
|
if (string.Equals(inheritedContentType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
info.ContentTypeOptions = GetContentTypeOptions(true);
|
info.ContentTypeOptions = info.ContentTypeOptions
|
||||||
info.ContentType = configuredContentType;
|
.Where(i => string.IsNullOrWhiteSpace(i.Value) || string.Equals(i.Value, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
|
||||||
|
.ToList();
|
||||||
if (string.Equals(inheritedContentType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
info.ContentTypeOptions = info.ContentTypeOptions
|
|
||||||
.Where(i => string.IsNullOrWhiteSpace(i.Value) || string.Equals(i.Value, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
|
|
||||||
.ToList();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -280,11 +275,7 @@ namespace MediaBrowser.Api
|
|||||||
episode.AbsoluteEpisodeNumber = request.AbsoluteEpisodeNumber;
|
episode.AbsoluteEpisodeNumber = request.AbsoluteEpisodeNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
var hasTags = item as IHasTags;
|
item.Tags = request.Tags;
|
||||||
if (hasTags != null)
|
|
||||||
{
|
|
||||||
hasTags.Tags = request.Tags;
|
|
||||||
}
|
|
||||||
|
|
||||||
var hasTaglines = item as IHasTaglines;
|
var hasTaglines = item as IHasTaglines;
|
||||||
if (hasTaglines != null)
|
if (hasTaglines != null)
|
||||||
@ -298,11 +289,7 @@ namespace MediaBrowser.Api
|
|||||||
hasShortOverview.ShortOverview = request.ShortOverview;
|
hasShortOverview.ShortOverview = request.ShortOverview;
|
||||||
}
|
}
|
||||||
|
|
||||||
var hasKeywords = item as IHasKeywords;
|
item.Keywords = request.Keywords;
|
||||||
if (hasKeywords != null)
|
|
||||||
{
|
|
||||||
hasKeywords.Keywords = request.Keywords;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request.Studios != null)
|
if (request.Studios != null)
|
||||||
{
|
{
|
||||||
@ -427,11 +414,6 @@ namespace MediaBrowser.Api
|
|||||||
series.Status = request.SeriesStatus;
|
series.Status = request.SeriesStatus;
|
||||||
series.AirDays = request.AirDays;
|
series.AirDays = request.AirDays;
|
||||||
series.AirTime = request.AirTime;
|
series.AirTime = request.AirTime;
|
||||||
|
|
||||||
if (request.DisplaySpecialsWithSeasons.HasValue)
|
|
||||||
{
|
|
||||||
series.DisplaySpecialsWithSeasons = request.DisplaySpecialsWithSeasons.Value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -493,7 +493,7 @@ namespace MediaBrowser.Api.Library
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetDownload request)
|
public Task<object> Get(GetDownload request)
|
||||||
{
|
{
|
||||||
var item = _libraryManager.GetItemById(request.Id);
|
var item = _libraryManager.GetItemById(request.Id);
|
||||||
var auth = _authContext.GetAuthorizationInfo(Request);
|
var auth = _authContext.GetAuthorizationInfo(Request);
|
||||||
@ -552,7 +552,7 @@ namespace MediaBrowser.Api.Library
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetFile request)
|
public Task<object> Get(GetFile request)
|
||||||
{
|
{
|
||||||
var item = _libraryManager.GetItemById(request.Id);
|
var item = _libraryManager.GetItemById(request.Id);
|
||||||
var locationType = item.LocationType;
|
var locationType = item.LocationType;
|
||||||
@ -565,7 +565,7 @@ namespace MediaBrowser.Api.Library
|
|||||||
throw new ArgumentException("This command cannot be used for directories.");
|
throw new ArgumentException("This command cannot be used for directories.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return ToStaticFileResult(item.Path);
|
return ResultFactory.GetStaticFileResult(Request, item.Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -146,6 +146,13 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
/// <value>The fields.</value>
|
/// <value>The fields.</value>
|
||||||
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
public string Fields { get; set; }
|
public string Fields { get; set; }
|
||||||
|
|
||||||
|
public bool EnableTotalRecordCount { get; set; }
|
||||||
|
|
||||||
|
public GetRecordings()
|
||||||
|
{
|
||||||
|
EnableTotalRecordCount = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Recordings/Groups", "GET", Summary = "Gets live tv recording groups")]
|
[Route("/LiveTv/Recordings/Groups", "GET", Summary = "Gets live tv recording groups")]
|
||||||
@ -200,6 +207,8 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
|
|
||||||
[ApiMember(Name = "SeriesTimerId", Description = "Optional filter by timers belonging to a series timer", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "SeriesTimerId", Description = "Optional filter by timers belonging to a series timer", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
public string SeriesTimerId { get; set; }
|
public string SeriesTimerId { get; set; }
|
||||||
|
|
||||||
|
public bool? IsActive { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Programs", "GET,POST", Summary = "Gets available live tv epgs..")]
|
[Route("/LiveTv/Programs", "GET,POST", Summary = "Gets available live tv epgs..")]
|
||||||
@ -439,6 +448,12 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Route("/LiveTv/ListingProviders/Default", "GET")]
|
||||||
|
[Authenticated(AllowBeforeStartupWizard = true)]
|
||||||
|
public class GetDefaultListingProvider : ListingsProviderInfo, IReturn<ListingsProviderInfo>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/ListingProviders", "POST", Summary = "Adds a listing provider")]
|
[Route("/LiveTv/ListingProviders", "POST", Summary = "Adds a listing provider")]
|
||||||
[Authenticated(AllowBeforeStartupWizard = true)]
|
[Authenticated(AllowBeforeStartupWizard = true)]
|
||||||
public class AddListingProvider : ListingsProviderInfo, IReturn<ListingsProviderInfo>
|
public class AddListingProvider : ListingsProviderInfo, IReturn<ListingsProviderInfo>
|
||||||
@ -478,6 +493,32 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Route("/LiveTv/ChannelMappingOptions")]
|
||||||
|
[Authenticated(AllowBeforeStartupWizard = true)]
|
||||||
|
public class GetChannelMappingOptions
|
||||||
|
{
|
||||||
|
[ApiMember(Name = "Id", Description = "Provider id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string ProviderId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Route("/LiveTv/ChannelMappings")]
|
||||||
|
[Authenticated(AllowBeforeStartupWizard = true)]
|
||||||
|
public class SetChannelMapping
|
||||||
|
{
|
||||||
|
[ApiMember(Name = "Id", Description = "Provider id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string ProviderId { get; set; }
|
||||||
|
public string TunerChannelNumber { get; set; }
|
||||||
|
public string ProviderChannelNumber { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ChannelMappingOptions
|
||||||
|
{
|
||||||
|
public List<TunerChannelMapping> TunerChannels { get; set; }
|
||||||
|
public List<NameIdPair> ProviderChannels { get; set; }
|
||||||
|
public List<NameValuePair> Mappings { get; set; }
|
||||||
|
public string ProviderName { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Registration", "GET")]
|
[Route("/LiveTv/Registration", "GET")]
|
||||||
[Authenticated]
|
[Authenticated]
|
||||||
public class GetLiveTvRegistrationInfo : IReturn<MBRegistrationRecord>
|
public class GetLiveTvRegistrationInfo : IReturn<MBRegistrationRecord>
|
||||||
@ -525,6 +566,11 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
_dtoService = dtoService;
|
_dtoService = dtoService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public object Get(GetDefaultListingProvider request)
|
||||||
|
{
|
||||||
|
return ToOptimizedResult(new ListingsProviderInfo());
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<object> Get(GetSatChannnelScanResult request)
|
public async Task<object> Get(GetSatChannnelScanResult request)
|
||||||
{
|
{
|
||||||
var result = await _liveTvManager.GetSatChannelScanResult(request, CancellationToken.None).ConfigureAwait(false);
|
var result = await _liveTvManager.GetSatChannelScanResult(request, CancellationToken.None).ConfigureAwait(false);
|
||||||
@ -539,6 +585,46 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<object> Post(SetChannelMapping request)
|
||||||
|
{
|
||||||
|
return await _liveTvManager.SetChannelMapping(request.ProviderId, request.TunerChannelNumber, request.ProviderChannelNumber).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<object> Get(GetChannelMappingOptions request)
|
||||||
|
{
|
||||||
|
var config = GetConfiguration();
|
||||||
|
|
||||||
|
var listingsProviderInfo = config.ListingProviders.First(i => string.Equals(request.ProviderId, i.Id, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
|
var listingsProviderName = _liveTvManager.ListingProviders.First(i => string.Equals(i.Type, listingsProviderInfo.Type, StringComparison.OrdinalIgnoreCase)).Name;
|
||||||
|
|
||||||
|
var tunerChannels = await _liveTvManager.GetChannelsForListingsProvider(request.ProviderId, CancellationToken.None)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
var providerChannels = await _liveTvManager.GetChannelsFromListingsProviderData(request.ProviderId, CancellationToken.None)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
var mappings = listingsProviderInfo.ChannelMappings.ToList();
|
||||||
|
|
||||||
|
var result = new ChannelMappingOptions
|
||||||
|
{
|
||||||
|
TunerChannels = tunerChannels.Select(i => _liveTvManager.GetTunerChannelMapping(i, mappings, providerChannels)).ToList(),
|
||||||
|
|
||||||
|
ProviderChannels = providerChannels.Select(i => new NameIdPair
|
||||||
|
{
|
||||||
|
Name = i.Name,
|
||||||
|
Id = i.Number
|
||||||
|
|
||||||
|
}).ToList(),
|
||||||
|
|
||||||
|
Mappings = mappings,
|
||||||
|
|
||||||
|
ProviderName = listingsProviderName
|
||||||
|
};
|
||||||
|
|
||||||
|
return ToOptimizedResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
public object Get(GetSatIniMappings request)
|
public object Get(GetSatIniMappings request)
|
||||||
{
|
{
|
||||||
return ToOptimizedResult(_liveTvManager.GetSatIniMappings());
|
return ToOptimizedResult(_liveTvManager.GetSatIniMappings());
|
||||||
@ -550,9 +636,7 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
|
|
||||||
var response = await _httpClient.Get(new HttpRequestOptions
|
var response = await _httpClient.Get(new HttpRequestOptions
|
||||||
{
|
{
|
||||||
Url = "https://json.schedulesdirect.org/20141201/available/countries",
|
Url = "https://json.schedulesdirect.org/20141201/available/countries"
|
||||||
CacheLength = TimeSpan.FromDays(1),
|
|
||||||
CacheMode = CacheMode.Unconditional
|
|
||||||
|
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
|
|
||||||
@ -582,11 +666,7 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
|
|
||||||
public void Delete(DeleteListingProvider request)
|
public void Delete(DeleteListingProvider request)
|
||||||
{
|
{
|
||||||
var config = GetConfiguration();
|
_liveTvManager.DeleteListingsProvider(request.Id);
|
||||||
|
|
||||||
config.ListingProviders = config.ListingProviders.Where(i => !string.Equals(request.Id, i.Id, StringComparison.OrdinalIgnoreCase)).ToList();
|
|
||||||
|
|
||||||
_config.SaveConfiguration("livetv", config);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<object> Post(AddTunerHost request)
|
public async Task<object> Post(AddTunerHost request)
|
||||||
@ -609,6 +689,11 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
return _config.GetConfiguration<LiveTvOptions>("livetv");
|
return _config.GetConfiguration<LiveTvOptions>("livetv");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdateConfiguration(LiveTvOptions options)
|
||||||
|
{
|
||||||
|
_config.SaveConfiguration("livetv", options);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<object> Get(GetLineups request)
|
public async Task<object> Get(GetLineups request)
|
||||||
{
|
{
|
||||||
var info = await _liveTvManager.GetLineups(request.Type, request.Id, request.Country, request.Location).ConfigureAwait(false);
|
var info = await _liveTvManager.GetLineups(request.Type, request.Id, request.Country, request.Location).ConfigureAwait(false);
|
||||||
@ -641,14 +726,14 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
|
|
||||||
var user = string.IsNullOrEmpty(request.UserId) ? null : _userManager.GetUserById(request.UserId);
|
var user = string.IsNullOrEmpty(request.UserId) ? null : _userManager.GetUserById(request.UserId);
|
||||||
|
|
||||||
var returnArray = _dtoService.GetBaseItemDtos(channelResult.Items, GetDtoOptions(Request), user).ToArray();
|
var returnArray = (await _dtoService.GetBaseItemDtos(channelResult.Items, GetDtoOptions(Request), user).ConfigureAwait(false)).ToArray();
|
||||||
|
|
||||||
var result = new QueryResult<BaseItemDto>
|
var result = new QueryResult<BaseItemDto>
|
||||||
{
|
{
|
||||||
Items = returnArray,
|
Items = returnArray,
|
||||||
TotalRecordCount = channelResult.TotalRecordCount
|
TotalRecordCount = channelResult.TotalRecordCount
|
||||||
};
|
};
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -752,7 +837,8 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
Limit = request.Limit,
|
Limit = request.Limit,
|
||||||
Status = request.Status,
|
Status = request.Status,
|
||||||
SeriesTimerId = request.SeriesTimerId,
|
SeriesTimerId = request.SeriesTimerId,
|
||||||
IsInProgress = request.IsInProgress
|
IsInProgress = request.IsInProgress,
|
||||||
|
EnableTotalRecordCount = request.EnableTotalRecordCount
|
||||||
|
|
||||||
}, options, CancellationToken.None).ConfigureAwait(false);
|
}, options, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
@ -783,7 +869,8 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
var result = await _liveTvManager.GetTimers(new TimerQuery
|
var result = await _liveTvManager.GetTimers(new TimerQuery
|
||||||
{
|
{
|
||||||
ChannelId = request.ChannelId,
|
ChannelId = request.ChannelId,
|
||||||
SeriesTimerId = request.SeriesTimerId
|
SeriesTimerId = request.SeriesTimerId,
|
||||||
|
IsActive = request.IsActive
|
||||||
|
|
||||||
}, CancellationToken.None).ConfigureAwait(false);
|
}, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Controller.LiveTv;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.Movies
|
namespace MediaBrowser.Api.Movies
|
||||||
{
|
{
|
||||||
@ -112,16 +113,14 @@ namespace MediaBrowser.Api.Movies
|
|||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public async Task<object> Get(GetSimilarMovies request)
|
public async Task<object> Get(GetSimilarMovies request)
|
||||||
{
|
{
|
||||||
var result = await GetSimilarItemsResult(
|
var result = await GetSimilarItemsResult(request).ConfigureAwait(false);
|
||||||
request, SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
|
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<object> Get(GetSimilarTrailers request)
|
public async Task<object> Get(GetSimilarTrailers request)
|
||||||
{
|
{
|
||||||
var result = await GetSimilarItemsResult(
|
var result = await GetSimilarItemsResult(request).ConfigureAwait(false);
|
||||||
request, SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
|
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
}
|
}
|
||||||
@ -130,148 +129,93 @@ namespace MediaBrowser.Api.Movies
|
|||||||
{
|
{
|
||||||
var user = _userManager.GetUserById(request.UserId);
|
var user = _userManager.GetUserById(request.UserId);
|
||||||
|
|
||||||
var query = new InternalItemsQuery(user)
|
|
||||||
{
|
|
||||||
IncludeItemTypes = new[] { typeof(Movie).Name }
|
|
||||||
};
|
|
||||||
|
|
||||||
if (user.Configuration.IncludeTrailersInSuggestions)
|
|
||||||
{
|
|
||||||
var includeList = query.IncludeItemTypes.ToList();
|
|
||||||
includeList.Add(typeof(Trailer).Name);
|
|
||||||
query.IncludeItemTypes = includeList.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
var parentIds = string.IsNullOrWhiteSpace(request.ParentId) ? new string[] { } : new[] { request.ParentId };
|
|
||||||
var movies = _libraryManager.GetItemList(query, parentIds)
|
|
||||||
.OrderBy(i => (int)i.SourceType);
|
|
||||||
|
|
||||||
var listEligibleForCategories = new List<BaseItem>();
|
|
||||||
var listEligibleForSuggestion = new List<BaseItem>();
|
|
||||||
|
|
||||||
var list = movies.ToList();
|
|
||||||
|
|
||||||
listEligibleForCategories.AddRange(list);
|
|
||||||
listEligibleForSuggestion.AddRange(list);
|
|
||||||
|
|
||||||
listEligibleForCategories = listEligibleForCategories
|
|
||||||
// Exclude trailers from the suggestion categories
|
|
||||||
.Where(i => i is Movie)
|
|
||||||
.DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
|
|
||||||
.DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString(), StringComparer.OrdinalIgnoreCase)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
listEligibleForSuggestion = listEligibleForSuggestion
|
|
||||||
.DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
|
|
||||||
.DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString(), StringComparer.OrdinalIgnoreCase)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var dtoOptions = GetDtoOptions(request);
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
dtoOptions.Fields = request.GetItemFields().ToList();
|
dtoOptions.Fields = request.GetItemFields().ToList();
|
||||||
|
|
||||||
var result = GetRecommendationCategories(user, listEligibleForCategories, listEligibleForSuggestion, request.CategoryLimit, request.ItemLimit, dtoOptions);
|
var result = GetRecommendationCategories(user, request.ParentId, request.CategoryLimit, request.ItemLimit, dtoOptions);
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<ItemsResult> GetSimilarItemsResult(BaseGetSimilarItemsFromItem request, Func<BaseItem, List<PersonInfo>, List<PersonInfo>, BaseItem, int> getSimilarityScore)
|
private async Task<QueryResult<BaseItemDto>> GetSimilarItemsResult(BaseGetSimilarItemsFromItem request)
|
||||||
{
|
{
|
||||||
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
|
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
|
||||||
|
|
||||||
var item = string.IsNullOrEmpty(request.Id) ?
|
var item = string.IsNullOrEmpty(request.Id) ?
|
||||||
(!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder :
|
(!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder :
|
||||||
_libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
|
_libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
|
||||||
|
|
||||||
var query = new InternalItemsQuery(user)
|
var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(Movie).Name }
|
Limit = request.Limit,
|
||||||
};
|
IncludeItemTypes = new[]
|
||||||
|
|
||||||
if (user == null || user.Configuration.IncludeTrailersInSuggestions)
|
|
||||||
{
|
|
||||||
var includeList = query.IncludeItemTypes.ToList();
|
|
||||||
includeList.Add(typeof(Trailer).Name);
|
|
||||||
query.IncludeItemTypes = includeList.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
var list = _libraryManager.GetItemList(query)
|
|
||||||
.OrderBy(i => (int)i.SourceType)
|
|
||||||
.DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N"))
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
if (item is Video)
|
|
||||||
{
|
|
||||||
var imdbId = item.GetProviderId(MetadataProviders.Imdb);
|
|
||||||
|
|
||||||
// Use imdb id to try to filter duplicates of the same item
|
|
||||||
if (!string.IsNullOrWhiteSpace(imdbId))
|
|
||||||
{
|
{
|
||||||
list = list
|
typeof(Movie).Name,
|
||||||
.Where(i => !string.Equals(imdbId, i.GetProviderId(MetadataProviders.Imdb), StringComparison.OrdinalIgnoreCase))
|
typeof(Trailer).Name,
|
||||||
.ToList();
|
typeof(LiveTvProgram).Name
|
||||||
}
|
},
|
||||||
}
|
IsMovie = true,
|
||||||
|
SimilarTo = item,
|
||||||
|
EnableGroupByMetadataKey = true
|
||||||
|
|
||||||
var items = SimilarItemsHelper.GetSimilaritems(item, _libraryManager, list, getSimilarityScore).ToList();
|
}).ToList();
|
||||||
|
|
||||||
IEnumerable<BaseItem> returnItems = items;
|
|
||||||
|
|
||||||
if (request.Limit.HasValue)
|
|
||||||
{
|
|
||||||
returnItems = returnItems.Take(request.Limit.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
var dtoOptions = GetDtoOptions(request);
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
var result = new ItemsResult
|
var result = new QueryResult<BaseItemDto>
|
||||||
{
|
{
|
||||||
Items = _dtoService.GetBaseItemDtos(returnItems, dtoOptions, user).ToArray(),
|
Items = (await _dtoService.GetBaseItemDtos(itemsResult, dtoOptions, user).ConfigureAwait(false)).ToArray(),
|
||||||
|
|
||||||
TotalRecordCount = items.Count
|
TotalRecordCount = itemsResult.Count
|
||||||
};
|
};
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<RecommendationDto> GetRecommendationCategories(User user, List<BaseItem> allMoviesForCategories, List<BaseItem> allMovies, int categoryLimit, int itemLimit, DtoOptions dtoOptions)
|
private IEnumerable<RecommendationDto> GetRecommendationCategories(User user, string parentId, int categoryLimit, int itemLimit, DtoOptions dtoOptions)
|
||||||
{
|
{
|
||||||
var categories = new List<RecommendationDto>();
|
var categories = new List<RecommendationDto>();
|
||||||
|
|
||||||
var recentlyPlayedMovies = allMoviesForCategories
|
var parentIdGuid = string.IsNullOrWhiteSpace(parentId) ? (Guid?)null : new Guid(parentId);
|
||||||
.Select(i =>
|
|
||||||
|
var query = new InternalItemsQuery(user)
|
||||||
|
{
|
||||||
|
IncludeItemTypes = new[]
|
||||||
{
|
{
|
||||||
var userdata = _userDataRepository.GetUserData(user, i);
|
typeof(Movie).Name,
|
||||||
return new Tuple<BaseItem, bool, DateTime>(i, userdata.Played, userdata.LastPlayedDate ?? DateTime.MinValue);
|
//typeof(Trailer).Name,
|
||||||
})
|
//typeof(LiveTvProgram).Name
|
||||||
.Where(i => i.Item2)
|
},
|
||||||
.OrderByDescending(i => i.Item3)
|
// IsMovie = true
|
||||||
.Select(i => i.Item1)
|
SortBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.Random },
|
||||||
.ToList();
|
SortOrder = SortOrder.Descending,
|
||||||
|
Limit = 7,
|
||||||
|
ParentId = parentIdGuid,
|
||||||
|
Recursive = true
|
||||||
|
};
|
||||||
|
|
||||||
var excludeFromLiked = recentlyPlayedMovies.Take(10);
|
var recentlyPlayedMovies = _libraryManager.GetItemList(query).ToList();
|
||||||
var likedMovies = allMovies
|
|
||||||
.Select(i =>
|
var likedMovies = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
|
{
|
||||||
|
IncludeItemTypes = new[]
|
||||||
{
|
{
|
||||||
var score = 0;
|
typeof(Movie).Name,
|
||||||
var userData = _userDataRepository.GetUserData(user, i);
|
typeof(Trailer).Name,
|
||||||
|
typeof(LiveTvProgram).Name
|
||||||
|
},
|
||||||
|
IsMovie = true,
|
||||||
|
SortBy = new[] { ItemSortBy.Random },
|
||||||
|
SortOrder = SortOrder.Descending,
|
||||||
|
Limit = 10,
|
||||||
|
IsFavoriteOrLiked = true,
|
||||||
|
ExcludeItemIds = recentlyPlayedMovies.Select(i => i.Id.ToString("N")).ToArray(),
|
||||||
|
EnableGroupByMetadataKey = true,
|
||||||
|
ParentId = parentIdGuid,
|
||||||
|
Recursive = true
|
||||||
|
|
||||||
if (userData.IsFavorite)
|
}).ToList();
|
||||||
{
|
|
||||||
score = 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
score = userData.Likes.HasValue ? userData.Likes.Value ? 1 : -1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Tuple<BaseItem, int>(i, score);
|
|
||||||
})
|
|
||||||
.OrderByDescending(i => i.Item2)
|
|
||||||
.ThenBy(i => Guid.NewGuid())
|
|
||||||
.Where(i => i.Item2 > 0)
|
|
||||||
.Select(i => i.Item1)
|
|
||||||
.Where(i => !excludeFromLiked.Contains(i));
|
|
||||||
|
|
||||||
var mostRecentMovies = recentlyPlayedMovies.Take(6).ToList();
|
var mostRecentMovies = recentlyPlayedMovies.Take(6).ToList();
|
||||||
// Get recently played directors
|
// Get recently played directors
|
||||||
@ -284,11 +228,11 @@ namespace MediaBrowser.Api.Movies
|
|||||||
.OrderBy(i => Guid.NewGuid())
|
.OrderBy(i => Guid.NewGuid())
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var similarToRecentlyPlayed = GetSimilarTo(user, allMovies, recentlyPlayedMovies.Take(7).OrderBy(i => Guid.NewGuid()), itemLimit, dtoOptions, RecommendationType.SimilarToRecentlyPlayed).GetEnumerator();
|
var similarToRecentlyPlayed = GetSimilarTo(user, recentlyPlayedMovies, itemLimit, dtoOptions, RecommendationType.SimilarToRecentlyPlayed).GetEnumerator();
|
||||||
var similarToLiked = GetSimilarTo(user, allMovies, likedMovies, itemLimit, dtoOptions, RecommendationType.SimilarToLikedItem).GetEnumerator();
|
var similarToLiked = GetSimilarTo(user, likedMovies, itemLimit, dtoOptions, RecommendationType.SimilarToLikedItem).GetEnumerator();
|
||||||
|
|
||||||
var hasDirectorFromRecentlyPlayed = GetWithDirector(user, allMovies, recentDirectors, itemLimit, dtoOptions, RecommendationType.HasDirectorFromRecentlyPlayed).GetEnumerator();
|
var hasDirectorFromRecentlyPlayed = GetWithDirector(user, recentDirectors, itemLimit, dtoOptions, RecommendationType.HasDirectorFromRecentlyPlayed).GetEnumerator();
|
||||||
var hasActorFromRecentlyPlayed = GetWithActor(user, allMovies, recentActors, itemLimit, dtoOptions, RecommendationType.HasActorFromRecentlyPlayed).GetEnumerator();
|
var hasActorFromRecentlyPlayed = GetWithActor(user, recentActors, itemLimit, dtoOptions, RecommendationType.HasActorFromRecentlyPlayed).GetEnumerator();
|
||||||
|
|
||||||
var categoryTypes = new List<IEnumerator<RecommendationDto>>
|
var categoryTypes = new List<IEnumerator<RecommendationDto>>
|
||||||
{
|
{
|
||||||
@ -331,44 +275,28 @@ namespace MediaBrowser.Api.Movies
|
|||||||
return categories.OrderBy(i => i.RecommendationType).ThenBy(i => Guid.NewGuid());
|
return categories.OrderBy(i => i.RecommendationType).ThenBy(i => Guid.NewGuid());
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<RecommendationDto> GetWithDirector(User user, List<BaseItem> allMovies, IEnumerable<string> directors, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
|
private IEnumerable<RecommendationDto> GetWithDirector(User user, IEnumerable<string> names, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
|
||||||
{
|
|
||||||
var userId = user.Id;
|
|
||||||
|
|
||||||
foreach (var director in directors)
|
|
||||||
{
|
|
||||||
var items = allMovies
|
|
||||||
.Where(i => _libraryManager.GetPeople(i).Any(p => string.Equals(p.Type, PersonType.Director, StringComparison.OrdinalIgnoreCase) && string.Equals(p.Name, director, StringComparison.OrdinalIgnoreCase)))
|
|
||||||
.Take(itemLimit)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
if (items.Count > 0)
|
|
||||||
{
|
|
||||||
yield return new RecommendationDto
|
|
||||||
{
|
|
||||||
BaselineItemName = director,
|
|
||||||
CategoryId = director.GetMD5().ToString("N"),
|
|
||||||
RecommendationType = type,
|
|
||||||
Items = _dtoService.GetBaseItemDtos(items, dtoOptions, user).ToArray()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<RecommendationDto> GetWithActor(User user, List<BaseItem> allMovies, IEnumerable<string> names, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
|
|
||||||
{
|
{
|
||||||
foreach (var name in names)
|
foreach (var name in names)
|
||||||
{
|
{
|
||||||
var itemsWithActor = _libraryManager.GetItemIds(new InternalItemsQuery(user)
|
var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
Person = name
|
Person = name,
|
||||||
|
// Account for duplicates by imdb id, since the database doesn't support this yet
|
||||||
|
Limit = itemLimit + 2,
|
||||||
|
PersonTypes = new[] { PersonType.Director },
|
||||||
|
IncludeItemTypes = new[]
|
||||||
|
{
|
||||||
|
typeof(Movie).Name,
|
||||||
|
typeof(Trailer).Name,
|
||||||
|
typeof(LiveTvProgram).Name
|
||||||
|
},
|
||||||
|
IsMovie = true,
|
||||||
|
EnableGroupByMetadataKey = true
|
||||||
|
|
||||||
});
|
}).DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N"))
|
||||||
|
.Take(itemLimit)
|
||||||
var items = allMovies
|
.ToList();
|
||||||
.Where(i => itemsWithActor.Contains(i.Id))
|
|
||||||
.Take(itemLimit)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
if (items.Count > 0)
|
if (items.Count > 0)
|
||||||
{
|
{
|
||||||
@ -377,20 +305,65 @@ namespace MediaBrowser.Api.Movies
|
|||||||
BaselineItemName = name,
|
BaselineItemName = name,
|
||||||
CategoryId = name.GetMD5().ToString("N"),
|
CategoryId = name.GetMD5().ToString("N"),
|
||||||
RecommendationType = type,
|
RecommendationType = type,
|
||||||
Items = _dtoService.GetBaseItemDtos(items, dtoOptions, user).ToArray()
|
Items = _dtoService.GetBaseItemDtos(items, dtoOptions, user).Result.ToArray()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<RecommendationDto> GetSimilarTo(User user, List<BaseItem> allMovies, IEnumerable<BaseItem> baselineItems, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
|
private IEnumerable<RecommendationDto> GetWithActor(User user, IEnumerable<string> names, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
|
||||||
|
{
|
||||||
|
foreach (var name in names)
|
||||||
|
{
|
||||||
|
var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
|
{
|
||||||
|
Person = name,
|
||||||
|
// Account for duplicates by imdb id, since the database doesn't support this yet
|
||||||
|
Limit = itemLimit + 2,
|
||||||
|
IncludeItemTypes = new[]
|
||||||
|
{
|
||||||
|
typeof(Movie).Name,
|
||||||
|
typeof(Trailer).Name,
|
||||||
|
typeof(LiveTvProgram).Name
|
||||||
|
},
|
||||||
|
IsMovie = true,
|
||||||
|
EnableGroupByMetadataKey = true
|
||||||
|
|
||||||
|
}).DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N"))
|
||||||
|
.Take(itemLimit)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if (items.Count > 0)
|
||||||
|
{
|
||||||
|
yield return new RecommendationDto
|
||||||
|
{
|
||||||
|
BaselineItemName = name,
|
||||||
|
CategoryId = name.GetMD5().ToString("N"),
|
||||||
|
RecommendationType = type,
|
||||||
|
Items = _dtoService.GetBaseItemDtos(items, dtoOptions, user).Result.ToArray()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<RecommendationDto> GetSimilarTo(User user, List<BaseItem> baselineItems, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
|
||||||
{
|
{
|
||||||
foreach (var item in baselineItems)
|
foreach (var item in baselineItems)
|
||||||
{
|
{
|
||||||
var similar = SimilarItemsHelper
|
var similar = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
.GetSimilaritems(item, _libraryManager, allMovies, SimilarItemsHelper.GetSimiliarityScore)
|
{
|
||||||
.Take(itemLimit)
|
Limit = itemLimit,
|
||||||
.ToList();
|
IncludeItemTypes = new[]
|
||||||
|
{
|
||||||
|
typeof(Movie).Name,
|
||||||
|
typeof(Trailer).Name,
|
||||||
|
typeof(LiveTvProgram).Name
|
||||||
|
},
|
||||||
|
IsMovie = true,
|
||||||
|
SimilarTo = item,
|
||||||
|
EnableGroupByMetadataKey = true
|
||||||
|
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
if (similar.Count > 0)
|
if (similar.Count > 0)
|
||||||
{
|
{
|
||||||
@ -399,7 +372,7 @@ namespace MediaBrowser.Api.Movies
|
|||||||
BaselineItemName = item.Name,
|
BaselineItemName = item.Name,
|
||||||
CategoryId = item.Id.ToString("N"),
|
CategoryId = item.Id.ToString("N"),
|
||||||
RecommendationType = type,
|
RecommendationType = type,
|
||||||
Items = _dtoService.GetBaseItemDtos(similar, dtoOptions, user).ToArray()
|
Items = _dtoService.GetBaseItemDtos(similar, dtoOptions, user).Result.ToArray()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ namespace MediaBrowser.Api.Movies
|
|||||||
|
|
||||||
getItems.IncludeItemTypes = "Trailer";
|
getItems.IncludeItemTypes = "Trailer";
|
||||||
|
|
||||||
return new ItemsService(_userManager, _libraryManager, _userDataRepository, _localizationManager, _dtoService, _collectionManager)
|
return new ItemsService(_userManager, _libraryManager, _localizationManager, _dtoService)
|
||||||
{
|
{
|
||||||
AuthorizationContext = AuthorizationContext,
|
AuthorizationContext = AuthorizationContext,
|
||||||
Logger = Logger,
|
Logger = Logger,
|
||||||
|
@ -8,6 +8,7 @@ using ServiceStack;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.Music
|
namespace MediaBrowser.Api.Music
|
||||||
{
|
{
|
||||||
@ -49,18 +50,18 @@ namespace MediaBrowser.Api.Music
|
|||||||
_dtoService = dtoService;
|
_dtoService = dtoService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetSimilarArtists request)
|
public async Task<object> Get(GetSimilarArtists request)
|
||||||
{
|
{
|
||||||
var dtoOptions = GetDtoOptions(request);
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
var result = SimilarItemsHelper.GetSimilarItemsResult(dtoOptions, _userManager,
|
var result = await SimilarItemsHelper.GetSimilarItemsResult(dtoOptions, _userManager,
|
||||||
_itemRepo,
|
_itemRepo,
|
||||||
_libraryManager,
|
_libraryManager,
|
||||||
_userDataRepository,
|
_userDataRepository,
|
||||||
_dtoService,
|
_dtoService,
|
||||||
Logger,
|
Logger,
|
||||||
request, new[] { typeof(MusicArtist) },
|
request, new[] { typeof(MusicArtist) },
|
||||||
SimilarItemsHelper.GetSimiliarityScore);
|
SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
}
|
}
|
||||||
@ -70,18 +71,18 @@ namespace MediaBrowser.Api.Music
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetSimilarAlbums request)
|
public async Task<object> Get(GetSimilarAlbums request)
|
||||||
{
|
{
|
||||||
var dtoOptions = GetDtoOptions(request);
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
var result = SimilarItemsHelper.GetSimilarItemsResult(dtoOptions, _userManager,
|
var result = await SimilarItemsHelper.GetSimilarItemsResult(dtoOptions, _userManager,
|
||||||
_itemRepo,
|
_itemRepo,
|
||||||
_libraryManager,
|
_libraryManager,
|
||||||
_userDataRepository,
|
_userDataRepository,
|
||||||
_dtoService,
|
_dtoService,
|
||||||
Logger,
|
Logger,
|
||||||
request, new[] { typeof(MusicAlbum) },
|
request, new[] { typeof(MusicAlbum) },
|
||||||
GetAlbumSimilarityScore);
|
GetAlbumSimilarityScore).ConfigureAwait(false);
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ using MediaBrowser.Model.Querying;
|
|||||||
using ServiceStack;
|
using ServiceStack;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.Music
|
namespace MediaBrowser.Api.Music
|
||||||
{
|
{
|
||||||
@ -76,7 +77,7 @@ namespace MediaBrowser.Api.Music
|
|||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetInstantMixFromItem request)
|
public Task<object> Get(GetInstantMixFromItem request)
|
||||||
{
|
{
|
||||||
var item = _libraryManager.GetItemById(request.Id);
|
var item = _libraryManager.GetItemById(request.Id);
|
||||||
|
|
||||||
@ -87,7 +88,7 @@ namespace MediaBrowser.Api.Music
|
|||||||
return GetResult(items, user, request);
|
return GetResult(items, user, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetInstantMixFromArtistId request)
|
public Task<object> Get(GetInstantMixFromArtistId request)
|
||||||
{
|
{
|
||||||
var item = _libraryManager.GetItemById(request.Id);
|
var item = _libraryManager.GetItemById(request.Id);
|
||||||
|
|
||||||
@ -98,7 +99,7 @@ namespace MediaBrowser.Api.Music
|
|||||||
return GetResult(items, user, request);
|
return GetResult(items, user, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetInstantMixFromMusicGenreId request)
|
public Task<object> Get(GetInstantMixFromMusicGenreId request)
|
||||||
{
|
{
|
||||||
var item = _libraryManager.GetItemById(request.Id);
|
var item = _libraryManager.GetItemById(request.Id);
|
||||||
|
|
||||||
@ -109,7 +110,7 @@ namespace MediaBrowser.Api.Music
|
|||||||
return GetResult(items, user, request);
|
return GetResult(items, user, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetInstantMixFromSong request)
|
public Task<object> Get(GetInstantMixFromSong request)
|
||||||
{
|
{
|
||||||
var item = _libraryManager.GetItemById(request.Id);
|
var item = _libraryManager.GetItemById(request.Id);
|
||||||
|
|
||||||
@ -120,7 +121,7 @@ namespace MediaBrowser.Api.Music
|
|||||||
return GetResult(items, user, request);
|
return GetResult(items, user, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetInstantMixFromAlbum request)
|
public Task<object> Get(GetInstantMixFromAlbum request)
|
||||||
{
|
{
|
||||||
var album = _libraryManager.GetItemById(request.Id);
|
var album = _libraryManager.GetItemById(request.Id);
|
||||||
|
|
||||||
@ -131,7 +132,7 @@ namespace MediaBrowser.Api.Music
|
|||||||
return GetResult(items, user, request);
|
return GetResult(items, user, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetInstantMixFromPlaylist request)
|
public Task<object> Get(GetInstantMixFromPlaylist request)
|
||||||
{
|
{
|
||||||
var playlist = (Playlist)_libraryManager.GetItemById(request.Id);
|
var playlist = (Playlist)_libraryManager.GetItemById(request.Id);
|
||||||
|
|
||||||
@ -142,7 +143,7 @@ namespace MediaBrowser.Api.Music
|
|||||||
return GetResult(items, user, request);
|
return GetResult(items, user, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetInstantMixFromMusicGenre request)
|
public Task<object> Get(GetInstantMixFromMusicGenre request)
|
||||||
{
|
{
|
||||||
var user = _userManager.GetUserById(request.UserId);
|
var user = _userManager.GetUserById(request.UserId);
|
||||||
|
|
||||||
@ -151,7 +152,7 @@ namespace MediaBrowser.Api.Music
|
|||||||
return GetResult(items, user, request);
|
return GetResult(items, user, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetInstantMixFromArtist request)
|
public Task<object> Get(GetInstantMixFromArtist request)
|
||||||
{
|
{
|
||||||
var user = _userManager.GetUserById(request.UserId);
|
var user = _userManager.GetUserById(request.UserId);
|
||||||
var artist = _libraryManager.GetArtist(request.Name);
|
var artist = _libraryManager.GetArtist(request.Name);
|
||||||
@ -161,7 +162,7 @@ namespace MediaBrowser.Api.Music
|
|||||||
return GetResult(items, user, request);
|
return GetResult(items, user, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
private object GetResult(IEnumerable<Audio> items, User user, BaseGetSimilarItems request)
|
private async Task<object> GetResult(IEnumerable<Audio> items, User user, BaseGetSimilarItems request)
|
||||||
{
|
{
|
||||||
var list = items.ToList();
|
var list = items.ToList();
|
||||||
|
|
||||||
@ -172,7 +173,7 @@ namespace MediaBrowser.Api.Music
|
|||||||
|
|
||||||
var dtoOptions = GetDtoOptions(request);
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
result.Items = _dtoService.GetBaseItemDtos(list.Take(request.Limit ?? list.Count), dtoOptions, user).ToArray();
|
result.Items = (await _dtoService.GetBaseItemDtos(list.Take(request.Limit ?? list.Count), dtoOptions, user).ConfigureAwait(false)).ToArray();
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@ namespace MediaBrowser.Api
|
|||||||
_appHost = appHost;
|
_appHost = appHost;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(ReviewRequest request)
|
public async Task<object> Get(ReviewRequest request)
|
||||||
{
|
{
|
||||||
var parms = "?id=" + request.Id;
|
var parms = "?id=" + request.Id;
|
||||||
|
|
||||||
@ -133,11 +133,13 @@ namespace MediaBrowser.Api
|
|||||||
parms += "&title=true";
|
parms += "&title=true";
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = _httpClient.Get(MbAdminUrl + "/service/packageReview/retrieve" + parms, CancellationToken.None).Result;
|
using (var result = await _httpClient.Get(MbAdminUrl + "/service/packageReview/retrieve" + parms, CancellationToken.None)
|
||||||
|
.ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
var reviews = _serializer.DeserializeFromStream<List<PackageReviewInfo>>(result);
|
||||||
|
|
||||||
var reviews = _serializer.DeserializeFromStream<List<PackageReviewInfo>>(result);
|
return ToOptimizedResult(reviews);
|
||||||
|
}
|
||||||
return ToOptimizedResult(reviews);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Post(CreateReviewRequest request)
|
public void Post(CreateReviewRequest request)
|
||||||
|
@ -286,11 +286,19 @@ namespace MediaBrowser.Api.Playback
|
|||||||
|
|
||||||
protected string GetH264Encoder(StreamState state)
|
protected string GetH264Encoder(StreamState state)
|
||||||
{
|
{
|
||||||
if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareAccelerationType, "h264_qsv", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
|
|
||||||
return "h264_qsv";
|
return "h264_qsv";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareAccelerationType, "libnvenc", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return "libnvenc";
|
||||||
|
}
|
||||||
|
if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareAccelerationType, "h264_omx", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return "h264_omx";
|
||||||
}
|
}
|
||||||
|
|
||||||
return "libx264";
|
return "libx264";
|
||||||
@ -395,15 +403,18 @@ namespace MediaBrowser.Api.Playback
|
|||||||
|
|
||||||
if (!string.IsNullOrEmpty(state.VideoRequest.Profile))
|
if (!string.IsNullOrEmpty(state.VideoRequest.Profile))
|
||||||
{
|
{
|
||||||
param += " -profile:v " + state.VideoRequest.Profile;
|
if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
// not supported by h264_omx
|
||||||
|
param += " -profile:v " + state.VideoRequest.Profile;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(state.VideoRequest.Level))
|
if (!string.IsNullOrEmpty(state.VideoRequest.Level))
|
||||||
{
|
{
|
||||||
var h264Encoder = GetH264Encoder(state);
|
|
||||||
|
|
||||||
// h264_qsv and libnvenc expect levels to be expressed as a decimal. libx264 supports decimal and non-decimal format
|
// h264_qsv and libnvenc expect levels to be expressed as a decimal. libx264 supports decimal and non-decimal format
|
||||||
if (String.Equals(h264Encoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) || String.Equals(h264Encoder, "libnvenc", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
string.Equals(videoCodec, "libnvenc", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
switch (state.VideoRequest.Level)
|
switch (state.VideoRequest.Level)
|
||||||
{
|
{
|
||||||
@ -438,16 +449,21 @@ namespace MediaBrowser.Api.Playback
|
|||||||
param += " -level " + state.VideoRequest.Level;
|
param += " -level " + state.VideoRequest.Level;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return param;
|
|
||||||
}
|
}
|
||||||
else
|
else if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
param += " -level " + state.VideoRequest.Level;
|
param += " -level " + state.VideoRequest.Level;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return "-pix_fmt yuv420p " + param;
|
if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
|
||||||
|
!string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) &&
|
||||||
|
!string.Equals(videoCodec, "libnvenc", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
param = "-pix_fmt yuv420p " + param;
|
||||||
|
}
|
||||||
|
|
||||||
|
return param;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected string GetAudioFilterParam(StreamState state, bool isHls)
|
protected string GetAudioFilterParam(StreamState state, bool isHls)
|
||||||
@ -563,14 +579,6 @@ namespace MediaBrowser.Api.Playback
|
|||||||
filters.Add(string.Format("scale=trunc(oh*a/2)*2:min(ih\\,{0})", maxHeightParam));
|
filters.Add(string.Format("scale=trunc(oh*a/2)*2:min(ih\\,{0})", maxHeightParam));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
if (filters.Count > 1)
|
|
||||||
{
|
|
||||||
//filters[filters.Count - 1] += ":flags=fast_bilinear";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var output = string.Empty;
|
var output = string.Empty;
|
||||||
|
|
||||||
if (state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode)
|
if (state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode)
|
||||||
@ -846,7 +854,7 @@ namespace MediaBrowser.Api.Playback
|
|||||||
if (MediaEncoder.SupportsDecoder("h264_qsv"))
|
if (MediaEncoder.SupportsDecoder("h264_qsv"))
|
||||||
{
|
{
|
||||||
// Seeing stalls and failures with decoding. Not worth it compared to encoding.
|
// Seeing stalls and failures with decoding. Not worth it compared to encoding.
|
||||||
//return "-c:v h264_qsv ";
|
return "-c:v h264_qsv ";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "mpeg2video":
|
case "mpeg2video":
|
||||||
@ -980,11 +988,6 @@ namespace MediaBrowser.Api.Playback
|
|||||||
var transcodingId = Guid.NewGuid().ToString("N");
|
var transcodingId = Guid.NewGuid().ToString("N");
|
||||||
var commandLineArgs = GetCommandLineArguments(outputPath, state, true);
|
var commandLineArgs = GetCommandLineArguments(outputPath, state, true);
|
||||||
|
|
||||||
if (ApiEntryPoint.Instance.GetEncodingOptions().EnableDebugLogging)
|
|
||||||
{
|
|
||||||
commandLineArgs = "-loglevel debug " + commandLineArgs;
|
|
||||||
}
|
|
||||||
|
|
||||||
var process = new Process
|
var process = new Process
|
||||||
{
|
{
|
||||||
StartInfo = new ProcessStartInfo
|
StartInfo = new ProcessStartInfo
|
||||||
@ -1212,7 +1215,7 @@ namespace MediaBrowser.Api.Playback
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int? GetVideoBitrateParamValue(VideoStreamRequest request, MediaStream videoStream)
|
private int? GetVideoBitrateParamValue(VideoStreamRequest request, MediaStream videoStream, string outputVideoCodec)
|
||||||
{
|
{
|
||||||
var bitrate = request.VideoBitRate;
|
var bitrate = request.VideoBitRate;
|
||||||
|
|
||||||
@ -1237,6 +1240,18 @@ namespace MediaBrowser.Api.Playback
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bitrate.HasValue)
|
||||||
|
{
|
||||||
|
var inputVideoCodec = videoStream == null ? null : videoStream.Codec;
|
||||||
|
bitrate = ResolutionNormalizer.ScaleBitrate(bitrate.Value, inputVideoCodec, outputVideoCodec);
|
||||||
|
|
||||||
|
// If a max bitrate was requested, don't let the scaled bitrate exceed it
|
||||||
|
if (request.VideoBitRate.HasValue)
|
||||||
|
{
|
||||||
|
bitrate = Math.Min(bitrate.Value, request.VideoBitRate.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return bitrate;
|
return bitrate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1518,6 +1533,13 @@ namespace MediaBrowser.Api.Playback
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (i == 25)
|
else if (i == 25)
|
||||||
|
{
|
||||||
|
if (videoRequest != null)
|
||||||
|
{
|
||||||
|
videoRequest.ForceLiveStream = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (i == 26)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(val) && videoRequest != null)
|
if (!string.IsNullOrWhiteSpace(val) && videoRequest != null)
|
||||||
{
|
{
|
||||||
@ -1528,7 +1550,7 @@ namespace MediaBrowser.Api.Playback
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (i == 26)
|
else if (i == 27)
|
||||||
{
|
{
|
||||||
request.TranscodingMaxAudioChannels = int.Parse(val, UsCulture);
|
request.TranscodingMaxAudioChannels = int.Parse(val, UsCulture);
|
||||||
}
|
}
|
||||||
@ -1636,7 +1658,8 @@ namespace MediaBrowser.Api.Playback
|
|||||||
if (!string.IsNullOrWhiteSpace(request.AudioCodec))
|
if (!string.IsNullOrWhiteSpace(request.AudioCodec))
|
||||||
{
|
{
|
||||||
state.SupportedAudioCodecs = request.AudioCodec.Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
|
state.SupportedAudioCodecs = request.AudioCodec.Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
|
||||||
state.Request.AudioCodec = state.SupportedAudioCodecs.FirstOrDefault();
|
state.Request.AudioCodec = state.SupportedAudioCodecs.FirstOrDefault(i => MediaEncoder.CanEncodeToAudioCodec(i))
|
||||||
|
?? state.SupportedAudioCodecs.FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
var item = LibraryManager.GetItemById(request.Id);
|
var item = LibraryManager.GetItemById(request.Id);
|
||||||
@ -1690,7 +1713,7 @@ namespace MediaBrowser.Api.Playback
|
|||||||
if (videoRequest != null)
|
if (videoRequest != null)
|
||||||
{
|
{
|
||||||
state.OutputVideoCodec = state.VideoRequest.VideoCodec;
|
state.OutputVideoCodec = state.VideoRequest.VideoCodec;
|
||||||
state.OutputVideoBitrate = GetVideoBitrateParamValue(state.VideoRequest, state.VideoStream);
|
state.OutputVideoBitrate = GetVideoBitrateParamValue(state.VideoRequest, state.VideoStream, state.OutputVideoCodec);
|
||||||
|
|
||||||
if (state.OutputVideoBitrate.HasValue)
|
if (state.OutputVideoBitrate.HasValue)
|
||||||
{
|
{
|
||||||
|
@ -63,9 +63,9 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
/// <param name="isLive">if set to <c>true</c> [is live].</param>
|
/// <param name="isLive">if set to <c>true</c> [is live].</param>
|
||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
protected object ProcessRequest(StreamRequest request, bool isLive)
|
protected async Task<object> ProcessRequest(StreamRequest request, bool isLive)
|
||||||
{
|
{
|
||||||
return ProcessRequestAsync(request, isLive).Result;
|
return await ProcessRequestAsync(request, isLive).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -475,7 +475,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
ApiEntryPoint.Instance.OnTranscodeEndRequest(transcodingJob);
|
ApiEntryPoint.Instance.OnTranscodeEndRequest(transcodingJob);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}).Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<object> GetMasterPlaylistInternal(StreamRequest request, string method)
|
private async Task<object> GetMasterPlaylistInternal(StreamRequest request, string method)
|
||||||
|
@ -5,6 +5,7 @@ using ServiceStack;
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.Playback.Hls
|
namespace MediaBrowser.Api.Playback.Hls
|
||||||
{
|
{
|
||||||
@ -89,7 +90,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
_config = config;
|
_config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetHlsPlaylistLegacy request)
|
public Task<object> Get(GetHlsPlaylistLegacy request)
|
||||||
{
|
{
|
||||||
var file = request.PlaylistId + Path.GetExtension(Request.PathInfo);
|
var file = request.PlaylistId + Path.GetExtension(Request.PathInfo);
|
||||||
file = Path.Combine(_appPaths.TranscodingTempPath, file);
|
file = Path.Combine(_appPaths.TranscodingTempPath, file);
|
||||||
@ -107,7 +108,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetHlsVideoSegmentLegacy request)
|
public Task<object> Get(GetHlsVideoSegmentLegacy request)
|
||||||
{
|
{
|
||||||
var file = request.SegmentId + Path.GetExtension(Request.PathInfo);
|
var file = request.SegmentId + Path.GetExtension(Request.PathInfo);
|
||||||
file = Path.Combine(_config.ApplicationPaths.TranscodingTempPath, file);
|
file = Path.Combine(_config.ApplicationPaths.TranscodingTempPath, file);
|
||||||
@ -131,10 +132,10 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
var file = request.SegmentId + Path.GetExtension(Request.PathInfo);
|
var file = request.SegmentId + Path.GetExtension(Request.PathInfo);
|
||||||
file = Path.Combine(_appPaths.TranscodingTempPath, file);
|
file = Path.Combine(_appPaths.TranscodingTempPath, file);
|
||||||
|
|
||||||
return ResultFactory.GetStaticFileResult(Request, file, FileShare.ReadWrite);
|
return ResultFactory.GetStaticFileResult(Request, file, FileShare.ReadWrite).Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private object GetFileResult(string path, string playlistPath)
|
private Task<object> GetFileResult(string path, string playlistPath)
|
||||||
{
|
{
|
||||||
var transcodingJob = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType.Hls);
|
var transcodingJob = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType.Hls);
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ using MediaBrowser.Model.IO;
|
|||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
using ServiceStack;
|
using ServiceStack;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using CommonIO;
|
using CommonIO;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.Playback.Progressive
|
namespace MediaBrowser.Api.Playback.Progressive
|
||||||
@ -40,7 +41,7 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetAudioStream request)
|
public Task<object> Get(GetAudioStream request)
|
||||||
{
|
{
|
||||||
return ProcessRequest(request, false);
|
return ProcessRequest(request, false);
|
||||||
}
|
}
|
||||||
@ -50,7 +51,7 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Head(GetAudioStream request)
|
public Task<object> Head(GetAudioStream request)
|
||||||
{
|
{
|
||||||
return ProcessRequest(request, true);
|
return ProcessRequest(request, true);
|
||||||
}
|
}
|
||||||
|
@ -113,11 +113,11 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
/// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param>
|
/// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
protected object ProcessRequest(StreamRequest request, bool isHeadRequest)
|
protected async Task<object> ProcessRequest(StreamRequest request, bool isHeadRequest)
|
||||||
{
|
{
|
||||||
var cancellationTokenSource = new CancellationTokenSource();
|
var cancellationTokenSource = new CancellationTokenSource();
|
||||||
|
|
||||||
var state = GetState(request, cancellationTokenSource.Token).Result;
|
var state = await GetState(request, cancellationTokenSource.Token).ConfigureAwait(false);
|
||||||
|
|
||||||
var responseHeaders = new Dictionary<string, string>();
|
var responseHeaders = new Dictionary<string, string>();
|
||||||
|
|
||||||
@ -128,7 +128,8 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
|
|
||||||
using (state)
|
using (state)
|
||||||
{
|
{
|
||||||
return GetStaticRemoteStreamResult(state, responseHeaders, isHeadRequest, cancellationTokenSource).Result;
|
return await GetStaticRemoteStreamResult(state, responseHeaders, isHeadRequest, cancellationTokenSource)
|
||||||
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +139,7 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
}
|
}
|
||||||
|
|
||||||
var outputPath = state.OutputFilePath;
|
var outputPath = state.OutputFilePath;
|
||||||
var outputPathExists = FileSystem.FileExists(outputPath);
|
var outputPathExists = FileSystem.FileExists(outputPath);
|
||||||
|
|
||||||
var isTranscodeCached = outputPathExists && !ApiEntryPoint.Instance.HasActiveTranscodingJob(outputPath, TranscodingJobType.Progressive);
|
var isTranscodeCached = outputPathExists && !ApiEntryPoint.Instance.HasActiveTranscodingJob(outputPath, TranscodingJobType.Progressive);
|
||||||
|
|
||||||
@ -151,13 +152,13 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
|
|
||||||
using (state)
|
using (state)
|
||||||
{
|
{
|
||||||
return ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions
|
return await ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions
|
||||||
{
|
{
|
||||||
ResponseHeaders = responseHeaders,
|
ResponseHeaders = responseHeaders,
|
||||||
ContentType = contentType,
|
ContentType = contentType,
|
||||||
IsHeadRequest = isHeadRequest,
|
IsHeadRequest = isHeadRequest,
|
||||||
Path = state.MediaPath
|
Path = state.MediaPath
|
||||||
});
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,13 +169,13 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions
|
return await ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions
|
||||||
{
|
{
|
||||||
ResponseHeaders = responseHeaders,
|
ResponseHeaders = responseHeaders,
|
||||||
ContentType = contentType,
|
ContentType = contentType,
|
||||||
IsHeadRequest = isHeadRequest,
|
IsHeadRequest = isHeadRequest,
|
||||||
Path = outputPath
|
Path = outputPath
|
||||||
});
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@ -185,7 +186,8 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
// Need to start ffmpeg
|
// Need to start ffmpeg
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return GetStreamResult(state, responseHeaders, isHeadRequest, cancellationTokenSource).Result;
|
return await GetStreamResult(state, responseHeaders, isHeadRequest, cancellationTokenSource)
|
||||||
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@ -229,7 +231,7 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
|
|
||||||
if (trySupportSeek)
|
if (trySupportSeek)
|
||||||
{
|
{
|
||||||
foreach (var name in new[] {"Content-Range", "Accept-Ranges"})
|
foreach (var name in new[] { "Content-Range", "Accept-Ranges" })
|
||||||
{
|
{
|
||||||
var val = response.Headers[name];
|
var val = response.Headers[name];
|
||||||
if (!string.IsNullOrWhiteSpace(val))
|
if (!string.IsNullOrWhiteSpace(val))
|
||||||
@ -242,12 +244,12 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
{
|
{
|
||||||
responseHeaders["Accept-Ranges"] = "none";
|
responseHeaders["Accept-Ranges"] = "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.ContentLength.HasValue)
|
if (response.ContentLength.HasValue)
|
||||||
{
|
{
|
||||||
responseHeaders["Content-Length"] = response.ContentLength.Value.ToString(UsCulture);
|
responseHeaders["Content-Length"] = response.ContentLength.Value.ToString(UsCulture);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isHeadRequest)
|
if (isHeadRequest)
|
||||||
{
|
{
|
||||||
using (response)
|
using (response)
|
||||||
@ -324,7 +326,7 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
{
|
{
|
||||||
TranscodingJob job;
|
TranscodingJob job;
|
||||||
|
|
||||||
if (!FileSystem.FileExists(outputPath))
|
if (!FileSystem.FileExists(outputPath))
|
||||||
{
|
{
|
||||||
job = await StartFfMpeg(state, outputPath, cancellationTokenSource).ConfigureAwait(false);
|
job = await StartFfMpeg(state, outputPath, cancellationTokenSource).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ using MediaBrowser.Model.Serialization;
|
|||||||
using ServiceStack;
|
using ServiceStack;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using CommonIO;
|
using CommonIO;
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
@ -76,7 +77,7 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetVideoStream request)
|
public Task<object> Get(GetVideoStream request)
|
||||||
{
|
{
|
||||||
return ProcessRequest(request, false);
|
return ProcessRequest(request, false);
|
||||||
}
|
}
|
||||||
@ -86,7 +87,7 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Head(GetVideoStream request)
|
public Task<object> Head(GetVideoStream request)
|
||||||
{
|
{
|
||||||
return ProcessRequest(request, true);
|
return ProcessRequest(request, true);
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ namespace MediaBrowser.Api.Playback
|
|||||||
public long? InputFileSize { get; set; }
|
public long? InputFileSize { get; set; }
|
||||||
|
|
||||||
public string OutputAudioSync = "1";
|
public string OutputAudioSync = "1";
|
||||||
public string OutputVideoSync = "vfr";
|
public string OutputVideoSync = "-1";
|
||||||
|
|
||||||
public List<string> SupportedAudioCodecs { get; set; }
|
public List<string> SupportedAudioCodecs { get; set; }
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@ namespace MediaBrowser.Api
|
|||||||
Task.WaitAll(task);
|
Task.WaitAll(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetPlaylistItems request)
|
public async Task<object> Get(GetPlaylistItems request)
|
||||||
{
|
{
|
||||||
var playlist = (Playlist)_libraryManager.GetItemById(request.Id);
|
var playlist = (Playlist)_libraryManager.GetItemById(request.Id);
|
||||||
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
|
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
|
||||||
@ -178,7 +178,7 @@ namespace MediaBrowser.Api
|
|||||||
|
|
||||||
var dtoOptions = GetDtoOptions(request);
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
var dtos = _dtoService.GetBaseItemDtos(items.Select(i => i.Item2), dtoOptions, user)
|
var dtos = (await _dtoService.GetBaseItemDtos(items.Select(i => i.Item2), dtoOptions, user).ConfigureAwait(false))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
var index = 0;
|
var index = 0;
|
||||||
|
@ -213,7 +213,6 @@ namespace MediaBrowser.Api.Reports
|
|||||||
NameStartsWith = request.NameStartsWith,
|
NameStartsWith = request.NameStartsWith,
|
||||||
NameStartsWithOrGreater = request.NameStartsWithOrGreater,
|
NameStartsWithOrGreater = request.NameStartsWithOrGreater,
|
||||||
HasImdbId = request.HasImdbId,
|
HasImdbId = request.HasImdbId,
|
||||||
IsYearMismatched = request.IsYearMismatched,
|
|
||||||
IsPlaceHolder = request.IsPlaceHolder,
|
IsPlaceHolder = request.IsPlaceHolder,
|
||||||
IsLocked = request.IsLocked,
|
IsLocked = request.IsLocked,
|
||||||
IsInBoxSet = request.IsInBoxSet,
|
IsInBoxSet = request.IsInBoxSet,
|
||||||
|
@ -9,6 +9,8 @@ using ServiceStack;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Model.Dto;
|
||||||
|
|
||||||
namespace MediaBrowser.Api
|
namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
@ -54,7 +56,7 @@ namespace MediaBrowser.Api
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class SimilarItemsHelper
|
public static class SimilarItemsHelper
|
||||||
{
|
{
|
||||||
internal static ItemsResult GetSimilarItemsResult(DtoOptions dtoOptions, IUserManager userManager, IItemRepository itemRepository, ILibraryManager libraryManager, IUserDataManager userDataRepository, IDtoService dtoService, ILogger logger, BaseGetSimilarItemsFromItem request, Type[] includeTypes, Func<BaseItem, List<PersonInfo>, List<PersonInfo>, BaseItem, int> getSimilarityScore)
|
internal static async Task<QueryResult<BaseItemDto>> GetSimilarItemsResult(DtoOptions dtoOptions, IUserManager userManager, IItemRepository itemRepository, ILibraryManager libraryManager, IUserDataManager userDataRepository, IDtoService dtoService, ILogger logger, BaseGetSimilarItemsFromItem request, Type[] includeTypes, Func<BaseItem, List<PersonInfo>, List<PersonInfo>, BaseItem, int> getSimilarityScore)
|
||||||
{
|
{
|
||||||
var user = !string.IsNullOrWhiteSpace(request.UserId) ? userManager.GetUserById(request.UserId) : null;
|
var user = !string.IsNullOrWhiteSpace(request.UserId) ? userManager.GetUserById(request.UserId) : null;
|
||||||
|
|
||||||
@ -80,14 +82,14 @@ namespace MediaBrowser.Api
|
|||||||
returnItems = returnItems.Take(request.Limit.Value);
|
returnItems = returnItems.Take(request.Limit.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = new ItemsResult
|
var dtos = await dtoService.GetBaseItemDtos(returnItems, dtoOptions, user).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return new QueryResult<BaseItemDto>
|
||||||
{
|
{
|
||||||
Items = dtoService.GetBaseItemDtos(returnItems, dtoOptions, user).ToArray(),
|
Items = dtos.ToArray(),
|
||||||
|
|
||||||
TotalRecordCount = items.Count
|
TotalRecordCount = items.Count
|
||||||
};
|
};
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -116,24 +118,12 @@ namespace MediaBrowser.Api
|
|||||||
|
|
||||||
private static IEnumerable<string> GetTags(BaseItem item)
|
private static IEnumerable<string> GetTags(BaseItem item)
|
||||||
{
|
{
|
||||||
var hasTags = item as IHasTags;
|
return item.Tags;
|
||||||
if (hasTags != null)
|
|
||||||
{
|
|
||||||
return hasTags.Tags;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new List<string>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<string> GetKeywords(BaseItem item)
|
private static IEnumerable<string> GetKeywords(BaseItem item)
|
||||||
{
|
{
|
||||||
var hasTags = item as IHasKeywords;
|
return item.Keywords;
|
||||||
if (hasTags != null)
|
|
||||||
{
|
|
||||||
return hasTags.Keywords;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new List<string>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -11,6 +11,7 @@ using ServiceStack;
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Controller.MediaEncoding;
|
||||||
|
|
||||||
namespace MediaBrowser.Api
|
namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
@ -52,14 +53,16 @@ namespace MediaBrowser.Api
|
|||||||
private readonly IUserManager _userManager;
|
private readonly IUserManager _userManager;
|
||||||
private readonly IConnectManager _connectManager;
|
private readonly IConnectManager _connectManager;
|
||||||
private readonly ILiveTvManager _liveTvManager;
|
private readonly ILiveTvManager _liveTvManager;
|
||||||
|
private readonly IMediaEncoder _mediaEncoder;
|
||||||
|
|
||||||
public StartupWizardService(IServerConfigurationManager config, IServerApplicationHost appHost, IUserManager userManager, IConnectManager connectManager, ILiveTvManager liveTvManager)
|
public StartupWizardService(IServerConfigurationManager config, IServerApplicationHost appHost, IUserManager userManager, IConnectManager connectManager, ILiveTvManager liveTvManager, IMediaEncoder mediaEncoder)
|
||||||
{
|
{
|
||||||
_config = config;
|
_config = config;
|
||||||
_appHost = appHost;
|
_appHost = appHost;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
_connectManager = connectManager;
|
_connectManager = connectManager;
|
||||||
_liveTvManager = liveTvManager;
|
_liveTvManager = liveTvManager;
|
||||||
|
_mediaEncoder = mediaEncoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Post(ReportStartupWizardComplete request)
|
public void Post(ReportStartupWizardComplete request)
|
||||||
@ -69,13 +72,14 @@ namespace MediaBrowser.Api
|
|||||||
_config.SaveConfiguration();
|
_config.SaveConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetStartupInfo request)
|
public async Task<object> Get(GetStartupInfo request)
|
||||||
{
|
{
|
||||||
var info = _appHost.GetSystemInfo();
|
var info = await _appHost.GetSystemInfo().ConfigureAwait(false);
|
||||||
|
|
||||||
return new StartupInfo
|
return new StartupInfo
|
||||||
{
|
{
|
||||||
SupportsRunningAsService = info.SupportsRunningAsService
|
SupportsRunningAsService = info.SupportsRunningAsService,
|
||||||
|
HasMediaEncoder = !string.IsNullOrWhiteSpace(_mediaEncoder.EncoderPath)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,10 +115,10 @@ namespace MediaBrowser.Api
|
|||||||
{
|
{
|
||||||
config.EnableLocalizedGuids = true;
|
config.EnableLocalizedGuids = true;
|
||||||
config.EnableCustomPathSubFolders = true;
|
config.EnableCustomPathSubFolders = true;
|
||||||
config.EnableDateLastRefresh = true;
|
|
||||||
config.EnableStandaloneMusicKeys = true;
|
config.EnableStandaloneMusicKeys = true;
|
||||||
config.EnableCaseSensitiveItemIds = true;
|
config.EnableCaseSensitiveItemIds = true;
|
||||||
config.SchemaVersion = 79;
|
config.EnableFolderView = true;
|
||||||
|
config.SchemaVersion = 97;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Post(UpdateStartupConfiguration request)
|
public void Post(UpdateStartupConfiguration request)
|
||||||
@ -231,6 +235,7 @@ namespace MediaBrowser.Api
|
|||||||
public class StartupInfo
|
public class StartupInfo
|
||||||
{
|
{
|
||||||
public bool SupportsRunningAsService { get; set; }
|
public bool SupportsRunningAsService { get; set; }
|
||||||
|
public bool HasMediaEncoder { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class StartupUser
|
public class StartupUser
|
||||||
|
@ -98,6 +98,10 @@ namespace MediaBrowser.Api.Subtitles
|
|||||||
|
|
||||||
[ApiMember(Name = "EndPositionTicks", Description = "EndPositionTicks", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "EndPositionTicks", Description = "EndPositionTicks", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
public long? EndPositionTicks { get; set; }
|
public long? EndPositionTicks { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "CopyTimestamps", Description = "CopyTimestamps", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool CopyTimestamps { get; set; }
|
||||||
|
public bool AddVttTimeMap { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/Videos/{Id}/{MediaSourceId}/Subtitles/{Index}/subtitles.m3u8", "GET", Summary = "Gets an HLS subtitle playlist.")]
|
[Route("/Videos/{Id}/{MediaSourceId}/Subtitles/{Index}/subtitles.m3u8", "GET", Summary = "Gets an HLS subtitle playlist.")]
|
||||||
@ -175,7 +179,7 @@ namespace MediaBrowser.Api.Subtitles
|
|||||||
|
|
||||||
var endPositionTicks = Math.Min(runtime, positionTicks + segmentLengthTicks);
|
var endPositionTicks = Math.Min(runtime, positionTicks + segmentLengthTicks);
|
||||||
|
|
||||||
var url = string.Format("stream.vtt?StartPositionTicks={0}&EndPositionTicks={1}&api_key={2}",
|
var url = string.Format("stream.vtt?CopyTimestamps=true&AddVttTimeMap=true&StartPositionTicks={0}&EndPositionTicks={1}&api_key={2}",
|
||||||
positionTicks.ToString(CultureInfo.InvariantCulture),
|
positionTicks.ToString(CultureInfo.InvariantCulture),
|
||||||
endPositionTicks.ToString(CultureInfo.InvariantCulture),
|
endPositionTicks.ToString(CultureInfo.InvariantCulture),
|
||||||
accessToken);
|
accessToken);
|
||||||
@ -190,7 +194,7 @@ namespace MediaBrowser.Api.Subtitles
|
|||||||
return ResultFactory.GetResult(builder.ToString(), MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>());
|
return ResultFactory.GetResult(builder.ToString(), MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>());
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetSubtitle request)
|
public async Task<object> Get(GetSubtitle request)
|
||||||
{
|
{
|
||||||
if (string.Equals(request.Format, "js", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(request.Format, "js", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
@ -206,23 +210,35 @@ namespace MediaBrowser.Api.Subtitles
|
|||||||
var subtitleStream = mediaSource.MediaStreams
|
var subtitleStream = mediaSource.MediaStreams
|
||||||
.First(i => i.Type == MediaStreamType.Subtitle && i.Index == request.Index);
|
.First(i => i.Type == MediaStreamType.Subtitle && i.Index == request.Index);
|
||||||
|
|
||||||
return ToStaticFileResult(subtitleStream.Path);
|
return await ResultFactory.GetStaticFileResult(Request, subtitleStream.Path).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
var stream = GetSubtitles(request).Result;
|
using (var stream = await GetSubtitles(request).ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
using (var reader = new StreamReader(stream))
|
||||||
|
{
|
||||||
|
var text = reader.ReadToEnd();
|
||||||
|
|
||||||
return ResultFactory.GetResult(stream, MimeTypes.GetMimeType("file." + request.Format));
|
if (string.Equals(request.Format, "vtt", StringComparison.OrdinalIgnoreCase) && request.AddVttTimeMap)
|
||||||
|
{
|
||||||
|
text = text.Replace("WEBVTT", "WEBVTT\nX-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResultFactory.GetResult(text, MimeTypes.GetMimeType("file." + request.Format));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<Stream> GetSubtitles(GetSubtitle request)
|
private Task<Stream> GetSubtitles(GetSubtitle request)
|
||||||
{
|
{
|
||||||
return await _subtitleEncoder.GetSubtitles(request.Id,
|
return _subtitleEncoder.GetSubtitles(request.Id,
|
||||||
request.MediaSourceId,
|
request.MediaSourceId,
|
||||||
request.Index,
|
request.Index,
|
||||||
request.Format,
|
request.Format,
|
||||||
request.StartPositionTicks,
|
request.StartPositionTicks,
|
||||||
request.EndPositionTicks,
|
request.EndPositionTicks,
|
||||||
CancellationToken.None).ConfigureAwait(false);
|
request.CopyTimestamps,
|
||||||
|
CancellationToken.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(SearchRemoteSubtitles request)
|
public object Get(SearchRemoteSubtitles request)
|
||||||
@ -248,9 +264,9 @@ namespace MediaBrowser.Api.Subtitles
|
|||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetRemoteSubtitles request)
|
public async Task<object> Get(GetRemoteSubtitles request)
|
||||||
{
|
{
|
||||||
var result = _subtitleManager.GetRemoteSubtitles(request.Id, CancellationToken.None).Result;
|
var result = await _subtitleManager.GetRemoteSubtitles(request.Id, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
return ResultFactory.GetResult(result.Stream, MimeTypes.GetMimeType("file." + result.Format));
|
return ResultFactory.GetResult(result.Stream, MimeTypes.GetMimeType("file." + result.Format));
|
||||||
}
|
}
|
||||||
|
@ -227,7 +227,7 @@ namespace MediaBrowser.Api.Sync
|
|||||||
Task.WaitAll(task);
|
Task.WaitAll(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetSyncJobItemFile request)
|
public async Task<object> Get(GetSyncJobItemFile request)
|
||||||
{
|
{
|
||||||
var jobItem = _syncManager.GetJobItem(request.Id);
|
var jobItem = _syncManager.GetJobItem(request.Id);
|
||||||
|
|
||||||
@ -241,10 +241,9 @@ namespace MediaBrowser.Api.Sync
|
|||||||
throw new ArgumentException("The job item is not yet ready for transfer.");
|
throw new ArgumentException("The job item is not yet ready for transfer.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var task = _syncManager.ReportSyncJobItemTransferBeginning(request.Id);
|
await _syncManager.ReportSyncJobItemTransferBeginning(request.Id).ConfigureAwait(false);
|
||||||
Task.WaitAll(task);
|
|
||||||
|
|
||||||
return ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions
|
return await ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions
|
||||||
{
|
{
|
||||||
Path = jobItem.OutputPath,
|
Path = jobItem.OutputPath,
|
||||||
OnError = () =>
|
OnError = () =>
|
||||||
@ -252,10 +251,11 @@ namespace MediaBrowser.Api.Sync
|
|||||||
var failedTask = _syncManager.ReportSyncJobItemTransferFailed(request.Id);
|
var failedTask = _syncManager.ReportSyncJobItemTransferFailed(request.Id);
|
||||||
Task.WaitAll(failedTask);
|
Task.WaitAll(failedTask);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetSyncDialogOptions request)
|
public async Task<object> Get(GetSyncDialogOptions request)
|
||||||
{
|
{
|
||||||
var result = new SyncDialogOptions();
|
var result = new SyncDialogOptions();
|
||||||
|
|
||||||
@ -298,8 +298,7 @@ namespace MediaBrowser.Api.Sync
|
|||||||
.Select(_libraryManager.GetItemById)
|
.Select(_libraryManager.GetItemById)
|
||||||
.Where(i => i != null);
|
.Where(i => i != null);
|
||||||
|
|
||||||
var dtos = _dtoService.GetBaseItemDtos(items, dtoOptions, authenticatedUser)
|
var dtos = (await _dtoService.GetBaseItemDtos(items, dtoOptions, authenticatedUser).ConfigureAwait(false));
|
||||||
.ToList();
|
|
||||||
|
|
||||||
result.Options = SyncHelper.GetSyncOptions(dtos);
|
result.Options = SyncHelper.GetSyncOptions(dtos);
|
||||||
}
|
}
|
||||||
@ -343,7 +342,7 @@ namespace MediaBrowser.Api.Sync
|
|||||||
Task.WaitAll(task);
|
Task.WaitAll(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetSyncJobItemAdditionalFile request)
|
public Task<object> Get(GetSyncJobItemAdditionalFile request)
|
||||||
{
|
{
|
||||||
var jobItem = _syncManager.GetJobItem(request.Id);
|
var jobItem = _syncManager.GetJobItem(request.Id);
|
||||||
|
|
||||||
@ -359,7 +358,7 @@ namespace MediaBrowser.Api.Sync
|
|||||||
throw new ArgumentException("Sync job additional file not found.");
|
throw new ArgumentException("Sync job additional file not found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return ToStaticFileResult(file.Path);
|
return ResultFactory.GetStaticFileResult(Request, file.Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Post(EnableSyncJobItem request)
|
public void Post(EnableSyncJobItem request)
|
||||||
|
@ -43,7 +43,7 @@ namespace MediaBrowser.Api.System
|
|||||||
/// <returns>Task{SystemInfo}.</returns>
|
/// <returns>Task{SystemInfo}.</returns>
|
||||||
protected override Task<SystemInfo> GetDataToSend(WebSocketListenerState state)
|
protected override Task<SystemInfo> GetDataToSend(WebSocketListenerState state)
|
||||||
{
|
{
|
||||||
return Task.FromResult(_appHost.GetSystemInfo());
|
return _appHost.GetSystemInfo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ namespace MediaBrowser.Api.System
|
|||||||
/// Class GetSystemInfo
|
/// Class GetSystemInfo
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/System/Info", "GET", Summary = "Gets information about the server")]
|
[Route("/System/Info", "GET", Summary = "Gets information about the server")]
|
||||||
[Authenticated(EscapeParentalControl = true)]
|
[Authenticated(EscapeParentalControl = true, AllowBeforeStartupWizard = true)]
|
||||||
public class GetSystemInfo : IReturn<SystemInfo>
|
public class GetSystemInfo : IReturn<SystemInfo>
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -120,7 +120,7 @@ namespace MediaBrowser.Api.System
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
files = _fileSystem.GetFiles(_appPaths.LogDirectoryPath)
|
files = _fileSystem.GetFiles(_appPaths.LogDirectoryPath)
|
||||||
.Where(i => string.Equals(i.Extension, ".txt", StringComparison.OrdinalIgnoreCase))
|
.Where(i => string.Equals(i.Extension, ".txt", StringComparison.OrdinalIgnoreCase))
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
@ -144,9 +144,9 @@ namespace MediaBrowser.Api.System
|
|||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetLogFile request)
|
public Task<object> Get(GetLogFile request)
|
||||||
{
|
{
|
||||||
var file = _fileSystem.GetFiles(_appPaths.LogDirectoryPath)
|
var file = _fileSystem.GetFiles(_appPaths.LogDirectoryPath)
|
||||||
.First(i => string.Equals(i.Name, request.Name, StringComparison.OrdinalIgnoreCase));
|
.First(i => string.Equals(i.Name, request.Name, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
return ResultFactory.GetStaticFileResult(Request, file.FullName, FileShare.ReadWrite);
|
return ResultFactory.GetStaticFileResult(Request, file.FullName, FileShare.ReadWrite);
|
||||||
@ -157,16 +157,16 @@ namespace MediaBrowser.Api.System
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetSystemInfo request)
|
public async Task<object> Get(GetSystemInfo request)
|
||||||
{
|
{
|
||||||
var result = _appHost.GetSystemInfo();
|
var result = await _appHost.GetSystemInfo().ConfigureAwait(false);
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetPublicSystemInfo request)
|
public async Task<object> Get(GetPublicSystemInfo request)
|
||||||
{
|
{
|
||||||
var result = _appHost.GetSystemInfo();
|
var result = await _appHost.GetSystemInfo().ConfigureAwait(false);
|
||||||
|
|
||||||
var publicInfo = new PublicSystemInfo
|
var publicInfo = new PublicSystemInfo
|
||||||
{
|
{
|
||||||
|
@ -12,6 +12,8 @@ using ServiceStack;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Model.Dto;
|
||||||
|
|
||||||
namespace MediaBrowser.Api
|
namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
@ -271,29 +273,51 @@ namespace MediaBrowser.Api
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetSimilarShows request)
|
public async Task<object> Get(GetSimilarShows request)
|
||||||
{
|
{
|
||||||
var dtoOptions = GetDtoOptions(request);
|
var result = await GetSimilarItemsResult(request).ConfigureAwait(false);
|
||||||
|
|
||||||
var result = SimilarItemsHelper.GetSimilarItemsResult(dtoOptions, _userManager,
|
|
||||||
_itemRepo,
|
|
||||||
_libraryManager,
|
|
||||||
_userDataManager,
|
|
||||||
_dtoService,
|
|
||||||
Logger,
|
|
||||||
request, new[] { typeof(Series) },
|
|
||||||
SimilarItemsHelper.GetSimiliarityScore);
|
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetUpcomingEpisodes request)
|
private async Task<QueryResult<BaseItemDto>> GetSimilarItemsResult(BaseGetSimilarItemsFromItem request)
|
||||||
|
{
|
||||||
|
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
|
||||||
|
|
||||||
|
var item = string.IsNullOrEmpty(request.Id) ?
|
||||||
|
(!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder :
|
||||||
|
_libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
|
||||||
|
|
||||||
|
var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
|
{
|
||||||
|
Limit = request.Limit,
|
||||||
|
IncludeItemTypes = new[]
|
||||||
|
{
|
||||||
|
typeof(Series).Name
|
||||||
|
},
|
||||||
|
SimilarTo = item
|
||||||
|
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
|
var result = new QueryResult<BaseItemDto>
|
||||||
|
{
|
||||||
|
Items = (await _dtoService.GetBaseItemDtos(itemsResult, dtoOptions, user).ConfigureAwait(false)).ToArray(),
|
||||||
|
|
||||||
|
TotalRecordCount = itemsResult.Count
|
||||||
|
};
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<object> Get(GetUpcomingEpisodes request)
|
||||||
{
|
{
|
||||||
var user = _userManager.GetUserById(request.UserId);
|
var user = _userManager.GetUserById(request.UserId);
|
||||||
|
|
||||||
var minPremiereDate = DateTime.Now.Date.ToUniversalTime().AddDays(-1);
|
var minPremiereDate = DateTime.Now.Date.ToUniversalTime().AddDays(-1);
|
||||||
|
|
||||||
var parentIds = string.IsNullOrWhiteSpace(request.ParentId) ? new string[] { } : new[] { request.ParentId };
|
var parentIdGuid = string.IsNullOrWhiteSpace(request.ParentId) ? (Guid?)null : new Guid(request.ParentId);
|
||||||
|
|
||||||
var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
@ -302,13 +326,15 @@ namespace MediaBrowser.Api
|
|||||||
SortOrder = SortOrder.Ascending,
|
SortOrder = SortOrder.Ascending,
|
||||||
MinPremiereDate = minPremiereDate,
|
MinPremiereDate = minPremiereDate,
|
||||||
StartIndex = request.StartIndex,
|
StartIndex = request.StartIndex,
|
||||||
Limit = request.Limit
|
Limit = request.Limit,
|
||||||
|
ParentId = parentIdGuid,
|
||||||
|
Recursive = true
|
||||||
|
|
||||||
}, parentIds).ToList();
|
}).ToList();
|
||||||
|
|
||||||
var options = GetDtoOptions(request);
|
var options = GetDtoOptions(request);
|
||||||
|
|
||||||
var returnItems = _dtoService.GetBaseItemDtos(itemsResult, options, user).ToArray();
|
var returnItems = (await _dtoService.GetBaseItemDtos(itemsResult, options, user).ConfigureAwait(false)).ToArray();
|
||||||
|
|
||||||
var result = new ItemsResult
|
var result = new ItemsResult
|
||||||
{
|
{
|
||||||
@ -324,7 +350,7 @@ namespace MediaBrowser.Api
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetNextUpEpisodes request)
|
public async Task<object> Get(GetNextUpEpisodes request)
|
||||||
{
|
{
|
||||||
var result = _tvSeriesManager.GetNextUp(new NextUpQuery
|
var result = _tvSeriesManager.GetNextUp(new NextUpQuery
|
||||||
{
|
{
|
||||||
@ -339,7 +365,7 @@ namespace MediaBrowser.Api
|
|||||||
|
|
||||||
var options = GetDtoOptions(request);
|
var options = GetDtoOptions(request);
|
||||||
|
|
||||||
var returnItems = _dtoService.GetBaseItemDtos(result.Items, options, user).ToArray();
|
var returnItems = (await _dtoService.GetBaseItemDtos(result.Items, options, user).ConfigureAwait(false)).ToArray();
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(new ItemsResult
|
return ToOptimizedSerializedResultUsingCache(new ItemsResult
|
||||||
{
|
{
|
||||||
@ -372,7 +398,7 @@ namespace MediaBrowser.Api
|
|||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetSeasons request)
|
public async Task<object> Get(GetSeasons request)
|
||||||
{
|
{
|
||||||
var user = _userManager.GetUserById(request.UserId);
|
var user = _userManager.GetUserById(request.UserId);
|
||||||
|
|
||||||
@ -403,7 +429,7 @@ namespace MediaBrowser.Api
|
|||||||
|
|
||||||
var dtoOptions = GetDtoOptions(request);
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
var returnItems = _dtoService.GetBaseItemDtos(seasons, dtoOptions, user)
|
var returnItems = (await _dtoService.GetBaseItemDtos(seasons, dtoOptions, user).ConfigureAwait(false))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
return new ItemsResult
|
return new ItemsResult
|
||||||
@ -430,7 +456,7 @@ namespace MediaBrowser.Api
|
|||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetEpisodes request)
|
public async Task<object> Get(GetEpisodes request)
|
||||||
{
|
{
|
||||||
var user = _userManager.GetUserById(request.UserId);
|
var user = _userManager.GetUserById(request.UserId);
|
||||||
|
|
||||||
@ -512,7 +538,7 @@ namespace MediaBrowser.Api
|
|||||||
|
|
||||||
var dtoOptions = GetDtoOptions(request);
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
var dtos = _dtoService.GetBaseItemDtos(pagedItems, dtoOptions, user)
|
var dtos = (await _dtoService.GetBaseItemDtos(pagedItems, dtoOptions, user).ConfigureAwait(false))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
return new ItemsResult
|
return new ItemsResult
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using MediaBrowser.Controller.Dto;
|
using System;
|
||||||
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.Audio;
|
using MediaBrowser.Controller.Entities.Audio;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
@ -8,6 +9,8 @@ using MediaBrowser.Model.Dto;
|
|||||||
using ServiceStack;
|
using ServiceStack;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using MediaBrowser.Model.Entities;
|
||||||
|
using MediaBrowser.Model.Querying;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.UserLibrary
|
namespace MediaBrowser.Api.UserLibrary
|
||||||
{
|
{
|
||||||
@ -100,7 +103,12 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetArtists request)
|
public object Get(GetArtists request)
|
||||||
{
|
{
|
||||||
var result = GetResult(request);
|
if (string.IsNullOrWhiteSpace(request.IncludeItemTypes))
|
||||||
|
{
|
||||||
|
//request.IncludeItemTypes = "Audio,MusicVideo";
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = GetResultSlim(request);
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
@ -112,11 +120,26 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetAlbumArtists request)
|
public object Get(GetAlbumArtists request)
|
||||||
{
|
{
|
||||||
var result = GetResult(request);
|
if (string.IsNullOrWhiteSpace(request.IncludeItemTypes))
|
||||||
|
{
|
||||||
|
//request.IncludeItemTypes = "Audio,MusicVideo";
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = GetResultSlim(request);
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override QueryResult<Tuple<BaseItem, ItemCounts>> GetItems(GetItemsByName request, InternalItemsQuery query)
|
||||||
|
{
|
||||||
|
if (request is GetAlbumArtists)
|
||||||
|
{
|
||||||
|
return LibraryManager.GetAlbumArtists(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
return LibraryManager.GetArtists(query);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets all items.
|
/// Gets all items.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -125,16 +148,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
|
/// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
|
||||||
protected override IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items)
|
protected override IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items)
|
||||||
{
|
{
|
||||||
if (request is GetAlbumArtists)
|
throw new NotImplementedException();
|
||||||
{
|
|
||||||
return LibraryManager.GetAlbumArtists(items
|
|
||||||
.Where(i => !i.IsFolder)
|
|
||||||
.OfType<IHasAlbumArtist>());
|
|
||||||
}
|
|
||||||
|
|
||||||
return LibraryManager.GetArtists(items
|
|
||||||
.Where(i => !i.IsFolder)
|
|
||||||
.OfType<IHasArtist>());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ using ServiceStack;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using MediaBrowser.Model.Dto;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.UserLibrary
|
namespace MediaBrowser.Api.UserLibrary
|
||||||
{
|
{
|
||||||
@ -83,6 +84,137 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected ItemsResult GetResultSlim(GetItemsByName request)
|
||||||
|
{
|
||||||
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
|
User user = null;
|
||||||
|
BaseItem parentItem;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(request.UserId))
|
||||||
|
{
|
||||||
|
user = UserManager.GetUserById(request.UserId);
|
||||||
|
parentItem = string.IsNullOrEmpty(request.ParentId) ? user.RootFolder : LibraryManager.GetItemById(request.ParentId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parentItem = string.IsNullOrEmpty(request.ParentId) ? LibraryManager.RootFolder : LibraryManager.GetItemById(request.ParentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
var excludeItemTypes = request.GetExcludeItemTypes();
|
||||||
|
var includeItemTypes = request.GetIncludeItemTypes();
|
||||||
|
var mediaTypes = request.GetMediaTypes();
|
||||||
|
|
||||||
|
var query = new InternalItemsQuery(user)
|
||||||
|
{
|
||||||
|
ExcludeItemTypes = excludeItemTypes,
|
||||||
|
IncludeItemTypes = includeItemTypes,
|
||||||
|
MediaTypes = mediaTypes,
|
||||||
|
StartIndex = request.StartIndex,
|
||||||
|
Limit = request.Limit,
|
||||||
|
IsFavorite = request.IsFavorite,
|
||||||
|
NameLessThan = request.NameLessThan,
|
||||||
|
NameStartsWith = request.NameStartsWith,
|
||||||
|
NameStartsWithOrGreater = request.NameStartsWithOrGreater,
|
||||||
|
AlbumArtistStartsWithOrGreater = request.AlbumArtistStartsWithOrGreater,
|
||||||
|
Tags = request.GetTags(),
|
||||||
|
OfficialRatings = request.GetOfficialRatings(),
|
||||||
|
Genres = request.GetGenres(),
|
||||||
|
GenreIds = request.GetGenreIds(),
|
||||||
|
Studios = request.GetStudios(),
|
||||||
|
StudioIds = request.GetStudioIds(),
|
||||||
|
Person = request.Person,
|
||||||
|
PersonIds = request.GetPersonIds(),
|
||||||
|
PersonTypes = request.GetPersonTypes(),
|
||||||
|
Years = request.GetYears(),
|
||||||
|
MinCommunityRating = request.MinCommunityRating
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(request.ParentId))
|
||||||
|
{
|
||||||
|
if (parentItem is Folder)
|
||||||
|
{
|
||||||
|
query.AncestorIds = new[] { request.ParentId };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
query.ItemIds = new[] { request.ParentId };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var filter in request.GetFilters())
|
||||||
|
{
|
||||||
|
switch (filter)
|
||||||
|
{
|
||||||
|
case ItemFilter.Dislikes:
|
||||||
|
query.IsLiked = false;
|
||||||
|
break;
|
||||||
|
case ItemFilter.IsFavorite:
|
||||||
|
query.IsFavorite = true;
|
||||||
|
break;
|
||||||
|
case ItemFilter.IsFavoriteOrLikes:
|
||||||
|
query.IsFavoriteOrLiked = true;
|
||||||
|
break;
|
||||||
|
case ItemFilter.IsFolder:
|
||||||
|
query.IsFolder = true;
|
||||||
|
break;
|
||||||
|
case ItemFilter.IsNotFolder:
|
||||||
|
query.IsFolder = false;
|
||||||
|
break;
|
||||||
|
case ItemFilter.IsPlayed:
|
||||||
|
query.IsPlayed = true;
|
||||||
|
break;
|
||||||
|
case ItemFilter.IsRecentlyAdded:
|
||||||
|
break;
|
||||||
|
case ItemFilter.IsResumable:
|
||||||
|
query.IsResumable = true;
|
||||||
|
break;
|
||||||
|
case ItemFilter.IsUnplayed:
|
||||||
|
query.IsPlayed = false;
|
||||||
|
break;
|
||||||
|
case ItemFilter.Likes:
|
||||||
|
query.IsLiked = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = GetItems(request, query);
|
||||||
|
|
||||||
|
var dtos = result.Items.Select(i =>
|
||||||
|
{
|
||||||
|
var dto = DtoService.GetItemByNameDto(i.Item1, dtoOptions, null, user);
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(request.IncludeItemTypes))
|
||||||
|
{
|
||||||
|
SetItemCounts(dto, i.Item2);
|
||||||
|
}
|
||||||
|
return dto;
|
||||||
|
});
|
||||||
|
|
||||||
|
return new ItemsResult
|
||||||
|
{
|
||||||
|
Items = dtos.ToArray(),
|
||||||
|
TotalRecordCount = result.TotalRecordCount
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual QueryResult<Tuple<BaseItem, ItemCounts>> GetItems(GetItemsByName request, InternalItemsQuery query)
|
||||||
|
{
|
||||||
|
return new QueryResult<Tuple<BaseItem, ItemCounts>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetItemCounts(BaseItemDto dto, ItemCounts counts)
|
||||||
|
{
|
||||||
|
dto.ChildCount = counts.ItemCount;
|
||||||
|
dto.SeriesCount = counts.SeriesCount;
|
||||||
|
dto.EpisodeCount = counts.EpisodeCount;
|
||||||
|
dto.MovieCount = counts.MovieCount;
|
||||||
|
dto.TrailerCount = counts.TrailerCount;
|
||||||
|
dto.AlbumCount = counts.AlbumCount;
|
||||||
|
dto.SongCount = counts.SongCount;
|
||||||
|
dto.GameCount = counts.GameCount;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the specified request.
|
/// Gets the specified request.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -333,12 +465,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
var tags = request.GetTags();
|
var tags = request.GetTags();
|
||||||
if (tags.Length > 0)
|
if (tags.Length > 0)
|
||||||
{
|
{
|
||||||
var hasTags = i as IHasTags;
|
if (!tags.Any(v => i.Tags.Contains(v, StringComparer.OrdinalIgnoreCase)))
|
||||||
if (hasTags == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!tags.Any(v => hasTags.Tags.Contains(v, StringComparer.OrdinalIgnoreCase)))
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -379,7 +506,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// <param name="includeItemTypes">The include item types.</param>
|
/// <param name="includeItemTypes">The include item types.</param>
|
||||||
/// <param name="mediaTypes">The media types.</param>
|
/// <param name="mediaTypes">The media types.</param>
|
||||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
/// <returns>IEnumerable{BaseItem}.</returns>
|
||||||
protected bool FilterItem(GetItemsByName request, BaseItem f, string[] excludeItemTypes, string[] includeItemTypes, string[] mediaTypes)
|
private bool FilterItem(GetItemsByName request, BaseItem f, string[] excludeItemTypes, string[] includeItemTypes, string[] mediaTypes)
|
||||||
{
|
{
|
||||||
// Exclude item types
|
// Exclude item types
|
||||||
if (excludeItemTypes.Length > 0)
|
if (excludeItemTypes.Length > 0)
|
||||||
|
@ -100,9 +100,6 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
[ApiMember(Name = "HasTvdbId", Description = "Optional filter by items that have a tvdb id or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "HasTvdbId", Description = "Optional filter by items that have a tvdb id or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
public bool? HasTvdbId { get; set; }
|
public bool? HasTvdbId { get; set; }
|
||||||
|
|
||||||
[ApiMember(Name = "IsYearMismatched", Description = "Optional filter by items that are potentially misidentified.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? IsYearMismatched { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "IsInBoxSet", Description = "Optional filter by items that are in boxsets, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "IsInBoxSet", Description = "Optional filter by items that are in boxsets, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
public bool? IsInBoxSet { get; set; }
|
public bool? IsInBoxSet { get; set; }
|
||||||
|
|
||||||
|
@ -9,16 +9,13 @@ using ServiceStack;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using MediaBrowser.Model.Querying;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.UserLibrary
|
namespace MediaBrowser.Api.UserLibrary
|
||||||
{
|
{
|
||||||
[Route("/GameGenres", "GET", Summary = "Gets all Game genres from a given item, folder, or the entire library")]
|
[Route("/GameGenres", "GET", Summary = "Gets all Game genres from a given item, folder, or the entire library")]
|
||||||
public class GetGameGenres : GetItemsByName
|
public class GetGameGenres : GetItemsByName
|
||||||
{
|
{
|
||||||
public GetGameGenres()
|
|
||||||
{
|
|
||||||
MediaTypes = MediaType.Game;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/GameGenres/{Name}", "GET", Summary = "Gets a Game genre, by name")]
|
[Route("/GameGenres/{Name}", "GET", Summary = "Gets a Game genre, by name")]
|
||||||
@ -87,11 +84,16 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetGameGenres request)
|
public object Get(GetGameGenres request)
|
||||||
{
|
{
|
||||||
var result = GetResult(request);
|
var result = GetResultSlim(request);
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override QueryResult<Tuple<BaseItem, ItemCounts>> GetItems(GetItemsByName request, InternalItemsQuery query)
|
||||||
|
{
|
||||||
|
return LibraryManager.GetGameGenres(query);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets all items.
|
/// Gets all items.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -100,22 +102,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
|
/// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
|
||||||
protected override IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items)
|
protected override IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items)
|
||||||
{
|
{
|
||||||
return items
|
throw new NotImplementedException();
|
||||||
.SelectMany(i => i.Genres)
|
|
||||||
.DistinctNames()
|
|
||||||
.Select(name =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return LibraryManager.GetGameGenre(name);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.ErrorException("Error getting genre {0}", ex, name);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.Where(i => i != null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ using ServiceStack;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using MediaBrowser.Model.Querying;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.UserLibrary
|
namespace MediaBrowser.Api.UserLibrary
|
||||||
{
|
{
|
||||||
@ -92,11 +93,28 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetGenres request)
|
public object Get(GetGenres request)
|
||||||
{
|
{
|
||||||
var result = GetResult(request);
|
var result = GetResultSlim(request);
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override QueryResult<Tuple<BaseItem, ItemCounts>> GetItems(GetItemsByName request, InternalItemsQuery query)
|
||||||
|
{
|
||||||
|
var viewType = GetParentItemViewType(request);
|
||||||
|
|
||||||
|
if (string.Equals(viewType, CollectionType.Music) || string.Equals(viewType, CollectionType.MusicVideos))
|
||||||
|
{
|
||||||
|
return LibraryManager.GetMusicGenres(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.Equals(viewType, CollectionType.Games))
|
||||||
|
{
|
||||||
|
return LibraryManager.GetGameGenres(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
return LibraryManager.GetGenres(query);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets all items.
|
/// Gets all items.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -105,52 +123,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
|
/// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
|
||||||
protected override IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items)
|
protected override IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items)
|
||||||
{
|
{
|
||||||
var viewType = GetParentItemViewType(request);
|
throw new NotImplementedException();
|
||||||
|
|
||||||
if (string.Equals(viewType, CollectionType.Music) || string.Equals(viewType, CollectionType.MusicVideos))
|
|
||||||
{
|
|
||||||
return items
|
|
||||||
.SelectMany(i => i.Genres)
|
|
||||||
.DistinctNames()
|
|
||||||
.Select(name => LibraryManager.GetMusicGenre(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.Equals(viewType, CollectionType.Games))
|
|
||||||
{
|
|
||||||
return items
|
|
||||||
.SelectMany(i => i.Genres)
|
|
||||||
.DistinctNames()
|
|
||||||
.Select(name =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return LibraryManager.GetGameGenre(name);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.ErrorException("Error getting genre {0}", ex, name);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.Where(i => i != null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return items
|
|
||||||
.SelectMany(i => i.Genres)
|
|
||||||
.DistinctNames()
|
|
||||||
.Select(name =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return LibraryManager.GetGenre(name);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.ErrorException("Error getting genre {0}", ex, name);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.Where(i => i != null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,6 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// The _user manager
|
/// The _user manager
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly IUserManager _userManager;
|
private readonly IUserManager _userManager;
|
||||||
private readonly IUserDataManager _userDataRepository;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The _library manager
|
/// The _library manager
|
||||||
@ -43,25 +42,37 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
private readonly ILocalizationManager _localization;
|
private readonly ILocalizationManager _localization;
|
||||||
|
|
||||||
private readonly IDtoService _dtoService;
|
private readonly IDtoService _dtoService;
|
||||||
private readonly ICollectionManager _collectionManager;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ItemsService" /> class.
|
/// Initializes a new instance of the <see cref="ItemsService" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="userManager">The user manager.</param>
|
/// <param name="userManager">The user manager.</param>
|
||||||
/// <param name="libraryManager">The library manager.</param>
|
/// <param name="libraryManager">The library manager.</param>
|
||||||
/// <param name="userDataRepository">The user data repository.</param>
|
|
||||||
/// <param name="localization">The localization.</param>
|
/// <param name="localization">The localization.</param>
|
||||||
/// <param name="dtoService">The dto service.</param>
|
/// <param name="dtoService">The dto service.</param>
|
||||||
/// <param name="collectionManager">The collection manager.</param>
|
public ItemsService(IUserManager userManager, ILibraryManager libraryManager, ILocalizationManager localization, IDtoService dtoService)
|
||||||
public ItemsService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, ILocalizationManager localization, IDtoService dtoService, ICollectionManager collectionManager)
|
|
||||||
{
|
{
|
||||||
|
if (userManager == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("userManager");
|
||||||
|
}
|
||||||
|
if (libraryManager == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("libraryManager");
|
||||||
|
}
|
||||||
|
if (localization == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("localization");
|
||||||
|
}
|
||||||
|
if (dtoService == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("dtoService");
|
||||||
|
}
|
||||||
|
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_userDataRepository = userDataRepository;
|
|
||||||
_localization = localization;
|
_localization = localization;
|
||||||
_dtoService = dtoService;
|
_dtoService = dtoService;
|
||||||
_collectionManager = collectionManager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -71,6 +82,11 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public async Task<object> Get(GetItems request)
|
public async Task<object> Get(GetItems request)
|
||||||
{
|
{
|
||||||
|
if (request == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("request");
|
||||||
|
}
|
||||||
|
|
||||||
var result = await GetItems(request).ConfigureAwait(false);
|
var result = await GetItems(request).ConfigureAwait(false);
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
@ -84,15 +100,32 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
private async Task<ItemsResult> GetItems(GetItems request)
|
private async Task<ItemsResult> GetItems(GetItems request)
|
||||||
{
|
{
|
||||||
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
|
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
|
||||||
|
|
||||||
var result = await GetItemsToSerialize(request, user).ConfigureAwait(false);
|
var result = await GetItemsToSerialize(request, user).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (result == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("GetItemsToSerialize returned null");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.Items == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("GetItemsToSerialize result.Items returned null");
|
||||||
|
}
|
||||||
|
|
||||||
var dtoOptions = GetDtoOptions(request);
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
|
var dtoList = await _dtoService.GetBaseItemDtos(result.Items, dtoOptions, user).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (dtoList == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("GetBaseItemDtos returned null");
|
||||||
|
}
|
||||||
|
|
||||||
return new ItemsResult
|
return new ItemsResult
|
||||||
{
|
{
|
||||||
TotalRecordCount = result.TotalRecordCount,
|
TotalRecordCount = result.TotalRecordCount,
|
||||||
Items = _dtoService.GetBaseItemDtos(result.Items, dtoOptions, user).ToArray()
|
Items = dtoList.ToArray()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,11 +152,17 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
|
|
||||||
// Default list type = children
|
// Default list type = children
|
||||||
|
|
||||||
|
var folder = item as Folder;
|
||||||
|
if (folder == null)
|
||||||
|
{
|
||||||
|
folder = user == null ? _libraryManager.RootFolder : _libraryManager.GetUserRootFolder();
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(request.Ids))
|
if (!string.IsNullOrEmpty(request.Ids))
|
||||||
{
|
{
|
||||||
request.Recursive = true;
|
request.Recursive = true;
|
||||||
var query = GetItemsQuery(request, user);
|
var query = GetItemsQuery(request, user);
|
||||||
var result = await ((Folder)item).GetItems(query).ConfigureAwait(false);
|
var result = await folder.GetItems(query).ConfigureAwait(false);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(request.SortBy))
|
if (string.IsNullOrWhiteSpace(request.SortBy))
|
||||||
{
|
{
|
||||||
@ -138,22 +177,22 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
|
|
||||||
if (request.Recursive)
|
if (request.Recursive)
|
||||||
{
|
{
|
||||||
return await ((Folder)item).GetItems(GetItemsQuery(request, user)).ConfigureAwait(false);
|
return await folder.GetItems(GetItemsQuery(request, user)).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
return await ((Folder)item).GetItems(GetItemsQuery(request, null)).ConfigureAwait(false);
|
return await folder.GetItems(GetItemsQuery(request, null)).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
var userRoot = item as UserRootFolder;
|
var userRoot = item as UserRootFolder;
|
||||||
|
|
||||||
if (userRoot == null)
|
if (userRoot == null)
|
||||||
{
|
{
|
||||||
return await ((Folder)item).GetItems(GetItemsQuery(request, user)).ConfigureAwait(false);
|
return await folder.GetItems(GetItemsQuery(request, user)).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerable<BaseItem> items = ((Folder)item).GetChildren(user, true);
|
IEnumerable<BaseItem> items = folder.GetChildren(user, true);
|
||||||
|
|
||||||
var itemsArray = items.ToArray();
|
var itemsArray = items.ToArray();
|
||||||
|
|
||||||
@ -187,7 +226,6 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
NameStartsWith = request.NameStartsWith,
|
NameStartsWith = request.NameStartsWith,
|
||||||
NameStartsWithOrGreater = request.NameStartsWithOrGreater,
|
NameStartsWithOrGreater = request.NameStartsWithOrGreater,
|
||||||
HasImdbId = request.HasImdbId,
|
HasImdbId = request.HasImdbId,
|
||||||
IsYearMismatched = request.IsYearMismatched,
|
|
||||||
IsPlaceHolder = request.IsPlaceHolder,
|
IsPlaceHolder = request.IsPlaceHolder,
|
||||||
IsLocked = request.IsLocked,
|
IsLocked = request.IsLocked,
|
||||||
IsInBoxSet = request.IsInBoxSet,
|
IsInBoxSet = request.IsInBoxSet,
|
||||||
@ -301,7 +339,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
{
|
{
|
||||||
query.LocationTypes = request.LocationTypes.Split(',').Select(d => (LocationType)Enum.Parse(typeof(LocationType), d, true)).ToArray();
|
query.LocationTypes = request.LocationTypes.Split(',').Select(d => (LocationType)Enum.Parse(typeof(LocationType), d, true)).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Min official rating
|
// Min official rating
|
||||||
if (!string.IsNullOrWhiteSpace(request.MinOfficialRating))
|
if (!string.IsNullOrWhiteSpace(request.MinOfficialRating))
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using MediaBrowser.Controller.Dto;
|
using System;
|
||||||
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.Audio;
|
using MediaBrowser.Controller.Entities.Audio;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
@ -8,16 +9,14 @@ using MediaBrowser.Model.Dto;
|
|||||||
using ServiceStack;
|
using ServiceStack;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using MediaBrowser.Model.Entities;
|
||||||
|
using MediaBrowser.Model.Querying;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.UserLibrary
|
namespace MediaBrowser.Api.UserLibrary
|
||||||
{
|
{
|
||||||
[Route("/MusicGenres", "GET", Summary = "Gets all music genres from a given item, folder, or the entire library")]
|
[Route("/MusicGenres", "GET", Summary = "Gets all music genres from a given item, folder, or the entire library")]
|
||||||
public class GetMusicGenres : GetItemsByName
|
public class GetMusicGenres : GetItemsByName
|
||||||
{
|
{
|
||||||
public GetMusicGenres()
|
|
||||||
{
|
|
||||||
IncludeItemTypes = typeof(Audio).Name;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/MusicGenres/{Name}", "GET", Summary = "Gets a music genre, by name")]
|
[Route("/MusicGenres/{Name}", "GET", Summary = "Gets a music genre, by name")]
|
||||||
@ -86,11 +85,16 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetMusicGenres request)
|
public object Get(GetMusicGenres request)
|
||||||
{
|
{
|
||||||
var result = GetResult(request);
|
var result = GetResultSlim(request);
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override QueryResult<Tuple<BaseItem, ItemCounts>> GetItems(GetItemsByName request, InternalItemsQuery query)
|
||||||
|
{
|
||||||
|
return LibraryManager.GetMusicGenres(query);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets all items.
|
/// Gets all items.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -99,10 +103,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
|
/// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
|
||||||
protected override IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items)
|
protected override IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items)
|
||||||
{
|
{
|
||||||
return items
|
throw new NotImplementedException();
|
||||||
.SelectMany(i => i.Genres)
|
|
||||||
.DistinctNames()
|
|
||||||
.Select(name => LibraryManager.GetMusicGenre(name));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -247,9 +247,9 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// Posts the specified request.
|
/// Posts the specified request.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
public object Post(MarkPlayedItem request)
|
public async Task<object> Post(MarkPlayedItem request)
|
||||||
{
|
{
|
||||||
var result = MarkPlayed(request).Result;
|
var result = await MarkPlayed(request).ConfigureAwait(false);
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
@ -429,7 +429,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
await item.MarkUnplayed(user).ConfigureAwait(false);
|
await item.MarkUnplayed(user).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _userDataRepository.GetUserDataDto(item, user);
|
return await _userDataRepository.GetUserDataDto(item, user).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using MediaBrowser.Controller.Dto;
|
using System;
|
||||||
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
@ -7,6 +8,7 @@ using MediaBrowser.Model.Dto;
|
|||||||
using ServiceStack;
|
using ServiceStack;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using MediaBrowser.Model.Querying;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.UserLibrary
|
namespace MediaBrowser.Api.UserLibrary
|
||||||
{
|
{
|
||||||
@ -90,11 +92,16 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetStudios request)
|
public object Get(GetStudios request)
|
||||||
{
|
{
|
||||||
var result = GetResult(request);
|
var result = GetResultSlim(request);
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override QueryResult<Tuple<BaseItem, ItemCounts>> GetItems(GetItemsByName request, InternalItemsQuery query)
|
||||||
|
{
|
||||||
|
return LibraryManager.GetStudios(query);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets all items.
|
/// Gets all items.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -488,9 +488,9 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// Posts the specified request.
|
/// Posts the specified request.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
public object Post(MarkFavoriteItem request)
|
public async Task<object> Post(MarkFavoriteItem request)
|
||||||
{
|
{
|
||||||
var dto = MarkFavorite(request.UserId, request.Id, true).Result;
|
var dto = await MarkFavorite(request.UserId, request.Id, true).ConfigureAwait(false);
|
||||||
|
|
||||||
return ToOptimizedResult(dto);
|
return ToOptimizedResult(dto);
|
||||||
}
|
}
|
||||||
@ -527,7 +527,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
|
|
||||||
await _userDataRepository.SaveUserData(user.Id, item, data, UserDataSaveReason.UpdateUserRating, CancellationToken.None).ConfigureAwait(false);
|
await _userDataRepository.SaveUserData(user.Id, item, data, UserDataSaveReason.UpdateUserRating, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
return _userDataRepository.GetUserDataDto(item, user);
|
return await _userDataRepository.GetUserDataDto(item, user).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -545,9 +545,9 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// Posts the specified request.
|
/// Posts the specified request.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
public object Post(UpdateUserItemRating request)
|
public async Task<object> Post(UpdateUserItemRating request)
|
||||||
{
|
{
|
||||||
var dto = UpdateUserItemRating(request.UserId, request.Id, request.Likes).Result;
|
var dto = await UpdateUserItemRating(request.UserId, request.Id, request.Likes).ConfigureAwait(false);
|
||||||
|
|
||||||
return ToOptimizedResult(dto);
|
return ToOptimizedResult(dto);
|
||||||
}
|
}
|
||||||
@ -572,7 +572,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
|
|
||||||
await _userDataRepository.SaveUserData(user.Id, item, data, UserDataSaveReason.UpdateUserRating, CancellationToken.None).ConfigureAwait(false);
|
await _userDataRepository.SaveUserData(user.Id, item, data, UserDataSaveReason.UpdateUserRating, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
return _userDataRepository.GetUserDataDto(item, user);
|
return await _userDataRepository.GetUserDataDto(item, user).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -385,7 +385,7 @@ namespace MediaBrowser.Api
|
|||||||
throw new ResourceNotFoundException("User not found");
|
throw new ResourceNotFoundException("User not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
await _sessionMananger.RevokeUserTokens(user.Id.ToString("N")).ConfigureAwait(false);
|
await _sessionMananger.RevokeUserTokens(user.Id.ToString("N"), null).ConfigureAwait(false);
|
||||||
|
|
||||||
await _userManager.DeleteUser(user).ConfigureAwait(false);
|
await _userManager.DeleteUser(user).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@ -465,6 +465,10 @@ namespace MediaBrowser.Api
|
|||||||
}
|
}
|
||||||
|
|
||||||
await _userManager.ChangePassword(user, request.NewPassword).ConfigureAwait(false);
|
await _userManager.ChangePassword(user, request.NewPassword).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var currentToken = AuthorizationContext.GetAuthorizationInfo(Request).Token;
|
||||||
|
|
||||||
|
await _sessionMananger.RevokeUserTokens(user.Id.ToString("N"), currentToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -602,7 +606,8 @@ namespace MediaBrowser.Api
|
|||||||
throw new ArgumentException("There must be at least one enabled user in the system.");
|
throw new ArgumentException("There must be at least one enabled user in the system.");
|
||||||
}
|
}
|
||||||
|
|
||||||
await _sessionMananger.RevokeUserTokens(user.Id.ToString("N")).ConfigureAwait(false);
|
var currentToken = AuthorizationContext.GetAuthorizationInfo(Request).Token;
|
||||||
|
await _sessionMananger.RevokeUserTokens(user.Id.ToString("N"), currentToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
await _userManager.UpdateUserPolicy(request.Id, request).ConfigureAwait(false);
|
await _userManager.UpdateUserPolicy(request.Id, request).ConfigureAwait(false);
|
||||||
|
@ -199,7 +199,7 @@ namespace MediaBrowser.Common.Implementations
|
|||||||
ILogManager logManager,
|
ILogManager logManager,
|
||||||
IFileSystem fileSystem)
|
IFileSystem fileSystem)
|
||||||
{
|
{
|
||||||
XmlSerializer = new MediaBrowser.Common.Implementations.Serialization.XmlSerializer (fileSystem);
|
XmlSerializer = new XmlSerializer (fileSystem, logManager.GetLogger("XmlSerializer"));
|
||||||
FailedAssemblies = new List<string>();
|
FailedAssemblies = new List<string>();
|
||||||
|
|
||||||
ApplicationPaths = applicationPaths;
|
ApplicationPaths = applicationPaths;
|
||||||
@ -321,7 +321,7 @@ namespace MediaBrowser.Common.Implementations
|
|||||||
|
|
||||||
protected virtual IJsonSerializer CreateJsonSerializer()
|
protected virtual IJsonSerializer CreateJsonSerializer()
|
||||||
{
|
{
|
||||||
return new JsonSerializer(FileSystemManager);
|
return new JsonSerializer(FileSystemManager, LogManager.GetLogger("JsonSerializer"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetHttpLimit()
|
private void SetHttpLimit()
|
||||||
@ -552,7 +552,7 @@ namespace MediaBrowser.Common.Implementations
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.Error("Error creating {0}", ex, type.Name);
|
Logger.ErrorException("Error creating {0}", ex, type.Name);
|
||||||
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
@ -571,7 +571,7 @@ namespace MediaBrowser.Common.Implementations
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.Error("Error creating {0}", ex, type.Name);
|
Logger.ErrorException("Error creating {0}", ex, type.Name);
|
||||||
// Don't blow up in release mode
|
// Don't blow up in release mode
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -128,11 +128,6 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
|
|
||||||
private void AddIpv4Option(HttpWebRequest request, HttpRequestOptions options)
|
private void AddIpv4Option(HttpWebRequest request, HttpRequestOptions options)
|
||||||
{
|
{
|
||||||
if (!options.PreferIpv4)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
request.ServicePoint.BindIPEndPointDelegate = (servicePount, remoteEndPoint, retryCount) =>
|
request.ServicePoint.BindIPEndPointDelegate = (servicePount, remoteEndPoint, retryCount) =>
|
||||||
{
|
{
|
||||||
if (remoteEndPoint.AddressFamily == AddressFamily.InterNetwork)
|
if (remoteEndPoint.AddressFamily == AddressFamily.InterNetwork)
|
||||||
@ -143,18 +138,23 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private WebRequest GetRequest(HttpRequestOptions options, string method, bool enableHttpCompression)
|
private WebRequest GetRequest(HttpRequestOptions options, string method)
|
||||||
{
|
{
|
||||||
var request = CreateWebRequest(options.Url);
|
var request = CreateWebRequest(options.Url);
|
||||||
var httpWebRequest = request as HttpWebRequest;
|
var httpWebRequest = request as HttpWebRequest;
|
||||||
|
|
||||||
if (httpWebRequest != null)
|
if (httpWebRequest != null)
|
||||||
{
|
{
|
||||||
AddIpv4Option(httpWebRequest, options);
|
if (options.PreferIpv4)
|
||||||
|
{
|
||||||
|
AddIpv4Option(httpWebRequest, options);
|
||||||
|
}
|
||||||
|
|
||||||
AddRequestHeaders(httpWebRequest, options);
|
AddRequestHeaders(httpWebRequest, options);
|
||||||
|
|
||||||
httpWebRequest.AutomaticDecompression = enableHttpCompression ? DecompressionMethods.Deflate : DecompressionMethods.None;
|
httpWebRequest.AutomaticDecompression = options.EnableHttpCompression ?
|
||||||
|
(options.DecompressionMethod ?? DecompressionMethods.Deflate) :
|
||||||
|
DecompressionMethods.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache);
|
request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache);
|
||||||
@ -366,7 +366,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var httpWebRequest = GetRequest(options, httpMethod, options.EnableHttpCompression);
|
var httpWebRequest = GetRequest(options, httpMethod);
|
||||||
|
|
||||||
if (options.RequestContentBytes != null ||
|
if (options.RequestContentBytes != null ||
|
||||||
!string.IsNullOrEmpty(options.RequestContent) ||
|
!string.IsNullOrEmpty(options.RequestContent) ||
|
||||||
@ -556,7 +556,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
|
|
||||||
options.CancellationToken.ThrowIfCancellationRequested();
|
options.CancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
var httpWebRequest = GetRequest(options, "GET", options.EnableHttpCompression);
|
var httpWebRequest = GetRequest(options, "GET");
|
||||||
|
|
||||||
if (options.ResourcePool != null)
|
if (options.ResourcePool != null)
|
||||||
{
|
{
|
||||||
|
@ -55,7 +55,7 @@
|
|||||||
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
|
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<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.3.4\lib\net45\NLog.dll</HintPath>
|
<HintPath>..\packages\NLog.4.3.5\lib\net45\NLog.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Patterns.Logging">
|
<Reference Include="Patterns.Logging">
|
||||||
@ -65,8 +65,8 @@
|
|||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\ThirdParty\SharpCompress\SharpCompress.dll</HintPath>
|
<HintPath>..\ThirdParty\SharpCompress\SharpCompress.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="SimpleInjector, Version=3.1.4.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
|
<Reference Include="SimpleInjector, Version=3.2.0.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\SimpleInjector.3.1.4\lib\net45\SimpleInjector.dll</HintPath>
|
<HintPath>..\packages\SimpleInjector.3.2.0\lib\net45\SimpleInjector.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
|
@ -122,30 +122,27 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_lastExecutionResult == null)
|
var path = GetHistoryFilePath();
|
||||||
{
|
|
||||||
var path = GetHistoryFilePath();
|
|
||||||
|
|
||||||
lock (_lastExecutionResultSyncLock)
|
lock (_lastExecutionResultSyncLock)
|
||||||
|
{
|
||||||
|
if (_lastExecutionResult == null)
|
||||||
{
|
{
|
||||||
if (_lastExecutionResult == null)
|
try
|
||||||
{
|
{
|
||||||
try
|
_lastExecutionResult = JsonSerializer.DeserializeFromFile<TaskResult>(path);
|
||||||
{
|
}
|
||||||
return JsonSerializer.DeserializeFromFile<TaskResult>(path);
|
catch (DirectoryNotFoundException)
|
||||||
}
|
{
|
||||||
catch (DirectoryNotFoundException)
|
// File doesn't exist. No biggie
|
||||||
{
|
}
|
||||||
// File doesn't exist. No biggie
|
catch (FileNotFoundException)
|
||||||
}
|
{
|
||||||
catch (FileNotFoundException)
|
// File doesn't exist. No biggie
|
||||||
{
|
}
|
||||||
// File doesn't exist. No biggie
|
catch (Exception ex)
|
||||||
}
|
{
|
||||||
catch (Exception ex)
|
Logger.ErrorException("Error deserializing {0}", ex, path);
|
||||||
{
|
|
||||||
Logger.ErrorException("Error deserializing {0}", ex, path);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using CommonIO;
|
using CommonIO;
|
||||||
|
using MediaBrowser.Model.Logging;
|
||||||
|
|
||||||
namespace MediaBrowser.Common.Implementations.Serialization
|
namespace MediaBrowser.Common.Implementations.Serialization
|
||||||
{
|
{
|
||||||
@ -11,10 +12,12 @@ namespace MediaBrowser.Common.Implementations.Serialization
|
|||||||
public class JsonSerializer : IJsonSerializer
|
public class JsonSerializer : IJsonSerializer
|
||||||
{
|
{
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
|
private readonly ILogger _logger;
|
||||||
public JsonSerializer(IFileSystem fileSystem)
|
|
||||||
|
public JsonSerializer(IFileSystem fileSystem, ILogger logger)
|
||||||
{
|
{
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
|
_logger = logger;
|
||||||
Configure();
|
Configure();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,6 +68,7 @@ namespace MediaBrowser.Common.Implementations.Serialization
|
|||||||
|
|
||||||
private Stream OpenFile(string path)
|
private Stream OpenFile(string path)
|
||||||
{
|
{
|
||||||
|
_logger.Debug("Deserializing file {0}", path);
|
||||||
return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 131072);
|
return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 131072);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ using System.Collections.Concurrent;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using CommonIO;
|
using CommonIO;
|
||||||
|
using MediaBrowser.Model.Logging;
|
||||||
|
|
||||||
namespace MediaBrowser.Common.Implementations.Serialization
|
namespace MediaBrowser.Common.Implementations.Serialization
|
||||||
{
|
{
|
||||||
@ -12,12 +13,14 @@ namespace MediaBrowser.Common.Implementations.Serialization
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class XmlSerializer : IXmlSerializer
|
public class XmlSerializer : IXmlSerializer
|
||||||
{
|
{
|
||||||
private IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
public XmlSerializer(IFileSystem fileSystem)
|
public XmlSerializer(IFileSystem fileSystem, ILogger logger)
|
||||||
{
|
{
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
}
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
// Need to cache these
|
// Need to cache these
|
||||||
// http://dotnetcodebox.blogspot.com/2013/01/xmlserializer-class-may-result-in.html
|
// http://dotnetcodebox.blogspot.com/2013/01/xmlserializer-class-may-result-in.html
|
||||||
@ -91,6 +94,7 @@ namespace MediaBrowser.Common.Implementations.Serialization
|
|||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object DeserializeFromFile(Type type, string file)
|
public object DeserializeFromFile(Type type, string file)
|
||||||
{
|
{
|
||||||
|
_logger.Debug("Deserializing file {0}", file);
|
||||||
using (var stream = _fileSystem.OpenRead(file))
|
using (var stream = _fileSystem.OpenRead(file))
|
||||||
{
|
{
|
||||||
return DeserializeFromStream(type, stream);
|
return DeserializeFromStream(type, stream);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<packages>
|
<packages>
|
||||||
<package id="CommonIO" version="1.0.0.9" targetFramework="net45" />
|
<package id="CommonIO" version="1.0.0.9" targetFramework="net45" />
|
||||||
<package id="morelinq" version="1.4.0" targetFramework="net45" />
|
<package id="morelinq" version="1.4.0" targetFramework="net45" />
|
||||||
<package id="NLog" version="4.3.4" targetFramework="net45" />
|
<package id="NLog" version="4.3.5" targetFramework="net45" />
|
||||||
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
||||||
<package id="SimpleInjector" version="3.1.4" targetFramework="net45" />
|
<package id="SimpleInjector" version="3.2.0" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace MediaBrowser.Common.Net
|
namespace MediaBrowser.Common.Net
|
||||||
@ -16,6 +17,8 @@ namespace MediaBrowser.Common.Net
|
|||||||
/// <value>The URL.</value>
|
/// <value>The URL.</value>
|
||||||
public string Url { get; set; }
|
public string Url { get; set; }
|
||||||
|
|
||||||
|
public DecompressionMethods? DecompressionMethod { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the accept header.
|
/// Gets or sets the accept header.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -53,6 +53,12 @@ namespace MediaBrowser.Controller.Channels
|
|||||||
|
|
||||||
public bool IsInfiniteStream { get; set; }
|
public bool IsInfiniteStream { get; set; }
|
||||||
|
|
||||||
|
public string HomePageUrl { get; set; }
|
||||||
|
|
||||||
|
public List<string> Artists { get; set; }
|
||||||
|
|
||||||
|
public List<string> AlbumArtists { get; set; }
|
||||||
|
|
||||||
public ChannelItemInfo()
|
public ChannelItemInfo()
|
||||||
{
|
{
|
||||||
MediaSources = new List<ChannelMediaInfo>();
|
MediaSources = new List<ChannelMediaInfo>();
|
||||||
@ -62,6 +68,8 @@ namespace MediaBrowser.Controller.Channels
|
|||||||
People = new List<PersonInfo>();
|
People = new List<PersonInfo>();
|
||||||
Tags = new List<string>();
|
Tags = new List<string>();
|
||||||
ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
Artists = new List<string>();
|
||||||
|
AlbumArtists = new List<string>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ namespace MediaBrowser.Controller.Chapters
|
|||||||
/// <param name="chapters">The chapters.</param>
|
/// <param name="chapters">The chapters.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task SaveChapters(string itemId, IEnumerable<ChapterInfo> chapters, CancellationToken cancellationToken);
|
Task SaveChapters(string itemId, List<ChapterInfo> chapters, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Searches the specified video.
|
/// Searches the specified video.
|
||||||
|
@ -23,10 +23,5 @@ namespace MediaBrowser.Controller.Drawing
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The height.</value>
|
/// <value>The height.</value>
|
||||||
public int Height { get; set; }
|
public int Height { get; set; }
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the text.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The text.</value>
|
|
||||||
public string Text { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ using MediaBrowser.Controller.Entities;
|
|||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Querying;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Dto
|
namespace MediaBrowser.Controller.Dto
|
||||||
{
|
{
|
||||||
@ -68,7 +69,7 @@ namespace MediaBrowser.Controller.Dto
|
|||||||
/// <param name="user">The user.</param>
|
/// <param name="user">The user.</param>
|
||||||
/// <param name="owner">The owner.</param>
|
/// <param name="owner">The owner.</param>
|
||||||
/// <returns>IEnumerable<BaseItemDto>.</returns>
|
/// <returns>IEnumerable<BaseItemDto>.</returns>
|
||||||
IEnumerable<BaseItemDto> GetBaseItemDtos(IEnumerable<BaseItem> items, DtoOptions options, User user = null,
|
Task<List<BaseItemDto>> GetBaseItemDtos(IEnumerable<BaseItem> items, DtoOptions options, User user = null,
|
||||||
BaseItem owner = null);
|
BaseItem owner = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -20,15 +20,12 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
IHasArtist,
|
IHasArtist,
|
||||||
IHasMusicGenres,
|
IHasMusicGenres,
|
||||||
IHasLookupInfo<SongInfo>,
|
IHasLookupInfo<SongInfo>,
|
||||||
IHasTags,
|
|
||||||
IHasMediaSources,
|
IHasMediaSources,
|
||||||
IThemeMedia,
|
IThemeMedia,
|
||||||
IArchivable
|
IArchivable
|
||||||
{
|
{
|
||||||
public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
|
public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
|
||||||
|
|
||||||
public long? Size { get; set; }
|
|
||||||
public string Container { get; set; }
|
|
||||||
public int? TotalBitrate { get; set; }
|
public int? TotalBitrate { get; set; }
|
||||||
public ExtraType? ExtraType { get; set; }
|
public ExtraType? ExtraType { get; set; }
|
||||||
|
|
||||||
|
@ -179,17 +179,13 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
{
|
{
|
||||||
var items = GetRecursiveChildren().ToList();
|
var items = GetRecursiveChildren().ToList();
|
||||||
|
|
||||||
var songs = items.OfType<Audio>().ToList();
|
var totalItems = items.Count;
|
||||||
|
|
||||||
var others = items.Except(songs).ToList();
|
|
||||||
|
|
||||||
var totalItems = songs.Count + others.Count;
|
|
||||||
var numComplete = 0;
|
var numComplete = 0;
|
||||||
|
|
||||||
var childUpdateType = ItemUpdateType.None;
|
var childUpdateType = ItemUpdateType.None;
|
||||||
|
|
||||||
// Refresh songs
|
// Refresh songs
|
||||||
foreach (var item in songs)
|
foreach (var item in items)
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
@ -199,7 +195,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
numComplete++;
|
numComplete++;
|
||||||
double percent = numComplete;
|
double percent = numComplete;
|
||||||
percent /= totalItems;
|
percent /= totalItems;
|
||||||
progress.Report(percent * 100);
|
progress.Report(percent * 95);
|
||||||
}
|
}
|
||||||
|
|
||||||
var parentRefreshOptions = refreshOptions;
|
var parentRefreshOptions = refreshOptions;
|
||||||
@ -212,19 +208,6 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
// Refresh current item
|
// Refresh current item
|
||||||
await RefreshMetadata(parentRefreshOptions, cancellationToken).ConfigureAwait(false);
|
await RefreshMetadata(parentRefreshOptions, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
// Refresh all non-songs
|
|
||||||
foreach (var item in others)
|
|
||||||
{
|
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
var updateType = await item.RefreshMetadata(parentRefreshOptions, cancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
numComplete++;
|
|
||||||
double percent = numComplete;
|
|
||||||
percent /= totalItems;
|
|
||||||
progress.Report(percent * 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
progress.Report(100);
|
progress.Report(100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ using System.Linq;
|
|||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Extensions;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities.Audio
|
namespace MediaBrowser.Controller.Entities.Audio
|
||||||
{
|
{
|
||||||
@ -62,13 +63,6 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
query.ArtistNames = new[] { Name };
|
query.ArtistNames = new[] { Name };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Need this for now since the artist filter isn't yet supported by the db
|
|
||||||
if (ConfigurationManager.Configuration.SchemaVersion < 79)
|
|
||||||
{
|
|
||||||
var filter = GetItemFilter();
|
|
||||||
return LibraryManager.GetItemList(query).Where(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
return LibraryManager.GetItemList(query);
|
return LibraryManager.GetItemList(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,6 +80,15 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override int GetChildCount(User user)
|
||||||
|
{
|
||||||
|
if (IsAccessedByName)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return base.GetChildCount(user);
|
||||||
|
}
|
||||||
|
|
||||||
public override bool IsSaveLocalMetadataEnabled()
|
public override bool IsSaveLocalMetadataEnabled()
|
||||||
{
|
{
|
||||||
if (IsAccessedByName)
|
if (IsAccessedByName)
|
||||||
@ -163,10 +166,17 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
list.Add("Artist-Musicbrainz-" + id);
|
list.Add("Artist-Musicbrainz-" + id);
|
||||||
}
|
}
|
||||||
|
|
||||||
list.Add("Artist-" + item.Name);
|
list.Add("Artist-" + (item.Name ?? string.Empty).RemoveDiacritics());
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string PresentationUniqueKey
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return "Artist-" + (Name ?? string.Empty).RemoveDiacritics();
|
||||||
|
}
|
||||||
|
}
|
||||||
protected override bool GetBlockUnratedValue(UserPolicy config)
|
protected override bool GetBlockUnratedValue(UserPolicy config)
|
||||||
{
|
{
|
||||||
return config.BlockUnratedItems.Contains(UnratedItem.Music);
|
return config.BlockUnratedItems.Contains(UnratedItem.Music);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
using MediaBrowser.Common.Extensions;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities.Audio
|
namespace MediaBrowser.Controller.Entities.Audio
|
||||||
{
|
{
|
||||||
@ -14,10 +15,18 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
{
|
{
|
||||||
var list = base.GetUserDataKeys();
|
var list = base.GetUserDataKeys();
|
||||||
|
|
||||||
list.Insert(0, "MusicGenre-" + Name);
|
list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string PresentationUniqueKey
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return GetUserDataKeys()[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public override bool SupportsAddingToPlaylist
|
public override bool SupportsAddingToPlaylist
|
||||||
{
|
{
|
||||||
|
@ -26,6 +26,7 @@ using System.Threading.Tasks;
|
|||||||
using CommonIO;
|
using CommonIO;
|
||||||
using MediaBrowser.Controller.Sorting;
|
using MediaBrowser.Controller.Sorting;
|
||||||
using MediaBrowser.Model.LiveTv;
|
using MediaBrowser.Model.LiveTv;
|
||||||
|
using MediaBrowser.Model.Providers;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
@ -36,6 +37,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
protected BaseItem()
|
protected BaseItem()
|
||||||
{
|
{
|
||||||
|
Keywords = new List<string>();
|
||||||
Tags = new List<string>();
|
Tags = new List<string>();
|
||||||
Genres = new List<string>();
|
Genres = new List<string>();
|
||||||
Studios = new List<string>();
|
Studios = new List<string>();
|
||||||
@ -67,12 +69,20 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public string PreferredMetadataLanguage { get; set; }
|
public string PreferredMetadataLanguage { get; set; }
|
||||||
|
|
||||||
|
public long? Size { get; set; }
|
||||||
|
public string Container { get; set; }
|
||||||
|
public string ShortOverview { get; set; }
|
||||||
|
|
||||||
public List<ItemImageInfo> ImageInfos { get; set; }
|
public List<ItemImageInfo> ImageInfos { get; set; }
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public bool IsVirtualItem { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the album.
|
/// Gets or sets the album.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The album.</value>
|
/// <value>The album.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
public string Album { get; set; }
|
public string Album { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -810,6 +820,8 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public List<string> Tags { get; set; }
|
public List<string> Tags { get; set; }
|
||||||
|
|
||||||
|
public List<string> Keywords { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the home page URL.
|
/// Gets or sets the home page URL.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -1031,9 +1043,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
: options;
|
: options;
|
||||||
|
|
||||||
var result = await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false);
|
return await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
@ -1394,15 +1404,10 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
private bool IsVisibleViaTags(User user)
|
private bool IsVisibleViaTags(User user)
|
||||||
{
|
{
|
||||||
var hasTags = this as IHasTags;
|
var policy = user.Policy;
|
||||||
|
if (policy.BlockedTags.Any(i => Tags.Contains(i, StringComparer.OrdinalIgnoreCase)))
|
||||||
if (hasTags != null)
|
|
||||||
{
|
{
|
||||||
var policy = user.Policy;
|
return false;
|
||||||
if (policy.BlockedTags.Any(i => hasTags.Tags.Contains(i, StringComparer.OrdinalIgnoreCase)))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -2088,7 +2093,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user)
|
public virtual Task FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user)
|
||||||
{
|
{
|
||||||
if (RunTimeTicks.HasValue)
|
if (RunTimeTicks.HasValue)
|
||||||
{
|
{
|
||||||
@ -2104,6 +2109,8 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Task.FromResult(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Task RefreshMetadataForOwnedVideo(MetadataRefreshOptions options, string path, CancellationToken cancellationToken)
|
protected Task RefreshMetadataForOwnedVideo(MetadataRefreshOptions options, string path, CancellationToken cancellationToken)
|
||||||
@ -2168,7 +2175,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (GetParent() is AggregateFolder || this is BasePluginFolder)
|
if (GetParent() is AggregateFolder || this is BasePluginFolder || this is Channel)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2214,5 +2221,10 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
DeleteFileLocation = false
|
DeleteFileLocation = false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual List<ExternalUrl> GetRelatedUrls()
|
||||||
|
{
|
||||||
|
return new List<ExternalUrl>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,7 +6,7 @@ using MediaBrowser.Model.Entities;
|
|||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
public class Book : BaseItem, IHasTags, IHasLookupInfo<BookInfo>, IHasSeries
|
public class Book : BaseItem, IHasLookupInfo<BookInfo>, IHasSeries
|
||||||
{
|
{
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public override string MediaType
|
public override string MediaType
|
||||||
|
@ -13,6 +13,7 @@ using System.Runtime.Serialization;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CommonIO;
|
using CommonIO;
|
||||||
|
using MediaBrowser.Controller.Channels;
|
||||||
using MediaBrowser.Model.Channels;
|
using MediaBrowser.Model.Channels;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
@ -20,7 +21,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class Folder
|
/// Class Folder
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Folder : BaseItem, IHasThemeMedia, IHasTags
|
public class Folder : BaseItem, IHasThemeMedia
|
||||||
{
|
{
|
||||||
public static IUserManager UserManager { get; set; }
|
public static IUserManager UserManager { get; set; }
|
||||||
public static IUserViewManager UserViewManager { get; set; }
|
public static IUserViewManager UserViewManager { get; set; }
|
||||||
@ -164,49 +165,15 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
item.DateModified = DateTime.UtcNow;
|
item.DateModified = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddChildInternal(item.Id);
|
|
||||||
|
|
||||||
await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
|
await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void AddChildrenInternal(List<Guid> children)
|
|
||||||
{
|
|
||||||
lock (_childrenSyncLock)
|
|
||||||
{
|
|
||||||
var newChildren = ChildIds.ToList();
|
|
||||||
newChildren.AddRange(children);
|
|
||||||
_children = newChildren.ToList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
protected void AddChildInternal(Guid child)
|
|
||||||
{
|
|
||||||
lock (_childrenSyncLock)
|
|
||||||
{
|
|
||||||
var childIds = ChildIds.ToList();
|
|
||||||
if (!childIds.Contains(child))
|
|
||||||
{
|
|
||||||
childIds.Add(child);
|
|
||||||
_children = childIds.ToList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void RemoveChildrenInternal(List<Guid> children)
|
|
||||||
{
|
|
||||||
lock (_childrenSyncLock)
|
|
||||||
{
|
|
||||||
_children = ChildIds.Except(children).ToList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes the child.
|
/// Removes the child.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">The item.</param>
|
/// <param name="item">The item.</param>
|
||||||
public void RemoveChild(BaseItem item)
|
public void RemoveChild(BaseItem item)
|
||||||
{
|
{
|
||||||
RemoveChildrenInternal(new[] { item.Id }.ToList());
|
|
||||||
|
|
||||||
item.SetParent(null);
|
item.SetParent(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,33 +208,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The children
|
|
||||||
/// </summary>
|
|
||||||
private IReadOnlyList<Guid> _children;
|
|
||||||
/// <summary>
|
|
||||||
/// The _children sync lock
|
|
||||||
/// </summary>
|
|
||||||
private readonly object _childrenSyncLock = new object();
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the actual children.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The actual children.</value>
|
|
||||||
protected virtual IEnumerable<Guid> ChildIds
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
lock (_childrenSyncLock)
|
|
||||||
{
|
|
||||||
if (_children == null)
|
|
||||||
{
|
|
||||||
_children = LoadChildren().ToList();
|
|
||||||
}
|
|
||||||
return _children.ToList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the actual children.
|
/// Gets the actual children.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -277,7 +217,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return ChildIds.Select(LibraryManager.GetItemById).Where(i => i != null);
|
return LoadChildren();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,7 +271,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<Guid> LoadChildren()
|
protected virtual IEnumerable<BaseItem> LoadChildren()
|
||||||
{
|
{
|
||||||
//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
|
||||||
return GetCachedChildren();
|
return GetCachedChildren();
|
||||||
@ -461,17 +401,15 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
foreach (var item in itemsRemoved)
|
foreach (var item in itemsRemoved)
|
||||||
{
|
{
|
||||||
if (item.LocationType == LocationType.Virtual ||
|
var itemLocationType = item.LocationType;
|
||||||
item.LocationType == LocationType.Remote)
|
if (itemLocationType == LocationType.Virtual ||
|
||||||
|
itemLocationType == LocationType.Remote)
|
||||||
{
|
{
|
||||||
// Don't remove these because there's no way to accurately validate them.
|
|
||||||
validChildren.Add(item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (!string.IsNullOrEmpty(item.Path) && IsPathOffline(item.Path))
|
else if (!string.IsNullOrEmpty(item.Path) && IsPathOffline(item.Path))
|
||||||
{
|
{
|
||||||
await UpdateIsOffline(item, true).ConfigureAwait(false);
|
await UpdateIsOffline(item, true).ConfigureAwait(false);
|
||||||
validChildren.Add(item);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -481,8 +419,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
if (actualRemovals.Count > 0)
|
if (actualRemovals.Count > 0)
|
||||||
{
|
{
|
||||||
RemoveChildrenInternal(actualRemovals.Select(i => i.Id).ToList());
|
|
||||||
|
|
||||||
foreach (var item in actualRemovals)
|
foreach (var item in actualRemovals)
|
||||||
{
|
{
|
||||||
Logger.Debug("Removed item: " + item.Path);
|
Logger.Debug("Removed item: " + item.Path);
|
||||||
@ -495,8 +431,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
|
|
||||||
await LibraryManager.CreateItems(newItems, cancellationToken).ConfigureAwait(false);
|
await LibraryManager.CreateItems(newItems, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
AddChildrenInternal(newItems.Select(i => i.Id).ToList());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -724,15 +658,36 @@ 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<Guid> GetCachedChildren()
|
protected IEnumerable<BaseItem> GetCachedChildren()
|
||||||
{
|
{
|
||||||
return ItemRepository.GetItemIdsList(new InternalItemsQuery
|
return ItemRepository.GetItemList(new InternalItemsQuery
|
||||||
{
|
{
|
||||||
ParentId = Id,
|
ParentId = Id,
|
||||||
GroupByPresentationUniqueKey = false
|
GroupByPresentationUniqueKey = false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual int GetChildCount(User user)
|
||||||
|
{
|
||||||
|
if (LinkedChildren.Count > 0)
|
||||||
|
{
|
||||||
|
if (!(this is ICollectionFolder))
|
||||||
|
{
|
||||||
|
return GetChildren(user, true).Count();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = GetItems(new InternalItemsQuery(user)
|
||||||
|
{
|
||||||
|
Recursive = false,
|
||||||
|
Limit = 0,
|
||||||
|
ParentId = Id
|
||||||
|
|
||||||
|
}).Result;
|
||||||
|
|
||||||
|
return result.TotalRecordCount;
|
||||||
|
}
|
||||||
|
|
||||||
public QueryResult<BaseItem> QueryRecursive(InternalItemsQuery query)
|
public QueryResult<BaseItem> QueryRecursive(InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
var user = query.User;
|
var user = query.User;
|
||||||
@ -768,58 +723,13 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
if (!(this is ICollectionFolder))
|
if (!(this is ICollectionFolder))
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to LinkedChildren");
|
Logger.Debug("Query requires post-filtering due to LinkedChildren. Type: " + GetType().Name);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var supportsUserDataQueries = ConfigurationManager.Configuration.SchemaVersion >= 76;
|
|
||||||
|
|
||||||
if (query.SortBy != null && query.SortBy.Length > 0)
|
if (query.SortBy != null && query.SortBy.Length > 0)
|
||||||
{
|
{
|
||||||
if (!supportsUserDataQueries)
|
|
||||||
{
|
|
||||||
if (query.SortBy.Contains(ItemSortBy.DatePlayed, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.IsFavoriteOrLiked");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (query.SortBy.Contains(ItemSortBy.PlayCount, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.PlayCount");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (query.SortBy.Contains(ItemSortBy.IsFavoriteOrLiked, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.IsFavoriteOrLiked");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (query.SortBy.Contains(ItemSortBy.IsPlayed, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.IsPlayed");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (query.SortBy.Contains(ItemSortBy.IsUnplayed, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.IsUnplayed");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ConfigurationManager.Configuration.SchemaVersion < 79)
|
|
||||||
{
|
|
||||||
if (query.SortBy.Contains(ItemSortBy.AlbumArtist, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.AlbumArtist");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (query.SortBy.Contains(ItemSortBy.Artist, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.Artist");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.SortBy.Contains(ItemSortBy.AiredEpisodeOrder, StringComparer.OrdinalIgnoreCase))
|
if (query.SortBy.Contains(ItemSortBy.AiredEpisodeOrder, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.AiredEpisodeOrder");
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.AiredEpisodeOrder");
|
||||||
@ -840,11 +750,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.Metascore");
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.Metascore");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (query.SortBy.Contains(ItemSortBy.OfficialRating, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.OfficialRating");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (query.SortBy.Contains(ItemSortBy.Players, StringComparer.OrdinalIgnoreCase))
|
if (query.SortBy.Contains(ItemSortBy.Players, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.Players");
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.Players");
|
||||||
@ -860,11 +765,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.SeriesSortName");
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.SeriesSortName");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (query.SortBy.Contains(ItemSortBy.Studio, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.Studio");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (query.SortBy.Contains(ItemSortBy.VideoBitRate, StringComparer.OrdinalIgnoreCase))
|
if (query.SortBy.Contains(ItemSortBy.VideoBitRate, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.VideoBitRate");
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.VideoBitRate");
|
||||||
@ -878,45 +778,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.PersonIds.Length > 0)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to PersonIds");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!supportsUserDataQueries)
|
|
||||||
{
|
|
||||||
if (query.IsLiked.HasValue)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to IsLiked");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.IsFavoriteOrLiked.HasValue)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to IsFavoriteOrLiked");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.IsFavorite.HasValue)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to IsFavorite");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.IsResumable.HasValue)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to IsResumable");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.IsPlayed.HasValue)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to IsPlayed");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.IsInBoxSet.HasValue)
|
if (query.IsInBoxSet.HasValue)
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to IsInBoxSet");
|
Logger.Debug("Query requires post-filtering due to IsInBoxSet");
|
||||||
@ -930,30 +791,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.HasImdbId.HasValue)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to HasImdbId");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.HasTmdbId.HasValue)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to HasTmdbId");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.HasTvdbId.HasValue)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to HasTvdbId");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.IsYearMismatched.HasValue)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to IsYearMismatched");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.HasOfficialRating.HasValue)
|
if (query.HasOfficialRating.HasValue)
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to HasOfficialRating");
|
Logger.Debug("Query requires post-filtering due to HasOfficialRating");
|
||||||
@ -1003,26 +840,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.ImageTypes.Length > 0)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to ImageTypes");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply studio filter
|
|
||||||
if (query.StudioIds.Length > 0)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to StudioIds");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply genre filter
|
|
||||||
if (query.GenreIds.Length > 0)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to GenreIds");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply person filter
|
// Apply person filter
|
||||||
if (query.ItemIdsFromPersonFilters != null)
|
if (query.ItemIdsFromPersonFilters != null)
|
||||||
{
|
{
|
||||||
@ -1042,12 +859,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.OfficialRatings.Length > 0)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to OfficialRatings");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.IsMissing.HasValue)
|
if (query.IsMissing.HasValue)
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to IsMissing");
|
Logger.Debug("Query requires post-filtering due to IsMissing");
|
||||||
@ -1066,7 +877,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UserViewBuilder.CollapseBoxSetItems(query, this, query.User))
|
if (UserViewBuilder.CollapseBoxSetItems(query, this, query.User, ConfigurationManager))
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to CollapseBoxSetItems");
|
Logger.Debug("Query requires post-filtering due to CollapseBoxSetItems");
|
||||||
return true;
|
return true;
|
||||||
@ -1102,15 +913,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ConfigurationManager.Configuration.SchemaVersion < 79)
|
|
||||||
{
|
|
||||||
if (query.ArtistNames.Length > 0)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to ArtistNames");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1183,7 +985,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
protected QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, InternalItemsQuery query)
|
protected QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
return UserViewBuilder.PostFilterAndSort(items, this, null, query, LibraryManager);
|
return UserViewBuilder.PostFilterAndSort(items, this, null, query, LibraryManager, ConfigurationManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
|
public virtual IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
|
||||||
@ -1601,72 +1403,61 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (this is Channel)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (SourceType != SourceType.Library)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user)
|
public override async Task FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user)
|
||||||
{
|
{
|
||||||
if (!SupportsUserDataFromChildren)
|
if (!SupportsUserDataFromChildren)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var recursiveItemCount = 0;
|
var unplayedQueryResult = await GetItems(new InternalItemsQuery(user)
|
||||||
var unplayed = 0;
|
|
||||||
|
|
||||||
double totalPercentPlayed = 0;
|
|
||||||
|
|
||||||
var itemsResult = GetItems(new InternalItemsQuery(user)
|
|
||||||
{
|
{
|
||||||
Recursive = true,
|
Recursive = true,
|
||||||
IsFolder = false,
|
IsFolder = false,
|
||||||
ExcludeLocationTypes = new[] { LocationType.Virtual },
|
IsVirtualItem = false,
|
||||||
EnableTotalRecordCount = false
|
EnableTotalRecordCount = true,
|
||||||
|
Limit = 0,
|
||||||
|
IsPlayed = false
|
||||||
|
|
||||||
}).Result;
|
}).ConfigureAwait(false);
|
||||||
|
|
||||||
var children = itemsResult.Items;
|
var allItemsQueryResult = await GetItems(new InternalItemsQuery(user)
|
||||||
|
|
||||||
// Loop through each recursive child
|
|
||||||
foreach (var child in children)
|
|
||||||
{
|
{
|
||||||
recursiveItemCount++;
|
Recursive = true,
|
||||||
|
IsFolder = false,
|
||||||
|
IsVirtualItem = false,
|
||||||
|
EnableTotalRecordCount = true,
|
||||||
|
Limit = 0
|
||||||
|
|
||||||
var isUnplayed = true;
|
}).ConfigureAwait(false);
|
||||||
|
|
||||||
var itemUserData = UserDataManager.GetUserData(user, child);
|
if (itemDto != null)
|
||||||
|
{
|
||||||
// Incrememt totalPercentPlayed
|
itemDto.RecursiveItemCount = allItemsQueryResult.TotalRecordCount;
|
||||||
if (itemUserData != null)
|
|
||||||
{
|
|
||||||
if (itemUserData.Played)
|
|
||||||
{
|
|
||||||
totalPercentPlayed += 100;
|
|
||||||
|
|
||||||
isUnplayed = false;
|
|
||||||
}
|
|
||||||
else if (itemUserData.PlaybackPositionTicks > 0 && child.RunTimeTicks.HasValue && child.RunTimeTicks.Value > 0)
|
|
||||||
{
|
|
||||||
double itemPercent = itemUserData.PlaybackPositionTicks;
|
|
||||||
itemPercent /= child.RunTimeTicks.Value;
|
|
||||||
totalPercentPlayed += itemPercent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isUnplayed)
|
|
||||||
{
|
|
||||||
unplayed++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dto.UnplayedItemCount = unplayed;
|
double recursiveItemCount = allItemsQueryResult.TotalRecordCount;
|
||||||
|
double unplayedCount = unplayedQueryResult.TotalRecordCount;
|
||||||
|
|
||||||
if (recursiveItemCount > 0)
|
if (recursiveItemCount > 0)
|
||||||
{
|
{
|
||||||
dto.PlayedPercentage = totalPercentPlayed / recursiveItemCount;
|
var unplayedPercentage = (unplayedCount / recursiveItemCount) * 100;
|
||||||
|
dto.PlayedPercentage = 100 - unplayedPercentage;
|
||||||
dto.Played = dto.PlayedPercentage.Value >= 100;
|
dto.Played = dto.PlayedPercentage.Value >= 100;
|
||||||
|
dto.UnplayedItemCount = unplayedQueryResult.TotalRecordCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ using System.Linq;
|
|||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
public class Game : BaseItem, IHasTrailers, IHasThemeMedia, IHasTags, IHasScreenshots, ISupportsPlaceHolders, IHasLookupInfo<GameInfo>
|
public class Game : BaseItem, IHasTrailers, IHasThemeMedia, IHasScreenshots, ISupportsPlaceHolders, IHasLookupInfo<GameInfo>
|
||||||
{
|
{
|
||||||
public List<Guid> ThemeSongIds { get; set; }
|
public List<Guid> ThemeSongIds { get; set; }
|
||||||
public List<Guid> ThemeVideoIds { get; set; }
|
public List<Guid> ThemeVideoIds { get; set; }
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
using MediaBrowser.Common.Extensions;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
@ -11,10 +12,18 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
var list = base.GetUserDataKeys();
|
var list = base.GetUserDataKeys();
|
||||||
|
|
||||||
list.Insert(0, "GameGenre-" + Name);
|
list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string PresentationUniqueKey
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return GetUserDataKeys()[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the folder containing the item.
|
/// Returns the folder containing the item.
|
||||||
/// If the item is a folder, it returns the folder itself
|
/// If the item is a folder, it returns the folder itself
|
||||||
|
@ -3,6 +3,7 @@ using MediaBrowser.Controller.Entities.Audio;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using MediaBrowser.Common.Extensions;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
@ -15,10 +16,18 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
var list = base.GetUserDataKeys();
|
var list = base.GetUserDataKeys();
|
||||||
|
|
||||||
list.Insert(0, "Genre-" + Name);
|
list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string PresentationUniqueKey
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return GetUserDataKeys()[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the folder containing the item.
|
/// Returns the folder containing the item.
|
||||||
/// If the item is a folder, it returns the folder itself
|
/// If the item is a folder, it returns the folder itself
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
@ -16,7 +17,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <param name="dto">The dto.</param>
|
/// <param name="dto">The dto.</param>
|
||||||
/// <param name="userData">The user data.</param>
|
/// <param name="userData">The user data.</param>
|
||||||
/// <param name="user">The user.</param>
|
/// <param name="user">The user.</param>
|
||||||
void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user);
|
Task FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user);
|
||||||
|
|
||||||
bool EnableRememberingTrackSelections { get; }
|
bool EnableRememberingTrackSelections { get; }
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
public User User { get; set; }
|
public User User { get; set; }
|
||||||
|
|
||||||
|
public BaseItem SimilarTo { get; set; }
|
||||||
|
|
||||||
public bool? IsFolder { get; set; }
|
public bool? IsFolder { get; set; }
|
||||||
public bool? IsFavorite { get; set; }
|
public bool? IsFavorite { get; set; }
|
||||||
public bool? IsFavoriteOrLiked { get; set; }
|
public bool? IsFavoriteOrLiked { get; set; }
|
||||||
@ -33,6 +35,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
public string[] ExcludeTags { get; set; }
|
public string[] ExcludeTags { get; set; }
|
||||||
public string[] ExcludeInheritedTags { get; set; }
|
public string[] ExcludeInheritedTags { get; set; }
|
||||||
public string[] Genres { get; set; }
|
public string[] Genres { get; set; }
|
||||||
|
public string[] Keywords { get; set; }
|
||||||
|
|
||||||
public bool? IsMissing { get; set; }
|
public bool? IsMissing { get; set; }
|
||||||
public bool? IsUnaired { get; set; }
|
public bool? IsUnaired { get; set; }
|
||||||
@ -43,6 +46,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
public string NameStartsWith { get; set; }
|
public string NameStartsWith { get; set; }
|
||||||
public string NameLessThan { get; set; }
|
public string NameLessThan { get; set; }
|
||||||
public string NameContains { get; set; }
|
public string NameContains { get; set; }
|
||||||
|
public string MinSortName { get; set; }
|
||||||
|
|
||||||
public string PresentationUniqueKey { get; set; }
|
public string PresentationUniqueKey { get; set; }
|
||||||
public string Path { get; set; }
|
public string Path { get; set; }
|
||||||
@ -52,6 +56,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
public string Person { get; set; }
|
public string Person { get; set; }
|
||||||
public string[] PersonIds { get; set; }
|
public string[] PersonIds { get; set; }
|
||||||
public string[] ItemIds { get; set; }
|
public string[] ItemIds { get; set; }
|
||||||
|
public string[] ExcludeItemIds { get; set; }
|
||||||
public string AdjacentTo { get; set; }
|
public string AdjacentTo { get; set; }
|
||||||
public string[] PersonTypes { get; set; }
|
public string[] PersonTypes { get; set; }
|
||||||
|
|
||||||
@ -60,7 +65,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
public bool? IsInBoxSet { get; set; }
|
public bool? IsInBoxSet { get; set; }
|
||||||
public bool? IsLocked { get; set; }
|
public bool? IsLocked { get; set; }
|
||||||
public bool? IsPlaceHolder { get; set; }
|
public bool? IsPlaceHolder { get; set; }
|
||||||
public bool? IsYearMismatched { get; set; }
|
|
||||||
|
|
||||||
public bool? HasImdbId { get; set; }
|
public bool? HasImdbId { get; set; }
|
||||||
public bool? HasOverview { get; set; }
|
public bool? HasOverview { get; set; }
|
||||||
@ -107,6 +111,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
internal List<Guid> ItemIdsFromPersonFilters { get; set; }
|
internal List<Guid> ItemIdsFromPersonFilters { get; set; }
|
||||||
public int? ParentIndexNumber { get; set; }
|
public int? ParentIndexNumber { get; set; }
|
||||||
|
public int? ParentIndexNumberNotEquals { get; set; }
|
||||||
public int? IndexNumber { get; set; }
|
public int? IndexNumber { get; set; }
|
||||||
public int? MinParentalRating { get; set; }
|
public int? MinParentalRating { get; set; }
|
||||||
public int? MaxParentalRating { get; set; }
|
public int? MaxParentalRating { get; set; }
|
||||||
@ -114,6 +119,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
public bool? IsCurrentSchema { get; set; }
|
public bool? IsCurrentSchema { get; set; }
|
||||||
public bool? HasDeadParentId { get; set; }
|
public bool? HasDeadParentId { get; set; }
|
||||||
public bool? IsOffline { get; set; }
|
public bool? IsOffline { get; set; }
|
||||||
|
public bool? IsVirtualItem { get; set; }
|
||||||
|
|
||||||
public Guid? ParentId { get; set; }
|
public Guid? ParentId { get; set; }
|
||||||
public string[] AncestorIds { get; set; }
|
public string[] AncestorIds { get; set; }
|
||||||
@ -137,6 +143,8 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
public bool GroupByPresentationUniqueKey { get; set; }
|
public bool GroupByPresentationUniqueKey { get; set; }
|
||||||
public bool EnableTotalRecordCount { get; set; }
|
public bool EnableTotalRecordCount { get; set; }
|
||||||
public bool ForceDirect { get; set; }
|
public bool ForceDirect { get; set; }
|
||||||
|
public Dictionary<string, string> ExcludeProviderIds { get; set; }
|
||||||
|
public bool EnableGroupByMetadataKey { get; set; }
|
||||||
|
|
||||||
public InternalItemsQuery()
|
public InternalItemsQuery()
|
||||||
{
|
{
|
||||||
@ -145,12 +153,14 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
AlbumNames = new string[] { };
|
AlbumNames = new string[] { };
|
||||||
ArtistNames = new string[] { };
|
ArtistNames = new string[] { };
|
||||||
|
ExcludeProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
BlockUnratedItems = new UnratedItem[] { };
|
BlockUnratedItems = new UnratedItem[] { };
|
||||||
Tags = new string[] { };
|
Tags = new string[] { };
|
||||||
OfficialRatings = new string[] { };
|
OfficialRatings = new string[] { };
|
||||||
SortBy = new string[] { };
|
SortBy = new string[] { };
|
||||||
MediaTypes = new string[] { };
|
MediaTypes = new string[] { };
|
||||||
|
Keywords = new string[] { };
|
||||||
IncludeItemTypes = new string[] { };
|
IncludeItemTypes = new string[] { };
|
||||||
ExcludeItemTypes = new string[] { };
|
ExcludeItemTypes = new string[] { };
|
||||||
Genres = new string[] { };
|
Genres = new string[] { };
|
||||||
@ -164,6 +174,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
PersonIds = new string[] { };
|
PersonIds = new string[] { };
|
||||||
ChannelIds = new string[] { };
|
ChannelIds = new string[] { };
|
||||||
ItemIds = new string[] { };
|
ItemIds = new string[] { };
|
||||||
|
ExcludeItemIds = new string[] { };
|
||||||
AncestorIds = new string[] { };
|
AncestorIds = new string[] { };
|
||||||
TopParentIds = new string[] { };
|
TopParentIds = new string[] { };
|
||||||
ExcludeTags = new string[] { };
|
ExcludeTags = new string[] { };
|
||||||
|
@ -1,21 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
public interface IHasKeywords
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the keywords.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The keywords.</value>
|
|
||||||
List<string> Keywords { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class KeywordExtensions
|
public static class KeywordExtensions
|
||||||
{
|
{
|
||||||
public static void AddKeyword(this IHasKeywords item, string name)
|
public static void AddKeyword(this BaseItem item, string name)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(name))
|
if (string.IsNullOrWhiteSpace(name))
|
||||||
{
|
{
|
@ -15,7 +15,7 @@ namespace MediaBrowser.Controller.Entities.Movies
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class BoxSet
|
/// Class BoxSet
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class BoxSet : Folder, IHasTrailers, IHasKeywords, IHasDisplayOrder, IHasLookupInfo<BoxSetInfo>, IHasShares
|
public class BoxSet : Folder, IHasTrailers, IHasDisplayOrder, IHasLookupInfo<BoxSetInfo>, IHasShares
|
||||||
{
|
{
|
||||||
public List<Share> Shares { get; set; }
|
public List<Share> Shares { get; set; }
|
||||||
|
|
||||||
@ -26,7 +26,6 @@ namespace MediaBrowser.Controller.Entities.Movies
|
|||||||
RemoteTrailerIds = new List<Guid>();
|
RemoteTrailerIds = new List<Guid>();
|
||||||
|
|
||||||
DisplayOrder = ItemSortBy.PremiereDate;
|
DisplayOrder = ItemSortBy.PremiereDate;
|
||||||
Keywords = new List<string>();
|
|
||||||
Shares = new List<Share>();
|
Shares = new List<Share>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,12 +46,6 @@ namespace MediaBrowser.Controller.Entities.Movies
|
|||||||
/// <value>The remote trailers.</value>
|
/// <value>The remote trailers.</value>
|
||||||
public List<MediaUrl> RemoteTrailers { get; set; }
|
public List<MediaUrl> RemoteTrailers { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the tags.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The tags.</value>
|
|
||||||
public List<string> Keywords { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the display order.
|
/// Gets or sets the display order.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -8,13 +8,14 @@ using System.Runtime.Serialization;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CommonIO;
|
using CommonIO;
|
||||||
|
using MediaBrowser.Model.Providers;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities.Movies
|
namespace MediaBrowser.Controller.Entities.Movies
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class Movie
|
/// Class Movie
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Movie : Video, IHasCriticRating, IHasSpecialFeatures, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTrailers, IHasThemeMedia, IHasTaglines, IHasAwards, IHasMetascore, IHasLookupInfo<MovieInfo>, ISupportsBoxSetGrouping, IHasOriginalTitle
|
public class Movie : Video, IHasCriticRating, IHasSpecialFeatures, IHasProductionLocations, IHasBudget, IHasTrailers, IHasThemeMedia, IHasTaglines, IHasAwards, IHasMetascore, IHasLookupInfo<MovieInfo>, ISupportsBoxSetGrouping, IHasOriginalTitle
|
||||||
{
|
{
|
||||||
public List<Guid> SpecialFeatureIds { get; set; }
|
public List<Guid> SpecialFeatureIds { get; set; }
|
||||||
|
|
||||||
@ -31,7 +32,6 @@ namespace MediaBrowser.Controller.Entities.Movies
|
|||||||
ThemeSongIds = new List<Guid>();
|
ThemeSongIds = new List<Guid>();
|
||||||
ThemeVideoIds = new List<Guid>();
|
ThemeVideoIds = new List<Guid>();
|
||||||
Taglines = new List<string>();
|
Taglines = new List<string>();
|
||||||
Keywords = new List<string>();
|
|
||||||
ProductionLocations = new List<string>();
|
ProductionLocations = new List<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +41,6 @@ namespace MediaBrowser.Controller.Entities.Movies
|
|||||||
|
|
||||||
public List<Guid> LocalTrailerIds { get; set; }
|
public List<Guid> LocalTrailerIds { get; set; }
|
||||||
public List<Guid> RemoteTrailerIds { get; set; }
|
public List<Guid> RemoteTrailerIds { get; set; }
|
||||||
public List<string> Keywords { get; set; }
|
|
||||||
|
|
||||||
public List<MediaUrl> RemoteTrailers { get; set; }
|
public List<MediaUrl> RemoteTrailers { get; set; }
|
||||||
|
|
||||||
@ -163,5 +162,22 @@ namespace MediaBrowser.Controller.Entities.Movies
|
|||||||
|
|
||||||
return hasChanges;
|
return hasChanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override List<ExternalUrl> GetRelatedUrls()
|
||||||
|
{
|
||||||
|
var list = base.GetRelatedUrls();
|
||||||
|
|
||||||
|
var imdbId = this.GetProviderId(MetadataProviders.Imdb);
|
||||||
|
if (!string.IsNullOrWhiteSpace(imdbId))
|
||||||
|
{
|
||||||
|
list.Add(new ExternalUrl
|
||||||
|
{
|
||||||
|
Name = "Trakt",
|
||||||
|
Url = string.Format("https://trakt.tv/movies/{0}", imdbId)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
@ -22,10 +23,18 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
var list = base.GetUserDataKeys();
|
var list = base.GetUserDataKeys();
|
||||||
|
|
||||||
list.Insert(0, "Person-" + Name);
|
list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string PresentationUniqueKey
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return GetUserDataKeys()[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public PersonLookupInfo GetLookupInfo()
|
public PersonLookupInfo GetLookupInfo()
|
||||||
{
|
{
|
||||||
return GetItemLookupInfo<PersonLookupInfo>();
|
return GetItemLookupInfo<PersonLookupInfo>();
|
||||||
|
@ -5,7 +5,7 @@ using System.Runtime.Serialization;
|
|||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
public class Photo : BaseItem, IHasTags, IHasTaglines
|
public class Photo : BaseItem, IHasTaglines
|
||||||
{
|
{
|
||||||
public List<string> Taglines { get; set; }
|
public List<string> Taglines { get; set; }
|
||||||
|
|
||||||
|
@ -2,22 +2,31 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
using MediaBrowser.Common.Extensions;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class Studio
|
/// Class Studio
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Studio : BaseItem, IItemByName, IHasTags
|
public class Studio : BaseItem, IItemByName
|
||||||
{
|
{
|
||||||
public override List<string> GetUserDataKeys()
|
public override List<string> GetUserDataKeys()
|
||||||
{
|
{
|
||||||
var list = base.GetUserDataKeys();
|
var list = base.GetUserDataKeys();
|
||||||
|
|
||||||
list.Insert(0, "Studio-" + Name);
|
list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string PresentationUniqueKey
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return GetUserDataKeys()[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the folder containing the item.
|
/// Returns the folder containing the item.
|
||||||
/// If the item is a folder, it returns the folder itself
|
/// If the item is a folder, it returns the folder itself
|
||||||
|
@ -11,13 +11,25 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class Episode
|
/// Class Episode
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Episode : Video, IHasLookupInfo<EpisodeInfo>, IHasSeries
|
public class Episode : Video, IHasTrailers, IHasLookupInfo<EpisodeInfo>, IHasSeries
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Gets the season in which it aired.
|
public Episode()
|
||||||
/// </summary>
|
{
|
||||||
/// <value>The aired season.</value>
|
RemoteTrailers = new List<MediaUrl>();
|
||||||
public int? AirsBeforeSeasonNumber { get; set; }
|
LocalTrailerIds = new List<Guid>();
|
||||||
|
RemoteTrailerIds = new List<Guid>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Guid> LocalTrailerIds { get; set; }
|
||||||
|
public List<Guid> RemoteTrailerIds { get; set; }
|
||||||
|
public List<MediaUrl> RemoteTrailers { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the season in which it aired.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The aired season.</value>
|
||||||
|
public int? AirsBeforeSeasonNumber { get; set; }
|
||||||
public int? AirsAfterSeasonNumber { get; set; }
|
public int? AirsAfterSeasonNumber { get; set; }
|
||||||
public int? AirsBeforeEpisodeNumber { get; set; }
|
public int? AirsBeforeEpisodeNumber { get; set; }
|
||||||
|
|
||||||
@ -96,7 +108,13 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
var series = Series;
|
var series = Series;
|
||||||
if (series != null && ParentIndexNumber.HasValue && IndexNumber.HasValue)
|
if (series != null && ParentIndexNumber.HasValue && IndexNumber.HasValue)
|
||||||
{
|
{
|
||||||
list.InsertRange(0, series.GetUserDataKeys().Select(i => i + ParentIndexNumber.Value.ToString("000") + IndexNumber.Value.ToString("000")));
|
var seriesUserDataKeys = series.GetUserDataKeys();
|
||||||
|
var take = seriesUserDataKeys.Count;
|
||||||
|
if (seriesUserDataKeys.Count > 1)
|
||||||
|
{
|
||||||
|
take--;
|
||||||
|
}
|
||||||
|
list.InsertRange(0, seriesUserDataKeys.Take(take).Select(i => i + ParentIndexNumber.Value.ToString("000") + IndexNumber.Value.ToString("000")));
|
||||||
}
|
}
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
|
@ -75,6 +75,11 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override int GetChildCount(User user)
|
||||||
|
{
|
||||||
|
return GetChildren(user, true).Count();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This Episode's Series Instance
|
/// This Episode's Series Instance
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -128,39 +133,16 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name;
|
return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool RequiresRefresh()
|
|
||||||
{
|
|
||||||
var result = base.RequiresRefresh();
|
|
||||||
|
|
||||||
if (!result)
|
|
||||||
{
|
|
||||||
if (!IsVirtualItem.HasValue)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
|
||||||
public bool? IsVirtualItem { get; set; }
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsMissingSeason
|
public bool IsMissingSeason
|
||||||
{
|
{
|
||||||
get { return (IsVirtualItem ?? DetectIsVirtualItem()) && !IsUnaired; }
|
get { return (IsVirtualItem) && !IsUnaired; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsVirtualUnaired
|
public bool IsVirtualUnaired
|
||||||
{
|
{
|
||||||
get { return (IsVirtualItem ?? DetectIsVirtualItem()) && IsUnaired; }
|
get { return (IsVirtualItem) && IsUnaired; }
|
||||||
}
|
|
||||||
|
|
||||||
private bool DetectIsVirtualItem()
|
|
||||||
{
|
|
||||||
return LocationType == LocationType.Virtual && GetEpisodes().All(i => i.LocationType == LocationType.Virtual);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
@ -196,52 +178,17 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
{
|
{
|
||||||
var config = user.Configuration;
|
var config = user.Configuration;
|
||||||
|
|
||||||
return GetEpisodes(user, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
|
return GetEpisodes(Series, user, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Episode> GetEpisodes(User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
|
public IEnumerable<Episode> GetEpisodes(Series series, User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
|
||||||
{
|
{
|
||||||
var series = Series;
|
return GetEpisodes(series, user, includeMissingEpisodes, includeVirtualUnairedEpisodes, null);
|
||||||
|
}
|
||||||
|
|
||||||
if (IndexNumber.HasValue && series != null)
|
public IEnumerable<Episode> GetEpisodes(Series series, User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes, IEnumerable<Episode> allSeriesEpisodes)
|
||||||
{
|
{
|
||||||
return series.GetEpisodes(user, this, includeMissingEpisodes, includeVirtualUnairedEpisodes);
|
return series.GetEpisodes(user, this, includeMissingEpisodes, includeVirtualUnairedEpisodes, allSeriesEpisodes);
|
||||||
}
|
|
||||||
|
|
||||||
var episodes = GetRecursiveChildren(user)
|
|
||||||
.OfType<Episode>();
|
|
||||||
|
|
||||||
if (series != null && series.ContainsEpisodesWithoutSeasonFolders)
|
|
||||||
{
|
|
||||||
var seasonNumber = IndexNumber;
|
|
||||||
var list = episodes.ToList();
|
|
||||||
|
|
||||||
if (seasonNumber.HasValue)
|
|
||||||
{
|
|
||||||
list.AddRange(series.GetRecursiveChildren(user).OfType<Episode>()
|
|
||||||
.Where(i => i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == seasonNumber.Value));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
list.AddRange(series.GetRecursiveChildren(user).OfType<Episode>()
|
|
||||||
.Where(i => !i.ParentIndexNumber.HasValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
episodes = list.DistinctBy(i => i.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!includeMissingEpisodes)
|
|
||||||
{
|
|
||||||
episodes = episodes.Where(i => !i.IsMissingEpisode);
|
|
||||||
}
|
|
||||||
if (!includeVirtualUnairedEpisodes)
|
|
||||||
{
|
|
||||||
episodes = episodes.Where(i => !i.IsVirtualUnaired);
|
|
||||||
}
|
|
||||||
|
|
||||||
return LibraryManager
|
|
||||||
.Sort(episodes, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending)
|
|
||||||
.Cast<Episode>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Episode> GetEpisodes()
|
public IEnumerable<Episode> GetEpisodes()
|
||||||
|
@ -9,6 +9,7 @@ using System.Linq;
|
|||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Model.Providers;
|
||||||
using MoreLinq;
|
using MoreLinq;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities.TV
|
namespace MediaBrowser.Controller.Entities.TV
|
||||||
@ -30,7 +31,6 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
RemoteTrailers = new List<MediaUrl>();
|
RemoteTrailers = new List<MediaUrl>();
|
||||||
LocalTrailerIds = new List<Guid>();
|
LocalTrailerIds = new List<Guid>();
|
||||||
RemoteTrailerIds = new List<Guid>();
|
RemoteTrailerIds = new List<Guid>();
|
||||||
DisplaySpecialsWithSeasons = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
@ -57,8 +57,6 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DisplaySpecialsWithSeasons { get; set; }
|
|
||||||
|
|
||||||
public List<Guid> LocalTrailerIds { get; set; }
|
public List<Guid> LocalTrailerIds { get; set; }
|
||||||
public List<Guid> RemoteTrailerIds { get; set; }
|
public List<Guid> RemoteTrailerIds { get; set; }
|
||||||
|
|
||||||
@ -94,10 +92,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return GetRecursiveChildren(i => i is Episode)
|
return DateLastMediaAdded ?? DateTime.MinValue;
|
||||||
.Select(i => i.DateCreated)
|
|
||||||
.OrderByDescending(i => i)
|
|
||||||
.FirstOrDefault();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,14 +101,30 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (EnablePooling())
|
var userdatakeys = GetUserDataKeys();
|
||||||
|
|
||||||
|
if (userdatakeys.Count > 1)
|
||||||
{
|
{
|
||||||
return GetUserDataKeys().First();
|
return userdatakeys[0];
|
||||||
}
|
}
|
||||||
return base.PresentationUniqueKey;
|
return base.PresentationUniqueKey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override int GetChildCount(User user)
|
||||||
|
{
|
||||||
|
var result = LibraryManager.GetItemsResult(new InternalItemsQuery(user)
|
||||||
|
{
|
||||||
|
AncestorWithPresentationUniqueKey = PresentationUniqueKey,
|
||||||
|
IncludeItemTypes = new[] { typeof(Season).Name },
|
||||||
|
SortBy = new[] { ItemSortBy.SortName },
|
||||||
|
IsVirtualItem = false,
|
||||||
|
Limit = 0
|
||||||
|
});
|
||||||
|
|
||||||
|
return result.TotalRecordCount;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the user data key.
|
/// Gets the user data key.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -182,27 +193,32 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
|
|
||||||
protected override Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery query)
|
protected override Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
|
if (query.User == null)
|
||||||
|
{
|
||||||
|
return base.GetItemsInternal(query);
|
||||||
|
}
|
||||||
|
|
||||||
var user = query.User;
|
var user = query.User;
|
||||||
|
|
||||||
|
if (query.Recursive)
|
||||||
|
{
|
||||||
|
query.AncestorWithPresentationUniqueKey = PresentationUniqueKey;
|
||||||
|
if (query.SortBy.Length == 0)
|
||||||
|
{
|
||||||
|
query.SortBy = new[] { ItemSortBy.SortName };
|
||||||
|
}
|
||||||
|
if (query.IncludeItemTypes.Length == 0)
|
||||||
|
{
|
||||||
|
query.IncludeItemTypes = new[] { typeof(Episode).Name, typeof(Season).Name };
|
||||||
|
}
|
||||||
|
query.IsVirtualItem = false;
|
||||||
|
return Task.FromResult(LibraryManager.GetItemsResult(query));
|
||||||
|
}
|
||||||
|
|
||||||
Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
|
Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
|
||||||
|
|
||||||
IEnumerable<BaseItem> items;
|
var items = GetSeasons(user).Where(filter);
|
||||||
|
|
||||||
if (query.User == null)
|
|
||||||
{
|
|
||||||
items = query.Recursive
|
|
||||||
? GetRecursiveChildren(filter)
|
|
||||||
: Children.Where(filter);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
items = query.Recursive
|
|
||||||
? GetSeasons(user).Cast<BaseItem>().Concat(GetEpisodes(user)).Where(filter)
|
|
||||||
: GetSeasons(user).Where(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = PostFilterAndSort(items, query);
|
var result = PostFilterAndSort(items, query);
|
||||||
|
|
||||||
return Task.FromResult(result);
|
return Task.FromResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,33 +226,13 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
{
|
{
|
||||||
IEnumerable<Season> seasons;
|
IEnumerable<Season> seasons;
|
||||||
|
|
||||||
if (EnablePooling())
|
seasons = LibraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
var seriesIds = LibraryManager.GetItemIds(new InternalItemsQuery(user)
|
AncestorWithPresentationUniqueKey = PresentationUniqueKey,
|
||||||
{
|
IncludeItemTypes = new[] { typeof(Season).Name },
|
||||||
PresentationUniqueKey = PresentationUniqueKey,
|
SortBy = new[] { ItemSortBy.SortName }
|
||||||
IncludeItemTypes = new[] { typeof(Series).Name }
|
|
||||||
});
|
|
||||||
|
|
||||||
if (seriesIds.Count > 1)
|
}).Cast<Season>();
|
||||||
{
|
|
||||||
seasons = LibraryManager.GetItemList(new InternalItemsQuery(user)
|
|
||||||
{
|
|
||||||
AncestorIds = seriesIds.Select(i => i.ToString("N")).ToArray(),
|
|
||||||
IncludeItemTypes = new[] { typeof(Season).Name },
|
|
||||||
SortBy = new[] { ItemSortBy.SortName }
|
|
||||||
|
|
||||||
}).Cast<Season>();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
seasons = LibraryManager.Sort(base.GetChildren(user, true), user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).OfType<Season>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
seasons = LibraryManager.Sort(base.GetChildren(user, true), user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).OfType<Season>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!includeMissingSeasons)
|
if (!includeMissingSeasons)
|
||||||
{
|
{
|
||||||
@ -259,8 +255,18 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
|
|
||||||
public IEnumerable<Episode> GetEpisodes(User user, bool includeMissing, bool includeVirtualUnaired)
|
public IEnumerable<Episode> GetEpisodes(User user, bool includeMissing, bool includeVirtualUnaired)
|
||||||
{
|
{
|
||||||
var allEpisodes = GetSeasons(user, true, true)
|
var allItems = LibraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
.SelectMany(i => i.GetEpisodes(user, includeMissing, includeVirtualUnaired))
|
{
|
||||||
|
AncestorWithPresentationUniqueKey = PresentationUniqueKey,
|
||||||
|
IncludeItemTypes = new[] { typeof(Episode).Name, typeof(Season).Name },
|
||||||
|
SortBy = new[] { ItemSortBy.SortName }
|
||||||
|
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
var allSeriesEpisodes = allItems.OfType<Episode>().ToList();
|
||||||
|
|
||||||
|
var allEpisodes = allItems.OfType<Season>()
|
||||||
|
.SelectMany(i => i.GetEpisodes(this, user, includeMissing, includeVirtualUnaired, allSeriesEpisodes))
|
||||||
.Reverse()
|
.Reverse()
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
@ -283,9 +289,6 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
var totalItems = seasons.Count + otherItems.Count;
|
var totalItems = seasons.Count + otherItems.Count;
|
||||||
var numComplete = 0;
|
var numComplete = 0;
|
||||||
|
|
||||||
refreshOptions = new MetadataRefreshOptions(refreshOptions);
|
|
||||||
refreshOptions.IsPostRecursiveRefresh = true;
|
|
||||||
|
|
||||||
// Refresh current item
|
// Refresh current item
|
||||||
await RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
|
await RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
@ -315,7 +318,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
&& refreshOptions.MetadataRefreshMode != MetadataRefreshMode.FullRefresh
|
&& refreshOptions.MetadataRefreshMode != MetadataRefreshMode.FullRefresh
|
||||||
&& !refreshOptions.ReplaceAllMetadata
|
&& !refreshOptions.ReplaceAllMetadata
|
||||||
&& episode.IsMissingEpisode
|
&& episode.IsMissingEpisode
|
||||||
&& episode.LocationType == Model.Entities.LocationType.Virtual
|
&& episode.LocationType == LocationType.Virtual
|
||||||
&& episode.PremiereDate.HasValue
|
&& episode.PremiereDate.HasValue
|
||||||
&& (DateTime.UtcNow - episode.PremiereDate.Value).TotalDays > 30)
|
&& (DateTime.UtcNow - episode.PremiereDate.Value).TotalDays > 30)
|
||||||
{
|
{
|
||||||
@ -333,6 +336,8 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
progress.Report(percent * 100);
|
progress.Report(percent * 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
refreshOptions = new MetadataRefreshOptions(refreshOptions);
|
||||||
|
refreshOptions.IsPostRecursiveRefresh = true;
|
||||||
await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false);
|
await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
progress.Report(100);
|
progress.Report(100);
|
||||||
@ -345,50 +350,32 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
return GetEpisodes(user, season, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
|
return GetEpisodes(user, season, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool EnablePooling()
|
private IEnumerable<Episode> GetAllEpisodes(User user)
|
||||||
{
|
{
|
||||||
return false;
|
return LibraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
|
{
|
||||||
|
AncestorWithPresentationUniqueKey = PresentationUniqueKey,
|
||||||
|
IncludeItemTypes = new[] { typeof(Episode).Name },
|
||||||
|
SortBy = new[] { ItemSortBy.SortName }
|
||||||
|
|
||||||
|
}).Cast<Episode>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Episode> GetEpisodes(User user, Season parentSeason, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
|
public IEnumerable<Episode> GetEpisodes(User user, Season parentSeason, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
|
||||||
{
|
{
|
||||||
IEnumerable<Episode> episodes;
|
IEnumerable<Episode> episodes = GetAllEpisodes(user);
|
||||||
|
|
||||||
if (EnablePooling())
|
return GetEpisodes(user, parentSeason, includeMissingEpisodes, includeVirtualUnairedEpisodes, episodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Episode> GetEpisodes(User user, Season parentSeason, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes, IEnumerable<Episode> allSeriesEpisodes)
|
||||||
|
{
|
||||||
|
if (allSeriesEpisodes == null)
|
||||||
{
|
{
|
||||||
var seriesIds = LibraryManager.GetItemIds(new InternalItemsQuery(user)
|
return GetEpisodes(user, parentSeason, includeMissingEpisodes, includeVirtualUnairedEpisodes);
|
||||||
{
|
|
||||||
PresentationUniqueKey = PresentationUniqueKey,
|
|
||||||
IncludeItemTypes = new[] { typeof(Series).Name }
|
|
||||||
});
|
|
||||||
|
|
||||||
if (seriesIds.Count > 1)
|
|
||||||
{
|
|
||||||
episodes = LibraryManager.GetItemList(new InternalItemsQuery(user)
|
|
||||||
{
|
|
||||||
AncestorIds = seriesIds.Select(i => i.ToString("N")).ToArray(),
|
|
||||||
IncludeItemTypes = new[] { typeof(Episode).Name },
|
|
||||||
SortBy = new[] { ItemSortBy.SortName }
|
|
||||||
|
|
||||||
}).Cast<Episode>();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
episodes = GetRecursiveChildren(user, new InternalItemsQuery(user)
|
|
||||||
{
|
|
||||||
IncludeItemTypes = new[] { typeof(Episode).Name }
|
|
||||||
}).Cast<Episode>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
episodes = GetRecursiveChildren(user, new InternalItemsQuery(user)
|
|
||||||
{
|
|
||||||
IncludeItemTypes = new[] { typeof(Episode).Name }
|
|
||||||
}).Cast<Episode>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
episodes = FilterEpisodesBySeason(episodes, parentSeason, DisplaySpecialsWithSeasons);
|
var episodes = FilterEpisodesBySeason(allSeriesEpisodes, parentSeason, ConfigurationManager.Configuration.DisplaySpecialsWithinSeasons);
|
||||||
|
|
||||||
if (!includeMissingEpisodes)
|
if (!includeMissingEpisodes)
|
||||||
{
|
{
|
||||||
@ -436,38 +423,31 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
public static IEnumerable<Episode> FilterEpisodesBySeason(IEnumerable<Episode> episodes, Season parentSeason, bool includeSpecials)
|
public static IEnumerable<Episode> FilterEpisodesBySeason(IEnumerable<Episode> episodes, Season parentSeason, bool includeSpecials)
|
||||||
{
|
{
|
||||||
var seasonNumber = parentSeason.IndexNumber;
|
var seasonNumber = parentSeason.IndexNumber;
|
||||||
if (!includeSpecials || (seasonNumber.HasValue && seasonNumber.Value == 0))
|
var seasonPresentationKey = parentSeason.PresentationUniqueKey;
|
||||||
|
|
||||||
|
var supportSpecialsInSeason = includeSpecials && seasonNumber.HasValue && seasonNumber.Value != 0;
|
||||||
|
|
||||||
|
return episodes.Where(episode =>
|
||||||
{
|
{
|
||||||
var seasonPresentationKey = parentSeason.PresentationUniqueKey;
|
var currentSeasonNumber = supportSpecialsInSeason ? episode.AiredSeasonNumber : episode.ParentIndexNumber;
|
||||||
|
if (currentSeasonNumber.HasValue && seasonNumber.HasValue && currentSeasonNumber.Value == seasonNumber.Value)
|
||||||
return episodes.Where(i =>
|
|
||||||
{
|
{
|
||||||
if ((i.ParentIndexNumber ?? -1) == seasonNumber)
|
return true;
|
||||||
{
|
}
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var season = i.Season;
|
if (!currentSeasonNumber.HasValue && !seasonNumber.HasValue && parentSeason.LocationType == LocationType.Virtual)
|
||||||
return season != null && string.Equals(season.PresentationUniqueKey, seasonPresentationKey, StringComparison.OrdinalIgnoreCase);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var seasonPresentationKey = parentSeason.PresentationUniqueKey;
|
|
||||||
|
|
||||||
return episodes.Where(episode =>
|
|
||||||
{
|
{
|
||||||
var currentSeasonNumber = episode.AiredSeasonNumber;
|
return true;
|
||||||
|
}
|
||||||
if (currentSeasonNumber.HasValue && seasonNumber.HasValue && currentSeasonNumber.Value == seasonNumber.Value)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!episode.ParentIndexNumber.HasValue)
|
||||||
|
{
|
||||||
var season = episode.Season;
|
var season = episode.Season;
|
||||||
return season != null && string.Equals(season.PresentationUniqueKey, seasonPresentationKey, StringComparison.OrdinalIgnoreCase);
|
return season != null && string.Equals(season.PresentationUniqueKey, seasonPresentationKey, StringComparison.OrdinalIgnoreCase);
|
||||||
});
|
}
|
||||||
}
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool GetBlockUnratedValue(UserPolicy config)
|
protected override bool GetBlockUnratedValue(UserPolicy config)
|
||||||
@ -508,5 +488,22 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
|
|
||||||
return hasChanges;
|
return hasChanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override List<ExternalUrl> GetRelatedUrls()
|
||||||
|
{
|
||||||
|
var list = base.GetRelatedUrls();
|
||||||
|
|
||||||
|
var imdbId = this.GetProviderId(MetadataProviders.Imdb);
|
||||||
|
if (!string.IsNullOrWhiteSpace(imdbId))
|
||||||
|
{
|
||||||
|
list.Add(new ExternalUrl
|
||||||
|
{
|
||||||
|
Name = "Trakt",
|
||||||
|
Url = string.Format("https://trakt.tv/shows/{0}", imdbId)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Interface IHasTags
|
|
||||||
/// </summary>
|
|
||||||
public interface IHasTags
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the tags.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The tags.</value>
|
|
||||||
List<string> Tags { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class TagExtensions
|
public static class TagExtensions
|
||||||
{
|
{
|
||||||
public static void AddTag(this IHasTags item, string name)
|
public static void AddTag(this BaseItem item, string name)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(name))
|
if (string.IsNullOrWhiteSpace(name))
|
||||||
{
|
{
|
@ -5,13 +5,14 @@ using System.Collections.Generic;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
using MediaBrowser.Controller.Entities.Movies;
|
using MediaBrowser.Controller.Entities.Movies;
|
||||||
|
using MediaBrowser.Model.Providers;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class Trailer
|
/// Class Trailer
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Trailer : Video, IHasCriticRating, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTaglines, IHasMetascore, IHasOriginalTitle, IHasLookupInfo<TrailerInfo>
|
public class Trailer : Video, IHasCriticRating, IHasProductionLocations, IHasBudget, IHasTaglines, IHasMetascore, IHasOriginalTitle, IHasLookupInfo<TrailerInfo>
|
||||||
{
|
{
|
||||||
public List<string> ProductionLocations { get; set; }
|
public List<string> ProductionLocations { get; set; }
|
||||||
|
|
||||||
@ -30,8 +31,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
public List<MediaUrl> RemoteTrailers { get; set; }
|
public List<MediaUrl> RemoteTrailers { get; set; }
|
||||||
|
|
||||||
public List<string> Keywords { get; set; }
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsLocalTrailer
|
public bool IsLocalTrailer
|
||||||
{
|
{
|
||||||
@ -110,5 +109,22 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
return hasChanges;
|
return hasChanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override List<ExternalUrl> GetRelatedUrls()
|
||||||
|
{
|
||||||
|
var list = base.GetRelatedUrls();
|
||||||
|
|
||||||
|
var imdbId = this.GetProviderId(MetadataProviders.Imdb);
|
||||||
|
if (!string.IsNullOrWhiteSpace(imdbId))
|
||||||
|
{
|
||||||
|
list.Add(new ExternalUrl
|
||||||
|
{
|
||||||
|
Name = "Trakt",
|
||||||
|
Url = string.Format("https://trakt.tv/movies/{0}", imdbId)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return PostFilterAndSort(result.Where(filter), query);
|
return PostFilterAndSort(result.Where(filter), query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override int GetChildCount(User user)
|
||||||
|
{
|
||||||
|
return GetChildren(user, true).Count();
|
||||||
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
protected override bool SupportsShortcutChildren
|
protected override bool SupportsShortcutChildren
|
||||||
{
|
{
|
||||||
|
@ -45,6 +45,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override int GetChildCount(User user)
|
||||||
|
{
|
||||||
|
return GetChildren(user, true).Count();
|
||||||
|
}
|
||||||
|
|
||||||
protected override Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery query)
|
protected override Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
var parent = this as Folder;
|
var parent = this as Folder;
|
||||||
@ -58,7 +63,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
parent = LibraryManager.GetItemById(ParentId) as Folder ?? parent;
|
parent = LibraryManager.GetItemById(ParentId) as Folder ?? parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new UserViewBuilder(UserViewManager, LiveTvManager, ChannelManager, LibraryManager, Logger, UserDataManager, TVSeriesManager, CollectionManager, PlaylistManager)
|
return new UserViewBuilder(UserViewManager, LiveTvManager, ChannelManager, LibraryManager, Logger, UserDataManager, TVSeriesManager, ConfigurationManager, PlaylistManager)
|
||||||
.GetUserItems(parent, this, ViewType, query);
|
.GetUserItems(parent, this, ViewType, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,8 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
using MediaBrowser.Model.Configuration;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
@ -30,10 +32,10 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly IUserDataManager _userDataManager;
|
private readonly IUserDataManager _userDataManager;
|
||||||
private readonly ITVSeriesManager _tvSeriesManager;
|
private readonly ITVSeriesManager _tvSeriesManager;
|
||||||
private readonly ICollectionManager _collectionManager;
|
private readonly IServerConfigurationManager _config;
|
||||||
private readonly IPlaylistManager _playlistManager;
|
private readonly IPlaylistManager _playlistManager;
|
||||||
|
|
||||||
public UserViewBuilder(IUserViewManager userViewManager, ILiveTvManager liveTvManager, IChannelManager channelManager, ILibraryManager libraryManager, ILogger logger, IUserDataManager userDataManager, ITVSeriesManager tvSeriesManager, ICollectionManager collectionManager, IPlaylistManager playlistManager)
|
public UserViewBuilder(IUserViewManager userViewManager, ILiveTvManager liveTvManager, IChannelManager channelManager, ILibraryManager libraryManager, ILogger logger, IUserDataManager userDataManager, ITVSeriesManager tvSeriesManager, IServerConfigurationManager config, IPlaylistManager playlistManager)
|
||||||
{
|
{
|
||||||
_userViewManager = userViewManager;
|
_userViewManager = userViewManager;
|
||||||
_liveTvManager = liveTvManager;
|
_liveTvManager = liveTvManager;
|
||||||
@ -42,7 +44,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
_userDataManager = userDataManager;
|
_userDataManager = userDataManager;
|
||||||
_tvSeriesManager = tvSeriesManager;
|
_tvSeriesManager = tvSeriesManager;
|
||||||
_collectionManager = collectionManager;
|
_config = config;
|
||||||
_playlistManager = playlistManager;
|
_playlistManager = playlistManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +161,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return await GetTvGenres(queryParent, user, query).ConfigureAwait(false);
|
return await GetTvGenres(queryParent, user, query).ConfigureAwait(false);
|
||||||
|
|
||||||
case SpecialFolder.TvGenre:
|
case SpecialFolder.TvGenre:
|
||||||
return await GetTvGenreItems(queryParent, displayParent, user, query).ConfigureAwait(false);
|
return GetTvGenreItems(queryParent, displayParent, user, query);
|
||||||
|
|
||||||
case SpecialFolder.TvResume:
|
case SpecialFolder.TvResume:
|
||||||
return GetTvResume(queryParent, user, query);
|
return GetTvResume(queryParent, user, query);
|
||||||
@ -332,13 +334,14 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
private QueryResult<BaseItem> GetMusicAlbumArtists(Folder parent, User user, InternalItemsQuery query)
|
private QueryResult<BaseItem> GetMusicAlbumArtists(Folder parent, User user, InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
var items = parent.QueryRecursive(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
Recursive = true,
|
Recursive = true,
|
||||||
ParentId = parent.Id,
|
ParentId = parent.Id,
|
||||||
IncludeItemTypes = new[] { typeof(Audio.Audio).Name }
|
IncludeItemTypes = new[] { typeof(Audio.Audio).Name },
|
||||||
|
EnableTotalRecordCount = false
|
||||||
|
|
||||||
}).Cast<IHasAlbumArtist>();
|
}).Items.Cast<IHasAlbumArtist>();
|
||||||
|
|
||||||
var artists = _libraryManager.GetAlbumArtists(items);
|
var artists = _libraryManager.GetAlbumArtists(items);
|
||||||
|
|
||||||
@ -347,13 +350,14 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
private QueryResult<BaseItem> GetMusicArtists(Folder parent, User user, InternalItemsQuery query)
|
private QueryResult<BaseItem> GetMusicArtists(Folder parent, User user, InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
var items = parent.QueryRecursive(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
Recursive = true,
|
Recursive = true,
|
||||||
ParentId = parent.Id,
|
ParentId = parent.Id,
|
||||||
IncludeItemTypes = new[] { typeof(Audio.Audio).Name, typeof(MusicVideo).Name }
|
IncludeItemTypes = new[] { typeof(Audio.Audio).Name, typeof(MusicVideo).Name },
|
||||||
|
EnableTotalRecordCount = false
|
||||||
|
|
||||||
}).Cast<IHasArtist>();
|
}).Items.Cast<IHasArtist>();
|
||||||
|
|
||||||
var artists = _libraryManager.GetArtists(items);
|
var artists = _libraryManager.GetArtists(items);
|
||||||
|
|
||||||
@ -362,13 +366,14 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
private QueryResult<BaseItem> GetFavoriteArtists(Folder parent, User user, InternalItemsQuery query)
|
private QueryResult<BaseItem> GetFavoriteArtists(Folder parent, User user, InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
var items = parent.QueryRecursive(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
Recursive = true,
|
Recursive = true,
|
||||||
ParentId = parent.Id,
|
ParentId = parent.Id,
|
||||||
IncludeItemTypes = new[] { typeof(Audio.Audio).Name }
|
IncludeItemTypes = new[] { typeof(Audio.Audio).Name },
|
||||||
|
EnableTotalRecordCount = false
|
||||||
|
|
||||||
}).Cast<IHasAlbumArtist>();
|
}).Items.Cast<IHasAlbumArtist>();
|
||||||
|
|
||||||
var artists = _libraryManager.GetAlbumArtists(items).Where(i => _userDataManager.GetUserData(user, i).IsFavorite);
|
var artists = _libraryManager.GetAlbumArtists(items).Where(i => _userDataManager.GetUserData(user, i).IsFavorite);
|
||||||
|
|
||||||
@ -545,7 +550,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
query.Limit = GetSpecialItemsLimit();
|
query.Limit = GetSpecialItemsLimit();
|
||||||
query.IncludeItemTypes = new[] { typeof(Movie).Name };
|
query.IncludeItemTypes = new[] { typeof(Movie).Name };
|
||||||
|
|
||||||
return _libraryManager.GetItemsResult(query);
|
return ConvertToResult(_libraryManager.GetItemList(query));
|
||||||
}
|
}
|
||||||
|
|
||||||
private QueryResult<BaseItem> GetMovieResume(Folder parent, User user, InternalItemsQuery query)
|
private QueryResult<BaseItem> GetMovieResume(Folder parent, User user, InternalItemsQuery query)
|
||||||
@ -559,7 +564,17 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
query.Limit = GetSpecialItemsLimit();
|
query.Limit = GetSpecialItemsLimit();
|
||||||
query.IncludeItemTypes = new[] { typeof(Movie).Name };
|
query.IncludeItemTypes = new[] { typeof(Movie).Name };
|
||||||
|
|
||||||
return _libraryManager.GetItemsResult(query);
|
return ConvertToResult(_libraryManager.GetItemList(query));
|
||||||
|
}
|
||||||
|
|
||||||
|
private QueryResult<BaseItem> ConvertToResult(IEnumerable<BaseItem> items)
|
||||||
|
{
|
||||||
|
var arr = items.ToArray();
|
||||||
|
return new QueryResult<BaseItem>
|
||||||
|
{
|
||||||
|
Items = arr,
|
||||||
|
TotalRecordCount = arr.Length
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<QueryResult<BaseItem>> GetMovieGenres(Folder parent, User user, InternalItemsQuery query)
|
private async Task<QueryResult<BaseItem>> GetMovieGenres(Folder parent, User user, InternalItemsQuery query)
|
||||||
@ -660,8 +675,9 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
query.SetUser(user);
|
query.SetUser(user);
|
||||||
query.Limit = GetSpecialItemsLimit();
|
query.Limit = GetSpecialItemsLimit();
|
||||||
query.IncludeItemTypes = new[] { typeof(Episode).Name };
|
query.IncludeItemTypes = new[] { typeof(Episode).Name };
|
||||||
|
query.ExcludeLocationTypes = new[] { LocationType.Virtual };
|
||||||
|
|
||||||
return _libraryManager.GetItemsResult(query);
|
return ConvertToResult(_libraryManager.GetItemList(query));
|
||||||
}
|
}
|
||||||
|
|
||||||
private QueryResult<BaseItem> GetTvNextUp(Folder parent, InternalItemsQuery query)
|
private QueryResult<BaseItem> GetTvNextUp(Folder parent, InternalItemsQuery query)
|
||||||
@ -690,7 +706,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
query.Limit = GetSpecialItemsLimit();
|
query.Limit = GetSpecialItemsLimit();
|
||||||
query.IncludeItemTypes = new[] { typeof(Episode).Name };
|
query.IncludeItemTypes = new[] { typeof(Episode).Name };
|
||||||
|
|
||||||
return _libraryManager.GetItemsResult(query);
|
return ConvertToResult(_libraryManager.GetItemList(query));
|
||||||
}
|
}
|
||||||
|
|
||||||
private QueryResult<BaseItem> GetTvSeries(Folder parent, User user, InternalItemsQuery query)
|
private QueryResult<BaseItem> GetTvSeries(Folder parent, User user, InternalItemsQuery query)
|
||||||
@ -737,7 +753,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return GetResult(genres, parent, query);
|
return GetResult(genres, parent, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<QueryResult<BaseItem>> GetTvGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query)
|
private QueryResult<BaseItem> GetTvGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
query.Recursive = true;
|
query.Recursive = true;
|
||||||
query.ParentId = queryParent.Id;
|
query.ParentId = queryParent.Id;
|
||||||
@ -766,7 +782,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
items = items.Where(i => Filter(i, query.User, query, _userDataManager, _libraryManager));
|
items = items.Where(i => Filter(i, query.User, query, _userDataManager, _libraryManager));
|
||||||
|
|
||||||
return PostFilterAndSort(items, queryParent, null, query, _libraryManager);
|
return PostFilterAndSort(items, queryParent, null, query, _libraryManager, _config);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool FilterItem(BaseItem item, InternalItemsQuery query)
|
public static bool FilterItem(BaseItem item, InternalItemsQuery query)
|
||||||
@ -779,14 +795,15 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
int? totalRecordLimit,
|
int? totalRecordLimit,
|
||||||
InternalItemsQuery query)
|
InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
return PostFilterAndSort(items, queryParent, totalRecordLimit, query, _libraryManager);
|
return PostFilterAndSort(items, queryParent, totalRecordLimit, query, _libraryManager, _config);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items,
|
public static QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items,
|
||||||
BaseItem queryParent,
|
BaseItem queryParent,
|
||||||
int? totalRecordLimit,
|
int? totalRecordLimit,
|
||||||
InternalItemsQuery query,
|
InternalItemsQuery query,
|
||||||
ILibraryManager libraryManager)
|
ILibraryManager libraryManager,
|
||||||
|
IServerConfigurationManager configurationManager)
|
||||||
{
|
{
|
||||||
var user = query.User;
|
var user = query.User;
|
||||||
|
|
||||||
@ -795,7 +812,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
query.IsVirtualUnaired,
|
query.IsVirtualUnaired,
|
||||||
query.IsUnaired);
|
query.IsUnaired);
|
||||||
|
|
||||||
items = CollapseBoxSetItemsIfNeeded(items, query, queryParent, user);
|
items = CollapseBoxSetItemsIfNeeded(items, query, queryParent, user, configurationManager);
|
||||||
|
|
||||||
// This must be the last filter
|
// This must be the last filter
|
||||||
if (!string.IsNullOrEmpty(query.AdjacentTo))
|
if (!string.IsNullOrEmpty(query.AdjacentTo))
|
||||||
@ -809,14 +826,15 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
public static IEnumerable<BaseItem> CollapseBoxSetItemsIfNeeded(IEnumerable<BaseItem> items,
|
public static IEnumerable<BaseItem> CollapseBoxSetItemsIfNeeded(IEnumerable<BaseItem> items,
|
||||||
InternalItemsQuery query,
|
InternalItemsQuery query,
|
||||||
BaseItem queryParent,
|
BaseItem queryParent,
|
||||||
User user)
|
User user,
|
||||||
|
IServerConfigurationManager configurationManager)
|
||||||
{
|
{
|
||||||
if (items == null)
|
if (items == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException("items");
|
throw new ArgumentNullException("items");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CollapseBoxSetItems(query, queryParent, user))
|
if (CollapseBoxSetItems(query, queryParent, user, configurationManager))
|
||||||
{
|
{
|
||||||
items = BaseItem.CollectionManager.CollapseItemsWithinBoxSets(items, user);
|
items = BaseItem.CollectionManager.CollapseItemsWithinBoxSets(items, user);
|
||||||
}
|
}
|
||||||
@ -849,7 +867,8 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
public static bool CollapseBoxSetItems(InternalItemsQuery query,
|
public static bool CollapseBoxSetItems(InternalItemsQuery query,
|
||||||
BaseItem queryParent,
|
BaseItem queryParent,
|
||||||
User user)
|
User user,
|
||||||
|
IServerConfigurationManager configurationManager)
|
||||||
{
|
{
|
||||||
// Could end up stuck in a loop like this
|
// Could end up stuck in a loop like this
|
||||||
if (queryParent is BoxSet)
|
if (queryParent is BoxSet)
|
||||||
@ -861,7 +880,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
if (!param.HasValue)
|
if (!param.HasValue)
|
||||||
{
|
{
|
||||||
if (user != null && !user.Configuration.GroupMoviesIntoBoxSets)
|
if (user != null && !configurationManager.Configuration.EnableGroupingIntoCollections)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -992,11 +1011,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.IsYearMismatched.HasValue)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(request.Person))
|
if (!string.IsNullOrWhiteSpace(request.Person))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -1415,16 +1429,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.IsYearMismatched.HasValue)
|
|
||||||
{
|
|
||||||
var filterValue = query.IsYearMismatched.Value;
|
|
||||||
|
|
||||||
if (IsYearMismatched(item, libraryManager) != filterValue)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.HasOfficialRating.HasValue)
|
if (query.HasOfficialRating.HasValue)
|
||||||
{
|
{
|
||||||
var filterValue = query.HasOfficialRating.Value;
|
var filterValue = query.HasOfficialRating.Value;
|
||||||
@ -1658,12 +1662,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
var tags = query.Tags;
|
var tags = query.Tags;
|
||||||
if (tags.Length > 0)
|
if (tags.Length > 0)
|
||||||
{
|
{
|
||||||
var hasTags = item as IHasTags;
|
if (!tags.Any(v => item.Tags.Contains(v, StringComparer.OrdinalIgnoreCase)))
|
||||||
if (hasTags == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!tags.Any(v => hasTags.Tags.Contains(v, StringComparer.OrdinalIgnoreCase)))
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1976,34 +1975,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return _userViewManager.GetUserSubView(parent.Id.ToString("N"), type, sortName, CancellationToken.None);
|
return _userViewManager.GetUserSubView(parent.Id.ToString("N"), type, sortName, CancellationToken.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsYearMismatched(BaseItem item, ILibraryManager libraryManager)
|
|
||||||
{
|
|
||||||
if (item.ProductionYear.HasValue)
|
|
||||||
{
|
|
||||||
var path = item.Path;
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(path))
|
|
||||||
{
|
|
||||||
var info = libraryManager.ParseName(Path.GetFileName(path));
|
|
||||||
var yearInName = info.Year;
|
|
||||||
|
|
||||||
// Go up a level if we didn't get a year
|
|
||||||
if (!yearInName.HasValue)
|
|
||||||
{
|
|
||||||
info = libraryManager.ParseName(Path.GetFileName(Path.GetDirectoryName(path)));
|
|
||||||
yearInName = info.Year;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (yearInName.HasValue)
|
|
||||||
{
|
|
||||||
return yearInName.Value != item.ProductionYear.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IEnumerable<BaseItem> FilterForAdjacency(IEnumerable<BaseItem> items, string adjacentToId)
|
public static IEnumerable<BaseItem> FilterForAdjacency(IEnumerable<BaseItem> items, string adjacentToId)
|
||||||
{
|
{
|
||||||
var list = items.ToList();
|
var list = items.ToList();
|
||||||
|
@ -21,7 +21,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class Video : BaseItem,
|
public class Video : BaseItem,
|
||||||
IHasAspectRatio,
|
IHasAspectRatio,
|
||||||
IHasTags,
|
|
||||||
ISupportsPlaceHolders,
|
ISupportsPlaceHolders,
|
||||||
IHasMediaSources,
|
IHasMediaSources,
|
||||||
IHasShortOverview,
|
IHasShortOverview,
|
||||||
@ -59,10 +58,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public long? Size { get; set; }
|
|
||||||
public string Container { get; set; }
|
|
||||||
public int? TotalBitrate { get; set; }
|
public int? TotalBitrate { get; set; }
|
||||||
public string ShortOverview { get; set; }
|
|
||||||
public ExtraType? ExtraType { get; set; }
|
public ExtraType? ExtraType { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -3,6 +3,7 @@ using MediaBrowser.Model.System;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller
|
namespace MediaBrowser.Controller
|
||||||
{
|
{
|
||||||
@ -17,7 +18,7 @@ namespace MediaBrowser.Controller
|
|||||||
/// Gets the system info.
|
/// Gets the system info.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>SystemInfo.</returns>
|
/// <returns>SystemInfo.</returns>
|
||||||
SystemInfo GetSystemInfo();
|
Task<SystemInfo> GetSystemInfo();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether [supports automatic run at startup].
|
/// Gets a value indicating whether [supports automatic run at startup].
|
||||||
@ -65,13 +66,13 @@ namespace MediaBrowser.Controller
|
|||||||
/// Gets the local ip address.
|
/// Gets the local ip address.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The local ip address.</value>
|
/// <value>The local ip address.</value>
|
||||||
List<IPAddress> LocalIpAddresses { get; }
|
Task<List<IPAddress>> GetLocalIpAddresses();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the local API URL.
|
/// Gets the local API URL.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The local API URL.</value>
|
/// <value>The local API URL.</value>
|
||||||
string LocalApiUrl { get; }
|
Task<string> GetLocalApiUrl();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the local API URL.
|
/// Gets the local API URL.
|
||||||
|
@ -11,6 +11,7 @@ using System.Collections.Generic;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CommonIO;
|
using CommonIO;
|
||||||
|
using MediaBrowser.Model.Dto;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Library
|
namespace MediaBrowser.Controller.Library
|
||||||
{
|
{
|
||||||
@ -150,13 +151,6 @@ namespace MediaBrowser.Controller.Library
|
|||||||
/// <returns>BaseItem.</returns>
|
/// <returns>BaseItem.</returns>
|
||||||
BaseItem GetItemById(Guid id);
|
BaseItem GetItemById(Guid id);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the memory item by identifier.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">The identifier.</param>
|
|
||||||
/// <returns>BaseItem.</returns>
|
|
||||||
BaseItem GetMemoryItemById(Guid id);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the intros.
|
/// Gets the intros.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -574,5 +568,12 @@ namespace MediaBrowser.Controller.Library
|
|||||||
void RemoveVirtualFolder(string name, bool refreshLibrary);
|
void RemoveVirtualFolder(string name, bool refreshLibrary);
|
||||||
void AddMediaPath(string virtualFolderName, string path);
|
void AddMediaPath(string virtualFolderName, string path);
|
||||||
void RemoveMediaPath(string virtualFolderName, string path);
|
void RemoveMediaPath(string virtualFolderName, string path);
|
||||||
|
|
||||||
|
QueryResult<Tuple<BaseItem, ItemCounts>> GetGenres(InternalItemsQuery query);
|
||||||
|
QueryResult<Tuple<BaseItem, ItemCounts>> GetMusicGenres(InternalItemsQuery query);
|
||||||
|
QueryResult<Tuple<BaseItem, ItemCounts>> GetGameGenres(InternalItemsQuery query);
|
||||||
|
QueryResult<Tuple<BaseItem, ItemCounts>> GetStudios(InternalItemsQuery query);
|
||||||
|
QueryResult<Tuple<BaseItem, ItemCounts>> GetArtists(InternalItemsQuery query);
|
||||||
|
QueryResult<Tuple<BaseItem, ItemCounts>> GetAlbumArtists(InternalItemsQuery query);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -40,7 +40,9 @@ namespace MediaBrowser.Controller.Library
|
|||||||
/// <param name="item">The item.</param>
|
/// <param name="item">The item.</param>
|
||||||
/// <param name="user">The user.</param>
|
/// <param name="user">The user.</param>
|
||||||
/// <returns>UserItemDataDto.</returns>
|
/// <returns>UserItemDataDto.</returns>
|
||||||
UserItemDataDto GetUserDataDto(IHasUserData item, User user);
|
Task<UserItemDataDto> GetUserDataDto(IHasUserData item, User user);
|
||||||
|
|
||||||
|
Task<UserItemDataDto> GetUserDataDto(IHasUserData item, BaseItemDto itemDto, User user);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get all user data for the given user
|
/// Get all user data for the given user
|
||||||
|
@ -15,5 +15,6 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
Task AddMetadata(ListingsProviderInfo info, List<ChannelInfo> channels, CancellationToken cancellationToken);
|
Task AddMetadata(ListingsProviderInfo info, List<ChannelInfo> channels, CancellationToken cancellationToken);
|
||||||
Task Validate(ListingsProviderInfo info, bool validateLogin, bool validateListings);
|
Task Validate(ListingsProviderInfo info, bool validateLogin, bool validateListings);
|
||||||
Task<List<NameIdPair>> GetLineups(ListingsProviderInfo info, string country, string location);
|
Task<List<NameIdPair>> GetLineups(ListingsProviderInfo info, string country, string location);
|
||||||
|
Task<List<ChannelInfo>> GetChannels(ListingsProviderInfo info, CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ using MediaBrowser.Model.Querying;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Model.Events;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.LiveTv
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
{
|
{
|
||||||
@ -344,6 +345,13 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
/// <param name="validateListings">if set to <c>true</c> [validate listings].</param>
|
/// <param name="validateListings">if set to <c>true</c> [validate listings].</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task<ListingsProviderInfo> SaveListingProvider(ListingsProviderInfo info, bool validateLogin, bool validateListings);
|
Task<ListingsProviderInfo> SaveListingProvider(ListingsProviderInfo info, bool validateLogin, bool validateListings);
|
||||||
|
|
||||||
|
void DeleteListingsProvider(string id);
|
||||||
|
|
||||||
|
Task<TunerChannelMapping> SetChannelMapping(string providerId, string tunerChannelNumber, string providerChannelNumber);
|
||||||
|
|
||||||
|
TunerChannelMapping GetTunerChannelMapping(ChannelInfo channel, List<NameValuePair> mappings, List<ChannelInfo> providerChannels);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the lineups.
|
/// Gets the lineups.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -385,5 +393,15 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
List<NameValuePair> GetSatIniMappings();
|
List<NameValuePair> GetSatIniMappings();
|
||||||
|
|
||||||
Task<List<ChannelInfo>> GetSatChannelScanResult(TunerHostInfo info, CancellationToken cancellationToken);
|
Task<List<ChannelInfo>> GetSatChannelScanResult(TunerHostInfo info, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
Task<List<ChannelInfo>> GetChannelsForListingsProvider(string id, CancellationToken cancellationToken);
|
||||||
|
Task<List<ChannelInfo>> GetChannelsFromListingsProviderData(string id, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
List<IListingsProvider> ListingProviders { get;}
|
||||||
|
|
||||||
|
event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCancelled;
|
||||||
|
event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCancelled;
|
||||||
|
event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCreated;
|
||||||
|
event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCreated;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,4 +226,23 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task ResetTuner(string id, CancellationToken cancellationToken);
|
Task ResetTuner(string id, CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface ISupportsNewTimerIds
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates the timer asynchronous.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="info">The information.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>Task.</returns>
|
||||||
|
Task<string> CreateTimer(TimerInfo info, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates the series timer asynchronous.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="info">The information.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>Task.</returns>
|
||||||
|
Task<string> CreateSeriesTimer(SeriesTimerInfo info, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
|
using MediaBrowser.Model.Providers;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.LiveTv
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
{
|
{
|
||||||
@ -235,5 +236,25 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override List<ExternalUrl> GetRelatedUrls()
|
||||||
|
{
|
||||||
|
var list = base.GetRelatedUrls();
|
||||||
|
|
||||||
|
var imdbId = this.GetProviderId(MetadataProviders.Imdb);
|
||||||
|
if (!string.IsNullOrWhiteSpace(imdbId))
|
||||||
|
{
|
||||||
|
if (IsMovie)
|
||||||
|
{
|
||||||
|
list.Add(new ExternalUrl
|
||||||
|
{
|
||||||
|
Name = "Trakt",
|
||||||
|
Url = string.Format("https://trakt.tv/movies/{0}", imdbId)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
14
MediaBrowser.Controller/LiveTv/TimerEventInfo.cs
Normal file
14
MediaBrowser.Controller/LiveTv/TimerEventInfo.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
|
{
|
||||||
|
public class TimerEventInfo
|
||||||
|
{
|
||||||
|
public string Id { get; set; }
|
||||||
|
public string ProgramId { get; set; }
|
||||||
|
}
|
||||||
|
}
|
16
MediaBrowser.Controller/LiveTv/TunerChannelMapping.cs
Normal file
16
MediaBrowser.Controller/LiveTv/TunerChannelMapping.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
|
{
|
||||||
|
public class TunerChannelMapping
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Number { get; set; }
|
||||||
|
public string ProviderChannelNumber { get; set; }
|
||||||
|
public string ProviderChannelName { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -142,7 +142,7 @@
|
|||||||
<Compile Include="Entities\IHasDisplayOrder.cs" />
|
<Compile Include="Entities\IHasDisplayOrder.cs" />
|
||||||
<Compile Include="Entities\IHasId.cs" />
|
<Compile Include="Entities\IHasId.cs" />
|
||||||
<Compile Include="Entities\IHasImages.cs" />
|
<Compile Include="Entities\IHasImages.cs" />
|
||||||
<Compile Include="Entities\IHasKeywords.cs" />
|
<Compile Include="Entities\KeywordExtensions.cs" />
|
||||||
<Compile Include="Entities\IHasMediaSources.cs" />
|
<Compile Include="Entities\IHasMediaSources.cs" />
|
||||||
<Compile Include="Entities\IHasMetascore.cs" />
|
<Compile Include="Entities\IHasMetascore.cs" />
|
||||||
<Compile Include="Entities\IHasOriginalTitle.cs" />
|
<Compile Include="Entities\IHasOriginalTitle.cs" />
|
||||||
@ -154,7 +154,6 @@
|
|||||||
<Compile Include="Entities\IHasSpecialFeatures.cs" />
|
<Compile Include="Entities\IHasSpecialFeatures.cs" />
|
||||||
<Compile Include="Entities\IHasStartDate.cs" />
|
<Compile Include="Entities\IHasStartDate.cs" />
|
||||||
<Compile Include="Entities\IHasTaglines.cs" />
|
<Compile Include="Entities\IHasTaglines.cs" />
|
||||||
<Compile Include="Entities\IHasTags.cs" />
|
|
||||||
<Compile Include="Entities\IHasThemeMedia.cs" />
|
<Compile Include="Entities\IHasThemeMedia.cs" />
|
||||||
<Compile Include="Entities\IHasTrailers.cs" />
|
<Compile Include="Entities\IHasTrailers.cs" />
|
||||||
<Compile Include="Entities\IHasUserData.cs" />
|
<Compile Include="Entities\IHasUserData.cs" />
|
||||||
@ -177,6 +176,7 @@
|
|||||||
<Compile Include="Entities\PhotoAlbum.cs" />
|
<Compile Include="Entities\PhotoAlbum.cs" />
|
||||||
<Compile Include="Entities\Share.cs" />
|
<Compile Include="Entities\Share.cs" />
|
||||||
<Compile Include="Entities\SourceType.cs" />
|
<Compile Include="Entities\SourceType.cs" />
|
||||||
|
<Compile Include="Entities\TagExtensions.cs" />
|
||||||
<Compile Include="Entities\UserView.cs" />
|
<Compile Include="Entities\UserView.cs" />
|
||||||
<Compile Include="Entities\UserViewBuilder.cs" />
|
<Compile Include="Entities\UserViewBuilder.cs" />
|
||||||
<Compile Include="FileOrganization\IFileOrganizationService.cs" />
|
<Compile Include="FileOrganization\IFileOrganizationService.cs" />
|
||||||
@ -218,7 +218,9 @@
|
|||||||
<Compile Include="LiveTv\ProgramInfo.cs" />
|
<Compile Include="LiveTv\ProgramInfo.cs" />
|
||||||
<Compile Include="LiveTv\RecordingInfo.cs" />
|
<Compile Include="LiveTv\RecordingInfo.cs" />
|
||||||
<Compile Include="LiveTv\SeriesTimerInfo.cs" />
|
<Compile Include="LiveTv\SeriesTimerInfo.cs" />
|
||||||
|
<Compile Include="LiveTv\TimerEventInfo.cs" />
|
||||||
<Compile Include="LiveTv\TimerInfo.cs" />
|
<Compile Include="LiveTv\TimerInfo.cs" />
|
||||||
|
<Compile Include="LiveTv\TunerChannelMapping.cs" />
|
||||||
<Compile Include="Localization\ILocalizationManager.cs" />
|
<Compile Include="Localization\ILocalizationManager.cs" />
|
||||||
<Compile Include="MediaEncoding\ChapterImageRefreshOptions.cs" />
|
<Compile Include="MediaEncoding\ChapterImageRefreshOptions.cs" />
|
||||||
<Compile Include="MediaEncoding\EncodingJobOptions.cs" />
|
<Compile Include="MediaEncoding\EncodingJobOptions.cs" />
|
||||||
@ -290,21 +292,17 @@
|
|||||||
<Compile Include="Providers\IImageFileSaver.cs" />
|
<Compile Include="Providers\IImageFileSaver.cs" />
|
||||||
<Compile Include="Providers\IImageProvider.cs" />
|
<Compile Include="Providers\IImageProvider.cs" />
|
||||||
<Compile Include="Providers\IImageSaver.cs" />
|
<Compile Include="Providers\IImageSaver.cs" />
|
||||||
<Compile Include="Providers\IItemIdentityConverter.cs" />
|
|
||||||
<Compile Include="Providers\IItemIdentityProvider.cs" />
|
|
||||||
<Compile Include="Providers\ILocalImageFileProvider.cs" />
|
<Compile Include="Providers\ILocalImageFileProvider.cs" />
|
||||||
<Compile Include="Providers\ILocalMetadataProvider.cs" />
|
<Compile Include="Providers\ILocalMetadataProvider.cs" />
|
||||||
<Compile Include="Providers\ImageRefreshMode.cs" />
|
<Compile Include="Providers\ImageRefreshMode.cs" />
|
||||||
<Compile Include="Providers\ImageRefreshOptions.cs" />
|
<Compile Include="Providers\ImageRefreshOptions.cs" />
|
||||||
<Compile Include="Providers\IPreRefreshProvider.cs" />
|
<Compile Include="Providers\IPreRefreshProvider.cs" />
|
||||||
<Compile Include="Providers\IProviderRepository.cs" />
|
|
||||||
<Compile Include="Providers\IRemoteImageProvider.cs" />
|
<Compile Include="Providers\IRemoteImageProvider.cs" />
|
||||||
<Compile Include="Providers\ILocalImageProvider.cs" />
|
<Compile Include="Providers\ILocalImageProvider.cs" />
|
||||||
<Compile Include="Providers\IMetadataProvider.cs" />
|
<Compile Include="Providers\IMetadataProvider.cs" />
|
||||||
<Compile Include="Providers\IMetadataService.cs" />
|
<Compile Include="Providers\IMetadataService.cs" />
|
||||||
<Compile Include="Providers\IRemoteMetadataProvider.cs" />
|
<Compile Include="Providers\IRemoteMetadataProvider.cs" />
|
||||||
<Compile Include="Providers\IRemoteSearchProvider.cs" />
|
<Compile Include="Providers\IRemoteSearchProvider.cs" />
|
||||||
<Compile Include="Providers\ISeriesOrderProvider.cs" />
|
|
||||||
<Compile Include="Providers\ItemInfo.cs" />
|
<Compile Include="Providers\ItemInfo.cs" />
|
||||||
<Compile Include="Providers\LiveTvProgramLookupInfo.cs" />
|
<Compile Include="Providers\LiveTvProgramLookupInfo.cs" />
|
||||||
<Compile Include="Providers\LocalImageInfo.cs" />
|
<Compile Include="Providers\LocalImageInfo.cs" />
|
||||||
@ -330,12 +328,8 @@
|
|||||||
<Compile Include="Sorting\SortHelper.cs" />
|
<Compile Include="Sorting\SortHelper.cs" />
|
||||||
<Compile Include="Subtitles\ISubtitleManager.cs" />
|
<Compile Include="Subtitles\ISubtitleManager.cs" />
|
||||||
<Compile Include="Subtitles\ISubtitleProvider.cs" />
|
<Compile Include="Subtitles\ISubtitleProvider.cs" />
|
||||||
<Compile Include="Providers\ItemIdentifier.cs" />
|
|
||||||
<Compile Include="Providers\ItemIdentities.cs" />
|
|
||||||
<Compile Include="Providers\ItemLookupInfo.cs" />
|
<Compile Include="Providers\ItemLookupInfo.cs" />
|
||||||
<Compile Include="Providers\MetadataRefreshOptions.cs" />
|
<Compile Include="Providers\MetadataRefreshOptions.cs" />
|
||||||
<Compile Include="Providers\MetadataStatus.cs" />
|
|
||||||
<Compile Include="Providers\ISeriesOrderManager.cs" />
|
|
||||||
<Compile Include="Session\ISessionManager.cs" />
|
<Compile Include="Session\ISessionManager.cs" />
|
||||||
<Compile Include="Entities\AggregateFolder.cs" />
|
<Compile Include="Entities\AggregateFolder.cs" />
|
||||||
<Compile Include="Entities\Audio\Audio.cs" />
|
<Compile Include="Entities\Audio\Audio.cs" />
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using MediaBrowser.Model.Dlna;
|
using System.Linq;
|
||||||
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.MediaEncoding
|
namespace MediaBrowser.Controller.MediaEncoding
|
||||||
{
|
{
|
||||||
@ -74,7 +75,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
Level = info.VideoLevel;
|
Level = info.VideoLevel;
|
||||||
ItemId = info.ItemId;
|
ItemId = info.ItemId;
|
||||||
MediaSourceId = info.MediaSourceId;
|
MediaSourceId = info.MediaSourceId;
|
||||||
AudioCodec = info.AudioCodec;
|
AudioCodec = info.TargetAudioCodec;
|
||||||
MaxAudioChannels = info.MaxAudioChannels;
|
MaxAudioChannels = info.MaxAudioChannels;
|
||||||
AudioBitRate = info.AudioBitrate;
|
AudioBitRate = info.AudioBitrate;
|
||||||
AudioSampleRate = info.TargetAudioSampleRate;
|
AudioSampleRate = info.TargetAudioSampleRate;
|
||||||
|
@ -13,18 +13,14 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IMediaEncoder : ITranscoderSupport
|
public interface IMediaEncoder : ITranscoderSupport
|
||||||
{
|
{
|
||||||
|
string EncoderLocationType { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the encoder path.
|
/// Gets the encoder path.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The encoder path.</value>
|
/// <value>The encoder path.</value>
|
||||||
string EncoderPath { get; }
|
string EncoderPath { get; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the version.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The version.</value>
|
|
||||||
string Version { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Supportses the decoder.
|
/// Supportses the decoder.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -66,12 +62,12 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
/// <param name="maxWidth">The maximum width.</param>
|
/// <param name="maxWidth">The maximum width.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task ExtractVideoImagesOnInterval(string[] inputFiles,
|
Task ExtractVideoImagesOnInterval(string[] inputFiles,
|
||||||
MediaProtocol protocol,
|
MediaProtocol protocol,
|
||||||
Video3DFormat? threedFormat,
|
Video3DFormat? threedFormat,
|
||||||
TimeSpan interval,
|
TimeSpan interval,
|
||||||
string targetDirectory,
|
string targetDirectory,
|
||||||
string filenamePrefix,
|
string filenamePrefix,
|
||||||
int? maxWidth,
|
int? maxWidth,
|
||||||
CancellationToken cancellationToken);
|
CancellationToken cancellationToken);
|
||||||
|
|
||||||
@ -134,5 +130,9 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
/// <param name="path">The path.</param>
|
/// <param name="path">The path.</param>
|
||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
string EscapeSubtitleFilterPath(string path);
|
string EscapeSubtitleFilterPath(string path);
|
||||||
|
|
||||||
|
Task Init();
|
||||||
|
|
||||||
|
Task UpdateEncoderPath(string path, string pathType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,13 +10,6 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the subtitles.
|
/// Gets the subtitles.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="itemId">The item identifier.</param>
|
|
||||||
/// <param name="mediaSourceId">The media source identifier.</param>
|
|
||||||
/// <param name="subtitleStreamIndex">Index of the subtitle stream.</param>
|
|
||||||
/// <param name="outputFormat">The output format.</param>
|
|
||||||
/// <param name="startTimeTicks">The start time ticks.</param>
|
|
||||||
/// <param name="endTimeTicks">The end time ticks.</param>
|
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
|
||||||
/// <returns>Task{Stream}.</returns>
|
/// <returns>Task{Stream}.</returns>
|
||||||
Task<Stream> GetSubtitles(string itemId,
|
Task<Stream> GetSubtitles(string itemId,
|
||||||
string mediaSourceId,
|
string mediaSourceId,
|
||||||
@ -24,6 +17,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
string outputFormat,
|
string outputFormat,
|
||||||
long startTimeTicks,
|
long startTimeTicks,
|
||||||
long? endTimeTicks,
|
long? endTimeTicks,
|
||||||
|
bool preserveOriginalTimestamps,
|
||||||
CancellationToken cancellationToken);
|
CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -80,7 +80,7 @@ namespace MediaBrowser.Controller.Net
|
|||||||
/// <param name="responseHeaders">The response headers.</param>
|
/// <param name="responseHeaders">The response headers.</param>
|
||||||
/// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param>
|
/// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param>
|
||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
object GetStaticResult(IRequest requestContext,
|
Task<object> GetStaticResult(IRequest requestContext,
|
||||||
Guid cacheKey,
|
Guid cacheKey,
|
||||||
DateTime? lastDateModified,
|
DateTime? lastDateModified,
|
||||||
TimeSpan? cacheDuration,
|
TimeSpan? cacheDuration,
|
||||||
@ -94,7 +94,7 @@ namespace MediaBrowser.Controller.Net
|
|||||||
/// <param name="requestContext">The request context.</param>
|
/// <param name="requestContext">The request context.</param>
|
||||||
/// <param name="options">The options.</param>
|
/// <param name="options">The options.</param>
|
||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
object GetStaticResult(IRequest requestContext, StaticResultOptions options);
|
Task<object> GetStaticResult(IRequest requestContext, StaticResultOptions options);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the static file result.
|
/// Gets the static file result.
|
||||||
@ -103,7 +103,7 @@ namespace MediaBrowser.Controller.Net
|
|||||||
/// <param name="path">The path.</param>
|
/// <param name="path">The path.</param>
|
||||||
/// <param name="fileShare">The file share.</param>
|
/// <param name="fileShare">The file share.</param>
|
||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
object GetStaticFileResult(IRequest requestContext, string path, FileShare fileShare = FileShare.Read);
|
Task<object> GetStaticFileResult(IRequest requestContext, string path, FileShare fileShare = FileShare.Read);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the static file result.
|
/// Gets the static file result.
|
||||||
@ -111,7 +111,7 @@ namespace MediaBrowser.Controller.Net
|
|||||||
/// <param name="requestContext">The request context.</param>
|
/// <param name="requestContext">The request context.</param>
|
||||||
/// <param name="options">The options.</param>
|
/// <param name="options">The options.</param>
|
||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
object GetStaticFileResult(IRequest requestContext,
|
Task<object> GetStaticFileResult(IRequest requestContext,
|
||||||
StaticFileResultOptions options);
|
StaticFileResultOptions options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Querying;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Persistence
|
namespace MediaBrowser.Controller.Persistence
|
||||||
@ -81,7 +82,7 @@ namespace MediaBrowser.Controller.Persistence
|
|||||||
/// <param name="chapters">The chapters.</param>
|
/// <param name="chapters">The chapters.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task SaveChapters(Guid id, IEnumerable<ChapterInfo> chapters, CancellationToken cancellationToken);
|
Task SaveChapters(Guid id, List<ChapterInfo> chapters, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the media streams.
|
/// Gets the media streams.
|
||||||
@ -97,7 +98,7 @@ namespace MediaBrowser.Controller.Persistence
|
|||||||
/// <param name="streams">The streams.</param>
|
/// <param name="streams">The streams.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task SaveMediaStreams(Guid id, IEnumerable<MediaStream> streams, CancellationToken cancellationToken);
|
Task SaveMediaStreams(Guid id, List<MediaStream> streams, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the item ids.
|
/// Gets the item ids.
|
||||||
@ -153,7 +154,7 @@ namespace MediaBrowser.Controller.Persistence
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="query">The query.</param>
|
/// <param name="query">The query.</param>
|
||||||
/// <returns>List<BaseItem>.</returns>
|
/// <returns>List<BaseItem>.</returns>
|
||||||
IEnumerable<BaseItem> GetItemList(InternalItemsQuery query);
|
List<BaseItem> GetItemList(InternalItemsQuery query);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the inherited values.
|
/// Updates the inherited values.
|
||||||
@ -161,6 +162,13 @@ namespace MediaBrowser.Controller.Persistence
|
|||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task UpdateInheritedValues(CancellationToken cancellationToken);
|
Task UpdateInheritedValues(CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
QueryResult<Tuple<BaseItem, ItemCounts>> GetGenres(InternalItemsQuery query);
|
||||||
|
QueryResult<Tuple<BaseItem, ItemCounts>> GetMusicGenres(InternalItemsQuery query);
|
||||||
|
QueryResult<Tuple<BaseItem, ItemCounts>> GetGameGenres(InternalItemsQuery query);
|
||||||
|
QueryResult<Tuple<BaseItem, ItemCounts>> GetStudios(InternalItemsQuery query);
|
||||||
|
QueryResult<Tuple<BaseItem, ItemCounts>> GetArtists(InternalItemsQuery query);
|
||||||
|
QueryResult<Tuple<BaseItem, ItemCounts>> GetAlbumArtists(InternalItemsQuery query);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user