Merge pull request #1899 from MediaBrowser/beta

Beta
This commit is contained in:
Luke 2016-06-30 15:27:06 -04:00 committed by GitHub
commit 2708df6cc2
362 changed files with 16795 additions and 9358 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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,7 +259,7 @@ 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>

View File

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

View File

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

View File

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

View File

@ -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,7 +726,7 @@ 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>
{ {
@ -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);

View File

@ -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,52 +129,16 @@ 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;
@ -183,95 +146,76 @@ namespace MediaBrowser.Api.Movies
(!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()
}; };
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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);
@ -87,12 +103,29 @@ namespace MediaBrowser.Api.UserLibrary
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,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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&lt;BaseItemDto&gt;.</returns> /// <returns>IEnumerable&lt;BaseItemDto&gt;.</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>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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[] { };

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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&lt;BaseItem&gt;.</returns> /// <returns>List&lt;BaseItem&gt;.</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