mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-07-09 03:04:24 -04:00
commit
f868dd81e8
@ -285,14 +285,14 @@ namespace Emby.Drawing.ImageMagick
|
|||||||
|
|
||||||
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, 8);
|
var inputPaths = ImageHelpers.ProjectPaths(paths, 4);
|
||||||
using (var wandImages = new MagickWand(inputPaths.ToArray()))
|
using (var wandImages = new MagickWand(inputPaths.ToArray()))
|
||||||
{
|
{
|
||||||
var wand = new MagickWand(width, height);
|
var wand = new MagickWand(width, height);
|
||||||
wand.OpenImage("gradient:#111111-#111111");
|
wand.OpenImage("gradient:#111111-#111111");
|
||||||
using (var draw = new DrawingWand())
|
using (var draw = new DrawingWand())
|
||||||
{
|
{
|
||||||
var iSlice = Convert.ToInt32(width * .1166666667);
|
var iSlice = Convert.ToInt32(width * .1166666667 * 2);
|
||||||
int iTrans = Convert.ToInt32(height * .25);
|
int iTrans = Convert.ToInt32(height * .25);
|
||||||
int iHeight = Convert.ToInt32(height * .62);
|
int iHeight = Convert.ToInt32(height * .62);
|
||||||
var horizontalImagePadding = Convert.ToInt32(width * 0.0125);
|
var horizontalImagePadding = Convert.ToInt32(width * 0.0125);
|
||||||
|
@ -189,7 +189,7 @@ namespace Emby.Drawing
|
|||||||
dateModified = tuple.Item2;
|
dateModified = tuple.Item2;
|
||||||
}
|
}
|
||||||
|
|
||||||
var originalImageSize = GetImageSize(originalImagePath, dateModified);
|
var originalImageSize = GetImageSize(originalImagePath, dateModified, true);
|
||||||
|
|
||||||
// Determine the output size based on incoming parameters
|
// Determine the output size based on incoming parameters
|
||||||
var newSize = DrawingUtils.Resize(originalImageSize, options.Width, options.Height, options.MaxWidth, options.MaxHeight);
|
var newSize = DrawingUtils.Resize(originalImageSize, options.Width, options.Height, options.MaxWidth, options.MaxHeight);
|
||||||
@ -363,12 +363,12 @@ namespace Emby.Drawing
|
|||||||
/// <returns>ImageSize.</returns>
|
/// <returns>ImageSize.</returns>
|
||||||
public ImageSize GetImageSize(string path)
|
public ImageSize GetImageSize(string path)
|
||||||
{
|
{
|
||||||
return GetImageSize(path, File.GetLastWriteTimeUtc(path));
|
return GetImageSize(path, File.GetLastWriteTimeUtc(path), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImageSize GetImageSize(ItemImageInfo info)
|
public ImageSize GetImageSize(ItemImageInfo info)
|
||||||
{
|
{
|
||||||
return GetImageSize(info.Path, info.DateModified);
|
return GetImageSize(info.Path, info.DateModified, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -376,9 +376,10 @@ namespace Emby.Drawing
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="path">The path.</param>
|
/// <param name="path">The path.</param>
|
||||||
/// <param name="imageDateModified">The image date modified.</param>
|
/// <param name="imageDateModified">The image date modified.</param>
|
||||||
|
/// <param name="allowSlowMethod">if set to <c>true</c> [allow slow method].</param>
|
||||||
/// <returns>ImageSize.</returns>
|
/// <returns>ImageSize.</returns>
|
||||||
/// <exception cref="System.ArgumentNullException">path</exception>
|
/// <exception cref="System.ArgumentNullException">path</exception>
|
||||||
private ImageSize GetImageSize(string path, DateTime imageDateModified)
|
private ImageSize GetImageSize(string path, DateTime imageDateModified, bool allowSlowMethod)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(path))
|
if (string.IsNullOrEmpty(path))
|
||||||
{
|
{
|
||||||
@ -393,7 +394,7 @@ namespace Emby.Drawing
|
|||||||
|
|
||||||
if (!_cachedImagedSizes.TryGetValue(cacheHash, out size))
|
if (!_cachedImagedSizes.TryGetValue(cacheHash, out size))
|
||||||
{
|
{
|
||||||
size = GetImageSizeInternal(path);
|
size = GetImageSizeInternal(path, allowSlowMethod);
|
||||||
|
|
||||||
_cachedImagedSizes.AddOrUpdate(cacheHash, size, (keyName, oldValue) => size);
|
_cachedImagedSizes.AddOrUpdate(cacheHash, size, (keyName, oldValue) => size);
|
||||||
}
|
}
|
||||||
@ -405,8 +406,9 @@ namespace Emby.Drawing
|
|||||||
/// Gets the image size internal.
|
/// Gets the image size internal.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="path">The path.</param>
|
/// <param name="path">The path.</param>
|
||||||
|
/// <param name="allowSlowMethod">if set to <c>true</c> [allow slow method].</param>
|
||||||
/// <returns>ImageSize.</returns>
|
/// <returns>ImageSize.</returns>
|
||||||
private ImageSize GetImageSizeInternal(string path)
|
private ImageSize GetImageSizeInternal(string path, bool allowSlowMethod)
|
||||||
{
|
{
|
||||||
ImageSize size;
|
ImageSize size;
|
||||||
|
|
||||||
@ -416,7 +418,11 @@ namespace Emby.Drawing
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
_logger.Info("Failed to read image header for {0}. Doing it the slow way.", path);
|
if (!allowSlowMethod)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
//_logger.Info("Failed to read image header for {0}. Doing it the slow way.", path);
|
||||||
|
|
||||||
CheckDisposed();
|
CheckDisposed();
|
||||||
|
|
||||||
|
@ -336,12 +336,6 @@ namespace MediaBrowser.Api
|
|||||||
if (job.Type != TranscodingJobType.Progressive)
|
if (job.Type != TranscodingJobType.Progressive)
|
||||||
{
|
{
|
||||||
timerDuration = 1800000;
|
timerDuration = 1800000;
|
||||||
|
|
||||||
// We can really reduce the timeout for apps that are using the newer api
|
|
||||||
if (!string.IsNullOrWhiteSpace(job.PlaySessionId))
|
|
||||||
{
|
|
||||||
timerDuration = 300000;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
job.PingTimeout = timerDuration;
|
job.PingTimeout = timerDuration;
|
||||||
|
@ -7,7 +7,6 @@ using MediaBrowser.Controller.Providers;
|
|||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
using ServiceStack;
|
using ServiceStack;
|
||||||
using ServiceStack.Text.Controller;
|
|
||||||
using ServiceStack.Web;
|
using ServiceStack.Web;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@ -26,7 +25,7 @@ namespace MediaBrowser.Api
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Route("/System/Configuration/{Key}", "GET", Summary = "Gets a named configuration")]
|
[Route("/System/Configuration/{Key}", "GET", Summary = "Gets a named configuration")]
|
||||||
[Authenticated]
|
[Authenticated(AllowBeforeStartupWizard = true)]
|
||||||
public class GetNamedConfiguration
|
public class GetNamedConfiguration
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "Key", Description = "Key", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
[ApiMember(Name = "Key", Description = "Key", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||||
|
@ -221,7 +221,9 @@ namespace MediaBrowser.Api
|
|||||||
/// <returns>IEnumerable{FileSystemEntryInfo}.</returns>
|
/// <returns>IEnumerable{FileSystemEntryInfo}.</returns>
|
||||||
private IEnumerable<FileSystemEntryInfo> GetFileSystemEntries(GetDirectoryContents request)
|
private IEnumerable<FileSystemEntryInfo> GetFileSystemEntries(GetDirectoryContents request)
|
||||||
{
|
{
|
||||||
var entries = new DirectoryInfo(request.Path).EnumerateFileSystemInfos().Where(i =>
|
// using EnumerateFileSystemInfos doesn't handle reparse points (symlinks)
|
||||||
|
var entries = new DirectoryInfo(request.Path).EnumerateDirectories("*", SearchOption.TopDirectoryOnly)
|
||||||
|
.Concat<FileSystemInfo>(new DirectoryInfo(request.Path).EnumerateFiles("*", SearchOption.TopDirectoryOnly)).Where(i =>
|
||||||
{
|
{
|
||||||
if (!request.IncludeHidden && i.Attributes.HasFlag(FileAttributes.Hidden))
|
if (!request.IncludeHidden && i.Attributes.HasFlag(FileAttributes.Hidden))
|
||||||
{
|
{
|
||||||
|
@ -1,14 +1,20 @@
|
|||||||
using MediaBrowser.Controller.Activity;
|
using MediaBrowser.Api.Movies;
|
||||||
|
using MediaBrowser.Api.Music;
|
||||||
|
using MediaBrowser.Controller.Activity;
|
||||||
|
using MediaBrowser.Controller.Channels;
|
||||||
using MediaBrowser.Controller.Dto;
|
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.Entities.Movies;
|
using MediaBrowser.Controller.Entities.Movies;
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
|
using MediaBrowser.Controller.LiveTv;
|
||||||
using MediaBrowser.Controller.Localization;
|
using MediaBrowser.Controller.Localization;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
using MediaBrowser.Controller.Persistence;
|
using MediaBrowser.Controller.Persistence;
|
||||||
|
using MediaBrowser.Controller.TV;
|
||||||
using MediaBrowser.Model.Activity;
|
using MediaBrowser.Model.Activity;
|
||||||
|
using MediaBrowser.Model.Channels;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Querying;
|
||||||
@ -225,6 +231,17 @@ namespace MediaBrowser.Api.Library
|
|||||||
public string TvdbId { get; set; }
|
public string TvdbId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Route("/Library/Movies/Added", "POST", Summary = "Reports that new movies have been added by an external source")]
|
||||||
|
[Route("/Library/Movies/Updated", "POST", Summary = "Reports that new movies have been added by an external source")]
|
||||||
|
[Authenticated]
|
||||||
|
public class PostUpdatedMovies : IReturnVoid
|
||||||
|
{
|
||||||
|
[ApiMember(Name = "TmdbId", Description = "Tmdb Id", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||||
|
public string TmdbId { get; set; }
|
||||||
|
[ApiMember(Name = "ImdbId", Description = "Imdb Id", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||||
|
public string ImdbId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
[Route("/Items/{Id}/Download", "GET", Summary = "Downloads item media")]
|
[Route("/Items/{Id}/Download", "GET", Summary = "Downloads item media")]
|
||||||
[Authenticated(Roles = "download")]
|
[Authenticated(Roles = "download")]
|
||||||
public class GetDownload
|
public class GetDownload
|
||||||
@ -237,6 +254,12 @@ namespace MediaBrowser.Api.Library
|
|||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Route("/Items/{Id}/Similar", "GET", Summary = "Gets similar items")]
|
||||||
|
[Authenticated]
|
||||||
|
public class GetSimilarItems : BaseGetSimilarItemsFromItem
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class LibraryService
|
/// Class LibraryService
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -255,12 +278,16 @@ namespace MediaBrowser.Api.Library
|
|||||||
private readonly IAuthorizationContext _authContext;
|
private readonly IAuthorizationContext _authContext;
|
||||||
private readonly IActivityManager _activityManager;
|
private readonly IActivityManager _activityManager;
|
||||||
private readonly ILocalizationManager _localization;
|
private readonly ILocalizationManager _localization;
|
||||||
|
private readonly ILiveTvManager _liveTv;
|
||||||
|
private readonly IChannelManager _channelManager;
|
||||||
|
private readonly ITVSeriesManager _tvManager;
|
||||||
|
private readonly ILibraryMonitor _libraryMonitor;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="LibraryService" /> class.
|
/// Initializes a new instance of the <see cref="LibraryService" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public LibraryService(IItemRepository itemRepo, ILibraryManager libraryManager, IUserManager userManager,
|
public LibraryService(IItemRepository itemRepo, ILibraryManager libraryManager, IUserManager userManager,
|
||||||
IDtoService dtoService, IUserDataManager userDataManager, IAuthorizationContext authContext, IActivityManager activityManager, ILocalizationManager localization)
|
IDtoService dtoService, IUserDataManager userDataManager, IAuthorizationContext authContext, IActivityManager activityManager, ILocalizationManager localization, ILiveTvManager liveTv, IChannelManager channelManager, ITVSeriesManager tvManager, ILibraryMonitor libraryMonitor)
|
||||||
{
|
{
|
||||||
_itemRepo = itemRepo;
|
_itemRepo = itemRepo;
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
@ -270,6 +297,117 @@ namespace MediaBrowser.Api.Library
|
|||||||
_authContext = authContext;
|
_authContext = authContext;
|
||||||
_activityManager = activityManager;
|
_activityManager = activityManager;
|
||||||
_localization = localization;
|
_localization = localization;
|
||||||
|
_liveTv = liveTv;
|
||||||
|
_channelManager = channelManager;
|
||||||
|
_tvManager = tvManager;
|
||||||
|
_libraryMonitor = libraryMonitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Get(GetSimilarItems 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);
|
||||||
|
|
||||||
|
if (item is Game)
|
||||||
|
{
|
||||||
|
return new GamesService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService)
|
||||||
|
{
|
||||||
|
AuthorizationContext = AuthorizationContext,
|
||||||
|
Logger = Logger,
|
||||||
|
Request = Request,
|
||||||
|
SessionContext = SessionContext,
|
||||||
|
ResultFactory = ResultFactory
|
||||||
|
|
||||||
|
}.Get(new GetSimilarGames
|
||||||
|
{
|
||||||
|
Fields = request.Fields,
|
||||||
|
Id = request.Id,
|
||||||
|
Limit = request.Limit,
|
||||||
|
UserId = request.UserId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (item is MusicAlbum)
|
||||||
|
{
|
||||||
|
return new AlbumsService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService)
|
||||||
|
{
|
||||||
|
AuthorizationContext = AuthorizationContext,
|
||||||
|
Logger = Logger,
|
||||||
|
Request = Request,
|
||||||
|
SessionContext = SessionContext,
|
||||||
|
ResultFactory = ResultFactory
|
||||||
|
|
||||||
|
}.Get(new GetSimilarAlbums
|
||||||
|
{
|
||||||
|
Fields = request.Fields,
|
||||||
|
Id = request.Id,
|
||||||
|
Limit = request.Limit,
|
||||||
|
UserId = request.UserId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (item is MusicArtist)
|
||||||
|
{
|
||||||
|
return new AlbumsService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService)
|
||||||
|
{
|
||||||
|
AuthorizationContext = AuthorizationContext,
|
||||||
|
Logger = Logger,
|
||||||
|
Request = Request,
|
||||||
|
SessionContext = SessionContext,
|
||||||
|
ResultFactory = ResultFactory
|
||||||
|
|
||||||
|
}.Get(new GetSimilarArtists
|
||||||
|
{
|
||||||
|
Fields = request.Fields,
|
||||||
|
Id = request.Id,
|
||||||
|
Limit = request.Limit,
|
||||||
|
UserId = request.UserId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var program = item as IHasProgramAttributes;
|
||||||
|
var channelItem = item as ChannelVideoItem;
|
||||||
|
|
||||||
|
if (item is Movie || (program != null && program.IsMovie) || (channelItem != null && channelItem.ContentType == ChannelMediaContentType.Movie) || (channelItem != null && channelItem.ContentType == ChannelMediaContentType.MovieExtra))
|
||||||
|
{
|
||||||
|
return new MoviesService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService, _channelManager)
|
||||||
|
{
|
||||||
|
AuthorizationContext = AuthorizationContext,
|
||||||
|
Logger = Logger,
|
||||||
|
Request = Request,
|
||||||
|
SessionContext = SessionContext,
|
||||||
|
ResultFactory = ResultFactory
|
||||||
|
|
||||||
|
}.Get(new GetSimilarMovies
|
||||||
|
{
|
||||||
|
Fields = request.Fields,
|
||||||
|
Id = request.Id,
|
||||||
|
Limit = request.Limit,
|
||||||
|
UserId = request.UserId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item is Series || (program != null && program.IsSeries) || (channelItem != null && channelItem.ContentType == ChannelMediaContentType.Episode))
|
||||||
|
{
|
||||||
|
return new TvShowsService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService, _tvManager)
|
||||||
|
{
|
||||||
|
AuthorizationContext = AuthorizationContext,
|
||||||
|
Logger = Logger,
|
||||||
|
Request = Request,
|
||||||
|
SessionContext = SessionContext,
|
||||||
|
ResultFactory = ResultFactory
|
||||||
|
|
||||||
|
}.Get(new GetSimilarShows
|
||||||
|
{
|
||||||
|
Fields = request.Fields,
|
||||||
|
Id = request.Id,
|
||||||
|
Limit = request.Limit,
|
||||||
|
UserId = request.UserId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ItemsResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetMediaFolders request)
|
public object Get(GetMediaFolders request)
|
||||||
@ -297,7 +435,59 @@ namespace MediaBrowser.Api.Library
|
|||||||
|
|
||||||
public void Post(PostUpdatedSeries request)
|
public void Post(PostUpdatedSeries request)
|
||||||
{
|
{
|
||||||
Task.Run(() => _libraryManager.ValidateMediaLibrary(new Progress<double>(), CancellationToken.None));
|
var series = _libraryManager.GetItems(new InternalItemsQuery
|
||||||
|
{
|
||||||
|
IncludeItemTypes = new[] { typeof(Series).Name }
|
||||||
|
|
||||||
|
}).Items;
|
||||||
|
|
||||||
|
series = series.Where(i => string.Equals(request.TvdbId, i.GetProviderId(MetadataProviders.Tvdb), StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||||
|
|
||||||
|
if (series.Length > 0)
|
||||||
|
{
|
||||||
|
foreach (var item in series)
|
||||||
|
{
|
||||||
|
_libraryMonitor.ReportFileSystemChanged(item.Path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Task.Run(() => _libraryManager.ValidateMediaLibrary(new Progress<double>(), CancellationToken.None));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Post(PostUpdatedMovies request)
|
||||||
|
{
|
||||||
|
var movies = _libraryManager.GetItems(new InternalItemsQuery
|
||||||
|
{
|
||||||
|
IncludeItemTypes = new[] { typeof(Movie).Name }
|
||||||
|
|
||||||
|
}).Items;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(request.ImdbId))
|
||||||
|
{
|
||||||
|
movies = movies.Where(i => string.Equals(request.ImdbId, i.GetProviderId(MetadataProviders.Imdb), StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||||
|
}
|
||||||
|
else if (!string.IsNullOrWhiteSpace(request.TmdbId))
|
||||||
|
{
|
||||||
|
movies = movies.Where(i => string.Equals(request.TmdbId, i.GetProviderId(MetadataProviders.Tmdb), StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
movies = new BaseItem[] { };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (movies.Length > 0)
|
||||||
|
{
|
||||||
|
foreach (var item in movies)
|
||||||
|
{
|
||||||
|
_libraryMonitor.ReportFileSystemChanged(item.Path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Task.Run(() => _libraryManager.ValidateMediaLibrary(new Progress<double>(), CancellationToken.None));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetDownload request)
|
public object Get(GetDownload request)
|
||||||
@ -524,7 +714,6 @@ namespace MediaBrowser.Api.Library
|
|||||||
public void Delete(DeleteItem request)
|
public void Delete(DeleteItem request)
|
||||||
{
|
{
|
||||||
var item = _libraryManager.GetItemById(request.Id);
|
var item = _libraryManager.GetItemById(request.Id);
|
||||||
|
|
||||||
var auth = _authContext.GetAuthorizationInfo(Request);
|
var auth = _authContext.GetAuthorizationInfo(Request);
|
||||||
var user = _userManager.GetUserById(auth.UserId);
|
var user = _userManager.GetUserById(auth.UserId);
|
||||||
|
|
||||||
@ -533,9 +722,16 @@ namespace MediaBrowser.Api.Library
|
|||||||
throw new UnauthorizedAccessException();
|
throw new UnauthorizedAccessException();
|
||||||
}
|
}
|
||||||
|
|
||||||
var task = _libraryManager.DeleteItem(item);
|
if (item is ILiveTvRecording)
|
||||||
|
{
|
||||||
Task.WaitAll(task);
|
var task = _liveTv.DeleteRecording(request.Id);
|
||||||
|
Task.WaitAll(task);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var task = _libraryManager.DeleteItem(item);
|
||||||
|
Task.WaitAll(task);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Common.Configuration;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.LiveTv;
|
using MediaBrowser.Controller.LiveTv;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
@ -8,6 +10,7 @@ using MediaBrowser.Model.LiveTv;
|
|||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Querying;
|
||||||
using ServiceStack;
|
using ServiceStack;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@ -26,7 +29,7 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
|
|
||||||
[Route("/LiveTv/Channels", "GET", Summary = "Gets available live tv channels.")]
|
[Route("/LiveTv/Channels", "GET", Summary = "Gets available live tv channels.")]
|
||||||
[Authenticated]
|
[Authenticated]
|
||||||
public class GetChannels : IReturn<QueryResult<ChannelInfoDto>>
|
public class GetChannels : IReturn<QueryResult<ChannelInfoDto>>, IHasDtoOptions
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "Type", Description = "Optional filter by channel type.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "Type", Description = "Optional filter by channel type.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
public ChannelType? Type { get; set; }
|
public ChannelType? Type { get; set; }
|
||||||
@ -59,6 +62,30 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
|
|
||||||
[ApiMember(Name = "EnableFavoriteSorting", Description = "Incorporate favorite and like status into channel sorting.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "EnableFavoriteSorting", Description = "Incorporate favorite and like status into channel sorting.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
public bool EnableFavoriteSorting { get; set; }
|
public bool EnableFavoriteSorting { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool? EnableImages { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
||||||
|
public int? ImageTypeLimit { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string EnableImageTypes { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fields to return within the items, in addition to basic information
|
||||||
|
/// </summary>
|
||||||
|
/// <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)]
|
||||||
|
public string Fields { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "AddCurrentProgram", Description = "Optional. Adds current program info to each channel", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool AddCurrentProgram { get; set; }
|
||||||
|
|
||||||
|
public GetChannels()
|
||||||
|
{
|
||||||
|
AddCurrentProgram = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Channels/{Id}", "GET", Summary = "Gets a live tv channel")]
|
[Route("/LiveTv/Channels/{Id}", "GET", Summary = "Gets a live tv channel")]
|
||||||
@ -78,7 +105,7 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
|
|
||||||
[Route("/LiveTv/Recordings", "GET", Summary = "Gets live tv recordings")]
|
[Route("/LiveTv/Recordings", "GET", Summary = "Gets live tv recordings")]
|
||||||
[Authenticated]
|
[Authenticated]
|
||||||
public class GetRecordings : IReturn<QueryResult<BaseItemDto>>
|
public class GetRecordings : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "ChannelId", Description = "Optional filter by channel id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "ChannelId", Description = "Optional filter by channel id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
public string ChannelId { get; set; }
|
public string ChannelId { get; set; }
|
||||||
@ -103,6 +130,22 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
|
|
||||||
[ApiMember(Name = "SeriesTimerId", Description = "Optional filter by recordings belonging to a series timer", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "SeriesTimerId", Description = "Optional filter by recordings belonging to a series timer", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
public string SeriesTimerId { get; set; }
|
public string SeriesTimerId { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool? EnableImages { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
||||||
|
public int? ImageTypeLimit { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string EnableImageTypes { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fields to return within the items, in addition to basic information
|
||||||
|
/// </summary>
|
||||||
|
/// <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)]
|
||||||
|
public string Fields { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Recordings/Groups", "GET", Summary = "Gets live tv recording groups")]
|
[Route("/LiveTv/Recordings/Groups", "GET", Summary = "Gets live tv recording groups")]
|
||||||
@ -161,7 +204,7 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
|
|
||||||
[Route("/LiveTv/Programs", "GET,POST", Summary = "Gets available live tv epgs..")]
|
[Route("/LiveTv/Programs", "GET,POST", Summary = "Gets available live tv epgs..")]
|
||||||
[Authenticated]
|
[Authenticated]
|
||||||
public class GetPrograms : IReturn<QueryResult<BaseItemDto>>
|
public class GetPrograms : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "ChannelIds", Description = "The channels to return guide information for.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
|
[ApiMember(Name = "ChannelIds", Description = "The channels to return guide information for.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
|
||||||
public string ChannelIds { get; set; }
|
public string ChannelIds { get; set; }
|
||||||
@ -187,6 +230,9 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
[ApiMember(Name = "IsMovie", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
[ApiMember(Name = "IsMovie", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||||
public bool? IsMovie { get; set; }
|
public bool? IsMovie { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "IsKids", Description = "Optional filter for kids.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||||
|
public bool? IsKids { get; set; }
|
||||||
|
|
||||||
[ApiMember(Name = "IsSports", Description = "Optional filter for sports.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
[ApiMember(Name = "IsSports", Description = "Optional filter for sports.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||||
public bool? IsSports { get; set; }
|
public bool? IsSports { get; set; }
|
||||||
|
|
||||||
@ -204,11 +250,27 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
|
|
||||||
[ApiMember(Name = "Genres", Description = "The genres to return guide information for.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
|
[ApiMember(Name = "Genres", Description = "The genres to return guide information for.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
|
||||||
public string Genres { get; set; }
|
public string Genres { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool? EnableImages { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
||||||
|
public int? ImageTypeLimit { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string EnableImageTypes { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fields to return within the items, in addition to basic information
|
||||||
|
/// </summary>
|
||||||
|
/// <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)]
|
||||||
|
public string Fields { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Programs/Recommended", "GET", Summary = "Gets available live tv epgs..")]
|
[Route("/LiveTv/Programs/Recommended", "GET", Summary = "Gets available live tv epgs..")]
|
||||||
[Authenticated]
|
[Authenticated]
|
||||||
public class GetRecommendedPrograms : IReturn<QueryResult<BaseItemDto>>
|
public class GetRecommendedPrograms : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "UserId", Description = "Optional filter by user id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
|
[ApiMember(Name = "UserId", Description = "Optional filter by user id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
|
||||||
public string UserId { get; set; }
|
public string UserId { get; set; }
|
||||||
@ -227,6 +289,25 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
|
|
||||||
[ApiMember(Name = "IsMovie", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "IsMovie", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
public bool? IsMovie { get; set; }
|
public bool? IsMovie { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "IsKids", Description = "Optional filter for kids.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool? IsKids { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool? EnableImages { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
||||||
|
public int? ImageTypeLimit { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string EnableImageTypes { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fields to return within the items, in addition to basic information
|
||||||
|
/// </summary>
|
||||||
|
/// <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)]
|
||||||
|
public string Fields { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Programs/{Id}", "GET", Summary = "Gets a live tv program")]
|
[Route("/LiveTv/Programs/{Id}", "GET", Summary = "Gets a live tv program")]
|
||||||
@ -330,15 +411,108 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
public string UserId { get; set; }
|
public string UserId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Route("/LiveTv/TunerHosts", "POST", Summary = "Adds a tuner host")]
|
||||||
|
[Authenticated]
|
||||||
|
public class AddTunerHost : TunerHostInfo, IReturn<TunerHostInfo>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[Route("/LiveTv/TunerHosts", "DELETE", Summary = "Deletes a tuner host")]
|
||||||
|
[Authenticated]
|
||||||
|
public class DeleteTunerHost : IReturnVoid
|
||||||
|
{
|
||||||
|
[ApiMember(Name = "Id", Description = "Tuner host id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "DELETE")]
|
||||||
|
public string Id { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Route("/LiveTv/ListingProviders", "POST", Summary = "Adds a listing provider")]
|
||||||
|
[Authenticated(AllowBeforeStartupWizard = true)]
|
||||||
|
public class AddListingProvider : ListingsProviderInfo, IReturn<ListingsProviderInfo>
|
||||||
|
{
|
||||||
|
public bool ValidateLogin { get; set; }
|
||||||
|
public bool ValidateListings { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Route("/LiveTv/ListingProviders", "DELETE", Summary = "Deletes a listing provider")]
|
||||||
|
[Authenticated(AllowBeforeStartupWizard = true)]
|
||||||
|
public class DeleteListingProvider : IReturnVoid
|
||||||
|
{
|
||||||
|
[ApiMember(Name = "Id", Description = "Provider id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "DELETE")]
|
||||||
|
public string Id { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Route("/LiveTv/ListingProviders/Lineups", "GET", Summary = "Gets available lineups")]
|
||||||
|
[Authenticated(AllowBeforeStartupWizard = true)]
|
||||||
|
public class GetLineups : IReturn<List<NameIdPair>>
|
||||||
|
{
|
||||||
|
[ApiMember(Name = "Id", Description = "Provider id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "Type", Description = "Provider Type", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string Type { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "Location", Description = "Location", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string Location { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "Country", Description = "Country", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string Country { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Route("/LiveTv/ListingProviders/SchedulesDirect/Countries", "GET", Summary = "Gets available lineups")]
|
||||||
|
[Authenticated(AllowBeforeStartupWizard = true)]
|
||||||
|
public class GetSchedulesDirectCountries
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[Route("/LiveTv/Registration", "GET")]
|
||||||
|
[Authenticated]
|
||||||
|
public class GetLiveTvRegistrationInfo : IReturn<MBRegistrationRecord>
|
||||||
|
{
|
||||||
|
[ApiMember(Name = "ChannelId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string ChannelId { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "ProgramId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string ProgramId { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "Feature", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string Feature { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public class LiveTvService : BaseApiService
|
public class LiveTvService : BaseApiService
|
||||||
{
|
{
|
||||||
private readonly ILiveTvManager _liveTvManager;
|
private readonly ILiveTvManager _liveTvManager;
|
||||||
private readonly IUserManager _userManager;
|
private readonly IUserManager _userManager;
|
||||||
|
private readonly IConfigurationManager _config;
|
||||||
|
private readonly IHttpClient _httpClient;
|
||||||
|
|
||||||
public LiveTvService(ILiveTvManager liveTvManager, IUserManager userManager)
|
public LiveTvService(ILiveTvManager liveTvManager, IUserManager userManager, IConfigurationManager config, IHttpClient httpClient)
|
||||||
{
|
{
|
||||||
_liveTvManager = liveTvManager;
|
_liveTvManager = liveTvManager;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
|
_config = config;
|
||||||
|
_httpClient = httpClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<object> Get(GetLiveTvRegistrationInfo request)
|
||||||
|
{
|
||||||
|
var result = await _liveTvManager.GetRegistrationInfo(request.ChannelId, request.ProgramId, request.Feature).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return ToOptimizedResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<object> Get(GetSchedulesDirectCountries request)
|
||||||
|
{
|
||||||
|
// https://json.schedulesdirect.org/20141201/available/countries
|
||||||
|
|
||||||
|
var response = await _httpClient.Get(new HttpRequestOptions
|
||||||
|
{
|
||||||
|
Url = "https://json.schedulesdirect.org/20141201/available/countries",
|
||||||
|
CacheLength = TimeSpan.FromDays(1),
|
||||||
|
CacheMode = CacheMode.Unconditional
|
||||||
|
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return ResultFactory.GetResult(response, "application/json");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AssertUserCanManageLiveTv()
|
private void AssertUserCanManageLiveTv()
|
||||||
@ -356,6 +530,48 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<object> Post(AddListingProvider request)
|
||||||
|
{
|
||||||
|
var result = await _liveTvManager.SaveListingProvider(request, request.ValidateLogin, request.ValidateListings).ConfigureAwait(false);
|
||||||
|
return ToOptimizedResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Delete(DeleteListingProvider request)
|
||||||
|
{
|
||||||
|
var config = GetConfiguration();
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
var result = await _liveTvManager.SaveTunerHost(request).ConfigureAwait(false);
|
||||||
|
return ToOptimizedResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Delete(DeleteTunerHost request)
|
||||||
|
{
|
||||||
|
var config = GetConfiguration();
|
||||||
|
|
||||||
|
config.TunerHosts = config.TunerHosts.Where(i => !string.Equals(request.Id, i.Id, StringComparison.OrdinalIgnoreCase)).ToList();
|
||||||
|
|
||||||
|
_config.SaveConfiguration("livetv", config);
|
||||||
|
}
|
||||||
|
|
||||||
|
private LiveTvOptions GetConfiguration()
|
||||||
|
{
|
||||||
|
return _config.GetConfiguration<LiveTvOptions>("livetv");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<object> Get(GetLineups request)
|
||||||
|
{
|
||||||
|
var info = await _liveTvManager.GetLineups(request.Type, request.Id, request.Country, request.Location).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return ToOptimizedSerializedResultUsingCache(info);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<object> Get(GetLiveTvInfo request)
|
public async Task<object> Get(GetLiveTvInfo request)
|
||||||
{
|
{
|
||||||
var info = await _liveTvManager.GetLiveTvInfo(CancellationToken.None).ConfigureAwait(false);
|
var info = await _liveTvManager.GetLiveTvInfo(CancellationToken.None).ConfigureAwait(false);
|
||||||
@ -374,9 +590,10 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
IsFavorite = request.IsFavorite,
|
IsFavorite = request.IsFavorite,
|
||||||
IsLiked = request.IsLiked,
|
IsLiked = request.IsLiked,
|
||||||
IsDisliked = request.IsDisliked,
|
IsDisliked = request.IsDisliked,
|
||||||
EnableFavoriteSorting = request.EnableFavoriteSorting
|
EnableFavoriteSorting = request.EnableFavoriteSorting,
|
||||||
|
AddCurrentProgram = request.AddCurrentProgram
|
||||||
|
|
||||||
}, CancellationToken.None).ConfigureAwait(false);
|
}, GetDtoOptions(request), CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
}
|
}
|
||||||
@ -429,10 +646,11 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
query.SortBy = (request.SortBy ?? String.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
query.SortBy = (request.SortBy ?? String.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
query.SortOrder = request.SortOrder;
|
query.SortOrder = request.SortOrder;
|
||||||
query.IsMovie = request.IsMovie;
|
query.IsMovie = request.IsMovie;
|
||||||
|
query.IsKids = request.IsKids;
|
||||||
query.IsSports = request.IsSports;
|
query.IsSports = request.IsSports;
|
||||||
query.Genres = (request.Genres ?? String.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
query.Genres = (request.Genres ?? String.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
var result = await _liveTvManager.GetPrograms(query, CancellationToken.None).ConfigureAwait(false);
|
var result = await _liveTvManager.GetPrograms(query, GetDtoOptions(request), CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
@ -446,10 +664,11 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
Limit = request.Limit,
|
Limit = request.Limit,
|
||||||
HasAired = request.HasAired,
|
HasAired = request.HasAired,
|
||||||
IsMovie = request.IsMovie,
|
IsMovie = request.IsMovie,
|
||||||
|
IsKids = request.IsKids,
|
||||||
IsSports = request.IsSports
|
IsSports = request.IsSports
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = await _liveTvManager.GetRecommendedPrograms(query, CancellationToken.None).ConfigureAwait(false);
|
var result = await _liveTvManager.GetRecommendedPrograms(query, GetDtoOptions(request), CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
@ -461,7 +680,7 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
|
|
||||||
public async Task<object> Get(GetRecordings request)
|
public async Task<object> Get(GetRecordings request)
|
||||||
{
|
{
|
||||||
var options = new DtoOptions();
|
var options = GetDtoOptions(request);
|
||||||
options.DeviceId = AuthorizationContext.GetAuthorizationInfo(Request).DeviceId;
|
options.DeviceId = AuthorizationContext.GetAuthorizationInfo(Request).DeviceId;
|
||||||
|
|
||||||
var result = await _liveTvManager.GetRecordings(new RecordingQuery
|
var result = await _liveTvManager.GetRecordings(new RecordingQuery
|
||||||
|
@ -84,22 +84,26 @@
|
|||||||
<Compile Include="Playback\MediaInfoService.cs" />
|
<Compile Include="Playback\MediaInfoService.cs" />
|
||||||
<Compile Include="Playback\TranscodingThrottler.cs" />
|
<Compile Include="Playback\TranscodingThrottler.cs" />
|
||||||
<Compile Include="PlaylistService.cs" />
|
<Compile Include="PlaylistService.cs" />
|
||||||
|
<Compile Include="Reports\Activities\ReportActivitiesBuilder.cs" />
|
||||||
|
<Compile Include="Reports\Common\HeaderActivitiesMetadata.cs" />
|
||||||
<Compile Include="Reports\Common\HeaderMetadata.cs" />
|
<Compile Include="Reports\Common\HeaderMetadata.cs" />
|
||||||
<Compile Include="Reports\Common\ItemViewType.cs" />
|
<Compile Include="Reports\Common\ItemViewType.cs" />
|
||||||
<Compile Include="Reports\Common\ReportBuilderBase.cs" />
|
<Compile Include="Reports\Common\ReportBuilderBase.cs" />
|
||||||
|
<Compile Include="Reports\Common\ReportDisplayType.cs" />
|
||||||
<Compile Include="Reports\Common\ReportExportType.cs" />
|
<Compile Include="Reports\Common\ReportExportType.cs" />
|
||||||
<Compile Include="Reports\Common\ReportFieldType.cs" />
|
<Compile Include="Reports\Common\ReportFieldType.cs" />
|
||||||
<Compile Include="Reports\Common\ReportHeaderIdType.cs" />
|
<Compile Include="Reports\Common\ReportHeaderIdType.cs" />
|
||||||
<Compile Include="Reports\Common\ReportHelper.cs" />
|
<Compile Include="Reports\Common\ReportHelper.cs" />
|
||||||
|
<Compile Include="Reports\Common\ReportIncludeItemTypes.cs" />
|
||||||
<Compile Include="Reports\Common\ReportViewType.cs" />
|
<Compile Include="Reports\Common\ReportViewType.cs" />
|
||||||
<Compile Include="Reports\Data\ReportBuilder.cs" />
|
<Compile Include="Reports\Data\ReportBuilder.cs" />
|
||||||
<Compile Include="Reports\Data\ReportExport.cs" />
|
<Compile Include="Reports\Data\ReportExport.cs" />
|
||||||
<Compile Include="Reports\Data\ReportGroup.cs" />
|
|
||||||
<Compile Include="Reports\Data\ReportHeader.cs" />
|
|
||||||
<Compile Include="Reports\Data\ReportItem.cs" />
|
|
||||||
<Compile Include="Reports\Data\ReportOptions.cs" />
|
<Compile Include="Reports\Data\ReportOptions.cs" />
|
||||||
<Compile Include="Reports\Data\ReportResult.cs" />
|
<Compile Include="Reports\Model\ReportGroup.cs" />
|
||||||
<Compile Include="Reports\Data\ReportRow.cs" />
|
<Compile Include="Reports\Model\ReportHeader.cs" />
|
||||||
|
<Compile Include="Reports\Model\ReportItem.cs" />
|
||||||
|
<Compile Include="Reports\Model\ReportResult.cs" />
|
||||||
|
<Compile Include="Reports\Model\ReportRow.cs" />
|
||||||
<Compile Include="Reports\ReportRequests.cs" />
|
<Compile Include="Reports\ReportRequests.cs" />
|
||||||
<Compile Include="Reports\ReportsService.cs" />
|
<Compile Include="Reports\ReportsService.cs" />
|
||||||
<Compile Include="Reports\Stat\ReportStatBuilder.cs" />
|
<Compile Include="Reports\Stat\ReportStatBuilder.cs" />
|
||||||
|
@ -28,6 +28,14 @@ namespace MediaBrowser.Api.Movies
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Class GetSimilarTrailers
|
||||||
|
/// </summary>
|
||||||
|
[Route("/Trailers/{Id}/Similar", "GET", Summary = "Finds movies and trailers similar to a given trailer.")]
|
||||||
|
public class GetSimilarTrailers : BaseGetSimilarItemsFromItem
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
[Route("/Movies/Recommendations", "GET", Summary = "Gets movie recommendations")]
|
[Route("/Movies/Recommendations", "GET", Summary = "Gets movie recommendations")]
|
||||||
public class GetMovieRecommendations : IReturn<RecommendationDto[]>, IHasItemFields
|
public class GetMovieRecommendations : IReturn<RecommendationDto[]>, IHasItemFields
|
||||||
{
|
{
|
||||||
@ -117,6 +125,17 @@ namespace MediaBrowser.Api.Movies
|
|||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<object> Get(GetSimilarTrailers request)
|
||||||
|
{
|
||||||
|
var result = await GetSimilarItemsResult(
|
||||||
|
// Strip out secondary versions
|
||||||
|
request, item => (item is Movie) && !((Video)item).PrimaryVersionId.HasValue,
|
||||||
|
|
||||||
|
SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<object> Get(GetMovieRecommendations request)
|
public async Task<object> Get(GetMovieRecommendations request)
|
||||||
{
|
{
|
||||||
var user = _userManager.GetUserById(request.UserId);
|
var user = _userManager.GetUserById(request.UserId);
|
||||||
@ -126,7 +145,7 @@ namespace MediaBrowser.Api.Movies
|
|||||||
movies = _libraryManager.ReplaceVideosWithPrimaryVersions(movies);
|
movies = _libraryManager.ReplaceVideosWithPrimaryVersions(movies);
|
||||||
|
|
||||||
var listEligibleForCategories = new List<BaseItem>();
|
var listEligibleForCategories = new List<BaseItem>();
|
||||||
var listEligibleForSuggestion = new List<BaseItem> ();
|
var listEligibleForSuggestion = new List<BaseItem>();
|
||||||
|
|
||||||
var list = movies.ToList();
|
var list = movies.ToList();
|
||||||
|
|
||||||
@ -159,7 +178,7 @@ namespace MediaBrowser.Api.Movies
|
|||||||
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, listEligibleForCategories, listEligibleForSuggestion, request.CategoryLimit, request.ItemLimit, dtoOptions);
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
@ -174,14 +193,14 @@ namespace MediaBrowser.Api.Movies
|
|||||||
_libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
|
_libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
|
||||||
|
|
||||||
Func<BaseItem, bool> filter = i => i.Id != item.Id && includeInSearch(i);
|
Func<BaseItem, bool> filter = i => i.Id != item.Id && includeInSearch(i);
|
||||||
|
|
||||||
var inputItems = user == null
|
var inputItems = user == null
|
||||||
? _libraryManager.RootFolder.GetRecursiveChildren(filter)
|
? _libraryManager.RootFolder.GetRecursiveChildren(filter)
|
||||||
: user.RootFolder.GetRecursiveChildren(user, filter);
|
: user.RootFolder.GetRecursiveChildren(user, filter);
|
||||||
|
|
||||||
var list = inputItems.ToList();
|
var list = inputItems.ToList();
|
||||||
|
|
||||||
if (item is Movie && user != null && user.Configuration.IncludeTrailersInSuggestions)
|
if (user != null && user.Configuration.IncludeTrailersInSuggestions)
|
||||||
{
|
{
|
||||||
var trailerResult = await _channelManager.GetAllMediaInternal(new AllChannelMediaQuery
|
var trailerResult = await _channelManager.GetAllMediaInternal(new AllChannelMediaQuery
|
||||||
{
|
{
|
||||||
@ -224,7 +243,7 @@ namespace MediaBrowser.Api.Movies
|
|||||||
}
|
}
|
||||||
|
|
||||||
var dtoOptions = GetDtoOptions(request);
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
var result = new ItemsResult
|
var result = new ItemsResult
|
||||||
{
|
{
|
||||||
Items = _dtoService.GetBaseItemDtos(returnItems, dtoOptions, user).ToArray(),
|
Items = _dtoService.GetBaseItemDtos(returnItems, dtoOptions, user).ToArray(),
|
||||||
|
@ -2,15 +2,12 @@
|
|||||||
using MediaBrowser.Controller.Channels;
|
using MediaBrowser.Controller.Channels;
|
||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.Movies;
|
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
using MediaBrowser.Controller.Persistence;
|
|
||||||
using MediaBrowser.Model.Channels;
|
using MediaBrowser.Model.Channels;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Querying;
|
||||||
using ServiceStack;
|
using ServiceStack;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@ -18,23 +15,9 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace MediaBrowser.Api.Movies
|
namespace MediaBrowser.Api.Movies
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Class GetSimilarTrailers
|
|
||||||
/// </summary>
|
|
||||||
[Route("/Trailers/{Id}/Similar", "GET", Summary = "Finds movies and trailers similar to a given trailer.")]
|
|
||||||
public class GetSimilarTrailers : BaseGetSimilarItemsFromItem
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[Route("/Trailers", "GET", Summary = "Finds movies and trailers similar to a given trailer.")]
|
[Route("/Trailers", "GET", Summary = "Finds movies and trailers similar to a given trailer.")]
|
||||||
public class Getrailers : BaseItemsRequest, IReturn<ItemsResult>
|
public class Getrailers : BaseItemsRequest, IReturn<ItemsResult>
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the user id.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The user id.</value>
|
|
||||||
[ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")]
|
|
||||||
public string UserId { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -57,7 +40,6 @@ namespace MediaBrowser.Api.Movies
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
|
|
||||||
private readonly IItemRepository _itemRepo;
|
|
||||||
private readonly IDtoService _dtoService;
|
private readonly IDtoService _dtoService;
|
||||||
private readonly IChannelManager _channelManager;
|
private readonly IChannelManager _channelManager;
|
||||||
|
|
||||||
@ -67,40 +49,15 @@ namespace MediaBrowser.Api.Movies
|
|||||||
/// <param name="userManager">The user manager.</param>
|
/// <param name="userManager">The user manager.</param>
|
||||||
/// <param name="userDataRepository">The user data repository.</param>
|
/// <param name="userDataRepository">The user data repository.</param>
|
||||||
/// <param name="libraryManager">The library manager.</param>
|
/// <param name="libraryManager">The library manager.</param>
|
||||||
public TrailersService(IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, IItemRepository itemRepo, IDtoService dtoService, IChannelManager channelManager)
|
public TrailersService(IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, IDtoService dtoService, IChannelManager channelManager)
|
||||||
{
|
{
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
_userDataRepository = userDataRepository;
|
_userDataRepository = userDataRepository;
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_itemRepo = itemRepo;
|
|
||||||
_dtoService = dtoService;
|
_dtoService = dtoService;
|
||||||
_channelManager = channelManager;
|
_channelManager = channelManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the specified request.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="request">The request.</param>
|
|
||||||
/// <returns>System.Object.</returns>
|
|
||||||
public object Get(GetSimilarTrailers request)
|
|
||||||
{
|
|
||||||
var dtoOptions = GetDtoOptions(request);
|
|
||||||
|
|
||||||
var result = SimilarItemsHelper.GetSimilarItemsResult(dtoOptions, _userManager,
|
|
||||||
_itemRepo,
|
|
||||||
_libraryManager,
|
|
||||||
_userDataRepository,
|
|
||||||
_dtoService,
|
|
||||||
Logger,
|
|
||||||
|
|
||||||
// Strip out secondary versions
|
|
||||||
request, item => (item is Movie) && !((Video)item).PrimaryVersionId.HasValue,
|
|
||||||
|
|
||||||
SimilarItemsHelper.GetSimiliarityScore);
|
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<object> Get(Getrailers request)
|
public async Task<object> Get(Getrailers request)
|
||||||
{
|
{
|
||||||
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
|
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
|
||||||
|
@ -4,6 +4,7 @@ using MediaBrowser.Controller.Entities.Audio;
|
|||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
using MediaBrowser.Controller.Persistence;
|
using MediaBrowser.Controller.Persistence;
|
||||||
|
using MediaBrowser.Model.Querying;
|
||||||
using ServiceStack;
|
using ServiceStack;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -16,6 +17,11 @@ namespace MediaBrowser.Api.Music
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Route("/Artists/{Id}/Similar", "GET", Summary = "Finds albums similar to a given album.")]
|
||||||
|
public class GetSimilarArtists : BaseGetSimilarItemsFromItem
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
[Authenticated]
|
[Authenticated]
|
||||||
public class AlbumsService : BaseApiService
|
public class AlbumsService : BaseApiService
|
||||||
{
|
{
|
||||||
@ -44,6 +50,17 @@ namespace MediaBrowser.Api.Music
|
|||||||
_dtoService = dtoService;
|
_dtoService = dtoService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public object Get(GetSimilarArtists request)
|
||||||
|
{
|
||||||
|
var result = GetSimilarItemsResult(
|
||||||
|
|
||||||
|
request,
|
||||||
|
|
||||||
|
SimilarItemsHelper.GetSimiliarityScore);
|
||||||
|
|
||||||
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the specified request.
|
/// Gets the specified request.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -65,6 +82,39 @@ namespace MediaBrowser.Api.Music
|
|||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ItemsResult GetSimilarItemsResult(BaseGetSimilarItemsFromItem request, Func<BaseItem, List<PersonInfo>, List<PersonInfo>, BaseItem, int> getSimilarityScore)
|
||||||
|
{
|
||||||
|
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 inputItems = _libraryManager.GetArtists(user.RootFolder.GetRecursiveChildren(user, i => i is IHasArtist).OfType<IHasArtist>());
|
||||||
|
|
||||||
|
var list = inputItems.ToList();
|
||||||
|
|
||||||
|
var items = SimilarItemsHelper.GetSimilaritems(item, _libraryManager, list, getSimilarityScore).ToList();
|
||||||
|
|
||||||
|
IEnumerable<BaseItem> returnItems = items;
|
||||||
|
|
||||||
|
if (request.Limit.HasValue)
|
||||||
|
{
|
||||||
|
returnItems = returnItems.Take(request.Limit.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
|
var result = new ItemsResult
|
||||||
|
{
|
||||||
|
Items = _dtoService.GetBaseItemDtos(returnItems, dtoOptions, user).ToArray(),
|
||||||
|
|
||||||
|
TotalRecordCount = items.Count
|
||||||
|
};
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the album similarity score.
|
/// Gets the album similarity score.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -54,6 +54,11 @@ namespace MediaBrowser.Api.Music
|
|||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Route("/Items/{Id}/InstantMix", "GET", Summary = "Creates an instant playlist based on a given item")]
|
||||||
|
public class GetInstantMixFromItem : BaseGetSimilarItemsFromItem
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
[Authenticated]
|
[Authenticated]
|
||||||
public class InstantMixService : BaseApiService
|
public class InstantMixService : BaseApiService
|
||||||
{
|
{
|
||||||
@ -71,6 +76,17 @@ namespace MediaBrowser.Api.Music
|
|||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public object Get(GetInstantMixFromItem request)
|
||||||
|
{
|
||||||
|
var item = _libraryManager.GetItemById(request.Id);
|
||||||
|
|
||||||
|
var user = _userManager.GetUserById(request.UserId);
|
||||||
|
|
||||||
|
var items = _musicManager.GetInstantMixFromItem(item, user);
|
||||||
|
|
||||||
|
return GetResult(items, user, request);
|
||||||
|
}
|
||||||
|
|
||||||
public object Get(GetInstantMixFromArtistId request)
|
public object Get(GetInstantMixFromArtistId request)
|
||||||
{
|
{
|
||||||
var item = _libraryManager.GetItemById(request.Id);
|
var item = _libraryManager.GetItemById(request.Id);
|
||||||
@ -138,8 +154,9 @@ namespace MediaBrowser.Api.Music
|
|||||||
public object Get(GetInstantMixFromArtist request)
|
public object Get(GetInstantMixFromArtist request)
|
||||||
{
|
{
|
||||||
var user = _userManager.GetUserById(request.UserId);
|
var user = _userManager.GetUserById(request.UserId);
|
||||||
|
var artist = _libraryManager.GetArtist(request.Name);
|
||||||
|
|
||||||
var items = _musicManager.GetInstantMixFromArtist(request.Name, user);
|
var items = _musicManager.GetInstantMixFromArtist(artist, user);
|
||||||
|
|
||||||
return GetResult(items, user, request);
|
return GetResult(items, user, request);
|
||||||
}
|
}
|
||||||
|
@ -190,7 +190,7 @@ namespace MediaBrowser.Api
|
|||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public async Task<object> Get(GetPackages request)
|
public async Task<object> Get(GetPackages request)
|
||||||
{
|
{
|
||||||
var packages = await _installationManager.GetAvailablePackages(CancellationToken.None, request.PackageType, _appHost.ApplicationVersion).ConfigureAwait(false);
|
var packages = await _installationManager.GetAvailablePackages(CancellationToken.None, false, request.PackageType, _appHost.ApplicationVersion).ConfigureAwait(false);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(request.TargetSystems))
|
if (!string.IsNullOrEmpty(request.TargetSystems))
|
||||||
{
|
{
|
||||||
|
@ -263,38 +263,27 @@ namespace MediaBrowser.Api.Playback
|
|||||||
return returnFirstIfNoIndex ? streams.FirstOrDefault() : null;
|
return returnFirstIfNoIndex ? streams.FirstOrDefault() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected EncodingQuality GetQualitySetting()
|
|
||||||
{
|
|
||||||
var quality = ApiEntryPoint.Instance.GetEncodingOptions().EncodingQuality;
|
|
||||||
|
|
||||||
if (quality == EncodingQuality.Auto)
|
|
||||||
{
|
|
||||||
var cpuCount = Environment.ProcessorCount;
|
|
||||||
|
|
||||||
if (cpuCount >= 4)
|
|
||||||
{
|
|
||||||
//return EncodingQuality.HighQuality;
|
|
||||||
}
|
|
||||||
|
|
||||||
return EncodingQuality.HighSpeed;
|
|
||||||
}
|
|
||||||
|
|
||||||
return quality;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the number of threads.
|
/// Gets the number of threads.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>System.Int32.</returns>
|
/// <returns>System.Int32.</returns>
|
||||||
protected int GetNumberOfThreads(StreamState state, bool isWebm)
|
protected int GetNumberOfThreads(StreamState state, bool isWebm)
|
||||||
{
|
{
|
||||||
|
var threads = ApiEntryPoint.Instance.GetEncodingOptions().EncodingThreadCount;
|
||||||
|
|
||||||
if (isWebm)
|
if (isWebm)
|
||||||
{
|
{
|
||||||
// Recommended per docs
|
// Recommended per docs
|
||||||
return Math.Max(Environment.ProcessorCount - 1, 2);
|
return Math.Max(Environment.ProcessorCount - 1, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
// Automatic
|
||||||
|
if (threads == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return threads;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected string H264Encoder
|
protected string H264Encoder
|
||||||
@ -326,77 +315,31 @@ namespace MediaBrowser.Api.Playback
|
|||||||
var isVc1 = state.VideoStream != null &&
|
var isVc1 = state.VideoStream != null &&
|
||||||
string.Equals(state.VideoStream.Codec, "vc1", StringComparison.OrdinalIgnoreCase);
|
string.Equals(state.VideoStream.Codec, "vc1", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
var qualitySetting = GetQualitySetting();
|
|
||||||
|
|
||||||
if (string.Equals(videoCodec, "libx264", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(videoCodec, "libx264", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
param = "-preset superfast";
|
param = "-preset superfast";
|
||||||
|
|
||||||
switch (qualitySetting)
|
param += " -crf 23";
|
||||||
{
|
|
||||||
case EncodingQuality.HighSpeed:
|
|
||||||
param += " -crf 23";
|
|
||||||
break;
|
|
||||||
case EncodingQuality.HighQuality:
|
|
||||||
param += " -crf 20";
|
|
||||||
break;
|
|
||||||
case EncodingQuality.MaxQuality:
|
|
||||||
param += " -crf 18";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (string.Equals(videoCodec, "libx265", StringComparison.OrdinalIgnoreCase))
|
else if (string.Equals(videoCodec, "libx265", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
param = "-preset fast";
|
param = "-preset fast";
|
||||||
|
|
||||||
switch (qualitySetting)
|
param += " -crf 28";
|
||||||
{
|
|
||||||
case EncodingQuality.HighSpeed:
|
|
||||||
param += " -crf 28";
|
|
||||||
break;
|
|
||||||
case EncodingQuality.HighQuality:
|
|
||||||
param += " -crf 25";
|
|
||||||
break;
|
|
||||||
case EncodingQuality.MaxQuality:
|
|
||||||
param += " -crf 21";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// h264 (h264_qsv)
|
// h264 (h264_qsv)
|
||||||
else if (string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase))
|
else if (string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
switch (qualitySetting)
|
param = "-preset 7";
|
||||||
{
|
|
||||||
case EncodingQuality.HighSpeed:
|
|
||||||
param = "-preset 7";
|
|
||||||
break;
|
|
||||||
case EncodingQuality.HighQuality:
|
|
||||||
param = "-preset 4";
|
|
||||||
break;
|
|
||||||
case EncodingQuality.MaxQuality:
|
|
||||||
param = "-preset 1";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// h264 (libnvenc)
|
// h264 (libnvenc)
|
||||||
else if (string.Equals(videoCodec, "libnvenc", StringComparison.OrdinalIgnoreCase))
|
else if (string.Equals(videoCodec, "libnvenc", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
switch (qualitySetting)
|
param = "-preset high-performance";
|
||||||
{
|
|
||||||
case EncodingQuality.HighSpeed:
|
|
||||||
param = "-preset high-performance";
|
|
||||||
break;
|
|
||||||
case EncodingQuality.HighQuality:
|
|
||||||
param = "";
|
|
||||||
break;
|
|
||||||
case EncodingQuality.MaxQuality:
|
|
||||||
param = "-preset high-quality";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// webm
|
// webm
|
||||||
@ -409,20 +352,7 @@ namespace MediaBrowser.Api.Playback
|
|||||||
var qmin = "0";
|
var qmin = "0";
|
||||||
var qmax = "50";
|
var qmax = "50";
|
||||||
|
|
||||||
switch (qualitySetting)
|
crf = "10";
|
||||||
{
|
|
||||||
case EncodingQuality.HighSpeed:
|
|
||||||
crf = "10";
|
|
||||||
break;
|
|
||||||
case EncodingQuality.HighQuality:
|
|
||||||
crf = "6";
|
|
||||||
break;
|
|
||||||
case EncodingQuality.MaxQuality:
|
|
||||||
crf = "4";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new ArgumentException("Unrecognized quality setting");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isVc1)
|
if (isVc1)
|
||||||
{
|
{
|
||||||
@ -689,7 +619,7 @@ namespace MediaBrowser.Api.Playback
|
|||||||
|
|
||||||
// TODO: Perhaps also use original_size=1920x800 ??
|
// TODO: Perhaps also use original_size=1920x800 ??
|
||||||
return string.Format("subtitles=filename='{0}'{1},setpts=PTS -{2}/TB",
|
return string.Format("subtitles=filename='{0}'{1},setpts=PTS -{2}/TB",
|
||||||
subtitlePath.Replace('\\', '/').Replace("'", "\\'").Replace(":/", "\\:/"),
|
MediaEncoder.EscapeSubtitleFilterPath(subtitlePath),
|
||||||
charsetParam,
|
charsetParam,
|
||||||
seconds.ToString(UsCulture));
|
seconds.ToString(UsCulture));
|
||||||
}
|
}
|
||||||
@ -697,7 +627,7 @@ namespace MediaBrowser.Api.Playback
|
|||||||
var mediaPath = state.MediaPath ?? string.Empty;
|
var mediaPath = state.MediaPath ?? string.Empty;
|
||||||
|
|
||||||
return string.Format("subtitles='{0}:si={1}',setpts=PTS -{2}/TB",
|
return string.Format("subtitles='{0}:si={1}',setpts=PTS -{2}/TB",
|
||||||
mediaPath.Replace('\\', '/').Replace("'", "\\'").Replace(":/", "\\:/"),
|
MediaEncoder.EscapeSubtitleFilterPath(mediaPath),
|
||||||
state.InternalSubtitleStreamOffset.ToString(UsCulture),
|
state.InternalSubtitleStreamOffset.ToString(UsCulture),
|
||||||
seconds.ToString(UsCulture));
|
seconds.ToString(UsCulture));
|
||||||
}
|
}
|
||||||
@ -794,7 +724,7 @@ namespace MediaBrowser.Api.Playback
|
|||||||
|
|
||||||
var channelLimit = codec.IndexOf("mp3", StringComparison.OrdinalIgnoreCase) != -1
|
var channelLimit = codec.IndexOf("mp3", StringComparison.OrdinalIgnoreCase) != -1
|
||||||
? 2
|
? 2
|
||||||
: 5;
|
: 6;
|
||||||
|
|
||||||
// If we don't have any media info then limit it to 5 to prevent encoding errors due to asking for too many channels
|
// If we don't have any media info then limit it to 5 to prevent encoding errors due to asking for too many channels
|
||||||
return Math.Min(request.MaxAudioChannels.Value, channelLimit);
|
return Math.Min(request.MaxAudioChannels.Value, channelLimit);
|
||||||
@ -819,11 +749,11 @@ namespace MediaBrowser.Api.Playback
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the audio encoder.
|
/// Gets the audio encoder.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">The request.</param>
|
/// <param name="state">The state.</param>
|
||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
protected string GetAudioEncoder(StreamRequest request)
|
protected string GetAudioEncoder(StreamState state)
|
||||||
{
|
{
|
||||||
var codec = request.AudioCodec;
|
var codec = state.OutputAudioCodec;
|
||||||
|
|
||||||
if (string.Equals(codec, "aac", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(codec, "aac", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
@ -848,11 +778,11 @@ namespace MediaBrowser.Api.Playback
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the name of the output video codec
|
/// Gets the name of the output video codec
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">The request.</param>
|
/// <param name="state">The state.</param>
|
||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
protected string GetVideoEncoder(VideoStreamRequest request)
|
protected string GetVideoEncoder(StreamState state)
|
||||||
{
|
{
|
||||||
var codec = request.VideoCodec;
|
var codec = state.OutputVideoCodec;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(codec))
|
if (!string.IsNullOrEmpty(codec))
|
||||||
{
|
{
|
||||||
@ -924,7 +854,7 @@ namespace MediaBrowser.Api.Playback
|
|||||||
state.IsoMount = await IsoManager.Mount(state.MediaPath, cancellationTokenSource.Token).ConfigureAwait(false);
|
state.IsoMount = await IsoManager.Mount(state.MediaPath, cancellationTokenSource.Token).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.MediaSource.RequiresOpening)
|
if (state.MediaSource.RequiresOpening && string.IsNullOrWhiteSpace(state.Request.LiveStreamId))
|
||||||
{
|
{
|
||||||
var liveStreamResponse = await MediaSourceManager.OpenLiveStream(new LiveStreamRequest
|
var liveStreamResponse = await MediaSourceManager.OpenLiveStream(new LiveStreamRequest
|
||||||
{
|
{
|
||||||
@ -1704,11 +1634,6 @@ namespace MediaBrowser.Api.Playback
|
|||||||
|
|
||||||
private void TryStreamCopy(StreamState state, VideoStreamRequest videoRequest)
|
private void TryStreamCopy(StreamState state, VideoStreamRequest videoRequest)
|
||||||
{
|
{
|
||||||
if (!EnableStreamCopy)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.VideoStream != null && CanStreamCopyVideo(videoRequest, state.VideoStream))
|
if (state.VideoStream != null && CanStreamCopyVideo(videoRequest, state.VideoStream))
|
||||||
{
|
{
|
||||||
state.OutputVideoCodec = "copy";
|
state.OutputVideoCodec = "copy";
|
||||||
@ -1720,14 +1645,6 @@ namespace MediaBrowser.Api.Playback
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual bool EnableStreamCopy
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AttachMediaSourceInfo(StreamState state,
|
private void AttachMediaSourceInfo(StreamState state,
|
||||||
MediaSourceInfo mediaSource,
|
MediaSourceInfo mediaSource,
|
||||||
VideoStreamRequest videoRequest,
|
VideoStreamRequest videoRequest,
|
||||||
@ -1811,13 +1728,18 @@ namespace MediaBrowser.Api.Playback
|
|||||||
state.MediaSource = mediaSource;
|
state.MediaSource = mediaSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool CanStreamCopyVideo(VideoStreamRequest request, MediaStream videoStream)
|
protected virtual bool CanStreamCopyVideo(VideoStreamRequest request, MediaStream videoStream)
|
||||||
{
|
{
|
||||||
if (videoStream.IsInterlaced)
|
if (videoStream.IsInterlaced)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (videoStream.IsAnamorphic ?? false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Can't stream copy if we're burning in subtitles
|
// Can't stream copy if we're burning in subtitles
|
||||||
if (request.SubtitleStreamIndex.HasValue)
|
if (request.SubtitleStreamIndex.HasValue)
|
||||||
{
|
{
|
||||||
@ -1954,7 +1876,7 @@ namespace MediaBrowser.Api.Playback
|
|||||||
return Array.FindIndex(list.ToArray(), t => string.Equals(t, profile, StringComparison.OrdinalIgnoreCase));
|
return Array.FindIndex(list.ToArray(), t => string.Equals(t, profile, StringComparison.OrdinalIgnoreCase));
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool CanStreamCopyAudio(VideoStreamRequest request, MediaStream audioStream, List<string> supportedAudioCodecs)
|
protected virtual bool CanStreamCopyAudio(VideoStreamRequest request, MediaStream audioStream, List<string> supportedAudioCodecs)
|
||||||
{
|
{
|
||||||
// Source and target codecs must match
|
// Source and target codecs must match
|
||||||
if (string.IsNullOrEmpty(audioStream.Codec) || !supportedAudioCodecs.Contains(audioStream.Codec, StringComparer.OrdinalIgnoreCase))
|
if (string.IsNullOrEmpty(audioStream.Codec) || !supportedAudioCodecs.Contains(audioStream.Codec, StringComparer.OrdinalIgnoreCase))
|
||||||
|
@ -378,7 +378,7 @@ namespace MediaBrowser.Api.Playback.Dash
|
|||||||
|
|
||||||
protected override string GetAudioArguments(StreamState state)
|
protected override string GetAudioArguments(StreamState state)
|
||||||
{
|
{
|
||||||
var codec = GetAudioEncoder(state.Request);
|
var codec = GetAudioEncoder(state);
|
||||||
|
|
||||||
if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
@ -408,7 +408,7 @@ namespace MediaBrowser.Api.Playback.Dash
|
|||||||
|
|
||||||
protected override string GetVideoArguments(StreamState state)
|
protected override string GetVideoArguments(StreamState state)
|
||||||
{
|
{
|
||||||
var codec = GetVideoEncoder(state.VideoRequest);
|
var codec = GetVideoEncoder(state);
|
||||||
|
|
||||||
var args = "-codec:v:0 " + codec;
|
var args = "-codec:v:0 " + codec;
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ using MediaBrowser.Controller.Devices;
|
|||||||
using MediaBrowser.Controller.Dlna;
|
using MediaBrowser.Controller.Dlna;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.MediaEncoding;
|
using MediaBrowser.Controller.MediaEncoding;
|
||||||
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Extensions;
|
using MediaBrowser.Model.Extensions;
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.Net;
|
using MediaBrowser.Model.Net;
|
||||||
@ -310,5 +311,35 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override bool CanStreamCopyVideo(VideoStreamRequest request, MediaStream videoStream)
|
||||||
|
{
|
||||||
|
if (videoStream.KeyFrames == null || videoStream.KeyFrames.Count == 0)
|
||||||
|
{
|
||||||
|
Logger.Debug("Cannot stream copy video due to missing keyframe info");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var previousSegment = 0;
|
||||||
|
foreach (var frame in videoStream.KeyFrames)
|
||||||
|
{
|
||||||
|
var length = frame - previousSegment;
|
||||||
|
|
||||||
|
// Don't allow really long segments because this could result in long download times
|
||||||
|
if (length > 10000)
|
||||||
|
{
|
||||||
|
Logger.Debug("Cannot stream copy video due to long segment length of {0}ms", length);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
previousSegment = frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.CanStreamCopyVideo(request, videoStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool CanStreamCopyAudio(VideoStreamRequest request, MediaStream audioStream, List<string> supportedAudioCodecs)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ using MediaBrowser.Model.IO;
|
|||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
using ServiceStack;
|
using ServiceStack;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@ -161,7 +160,6 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
var playlistPath = Path.ChangeExtension(state.OutputFilePath, ".m3u8");
|
var playlistPath = Path.ChangeExtension(state.OutputFilePath, ".m3u8");
|
||||||
|
|
||||||
var segmentPath = GetSegmentPath(state, playlistPath, requestedIndex);
|
var segmentPath = GetSegmentPath(state, playlistPath, requestedIndex);
|
||||||
var segmentLength = state.SegmentLength;
|
|
||||||
|
|
||||||
var segmentExtension = GetSegmentFileExtension(state);
|
var segmentExtension = GetSegmentFileExtension(state);
|
||||||
|
|
||||||
@ -170,7 +168,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
if (File.Exists(segmentPath))
|
if (File.Exists(segmentPath))
|
||||||
{
|
{
|
||||||
job = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType);
|
job = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType);
|
||||||
return await GetSegmentResult(playlistPath, segmentPath, requestedIndex, segmentLength, job, cancellationToken).ConfigureAwait(false);
|
return await GetSegmentResult(state, playlistPath, segmentPath, requestedIndex, job, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
await ApiEntryPoint.Instance.TranscodingStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false);
|
await ApiEntryPoint.Instance.TranscodingStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false);
|
||||||
@ -179,7 +177,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
if (File.Exists(segmentPath))
|
if (File.Exists(segmentPath))
|
||||||
{
|
{
|
||||||
job = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType);
|
job = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType);
|
||||||
return await GetSegmentResult(playlistPath, segmentPath, requestedIndex, segmentLength, job, cancellationToken).ConfigureAwait(false);
|
return await GetSegmentResult(state, playlistPath, segmentPath, requestedIndex, job, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -210,14 +208,12 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
{
|
{
|
||||||
ApiEntryPoint.Instance.KillTranscodingJobs(request.DeviceId, request.PlaySessionId, p => false);
|
ApiEntryPoint.Instance.KillTranscodingJobs(request.DeviceId, request.PlaySessionId, p => false);
|
||||||
|
|
||||||
await ReadSegmentLengths(playlistPath).ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (currentTranscodingIndex.HasValue)
|
if (currentTranscodingIndex.HasValue)
|
||||||
{
|
{
|
||||||
DeleteLastFile(playlistPath, segmentExtension, 0);
|
DeleteLastFile(playlistPath, segmentExtension, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
request.StartTimeTicks = GetSeekPositionTicks(state, playlistPath, requestedIndex);
|
request.StartTimeTicks = GetStartPositionTicks(state, requestedIndex);
|
||||||
|
|
||||||
job = await StartFfMpeg(state, playlistPath, cancellationTokenSource).ConfigureAwait(false);
|
job = await StartFfMpeg(state, playlistPath, cancellationTokenSource).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@ -252,84 +248,76 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
|
|
||||||
Logger.Info("returning {0}", segmentPath);
|
Logger.Info("returning {0}", segmentPath);
|
||||||
job = job ?? ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType);
|
job = job ?? ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType);
|
||||||
return await GetSegmentResult(playlistPath, segmentPath, requestedIndex, segmentLength, job, cancellationToken).ConfigureAwait(false);
|
return await GetSegmentResult(state, playlistPath, segmentPath, requestedIndex, job, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly ConcurrentDictionary<string, double> SegmentLengths = new ConcurrentDictionary<string, double>(StringComparer.OrdinalIgnoreCase);
|
// 256k
|
||||||
private async Task ReadSegmentLengths(string playlist)
|
private const int BufferSize = 262144;
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (var fileStream = GetPlaylistFileStream(playlist))
|
|
||||||
{
|
|
||||||
using (var reader = new StreamReader(fileStream))
|
|
||||||
{
|
|
||||||
double duration = -1;
|
|
||||||
|
|
||||||
while (!reader.EndOfStream)
|
private long GetStartPositionTicks(StreamState state, int requestedIndex)
|
||||||
{
|
|
||||||
var text = await reader.ReadLineAsync().ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (text.StartsWith("#EXTINF", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
var parts = text.Split(new[] { ':' }, 2);
|
|
||||||
if (parts.Length == 2)
|
|
||||||
{
|
|
||||||
var time = parts[1].Trim(new[] { ',' }).Trim();
|
|
||||||
double timeValue;
|
|
||||||
if (double.TryParse(time, NumberStyles.Any, CultureInfo.InvariantCulture, out timeValue))
|
|
||||||
{
|
|
||||||
duration = timeValue;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (duration != -1)
|
|
||||||
{
|
|
||||||
SegmentLengths.AddOrUpdate(text, duration, (k, v) => duration);
|
|
||||||
Logger.Debug("Added segment length of {0} for {1}", duration, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
duration = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (DirectoryNotFoundException)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (FileNotFoundException)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private long GetSeekPositionTicks(StreamState state, string playlist, int requestedIndex)
|
|
||||||
{
|
{
|
||||||
double startSeconds = 0;
|
double startSeconds = 0;
|
||||||
|
var lengths = GetSegmentLengths(state);
|
||||||
|
|
||||||
for (var i = 0; i < requestedIndex; i++)
|
for (var i = 0; i < requestedIndex; i++)
|
||||||
{
|
{
|
||||||
var segmentPath = GetSegmentPath(state, playlist, i);
|
startSeconds += lengths[requestedIndex];
|
||||||
|
|
||||||
//double length;
|
|
||||||
//if (SegmentLengths.TryGetValue(Path.GetFileName(segmentPath), out length))
|
|
||||||
//{
|
|
||||||
// Logger.Debug("Found segment length of {0} for index {1}", length, i);
|
|
||||||
// startSeconds += length;
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// startSeconds += state.SegmentLength;
|
|
||||||
//}
|
|
||||||
startSeconds += state.SegmentLength;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var position = TimeSpan.FromSeconds(startSeconds).Ticks;
|
var position = TimeSpan.FromSeconds(startSeconds).Ticks;
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private long GetEndPositionTicks(StreamState state, int requestedIndex)
|
||||||
|
{
|
||||||
|
double startSeconds = 0;
|
||||||
|
var lengths = GetSegmentLengths(state);
|
||||||
|
|
||||||
|
for (var i = 0; i <= requestedIndex; i++)
|
||||||
|
{
|
||||||
|
startSeconds += lengths[requestedIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
var position = TimeSpan.FromSeconds(startSeconds).Ticks;
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double[] GetSegmentLengths(StreamState state)
|
||||||
|
{
|
||||||
|
var result = new List<double>();
|
||||||
|
var encoder = GetVideoEncoder(state);
|
||||||
|
|
||||||
|
if (string.Equals(encoder, "copy", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
var videoStream = state.VideoStream;
|
||||||
|
if (videoStream.KeyFrames != null && videoStream.KeyFrames.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (var frame in videoStream.KeyFrames)
|
||||||
|
{
|
||||||
|
var seconds = TimeSpan.FromMilliseconds(frame).TotalSeconds;
|
||||||
|
seconds -= result.Sum();
|
||||||
|
result.Add(seconds);
|
||||||
|
}
|
||||||
|
return result.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var ticks = state.RunTimeTicks ?? 0;
|
||||||
|
|
||||||
|
var segmentLengthTicks = TimeSpan.FromSeconds(state.SegmentLength).Ticks;
|
||||||
|
|
||||||
|
while (ticks > 0)
|
||||||
|
{
|
||||||
|
var length = ticks >= segmentLengthTicks ? segmentLengthTicks : ticks;
|
||||||
|
|
||||||
|
result.Add(TimeSpan.FromTicks(length).TotalSeconds);
|
||||||
|
|
||||||
|
ticks -= length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
public int? GetCurrentTranscodingIndex(string playlist, string segmentExtension)
|
public int? GetCurrentTranscodingIndex(string playlist, string segmentExtension)
|
||||||
{
|
{
|
||||||
var job = ApiEntryPoint.Instance.GetTranscodingJob(playlist, TranscodingJobType);
|
var job = ApiEntryPoint.Instance.GetTranscodingJob(playlist, TranscodingJobType);
|
||||||
@ -434,17 +422,16 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
return Path.Combine(folder, filename + index.ToString(UsCulture) + GetSegmentFileExtension(state));
|
return Path.Combine(folder, filename + index.ToString(UsCulture) + GetSegmentFileExtension(state));
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<object> GetSegmentResult(string playlistPath,
|
private async Task<object> GetSegmentResult(StreamState state, string playlistPath,
|
||||||
string segmentPath,
|
string segmentPath,
|
||||||
int segmentIndex,
|
int segmentIndex,
|
||||||
int segmentLength,
|
|
||||||
TranscodingJob transcodingJob,
|
TranscodingJob transcodingJob,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
// If all transcoding has completed, just return immediately
|
// If all transcoding has completed, just return immediately
|
||||||
if (transcodingJob != null && transcodingJob.HasExited && File.Exists(segmentPath))
|
if (transcodingJob != null && transcodingJob.HasExited && File.Exists(segmentPath))
|
||||||
{
|
{
|
||||||
return GetSegmentResult(segmentPath, segmentIndex, segmentLength, transcodingJob);
|
return GetSegmentResult(state, segmentPath, segmentIndex, transcodingJob);
|
||||||
}
|
}
|
||||||
|
|
||||||
var segmentFilename = Path.GetFileName(segmentPath);
|
var segmentFilename = Path.GetFileName(segmentPath);
|
||||||
@ -455,21 +442,18 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
{
|
{
|
||||||
using (var fileStream = GetPlaylistFileStream(playlistPath))
|
using (var fileStream = GetPlaylistFileStream(playlistPath))
|
||||||
{
|
{
|
||||||
using (var reader = new StreamReader(fileStream))
|
using (var reader = new StreamReader(fileStream, Encoding.UTF8, true, BufferSize))
|
||||||
{
|
{
|
||||||
while (!reader.EndOfStream)
|
var text = await reader.ReadToEndAsync().ConfigureAwait(false);
|
||||||
{
|
|
||||||
var text = await reader.ReadLineAsync().ConfigureAwait(false);
|
|
||||||
|
|
||||||
// If it appears in the playlist, it's done
|
// If it appears in the playlist, it's done
|
||||||
if (text.IndexOf(segmentFilename, StringComparison.OrdinalIgnoreCase) != -1)
|
if (text.IndexOf(segmentFilename, StringComparison.OrdinalIgnoreCase) != -1)
|
||||||
|
{
|
||||||
|
if (File.Exists(segmentPath))
|
||||||
{
|
{
|
||||||
if (File.Exists(segmentPath))
|
return GetSegmentResult(state, segmentPath, segmentIndex, transcodingJob);
|
||||||
{
|
|
||||||
return GetSegmentResult(segmentPath, segmentIndex, segmentLength, transcodingJob);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
//break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -518,13 +502,12 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
//}
|
//}
|
||||||
|
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
return GetSegmentResult(segmentPath, segmentIndex, segmentLength, transcodingJob);
|
return GetSegmentResult(state, segmentPath, segmentIndex, transcodingJob);
|
||||||
}
|
}
|
||||||
|
|
||||||
private object GetSegmentResult(string segmentPath, int index, int segmentLength, TranscodingJob transcodingJob)
|
private object GetSegmentResult(StreamState state, string segmentPath, int index, TranscodingJob transcodingJob)
|
||||||
{
|
{
|
||||||
var segmentEndingSeconds = (1 + index) * segmentLength;
|
var segmentEndingPositionTicks = GetEndPositionTicks(state, index);
|
||||||
var segmentEndingPositionTicks = TimeSpan.FromSeconds(segmentEndingSeconds).Ticks;
|
|
||||||
|
|
||||||
return ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions
|
return ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions
|
||||||
{
|
{
|
||||||
@ -751,25 +734,23 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
{
|
{
|
||||||
var state = await GetState(request, CancellationToken.None).ConfigureAwait(false);
|
var state = await GetState(request, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var segmentLengths = GetSegmentLengths(state);
|
||||||
|
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
|
|
||||||
builder.AppendLine("#EXTM3U");
|
builder.AppendLine("#EXTM3U");
|
||||||
builder.AppendLine("#EXT-X-VERSION:3");
|
builder.AppendLine("#EXT-X-VERSION:3");
|
||||||
builder.AppendLine("#EXT-X-TARGETDURATION:" + (state.SegmentLength).ToString(UsCulture));
|
builder.AppendLine("#EXT-X-TARGETDURATION:" + Math.Ceiling((segmentLengths.Length > 0 ? segmentLengths.Max() : state.SegmentLength)).ToString(UsCulture));
|
||||||
builder.AppendLine("#EXT-X-MEDIA-SEQUENCE:0");
|
builder.AppendLine("#EXT-X-MEDIA-SEQUENCE:0");
|
||||||
|
|
||||||
var queryStringIndex = Request.RawUrl.IndexOf('?');
|
var queryStringIndex = Request.RawUrl.IndexOf('?');
|
||||||
var queryString = queryStringIndex == -1 ? string.Empty : Request.RawUrl.Substring(queryStringIndex);
|
var queryString = queryStringIndex == -1 ? string.Empty : Request.RawUrl.Substring(queryStringIndex);
|
||||||
|
|
||||||
var seconds = TimeSpan.FromTicks(state.RunTimeTicks ?? 0).TotalSeconds;
|
|
||||||
|
|
||||||
var index = 0;
|
var index = 0;
|
||||||
|
|
||||||
while (seconds > 0)
|
foreach (var length in segmentLengths)
|
||||||
{
|
{
|
||||||
var length = seconds >= state.SegmentLength ? state.SegmentLength : seconds;
|
builder.AppendLine("#EXTINF:" + length.ToString("0.000000", UsCulture) + ",");
|
||||||
|
|
||||||
builder.AppendLine("#EXTINF:" + length.ToString(UsCulture) + ",");
|
|
||||||
|
|
||||||
builder.AppendLine(string.Format("hlsdynamic/{0}/{1}{2}{3}",
|
builder.AppendLine(string.Format("hlsdynamic/{0}/{1}{2}{3}",
|
||||||
|
|
||||||
@ -778,7 +759,6 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
GetSegmentFileExtension(isOutputVideo),
|
GetSegmentFileExtension(isOutputVideo),
|
||||||
queryString));
|
queryString));
|
||||||
|
|
||||||
seconds -= state.SegmentLength;
|
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -791,7 +771,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
|
|
||||||
protected override string GetAudioArguments(StreamState state)
|
protected override string GetAudioArguments(StreamState state)
|
||||||
{
|
{
|
||||||
var codec = GetAudioEncoder(state.Request);
|
var codec = GetAudioEncoder(state);
|
||||||
|
|
||||||
if (!state.IsOutputVideo)
|
if (!state.IsOutputVideo)
|
||||||
{
|
{
|
||||||
@ -856,7 +836,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
var codec = GetVideoEncoder(state.VideoRequest);
|
var codec = GetVideoEncoder(state);
|
||||||
|
|
||||||
var args = "-codec:v:0 " + codec;
|
var args = "-codec:v:0 " + codec;
|
||||||
|
|
||||||
@ -877,7 +857,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var keyFrameArg = string.Format(" -force_key_frames expr:gte(t,n_forced*{0})",
|
var keyFrameArg = string.Format(" -force_key_frames \"expr:gte(t,n_forced*{0})\"",
|
||||||
state.SegmentLength.ToString(UsCulture));
|
state.SegmentLength.ToString(UsCulture));
|
||||||
|
|
||||||
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream;
|
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream;
|
||||||
@ -889,7 +869,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
// Add resolution params, if specified
|
// Add resolution params, if specified
|
||||||
if (!hasGraphicalSubs)
|
if (!hasGraphicalSubs)
|
||||||
{
|
{
|
||||||
args += GetOutputSizeParam(state, codec, false);
|
args += GetOutputSizeParam(state, codec, EnableCopyTs(state));
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is for internal graphical subs
|
// This is for internal graphical subs
|
||||||
@ -898,17 +878,17 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
args += GetGraphicalSubtitleParam(state, codec);
|
args += GetGraphicalSubtitleParam(state, codec);
|
||||||
}
|
}
|
||||||
|
|
||||||
args += " -flags +loop-global_header -sc_threshold 0";
|
args += " -flags -global_header -sc_threshold 0";
|
||||||
}
|
|
||||||
|
|
||||||
if (!EnableSplitTranscoding(state))
|
|
||||||
{
|
|
||||||
//args += " -copyts";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool EnableCopyTs(StreamState state)
|
||||||
|
{
|
||||||
|
return state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream;
|
||||||
|
}
|
||||||
|
|
||||||
protected override string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding)
|
protected override string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding)
|
||||||
{
|
{
|
||||||
var threads = GetNumberOfThreads(state, false);
|
var threads = GetNumberOfThreads(state, false);
|
||||||
@ -921,22 +901,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
var toTimeParam = string.Empty;
|
var toTimeParam = string.Empty;
|
||||||
var timestampOffsetParam = string.Empty;
|
var timestampOffsetParam = string.Empty;
|
||||||
|
|
||||||
if (EnableSplitTranscoding(state))
|
if (state.IsOutputVideo && !EnableCopyTs(state) && !string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase) && (state.Request.StartTimeTicks ?? 0) > 0)
|
||||||
{
|
|
||||||
var startTime = state.Request.StartTimeTicks ?? 0;
|
|
||||||
var durationSeconds = ApiEntryPoint.Instance.GetEncodingOptions().ThrottleThresholdInSeconds;
|
|
||||||
|
|
||||||
var endTime = startTime + TimeSpan.FromSeconds(durationSeconds).Ticks;
|
|
||||||
endTime = Math.Min(endTime, state.RunTimeTicks.Value);
|
|
||||||
|
|
||||||
if (endTime < state.RunTimeTicks.Value)
|
|
||||||
{
|
|
||||||
//toTimeParam = " -to " + MediaEncoder.GetTimeParameter(endTime);
|
|
||||||
toTimeParam = " -t " + MediaEncoder.GetTimeParameter(TimeSpan.FromSeconds(durationSeconds).Ticks);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.IsOutputVideo && !string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase) && (state.Request.StartTimeTicks ?? 0) > 0)
|
|
||||||
{
|
{
|
||||||
timestampOffsetParam = " -output_ts_offset " + MediaEncoder.GetTimeParameter(state.Request.StartTimeTicks ?? 0).ToString(CultureInfo.InvariantCulture);
|
timestampOffsetParam = " -output_ts_offset " + MediaEncoder.GetTimeParameter(state.Request.StartTimeTicks ?? 0).ToString(CultureInfo.InvariantCulture);
|
||||||
}
|
}
|
||||||
@ -978,36 +943,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
|
|
||||||
protected override bool EnableThrottling(StreamState state)
|
protected override bool EnableThrottling(StreamState state)
|
||||||
{
|
{
|
||||||
return !EnableSplitTranscoding(state);
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
private bool EnableSplitTranscoding(StreamState state)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
if (string.Equals(Request.QueryString["EnableSplitTranscoding"], "false", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.Equals(state.OutputAudioCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return state.RunTimeTicks.HasValue && state.IsOutputVideo;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool EnableStreamCopy
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -48,7 +48,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
protected override string GetAudioArguments(StreamState state)
|
protected override string GetAudioArguments(StreamState state)
|
||||||
{
|
{
|
||||||
var codec = GetAudioEncoder(state.Request);
|
var codec = GetAudioEncoder(state);
|
||||||
|
|
||||||
if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
@ -83,7 +83,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
protected override string GetVideoArguments(StreamState state)
|
protected override string GetVideoArguments(StreamState state)
|
||||||
{
|
{
|
||||||
var codec = GetVideoEncoder(state.VideoRequest);
|
var codec = GetVideoEncoder(state);
|
||||||
|
|
||||||
var args = "-codec:v:0 " + codec;
|
var args = "-codec:v:0 " + codec;
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
args;
|
args;
|
||||||
}
|
}
|
||||||
|
|
||||||
var keyFrameArg = string.Format(" -force_key_frames expr:gte(t,n_forced*{0})",
|
var keyFrameArg = string.Format(" -force_key_frames \"expr:gte(t,n_forced*{0})\"",
|
||||||
state.SegmentLength.ToString(UsCulture));
|
state.SegmentLength.ToString(UsCulture));
|
||||||
|
|
||||||
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream;
|
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream;
|
||||||
|
@ -91,6 +91,9 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
private readonly TranscodingJob _job;
|
private readonly TranscodingJob _job;
|
||||||
|
|
||||||
|
// 256k
|
||||||
|
private const int BufferSize = 262144;
|
||||||
|
|
||||||
private long _bytesWritten = 0;
|
private long _bytesWritten = 0;
|
||||||
|
|
||||||
public ProgressiveFileCopier(IFileSystem fileSystem, TranscodingJob job)
|
public ProgressiveFileCopier(IFileSystem fileSystem, TranscodingJob job)
|
||||||
@ -108,7 +111,7 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
{
|
{
|
||||||
while (eofCount < 15)
|
while (eofCount < 15)
|
||||||
{
|
{
|
||||||
CopyToInternal(fs, outputStream, 81920);
|
CopyToInternal(fs, outputStream, BufferSize);
|
||||||
|
|
||||||
var fsPosition = fs.Position;
|
var fsPosition = fs.Position;
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
protected override string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding)
|
protected override string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding)
|
||||||
{
|
{
|
||||||
// Get the output codec name
|
// Get the output codec name
|
||||||
var videoCodec = GetVideoEncoder(state.VideoRequest);
|
var videoCodec = GetVideoEncoder(state);
|
||||||
|
|
||||||
var format = string.Empty;
|
var format = string.Empty;
|
||||||
var keyFrame = string.Empty;
|
var keyFrame = string.Empty;
|
||||||
@ -183,7 +183,7 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the output codec name
|
// Get the output codec name
|
||||||
var codec = GetAudioEncoder(state.Request);
|
var codec = GetAudioEncoder(state);
|
||||||
|
|
||||||
var args = "-codec:a:0 " + codec;
|
var args = "-codec:a:0 " + codec;
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ namespace MediaBrowser.Api.Playback
|
|||||||
|
|
||||||
private async void DisposeLiveStream()
|
private async void DisposeLiveStream()
|
||||||
{
|
{
|
||||||
if (MediaSource.RequiresClosing && string.IsNullOrWhiteSpace(Request.LiveStreamId))
|
if ((MediaSource.RequiresClosing) && string.IsNullOrWhiteSpace(Request.LiveStreamId))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
259
MediaBrowser.Api/Reports/Activities/ReportActivitiesBuilder.cs
Normal file
259
MediaBrowser.Api/Reports/Activities/ReportActivitiesBuilder.cs
Normal file
@ -0,0 +1,259 @@
|
|||||||
|
using MediaBrowser.Model.Activity;
|
||||||
|
using MediaBrowser.Model.Querying;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Controller.Library;
|
||||||
|
namespace MediaBrowser.Api.Reports
|
||||||
|
{
|
||||||
|
/// <summary> A report activities builder. </summary>
|
||||||
|
/// <seealso cref="T:MediaBrowser.Api.Reports.ReportBuilderBase"/>
|
||||||
|
public class ReportActivitiesBuilder : ReportBuilderBase
|
||||||
|
{
|
||||||
|
#region [Constructors]
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the MediaBrowser.Api.Reports.ReportActivitiesBuilder class. </summary>
|
||||||
|
/// <param name="libraryManager"> Manager for library. </param>
|
||||||
|
/// <param name="userManager"> Manager for user. </param>
|
||||||
|
public ReportActivitiesBuilder(ILibraryManager libraryManager, IUserManager userManager)
|
||||||
|
: base(libraryManager)
|
||||||
|
{
|
||||||
|
_userManager = userManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region [Private Fields]
|
||||||
|
|
||||||
|
private readonly IUserManager _userManager; ///< Manager for user
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region [Public Methods]
|
||||||
|
|
||||||
|
/// <summary> Gets a result. </summary>
|
||||||
|
/// <param name="queryResult"> The query result. </param>
|
||||||
|
/// <param name="request"> The request. </param>
|
||||||
|
/// <returns> The result. </returns>
|
||||||
|
public ReportResult GetResult(QueryResult<ActivityLogEntry> queryResult, IReportsQuery request)
|
||||||
|
{
|
||||||
|
ReportDisplayType displayType = ReportHelper.GetReportDisplayType(request.DisplayType);
|
||||||
|
List<ReportOptions<ActivityLogEntry>> options = this.GetReportOptions<ActivityLogEntry>(request,
|
||||||
|
() => this.GetDefaultHeaderMetadata(),
|
||||||
|
(hm) => this.GetOption(hm)).Where(x => this.DisplayTypeVisible(x.Header.DisplayType, displayType)).ToList();
|
||||||
|
|
||||||
|
var headers = GetHeaders<ActivityLogEntry>(options);
|
||||||
|
var rows = GetReportRows(queryResult.Items, options);
|
||||||
|
|
||||||
|
ReportResult result = new ReportResult { Headers = headers };
|
||||||
|
HeaderMetadata groupBy = ReportHelper.GetHeaderMetadataType(request.GroupBy);
|
||||||
|
int i = headers.FindIndex(x => x.FieldName == groupBy);
|
||||||
|
if (groupBy != HeaderMetadata.None && i >= 0)
|
||||||
|
{
|
||||||
|
var rowsGroup = rows.SelectMany(x => x.Columns[i].Name.Split(';'), (x, g) => new { Group = g.Trim(), Rows = x })
|
||||||
|
.GroupBy(x => x.Group)
|
||||||
|
.OrderBy(x => x.Key)
|
||||||
|
.Select(x => new ReportGroup { Name = x.Key, Rows = x.Select(r => r.Rows).ToList() });
|
||||||
|
|
||||||
|
result.Groups = rowsGroup.ToList();
|
||||||
|
result.IsGrouped = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.Rows = rows;
|
||||||
|
result.IsGrouped = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region [Protected Internal Methods]
|
||||||
|
|
||||||
|
/// <summary> Gets the headers. </summary>
|
||||||
|
/// <typeparam name="H"> Type of the header. </typeparam>
|
||||||
|
/// <param name="request"> The request. </param>
|
||||||
|
/// <returns> The headers. </returns>
|
||||||
|
/// <seealso cref="M:MediaBrowser.Api.Reports.ReportBuilderBase.GetHeaders{H}(H)"/>
|
||||||
|
protected internal override List<ReportHeader> GetHeaders<H>(H request)
|
||||||
|
{
|
||||||
|
return this.GetHeaders<ActivityLogEntry>(request, () => this.GetDefaultHeaderMetadata(), (hm) => this.GetOption(hm));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region [Private Methods]
|
||||||
|
|
||||||
|
/// <summary> Gets default header metadata. </summary>
|
||||||
|
/// <returns> The default header metadata. </returns>
|
||||||
|
private List<HeaderMetadata> GetDefaultHeaderMetadata()
|
||||||
|
{
|
||||||
|
return new List<HeaderMetadata>
|
||||||
|
{
|
||||||
|
HeaderMetadata.UserPrimaryImage,
|
||||||
|
HeaderMetadata.Date,
|
||||||
|
HeaderMetadata.User,
|
||||||
|
HeaderMetadata.Type,
|
||||||
|
HeaderMetadata.Severity,
|
||||||
|
HeaderMetadata.Name,
|
||||||
|
HeaderMetadata.ShortOverview,
|
||||||
|
HeaderMetadata.Overview,
|
||||||
|
//HeaderMetadata.UserId
|
||||||
|
//HeaderMetadata.Item,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Gets an option. </summary>
|
||||||
|
/// <param name="header"> The header. </param>
|
||||||
|
/// <param name="sortField"> The sort field. </param>
|
||||||
|
/// <returns> The option. </returns>
|
||||||
|
private ReportOptions<ActivityLogEntry> GetOption(HeaderMetadata header, string sortField = "")
|
||||||
|
{
|
||||||
|
HeaderMetadata internalHeader = header;
|
||||||
|
|
||||||
|
ReportOptions<ActivityLogEntry> option = new ReportOptions<ActivityLogEntry>()
|
||||||
|
{
|
||||||
|
Header = new ReportHeader
|
||||||
|
{
|
||||||
|
HeaderFieldType = ReportFieldType.String,
|
||||||
|
SortField = sortField,
|
||||||
|
Type = "",
|
||||||
|
ItemViewType = ItemViewType.None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (header)
|
||||||
|
{
|
||||||
|
case HeaderMetadata.Name:
|
||||||
|
option.Column = (i, r) => i.Name;
|
||||||
|
option.Header.SortField = "";
|
||||||
|
break;
|
||||||
|
case HeaderMetadata.Overview:
|
||||||
|
option.Column = (i, r) => i.Overview;
|
||||||
|
option.Header.SortField = "";
|
||||||
|
option.Header.CanGroup = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HeaderMetadata.ShortOverview:
|
||||||
|
option.Column = (i, r) => i.ShortOverview;
|
||||||
|
option.Header.SortField = "";
|
||||||
|
option.Header.CanGroup = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HeaderMetadata.Type:
|
||||||
|
option.Column = (i, r) => i.Type;
|
||||||
|
option.Header.SortField = "";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HeaderMetadata.Date:
|
||||||
|
option.Column = (i, r) => i.Date;
|
||||||
|
option.Header.SortField = "";
|
||||||
|
option.Header.HeaderFieldType = ReportFieldType.DateTime;
|
||||||
|
option.Header.Type = "";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HeaderMetadata.UserPrimaryImage:
|
||||||
|
//option.Column = (i, r) => i.UserPrimaryImageTag;
|
||||||
|
option.Header.DisplayType = ReportDisplayType.Screen;
|
||||||
|
option.Header.ItemViewType = ItemViewType.UserPrimaryImage;
|
||||||
|
option.Header.ShowHeaderLabel = false;
|
||||||
|
internalHeader = HeaderMetadata.User;
|
||||||
|
option.Header.CanGroup = false;
|
||||||
|
option.Column = (i, r) =>
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(i.UserId))
|
||||||
|
{
|
||||||
|
MediaBrowser.Controller.Entities.User user = _userManager.GetUserById(i.UserId);
|
||||||
|
if (user != null)
|
||||||
|
{
|
||||||
|
var dto = _userManager.GetUserDto(user);
|
||||||
|
return dto.PrimaryImageTag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return string.Empty;
|
||||||
|
};
|
||||||
|
option.Header.SortField = "";
|
||||||
|
break;
|
||||||
|
case HeaderMetadata.Severity:
|
||||||
|
option.Column = (i, r) => i.Severity;
|
||||||
|
option.Header.SortField = "";
|
||||||
|
break;
|
||||||
|
case HeaderMetadata.Item:
|
||||||
|
option.Column = (i, r) => i.ItemId;
|
||||||
|
option.Header.SortField = "";
|
||||||
|
break;
|
||||||
|
case HeaderMetadata.User:
|
||||||
|
option.Column = (i, r) =>
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(i.UserId))
|
||||||
|
{
|
||||||
|
MediaBrowser.Controller.Entities.User user = _userManager.GetUserById(i.UserId);
|
||||||
|
if (user != null)
|
||||||
|
return user.Name;
|
||||||
|
}
|
||||||
|
return string.Empty;
|
||||||
|
};
|
||||||
|
option.Header.SortField = "";
|
||||||
|
break;
|
||||||
|
case HeaderMetadata.UserId:
|
||||||
|
option.Column = (i, r) => i.UserId;
|
||||||
|
option.Header.SortField = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
option.Header.Name = GetLocalizedHeader(internalHeader);
|
||||||
|
option.Header.FieldName = header;
|
||||||
|
|
||||||
|
return option;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Gets report rows. </summary>
|
||||||
|
/// <param name="items"> The items. </param>
|
||||||
|
/// <param name="options"> Options for controlling the operation. </param>
|
||||||
|
/// <returns> The report rows. </returns>
|
||||||
|
private List<ReportRow> GetReportRows(IEnumerable<ActivityLogEntry> items, List<ReportOptions<ActivityLogEntry>> options)
|
||||||
|
{
|
||||||
|
var rows = new List<ReportRow>();
|
||||||
|
|
||||||
|
foreach (ActivityLogEntry item in items)
|
||||||
|
{
|
||||||
|
ReportRow rRow = GetRow(item);
|
||||||
|
foreach (ReportOptions<ActivityLogEntry> option in options)
|
||||||
|
{
|
||||||
|
object itemColumn = option.Column != null ? option.Column(item, rRow) : "";
|
||||||
|
object itemId = option.ItemID != null ? option.ItemID(item) : "";
|
||||||
|
ReportItem rItem = new ReportItem
|
||||||
|
{
|
||||||
|
Name = ReportHelper.ConvertToString(itemColumn, option.Header.HeaderFieldType),
|
||||||
|
Id = ReportHelper.ConvertToString(itemId, ReportFieldType.Object)
|
||||||
|
};
|
||||||
|
rRow.Columns.Add(rItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
rows.Add(rRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Gets a row. </summary>
|
||||||
|
/// <param name="item"> The item. </param>
|
||||||
|
/// <returns> The row. </returns>
|
||||||
|
private ReportRow GetRow(ActivityLogEntry item)
|
||||||
|
{
|
||||||
|
ReportRow rRow = new ReportRow
|
||||||
|
{
|
||||||
|
Id = item.Id,
|
||||||
|
UserId = item.UserId
|
||||||
|
};
|
||||||
|
return rRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
20
MediaBrowser.Api/Reports/Common/HeaderActivitiesMetadata.cs
Normal file
20
MediaBrowser.Api/Reports/Common/HeaderActivitiesMetadata.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Api.Reports
|
||||||
|
{
|
||||||
|
public enum HeaderActivitiesMetadata
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Name,
|
||||||
|
Overview,
|
||||||
|
ShortOverview,
|
||||||
|
Type,
|
||||||
|
Date,
|
||||||
|
UserPrimaryImageTag,
|
||||||
|
Severity,
|
||||||
|
Item,
|
||||||
|
User
|
||||||
|
}
|
||||||
|
}
|
@ -35,13 +35,39 @@ namespace MediaBrowser.Api.Reports
|
|||||||
Subtitles,
|
Subtitles,
|
||||||
Genres,
|
Genres,
|
||||||
Countries,
|
Countries,
|
||||||
StatusImage,
|
Status,
|
||||||
Tracks,
|
Tracks,
|
||||||
EpisodeSeries,
|
EpisodeSeries,
|
||||||
EpisodeSeason,
|
EpisodeSeason,
|
||||||
AudioAlbumArtist,
|
AudioAlbumArtist,
|
||||||
MusicArtist,
|
MusicArtist,
|
||||||
AudioAlbum,
|
AudioAlbum,
|
||||||
Status
|
Locked,
|
||||||
|
Unidentified,
|
||||||
|
ImagePrimary,
|
||||||
|
ImageBackdrop,
|
||||||
|
ImageLogo,
|
||||||
|
Actor,
|
||||||
|
Studios,
|
||||||
|
Composer,
|
||||||
|
Director,
|
||||||
|
GuestStar,
|
||||||
|
Producer,
|
||||||
|
Writer,
|
||||||
|
Artist,
|
||||||
|
Years,
|
||||||
|
ParentalRatings,
|
||||||
|
CommunityRatings,
|
||||||
|
|
||||||
|
//Activity logs
|
||||||
|
Overview,
|
||||||
|
ShortOverview,
|
||||||
|
Type,
|
||||||
|
Date,
|
||||||
|
UserPrimaryImage,
|
||||||
|
Severity,
|
||||||
|
Item,
|
||||||
|
User,
|
||||||
|
UserId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,17 +4,23 @@ using System.Linq;
|
|||||||
|
|
||||||
namespace MediaBrowser.Api.Reports
|
namespace MediaBrowser.Api.Reports
|
||||||
{
|
{
|
||||||
public enum ItemViewType
|
public enum ItemViewType
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
Detail,
|
Detail,
|
||||||
Edit,
|
Edit,
|
||||||
List,
|
List,
|
||||||
ItemByNameDetails,
|
ItemByNameDetails,
|
||||||
StatusImage,
|
StatusImage,
|
||||||
EmbeddedImage,
|
EmbeddedImage,
|
||||||
SubtitleImage,
|
SubtitleImage,
|
||||||
TrailersImage,
|
TrailersImage,
|
||||||
SpecialsImage
|
SpecialsImage,
|
||||||
}
|
LockDataImage,
|
||||||
|
UnidentifiedImage,
|
||||||
|
TagsPrimaryImage,
|
||||||
|
TagsBackdropImage,
|
||||||
|
TagsLogoImage,
|
||||||
|
UserPrimaryImage
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,217 +13,351 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace MediaBrowser.Api.Reports
|
namespace MediaBrowser.Api.Reports
|
||||||
{
|
{
|
||||||
/// <summary> A report builder base. </summary>
|
/// <summary> A report builder base. </summary>
|
||||||
public class ReportBuilderBase
|
public abstract class ReportBuilderBase
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the MediaBrowser.Api.Reports.ReportBuilderBase class. </summary>
|
|
||||||
/// <param name="libraryManager"> Manager for library. </param>
|
|
||||||
public ReportBuilderBase(ILibraryManager libraryManager)
|
|
||||||
{
|
|
||||||
_libraryManager = libraryManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary> Manager for library. </summary>
|
#region [Constructors]
|
||||||
protected readonly ILibraryManager _libraryManager;
|
|
||||||
|
|
||||||
/// <summary> Gets audio stream. </summary>
|
/// <summary>
|
||||||
/// <param name="item"> The item. </param>
|
/// Initializes a new instance of the MediaBrowser.Api.Reports.ReportBuilderBase class. </summary>
|
||||||
/// <returns> The audio stream. </returns>
|
/// <param name="libraryManager"> Manager for library. </param>
|
||||||
protected string GetAudioStream(BaseItem item)
|
public ReportBuilderBase(ILibraryManager libraryManager)
|
||||||
{
|
{
|
||||||
var stream = GetStream(item, MediaStreamType.Audio);
|
_libraryManager = libraryManager;
|
||||||
if (stream != null)
|
}
|
||||||
return stream.Codec.ToUpper() == "DCA" ? stream.Profile : stream.Codec.
|
|
||||||
ToUpper();
|
|
||||||
|
|
||||||
return string.Empty;
|
#endregion
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary> Gets an episode. </summary>
|
#region [Protected Fields]
|
||||||
/// <param name="item"> The item. </param>
|
|
||||||
/// <returns> The episode. </returns>
|
|
||||||
protected string GetEpisode(BaseItem item)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (item.GetClientTypeName() == ChannelMediaContentType.Episode.ToString() && item.ParentIndexNumber != null)
|
/// <summary> Manager for library. </summary>
|
||||||
return "Season " + item.ParentIndexNumber;
|
protected readonly ILibraryManager _libraryManager; ///< Manager for library
|
||||||
else
|
|
||||||
return item.Name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary> Gets a genre. </summary>
|
protected Func<bool, string> GetBoolString = s => s == true ? "x" : ""; ///< .
|
||||||
/// <param name="name"> The name. </param>
|
|
||||||
/// <returns> The genre. </returns>
|
|
||||||
protected Genre GetGenre(string name)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(name))
|
|
||||||
return null;
|
|
||||||
return _libraryManager.GetGenre(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary> Gets genre identifier. </summary>
|
#endregion
|
||||||
/// <param name="name"> The name. </param>
|
|
||||||
/// <returns> The genre identifier. </returns>
|
|
||||||
protected string GetGenreID(string name)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(name))
|
|
||||||
return string.Empty;
|
|
||||||
return string.Format("{0:N}",
|
|
||||||
GetGenre(name).Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary> Gets list as string. </summary>
|
#region [Protected Internal Methods]
|
||||||
/// <param name="items"> The items. </param>
|
|
||||||
/// <returns> The list as string. </returns>
|
|
||||||
protected string GetListAsString(List<string> items)
|
|
||||||
{
|
|
||||||
return String.Join("; ", items);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary> Gets media source information. </summary>
|
/// <summary> Gets the headers. </summary>
|
||||||
/// <param name="item"> The item. </param>
|
/// <typeparam name="H"> Type of the header. </typeparam>
|
||||||
/// <returns> The media source information. </returns>
|
/// <param name="request"> The request. </param>
|
||||||
protected MediaSourceInfo GetMediaSourceInfo(BaseItem item)
|
/// <returns> The headers. </returns>
|
||||||
{
|
protected internal abstract List<ReportHeader> GetHeaders<H>(H request) where H : IReportsHeader;
|
||||||
var mediaSource = item as IHasMediaSources;
|
|
||||||
if (mediaSource != null)
|
|
||||||
return mediaSource.GetMediaSources(false).FirstOrDefault(n => n.Type == MediaSourceType.Default);
|
|
||||||
|
|
||||||
return null;
|
#endregion
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary> Gets an object. </summary>
|
#region [Protected Methods]
|
||||||
/// <typeparam name="T"> Generic type parameter. </typeparam>
|
|
||||||
/// <typeparam name="R"> Type of the r. </typeparam>
|
|
||||||
/// <param name="item"> The item. </param>
|
|
||||||
/// <param name="function"> The function. </param>
|
|
||||||
/// <param name="defaultValue"> The default value. </param>
|
|
||||||
/// <returns> The object. </returns>
|
|
||||||
protected R GetObject<T, R>(BaseItem item, Func<T, R> function, R defaultValue = default(R)) where T : class
|
|
||||||
{
|
|
||||||
var value = item as T;
|
|
||||||
if (value != null && function != null)
|
|
||||||
return function(value);
|
|
||||||
else
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary> Gets a person. </summary>
|
/// <summary> Gets active headers. </summary>
|
||||||
/// <param name="name"> The name. </param>
|
/// <typeparam name="T"> Generic type parameter. </typeparam>
|
||||||
/// <returns> The person. </returns>
|
/// <param name="options"> Options for controlling the operation. </param>
|
||||||
protected Person GetPerson(string name)
|
/// <returns> The active headers. </returns>
|
||||||
{
|
protected List<ReportHeader> GetActiveHeaders<T>(List<ReportOptions<T>> options, ReportDisplayType displayType)
|
||||||
if (string.IsNullOrEmpty(name))
|
{
|
||||||
return null;
|
List<ReportHeader> headers = new List<ReportHeader>();
|
||||||
return _libraryManager.GetPerson(name);
|
foreach (ReportOptions<T> option in options.Where(x => this.DisplayTypeVisible(x.Header.DisplayType, displayType)))
|
||||||
}
|
{
|
||||||
|
headers.Add(option.Header);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary> Gets person identifier. </summary>
|
return headers;
|
||||||
/// <param name="name"> The name. </param>
|
}
|
||||||
/// <returns> The person identifier. </returns>
|
|
||||||
protected string GetPersonID(string name)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(name))
|
|
||||||
return string.Empty;
|
|
||||||
return string.Format("{0:N}",
|
|
||||||
GetPerson(name).Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary> Gets runtime date time. </summary>
|
/// <summary> Gets audio stream. </summary>
|
||||||
/// <param name="runtime"> The runtime. </param>
|
/// <param name="item"> The item. </param>
|
||||||
/// <returns> The runtime date time. </returns>
|
/// <returns> The audio stream. </returns>
|
||||||
protected double? GetRuntimeDateTime(long? runtime)
|
protected string GetAudioStream(BaseItem item)
|
||||||
{
|
{
|
||||||
if (runtime.HasValue)
|
var stream = GetStream(item, MediaStreamType.Audio);
|
||||||
|
if (stream != null)
|
||||||
|
return stream.Codec.ToUpper() == "DCA" ? stream.Profile : stream.Codec.
|
||||||
|
ToUpper();
|
||||||
|
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Gets an episode. </summary>
|
||||||
|
/// <param name="item"> The item. </param>
|
||||||
|
/// <returns> The episode. </returns>
|
||||||
|
protected string GetEpisode(BaseItem item)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (item.GetClientTypeName() == ChannelMediaContentType.Episode.ToString() && item.ParentIndexNumber != null)
|
||||||
|
return "Season " + item.ParentIndexNumber;
|
||||||
|
else
|
||||||
|
return item.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Gets a genre. </summary>
|
||||||
|
/// <param name="name"> The name. </param>
|
||||||
|
/// <returns> The genre. </returns>
|
||||||
|
protected Genre GetGenre(string name)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(name))
|
||||||
|
return null;
|
||||||
|
return _libraryManager.GetGenre(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Gets genre identifier. </summary>
|
||||||
|
/// <param name="name"> The name. </param>
|
||||||
|
/// <returns> The genre identifier. </returns>
|
||||||
|
protected string GetGenreID(string name)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(name))
|
||||||
|
return string.Empty;
|
||||||
|
return string.Format("{0:N}",
|
||||||
|
GetGenre(name).Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Gets the headers. </summary>
|
||||||
|
/// <typeparam name="T"> Generic type parameter. </typeparam>
|
||||||
|
/// <param name="options"> Options for controlling the operation. </param>
|
||||||
|
/// <returns> The headers. </returns>
|
||||||
|
protected List<ReportHeader> GetHeaders<T>(List<ReportOptions<T>> options)
|
||||||
|
{
|
||||||
|
List<ReportHeader> headers = new List<ReportHeader>();
|
||||||
|
foreach (ReportOptions<T> option in options)
|
||||||
|
{
|
||||||
|
headers.Add(option.Header);
|
||||||
|
}
|
||||||
|
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Gets the headers. </summary>
|
||||||
|
/// <typeparam name="T"> Generic type parameter. </typeparam>
|
||||||
|
/// <param name="request"> The request. </param>
|
||||||
|
/// <param name="getHeadersMetadata"> The get headers metadata. </param>
|
||||||
|
/// <param name="getOptions"> Options for controlling the get. </param>
|
||||||
|
/// <returns> The headers. </returns>
|
||||||
|
protected List<ReportHeader> GetHeaders<T>(IReportsHeader request, Func<List<HeaderMetadata>> getHeadersMetadata, Func<HeaderMetadata, ReportOptions<T>> getOptions)
|
||||||
|
{
|
||||||
|
List<ReportOptions<T>> options = this.GetReportOptions(request, getHeadersMetadata, getOptions);
|
||||||
|
return this.GetHeaders(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Gets list as string. </summary>
|
||||||
|
/// <param name="items"> The items. </param>
|
||||||
|
/// <returns> The list as string. </returns>
|
||||||
|
protected string GetListAsString(List<string> items)
|
||||||
|
{
|
||||||
|
return String.Join("; ", items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Gets localized header. </summary>
|
||||||
|
/// <param name="internalHeader"> The internal header. </param>
|
||||||
|
/// <returns> The localized header. </returns>
|
||||||
|
protected static string GetLocalizedHeader(HeaderMetadata internalHeader)
|
||||||
|
{
|
||||||
|
string headerName = "";
|
||||||
|
if (internalHeader != HeaderMetadata.None)
|
||||||
|
{
|
||||||
|
string localHeader = "Header" + internalHeader.ToString();
|
||||||
|
headerName = ReportHelper.GetCoreLocalizedString(localHeader);
|
||||||
|
}
|
||||||
|
return headerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Gets media source information. </summary>
|
||||||
|
/// <param name="item"> The item. </param>
|
||||||
|
/// <returns> The media source information. </returns>
|
||||||
|
protected MediaSourceInfo GetMediaSourceInfo(BaseItem item)
|
||||||
|
{
|
||||||
|
var mediaSource = item as IHasMediaSources;
|
||||||
|
if (mediaSource != null)
|
||||||
|
return mediaSource.GetMediaSources(false).FirstOrDefault(n => n.Type == MediaSourceType.Default);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Gets an object. </summary>
|
||||||
|
/// <typeparam name="T"> Generic type parameter. </typeparam>
|
||||||
|
/// <typeparam name="R"> Type of the r. </typeparam>
|
||||||
|
/// <param name="item"> The item. </param>
|
||||||
|
/// <param name="function"> The function. </param>
|
||||||
|
/// <param name="defaultValue"> The default value. </param>
|
||||||
|
/// <returns> The object. </returns>
|
||||||
|
protected R GetObject<T, R>(BaseItem item, Func<T, R> function, R defaultValue = default(R)) where T : class
|
||||||
|
{
|
||||||
|
var value = item as T;
|
||||||
|
if (value != null && function != null)
|
||||||
|
return function(value);
|
||||||
|
else
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Gets a person. </summary>
|
||||||
|
/// <param name="name"> The name. </param>
|
||||||
|
/// <returns> The person. </returns>
|
||||||
|
protected Person GetPerson(string name)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(name))
|
||||||
|
return null;
|
||||||
|
return _libraryManager.GetPerson(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Gets person identifier. </summary>
|
||||||
|
/// <param name="name"> The name. </param>
|
||||||
|
/// <returns> The person identifier. </returns>
|
||||||
|
protected string GetPersonID(string name)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(name))
|
||||||
|
return string.Empty;
|
||||||
|
return string.Format("{0:N}",
|
||||||
|
GetPerson(name).Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Gets report options. </summary>
|
||||||
|
/// <typeparam name="T"> Generic type parameter. </typeparam>
|
||||||
|
/// <param name="request"> The request. </param>
|
||||||
|
/// <param name="getHeadersMetadata"> The get headers metadata. </param>
|
||||||
|
/// <param name="getOptions"> Options for controlling the get. </param>
|
||||||
|
/// <returns> The report options. </returns>
|
||||||
|
protected List<ReportOptions<T>> GetReportOptions<T>(IReportsHeader request, Func<List<HeaderMetadata>> getHeadersMetadata, Func<HeaderMetadata, ReportOptions<T>> getOptions)
|
||||||
|
{
|
||||||
|
List<HeaderMetadata> headersMetadata = getHeadersMetadata();
|
||||||
|
List<ReportOptions<T>> options = new List<ReportOptions<T>>();
|
||||||
|
ReportDisplayType displayType = ReportHelper.GetReportDisplayType(request.DisplayType);
|
||||||
|
foreach (HeaderMetadata header in headersMetadata)
|
||||||
|
{
|
||||||
|
ReportOptions<T> headerOptions = getOptions(header);
|
||||||
|
if (this.DisplayTypeVisible(headerOptions.Header.DisplayType, displayType))
|
||||||
|
options.Add(headerOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request != null && !string.IsNullOrEmpty(request.ReportColumns))
|
||||||
|
{
|
||||||
|
List<HeaderMetadata> headersMetadataFiltered = ReportHelper.GetFilteredReportHeaderMetadata(request.ReportColumns, () => headersMetadata);
|
||||||
|
foreach (ReportHeader header in options.Select(x => x.Header))
|
||||||
|
{
|
||||||
|
|
||||||
|
if (this.DisplayTypeVisible(header.DisplayType, displayType))
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!headersMetadataFiltered.Contains(header.FieldName) && displayType != ReportDisplayType.Export)
|
||||||
|
{
|
||||||
|
header.DisplayType = ReportDisplayType.None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
header.DisplayType = ReportDisplayType.None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Gets runtime date time. </summary>
|
||||||
|
/// <param name="runtime"> The runtime. </param>
|
||||||
|
/// <returns> The runtime date time. </returns>
|
||||||
|
protected double? GetRuntimeDateTime(long? runtime)
|
||||||
|
{
|
||||||
|
if (runtime.HasValue)
|
||||||
return Math.Ceiling(new TimeSpan(runtime.Value).TotalMinutes);
|
return Math.Ceiling(new TimeSpan(runtime.Value).TotalMinutes);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Gets series production year. </summary>
|
/// <summary> Gets series production year. </summary>
|
||||||
/// <param name="item"> The item. </param>
|
/// <param name="item"> The item. </param>
|
||||||
/// <returns> The series production year. </returns>
|
/// <returns> The series production year. </returns>
|
||||||
protected string GetSeriesProductionYear(BaseItem item)
|
protected string GetSeriesProductionYear(BaseItem item)
|
||||||
{
|
{
|
||||||
|
|
||||||
string productionYear = item.ProductionYear.ToString();
|
string productionYear = item.ProductionYear.ToString();
|
||||||
var series = item as Series;
|
var series = item as Series;
|
||||||
if (series == null)
|
if (series == null)
|
||||||
{
|
{
|
||||||
if (item.ProductionYear == null || item.ProductionYear == 0)
|
if (item.ProductionYear == null || item.ProductionYear == 0)
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
return productionYear;
|
return productionYear;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (series.Status == SeriesStatus.Continuing)
|
if (series.Status == SeriesStatus.Continuing)
|
||||||
return productionYear += "-Present";
|
return productionYear += "-Present";
|
||||||
|
|
||||||
if (series.EndDate != null && series.EndDate.Value.Year != series.ProductionYear)
|
if (series.EndDate != null && series.EndDate.Value.Year != series.ProductionYear)
|
||||||
return productionYear += "-" + series.EndDate.Value.Year;
|
return productionYear += "-" + series.EndDate.Value.Year;
|
||||||
|
|
||||||
return productionYear;
|
return productionYear;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Gets a stream. </summary>
|
/// <summary> Gets a stream. </summary>
|
||||||
/// <param name="item"> The item. </param>
|
/// <param name="item"> The item. </param>
|
||||||
/// <param name="streamType"> Type of the stream. </param>
|
/// <param name="streamType"> Type of the stream. </param>
|
||||||
/// <returns> The stream. </returns>
|
/// <returns> The stream. </returns>
|
||||||
protected MediaStream GetStream(BaseItem item, MediaStreamType streamType)
|
protected MediaStream GetStream(BaseItem item, MediaStreamType streamType)
|
||||||
{
|
{
|
||||||
var itemInfo = GetMediaSourceInfo(item);
|
var itemInfo = GetMediaSourceInfo(item);
|
||||||
if (itemInfo != null)
|
if (itemInfo != null)
|
||||||
return itemInfo.MediaStreams.FirstOrDefault(n => n.Type == streamType);
|
return itemInfo.MediaStreams.FirstOrDefault(n => n.Type == streamType);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Gets a studio. </summary>
|
/// <summary> Gets a studio. </summary>
|
||||||
/// <param name="name"> The name. </param>
|
/// <param name="name"> The name. </param>
|
||||||
/// <returns> The studio. </returns>
|
/// <returns> The studio. </returns>
|
||||||
protected Studio GetStudio(string name)
|
protected Studio GetStudio(string name)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(name))
|
if (string.IsNullOrEmpty(name))
|
||||||
return null;
|
return null;
|
||||||
return _libraryManager.GetStudio(name);
|
return _libraryManager.GetStudio(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Gets studio identifier. </summary>
|
/// <summary> Gets studio identifier. </summary>
|
||||||
/// <param name="name"> The name. </param>
|
/// <param name="name"> The name. </param>
|
||||||
/// <returns> The studio identifier. </returns>
|
/// <returns> The studio identifier. </returns>
|
||||||
protected string GetStudioID(string name)
|
protected string GetStudioID(string name)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(name))
|
if (string.IsNullOrEmpty(name))
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
return string.Format("{0:N}",
|
return string.Format("{0:N}",
|
||||||
GetStudio(name).Id);
|
GetStudio(name).Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Gets video resolution. </summary>
|
/// <summary> Gets video resolution. </summary>
|
||||||
/// <param name="item"> The item. </param>
|
/// <param name="item"> The item. </param>
|
||||||
/// <returns> The video resolution. </returns>
|
/// <returns> The video resolution. </returns>
|
||||||
protected string GetVideoResolution(BaseItem item)
|
protected string GetVideoResolution(BaseItem item)
|
||||||
{
|
{
|
||||||
var stream = GetStream(item,
|
var stream = GetStream(item,
|
||||||
MediaStreamType.Video);
|
MediaStreamType.Video);
|
||||||
if (stream != null && stream.Width != null)
|
if (stream != null && stream.Width != null)
|
||||||
return string.Format("{0} * {1}",
|
return string.Format("{0} * {1}",
|
||||||
stream.Width,
|
stream.Width,
|
||||||
(stream.Height != null ? stream.Height.ToString() : "-"));
|
(stream.Height != null ? stream.Height.ToString() : "-"));
|
||||||
|
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Gets video stream. </summary>
|
/// <summary> Gets video stream. </summary>
|
||||||
/// <param name="item"> The item. </param>
|
/// <param name="item"> The item. </param>
|
||||||
/// <returns> The video stream. </returns>
|
/// <returns> The video stream. </returns>
|
||||||
protected string GetVideoStream(BaseItem item)
|
protected string GetVideoStream(BaseItem item)
|
||||||
{
|
{
|
||||||
var stream = GetStream(item, MediaStreamType.Video);
|
var stream = GetStream(item, MediaStreamType.Video);
|
||||||
if (stream != null)
|
if (stream != null)
|
||||||
return stream.Codec.ToUpper();
|
return stream.Codec.ToUpper();
|
||||||
|
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
/// <summary> Displays a type visible. </summary>
|
||||||
|
/// <param name="headerDisplayType"> Type of the header display. </param>
|
||||||
|
/// <param name="displayType"> Type of the display. </param>
|
||||||
|
/// <returns> true if it succeeds, false if it fails. </returns>
|
||||||
|
protected bool DisplayTypeVisible(ReportDisplayType headerDisplayType, ReportDisplayType displayType)
|
||||||
|
{
|
||||||
|
if (headerDisplayType == ReportDisplayType.None)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool rval = headerDisplayType == displayType || headerDisplayType == ReportDisplayType.ScreenExport && (displayType == ReportDisplayType.Screen || displayType == ReportDisplayType.Export);
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
14
MediaBrowser.Api/Reports/Common/ReportDisplayType.cs
Normal file
14
MediaBrowser.Api/Reports/Common/ReportDisplayType.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Api.Reports
|
||||||
|
{
|
||||||
|
public enum ReportDisplayType
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Screen,
|
||||||
|
Export,
|
||||||
|
ScreenExport
|
||||||
|
}
|
||||||
|
}
|
@ -2,100 +2,137 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Api.Reports
|
namespace MediaBrowser.Api.Reports
|
||||||
{
|
{
|
||||||
public class ReportHelper
|
/// <summary> A report helper. </summary>
|
||||||
{
|
public class ReportHelper
|
||||||
/// <summary> Gets java script localized string. </summary>
|
{
|
||||||
/// <param name="phrase"> The phrase. </param>
|
#region [Public Methods]
|
||||||
/// <returns> The java script localized string. </returns>
|
|
||||||
public static string GetJavaScriptLocalizedString(string phrase)
|
|
||||||
{
|
|
||||||
var dictionary = BaseItem.LocalizationManager.GetJavaScriptLocalizationDictionary(BaseItem.ConfigurationManager.Configuration.UICulture);
|
|
||||||
|
|
||||||
string value;
|
/// <summary> Convert field to string. </summary>
|
||||||
|
/// <typeparam name="T"> Generic type parameter. </typeparam>
|
||||||
if (dictionary.TryGetValue(phrase, out value))
|
/// <param name="value"> The value. </param>
|
||||||
{
|
/// <param name="fieldType"> Type of the field. </param>
|
||||||
return value;
|
/// <returns> The field converted to string. </returns>
|
||||||
}
|
public static string ConvertToString<T>(T value, ReportFieldType fieldType)
|
||||||
|
{
|
||||||
return phrase;
|
if (value == null)
|
||||||
}
|
return "";
|
||||||
|
switch (fieldType)
|
||||||
/// <summary> Gets server localized string. </summary>
|
{
|
||||||
/// <param name="phrase"> The phrase. </param>
|
case ReportFieldType.String:
|
||||||
/// <returns> The server localized string. </returns>
|
return value.ToString();
|
||||||
public static string GetServerLocalizedString(string phrase)
|
case ReportFieldType.Boolean:
|
||||||
{
|
return value.ToString();
|
||||||
return BaseItem.LocalizationManager.GetLocalizedString(phrase, BaseItem.ConfigurationManager.Configuration.UICulture);
|
case ReportFieldType.Date:
|
||||||
}
|
return string.Format("{0:d}", value);
|
||||||
|
case ReportFieldType.Time:
|
||||||
/// <summary> Gets row type. </summary>
|
return string.Format("{0:t}", value);
|
||||||
/// <param name="rowType"> The type. </param>
|
case ReportFieldType.DateTime:
|
||||||
/// <returns> The row type. </returns>
|
return string.Format("{0:d}", value);
|
||||||
public static ReportViewType GetRowType(string rowType)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(rowType))
|
|
||||||
return ReportViewType.BaseItem;
|
|
||||||
|
|
||||||
ReportViewType rType;
|
|
||||||
|
|
||||||
if (!Enum.TryParse<ReportViewType>(rowType, out rType))
|
|
||||||
return ReportViewType.BaseItem;
|
|
||||||
|
|
||||||
return rType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary> Gets header metadata type. </summary>
|
|
||||||
/// <param name="header"> The header. </param>
|
|
||||||
/// <returns> The header metadata type. </returns>
|
|
||||||
public static HeaderMetadata GetHeaderMetadataType(string header)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(header))
|
|
||||||
return HeaderMetadata.None;
|
|
||||||
|
|
||||||
HeaderMetadata rType;
|
|
||||||
|
|
||||||
if (!Enum.TryParse<HeaderMetadata>(header, out rType))
|
|
||||||
return HeaderMetadata.None;
|
|
||||||
|
|
||||||
return rType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary> Convert field to string. </summary>
|
|
||||||
/// <typeparam name="T"> Generic type parameter. </typeparam>
|
|
||||||
/// <param name="value"> The value. </param>
|
|
||||||
/// <param name="fieldType"> Type of the field. </param>
|
|
||||||
/// <returns> The field converted to string. </returns>
|
|
||||||
public static string ConvertToString<T>(T value, ReportFieldType fieldType)
|
|
||||||
{
|
|
||||||
if (value == null)
|
|
||||||
return "";
|
|
||||||
switch (fieldType)
|
|
||||||
{
|
|
||||||
case ReportFieldType.String:
|
|
||||||
return value.ToString();
|
|
||||||
case ReportFieldType.Boolean:
|
|
||||||
return value.ToString();
|
|
||||||
case ReportFieldType.Date:
|
|
||||||
return string.Format("{0:d}", value);
|
|
||||||
case ReportFieldType.Time:
|
|
||||||
return string.Format("{0:t}", value);
|
|
||||||
case ReportFieldType.DateTime:
|
|
||||||
return string.Format("{0:d}", value);
|
|
||||||
case ReportFieldType.Minutes:
|
case ReportFieldType.Minutes:
|
||||||
return string.Format("{0}mn", value);
|
return string.Format("{0}mn", value);
|
||||||
case ReportFieldType.Int:
|
case ReportFieldType.Int:
|
||||||
return string.Format("", value);
|
return string.Format("", value);
|
||||||
default:
|
default:
|
||||||
if (value is Guid)
|
if (value is Guid)
|
||||||
return string.Format("{0:N}", value);
|
return string.Format("{0:N}", value);
|
||||||
return value.ToString();
|
return value.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/// <summary> Gets filtered report header metadata. </summary>
|
||||||
|
/// <param name="reportColumns"> The report columns. </param>
|
||||||
|
/// <param name="defaultReturnValue"> The default return value. </param>
|
||||||
|
/// <returns> The filtered report header metadata. </returns>
|
||||||
|
public static List<HeaderMetadata> GetFilteredReportHeaderMetadata(string reportColumns, Func<List<HeaderMetadata>> defaultReturnValue = null)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(reportColumns))
|
||||||
|
{
|
||||||
|
var s = reportColumns.Split('|').Select(x => ReportHelper.GetHeaderMetadataType(x)).Where(x => x != HeaderMetadata.None);
|
||||||
|
return s.ToList();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (defaultReturnValue != null)
|
||||||
|
return defaultReturnValue();
|
||||||
|
else
|
||||||
|
return new List<HeaderMetadata>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Gets header metadata type. </summary>
|
||||||
|
/// <param name="header"> The header. </param>
|
||||||
|
/// <returns> The header metadata type. </returns>
|
||||||
|
public static HeaderMetadata GetHeaderMetadataType(string header)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(header))
|
||||||
|
return HeaderMetadata.None;
|
||||||
|
|
||||||
|
HeaderMetadata rType;
|
||||||
|
|
||||||
|
if (!Enum.TryParse<HeaderMetadata>(header, out rType))
|
||||||
|
return HeaderMetadata.None;
|
||||||
|
|
||||||
|
return rType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Gets report view type. </summary>
|
||||||
|
/// <param name="rowType"> The type. </param>
|
||||||
|
/// <returns> The report view type. </returns>
|
||||||
|
public static ReportViewType GetReportViewType(string rowType)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(rowType))
|
||||||
|
return ReportViewType.ReportData;
|
||||||
|
|
||||||
|
ReportViewType rType;
|
||||||
|
|
||||||
|
if (!Enum.TryParse<ReportViewType>(rowType, out rType))
|
||||||
|
return ReportViewType.ReportData;
|
||||||
|
|
||||||
|
return rType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Gets row type. </summary>
|
||||||
|
/// <param name="rowType"> The type. </param>
|
||||||
|
/// <returns> The row type. </returns>
|
||||||
|
public static ReportIncludeItemTypes GetRowType(string rowType)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(rowType))
|
||||||
|
return ReportIncludeItemTypes.BaseItem;
|
||||||
|
|
||||||
|
ReportIncludeItemTypes rType;
|
||||||
|
|
||||||
|
if (!Enum.TryParse<ReportIncludeItemTypes>(rowType, out rType))
|
||||||
|
return ReportIncludeItemTypes.BaseItem;
|
||||||
|
|
||||||
|
return rType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Gets report display type. </summary>
|
||||||
|
/// <param name="displayType"> Type of the display. </param>
|
||||||
|
/// <returns> The report display type. </returns>
|
||||||
|
public static ReportDisplayType GetReportDisplayType(string displayType)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(displayType))
|
||||||
|
return ReportDisplayType.ScreenExport;
|
||||||
|
|
||||||
|
ReportDisplayType rType;
|
||||||
|
|
||||||
|
if (!Enum.TryParse<ReportDisplayType>(displayType, out rType))
|
||||||
|
return ReportDisplayType.ScreenExport;
|
||||||
|
|
||||||
|
return rType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Gets core localized string. </summary>
|
||||||
|
/// <param name="phrase"> The phrase. </param>
|
||||||
|
/// <returns> The core localized string. </returns>
|
||||||
|
public static string GetCoreLocalizedString(string phrase)
|
||||||
|
{
|
||||||
|
return BaseItem.LocalizationManager.GetLocalizedString(phrase);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
25
MediaBrowser.Api/Reports/Common/ReportIncludeItemTypes.cs
Normal file
25
MediaBrowser.Api/Reports/Common/ReportIncludeItemTypes.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Api.Reports
|
||||||
|
{
|
||||||
|
public enum ReportIncludeItemTypes
|
||||||
|
{
|
||||||
|
MusicArtist,
|
||||||
|
MusicAlbum,
|
||||||
|
Book,
|
||||||
|
BoxSet,
|
||||||
|
Episode,
|
||||||
|
Game,
|
||||||
|
Video,
|
||||||
|
Movie,
|
||||||
|
MusicVideo,
|
||||||
|
Trailer,
|
||||||
|
Season,
|
||||||
|
Series,
|
||||||
|
Audio,
|
||||||
|
BaseItem,
|
||||||
|
Artist
|
||||||
|
}
|
||||||
|
}
|
@ -6,20 +6,9 @@ namespace MediaBrowser.Api.Reports
|
|||||||
{
|
{
|
||||||
public enum ReportViewType
|
public enum ReportViewType
|
||||||
{
|
{
|
||||||
MusicArtist,
|
ReportData,
|
||||||
MusicAlbum,
|
ReportStatistics,
|
||||||
Book,
|
ReportActivities
|
||||||
BoxSet,
|
|
||||||
Episode,
|
|
||||||
Game,
|
|
||||||
Video,
|
|
||||||
Movie,
|
|
||||||
MusicVideo,
|
|
||||||
Trailer,
|
|
||||||
Season,
|
|
||||||
Series,
|
|
||||||
Audio,
|
|
||||||
BaseItem,
|
|
||||||
Artist
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,164 +17,98 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace MediaBrowser.Api.Reports
|
namespace MediaBrowser.Api.Reports
|
||||||
{
|
{
|
||||||
/// <summary> A report builder. </summary>
|
/// <summary> A report builder. </summary>
|
||||||
/// <seealso cref="T:MediaBrowser.Api.Reports.ReportBuilderBase"/>
|
/// <seealso cref="T:MediaBrowser.Api.Reports.ReportBuilderBase"/>
|
||||||
public class ReportBuilder : ReportBuilderBase
|
public class ReportBuilder : ReportBuilderBase
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
#region [Constructors]
|
||||||
/// Initializes a new instance of the MediaBrowser.Api.Reports.ReportBuilder class. </summary>
|
|
||||||
/// <param name="libraryManager"> Manager for library. </param>
|
|
||||||
public ReportBuilder(ILibraryManager libraryManager)
|
|
||||||
: base(libraryManager)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private Func<bool, string> GetBoolString = s => s == true ? "x" : "";
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the MediaBrowser.Api.Reports.ReportBuilder class. </summary>
|
||||||
|
/// <param name="libraryManager"> Manager for library. </param>
|
||||||
|
public ReportBuilder(ILibraryManager libraryManager)
|
||||||
|
: base(libraryManager)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public ReportResult GetReportResult(BaseItem[] items, ReportViewType reportRowType, BaseReportRequest request)
|
#endregion
|
||||||
{
|
|
||||||
List<HeaderMetadata> headersMetadata = this.GetFilteredReportHeaderMetadata(reportRowType, request);
|
|
||||||
|
|
||||||
var headers = GetReportHeaders(reportRowType, headersMetadata);
|
#region [Public Methods]
|
||||||
var rows = GetReportRows(items, headersMetadata);
|
|
||||||
|
|
||||||
ReportResult result = new ReportResult { Headers = headers };
|
/// <summary> Gets report result. </summary>
|
||||||
HeaderMetadata groupBy = ReportHelper.GetHeaderMetadataType(request.GroupBy);
|
/// <param name="items"> The items. </param>
|
||||||
int i = headers.FindIndex(x => x.FieldName == groupBy);
|
/// <param name="request"> The request. </param>
|
||||||
if (groupBy != HeaderMetadata.None && i > 0)
|
/// <returns> The report result. </returns>
|
||||||
{
|
public ReportResult GetResult(BaseItem[] items, IReportsQuery request)
|
||||||
var rowsGroup = rows.SelectMany(x => x.Columns[i].Name.Split(';'), (x, g) => new { Genre = g.Trim(), Rows = x })
|
{
|
||||||
.GroupBy(x => x.Genre)
|
ReportIncludeItemTypes reportRowType = ReportHelper.GetRowType(request.IncludeItemTypes);
|
||||||
.OrderBy(x => x.Key)
|
ReportDisplayType displayType = ReportHelper.GetReportDisplayType(request.DisplayType);
|
||||||
.Select(x => new ReportGroup { Name = x.Key, Rows = x.Select(r => r.Rows).ToList() });
|
|
||||||
|
|
||||||
result.Groups = rowsGroup.ToList();
|
List<ReportOptions<BaseItem>> options = this.GetReportOptions<BaseItem>(request,
|
||||||
result.IsGrouped = true;
|
() => this.GetDefaultHeaderMetadata(reportRowType),
|
||||||
}
|
(hm) => this.GetOption(hm)).Where(x => this.DisplayTypeVisible(x.Header.DisplayType, displayType)).ToList();
|
||||||
else
|
|
||||||
{
|
|
||||||
result.Rows = rows;
|
|
||||||
result.IsGrouped = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
var headers = GetHeaders<BaseItem>(options);
|
||||||
}
|
var rows = GetReportRows(items, options);
|
||||||
|
|
||||||
public List<ReportHeader> GetReportHeaders(ReportViewType reportRowType, BaseReportRequest request)
|
ReportResult result = new ReportResult { Headers = headers };
|
||||||
{
|
HeaderMetadata groupBy = ReportHelper.GetHeaderMetadataType(request.GroupBy);
|
||||||
List<ReportHeader> headersMetadata = this.GetReportHeaders(reportRowType);
|
int i = headers.FindIndex(x => x.FieldName == groupBy);
|
||||||
if (request != null && !string.IsNullOrEmpty(request.ReportColumns))
|
if (groupBy != HeaderMetadata.None && i >= 0)
|
||||||
{
|
{
|
||||||
List<HeaderMetadata> headersMetadataFiltered = this.GetFilteredReportHeaderMetadata(reportRowType, request);
|
var rowsGroup = rows.SelectMany(x => x.Columns[i].Name.Split(';'), (x, g) => new { Group = g.Trim(), Rows = x })
|
||||||
foreach (ReportHeader reportHeader in headersMetadata)
|
.GroupBy(x => x.Group)
|
||||||
{
|
.OrderBy(x => x.Key)
|
||||||
if (!headersMetadataFiltered.Contains(reportHeader.FieldName))
|
.Select(x => new ReportGroup { Name = x.Key, Rows = x.Select(r => r.Rows).ToList() });
|
||||||
{
|
|
||||||
reportHeader.Visible = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
result.Groups = rowsGroup.ToList();
|
||||||
|
result.IsGrouped = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.Rows = rows;
|
||||||
|
result.IsGrouped = false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
return headersMetadata;
|
#endregion
|
||||||
}
|
|
||||||
|
|
||||||
public List<ReportHeader> GetReportHeaders(ReportViewType reportRowType, List<HeaderMetadata> headersMetadata = null)
|
#region [Protected Internal Methods]
|
||||||
{
|
|
||||||
if (headersMetadata == null)
|
|
||||||
headersMetadata = this.GetDefaultReportHeaderMetadata(reportRowType);
|
|
||||||
|
|
||||||
List<ReportOptions<BaseItem>> options = new List<ReportOptions<BaseItem>>();
|
/// <summary> Gets the headers. </summary>
|
||||||
foreach (HeaderMetadata header in headersMetadata)
|
/// <typeparam name="H"> Type of the header. </typeparam>
|
||||||
{
|
/// <param name="request"> The request. </param>
|
||||||
options.Add(GetReportOption(header));
|
/// <returns> The headers. </returns>
|
||||||
}
|
/// <seealso cref="M:MediaBrowser.Api.Reports.ReportBuilderBase.GetHeaders{H}(H)"/>
|
||||||
|
protected internal override List<ReportHeader> GetHeaders<H>(H request)
|
||||||
|
{
|
||||||
|
ReportIncludeItemTypes reportRowType = ReportHelper.GetRowType(request.IncludeItemTypes);
|
||||||
|
return this.GetHeaders<BaseItem>(request, () => this.GetDefaultHeaderMetadata(reportRowType), (hm) => this.GetOption(hm));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
List<ReportHeader> headers = new List<ReportHeader>();
|
#region [Private Methods]
|
||||||
foreach (ReportOptions<BaseItem> option in options)
|
|
||||||
{
|
|
||||||
headers.Add(option.Header);
|
|
||||||
}
|
|
||||||
return headers;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<ReportRow> GetReportRows(IEnumerable<BaseItem> items, List<HeaderMetadata> headersMetadata)
|
/// <summary> Gets default report header metadata. </summary>
|
||||||
{
|
/// <param name="reportIncludeItemTypes"> Type of the report row. </param>
|
||||||
List<ReportOptions<BaseItem>> options = new List<ReportOptions<BaseItem>>();
|
/// <returns> The default report header metadata. </returns>
|
||||||
foreach (HeaderMetadata header in headersMetadata)
|
private List<HeaderMetadata> GetDefaultHeaderMetadata(ReportIncludeItemTypes reportIncludeItemTypes)
|
||||||
{
|
{
|
||||||
options.Add(GetReportOption(header));
|
switch (reportIncludeItemTypes)
|
||||||
}
|
{
|
||||||
|
case ReportIncludeItemTypes.Season:
|
||||||
var rows = new List<ReportRow>();
|
return new List<HeaderMetadata>
|
||||||
|
{
|
||||||
foreach (BaseItem item in items)
|
HeaderMetadata.Status,
|
||||||
{
|
HeaderMetadata.Locked,
|
||||||
ReportRow rRow = GetRow(item);
|
HeaderMetadata.Unidentified,
|
||||||
foreach (ReportOptions<BaseItem> option in options)
|
HeaderMetadata.ImagePrimary,
|
||||||
{
|
HeaderMetadata.ImageBackdrop,
|
||||||
object itemColumn = option.Column != null ? option.Column(item, rRow) : "";
|
HeaderMetadata.ImageLogo,
|
||||||
object itemId = option.ItemID != null ? option.ItemID(item) : "";
|
|
||||||
ReportItem rItem = new ReportItem
|
|
||||||
{
|
|
||||||
Name = ReportHelper.ConvertToString(itemColumn, option.Header.HeaderFieldType),
|
|
||||||
Id = ReportHelper.ConvertToString(itemId, ReportFieldType.Object)
|
|
||||||
};
|
|
||||||
rRow.Columns.Add(rItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
rows.Add(rRow);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rows;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary> Gets a row. </summary>
|
|
||||||
/// <param name="item"> The item. </param>
|
|
||||||
/// <returns> The row. </returns>
|
|
||||||
private ReportRow GetRow(BaseItem item)
|
|
||||||
{
|
|
||||||
var hasTrailers = item as IHasTrailers;
|
|
||||||
var hasSpecialFeatures = item as IHasSpecialFeatures;
|
|
||||||
var video = item as Video;
|
|
||||||
ReportRow rRow = new ReportRow
|
|
||||||
{
|
|
||||||
Id = item.Id.ToString("N"),
|
|
||||||
HasLockData = item.IsLocked,
|
|
||||||
IsUnidentified = item.IsUnidentified,
|
|
||||||
HasLocalTrailer = hasTrailers != null ? hasTrailers.GetTrailerIds().Count() > 0 : false,
|
|
||||||
HasImageTagsPrimary = (item.ImageInfos != null && item.ImageInfos.Count(n => n.Type == ImageType.Primary) > 0),
|
|
||||||
HasImageTagsBackdrop = (item.ImageInfos != null && item.ImageInfos.Count(n => n.Type == ImageType.Backdrop) > 0),
|
|
||||||
HasImageTagsLogo = (item.ImageInfos != null && item.ImageInfos.Count(n => n.Type == ImageType.Logo) > 0),
|
|
||||||
HasSpecials = hasSpecialFeatures != null ? hasSpecialFeatures.SpecialFeatureIds.Count > 0 : false,
|
|
||||||
HasSubtitles = video != null ? video.HasSubtitles : false,
|
|
||||||
RowType = ReportHelper.GetRowType(item.GetClientTypeName())
|
|
||||||
};
|
|
||||||
return rRow;
|
|
||||||
}
|
|
||||||
public List<HeaderMetadata> GetFilteredReportHeaderMetadata(ReportViewType reportRowType, BaseReportRequest request)
|
|
||||||
{
|
|
||||||
if (request != null && !string.IsNullOrEmpty(request.ReportColumns))
|
|
||||||
{
|
|
||||||
var s = request.ReportColumns.Split('|').Select(x => ReportHelper.GetHeaderMetadataType(x)).Where(x => x != HeaderMetadata.None);
|
|
||||||
return s.ToList();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return this.GetDefaultReportHeaderMetadata(reportRowType);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<HeaderMetadata> GetDefaultReportHeaderMetadata(ReportViewType reportRowType)
|
|
||||||
{
|
|
||||||
switch (reportRowType)
|
|
||||||
{
|
|
||||||
case ReportViewType.Season:
|
|
||||||
return new List<HeaderMetadata>
|
|
||||||
{
|
|
||||||
HeaderMetadata.StatusImage,
|
|
||||||
HeaderMetadata.Series,
|
HeaderMetadata.Series,
|
||||||
HeaderMetadata.Season,
|
HeaderMetadata.Season,
|
||||||
HeaderMetadata.SeasonNumber,
|
HeaderMetadata.SeasonNumber,
|
||||||
@ -183,10 +117,15 @@ namespace MediaBrowser.Api.Reports
|
|||||||
HeaderMetadata.Genres
|
HeaderMetadata.Genres
|
||||||
};
|
};
|
||||||
|
|
||||||
case ReportViewType.Series:
|
case ReportIncludeItemTypes.Series:
|
||||||
return new List<HeaderMetadata>
|
return new List<HeaderMetadata>
|
||||||
{
|
{
|
||||||
HeaderMetadata.StatusImage,
|
HeaderMetadata.Status,
|
||||||
|
HeaderMetadata.Locked,
|
||||||
|
HeaderMetadata.Unidentified,
|
||||||
|
HeaderMetadata.ImagePrimary,
|
||||||
|
HeaderMetadata.ImageBackdrop,
|
||||||
|
HeaderMetadata.ImageLogo,
|
||||||
HeaderMetadata.Name,
|
HeaderMetadata.Name,
|
||||||
HeaderMetadata.Network,
|
HeaderMetadata.Network,
|
||||||
HeaderMetadata.DateAdded,
|
HeaderMetadata.DateAdded,
|
||||||
@ -199,10 +138,15 @@ namespace MediaBrowser.Api.Reports
|
|||||||
HeaderMetadata.Specials
|
HeaderMetadata.Specials
|
||||||
};
|
};
|
||||||
|
|
||||||
case ReportViewType.MusicAlbum:
|
case ReportIncludeItemTypes.MusicAlbum:
|
||||||
return new List<HeaderMetadata>
|
return new List<HeaderMetadata>
|
||||||
{
|
{
|
||||||
HeaderMetadata.StatusImage,
|
HeaderMetadata.Status,
|
||||||
|
HeaderMetadata.Locked,
|
||||||
|
HeaderMetadata.Unidentified,
|
||||||
|
HeaderMetadata.ImagePrimary,
|
||||||
|
HeaderMetadata.ImageBackdrop,
|
||||||
|
HeaderMetadata.ImageLogo,
|
||||||
HeaderMetadata.Name,
|
HeaderMetadata.Name,
|
||||||
HeaderMetadata.AlbumArtist,
|
HeaderMetadata.AlbumArtist,
|
||||||
HeaderMetadata.DateAdded,
|
HeaderMetadata.DateAdded,
|
||||||
@ -212,10 +156,15 @@ namespace MediaBrowser.Api.Reports
|
|||||||
HeaderMetadata.Genres
|
HeaderMetadata.Genres
|
||||||
};
|
};
|
||||||
|
|
||||||
case ReportViewType.MusicArtist:
|
case ReportIncludeItemTypes.MusicArtist:
|
||||||
return new List<HeaderMetadata>
|
return new List<HeaderMetadata>
|
||||||
{
|
{
|
||||||
HeaderMetadata.StatusImage,
|
HeaderMetadata.Status,
|
||||||
|
HeaderMetadata.Locked,
|
||||||
|
HeaderMetadata.Unidentified,
|
||||||
|
HeaderMetadata.ImagePrimary,
|
||||||
|
HeaderMetadata.ImageBackdrop,
|
||||||
|
HeaderMetadata.ImageLogo,
|
||||||
HeaderMetadata.MusicArtist,
|
HeaderMetadata.MusicArtist,
|
||||||
HeaderMetadata.Countries,
|
HeaderMetadata.Countries,
|
||||||
HeaderMetadata.DateAdded,
|
HeaderMetadata.DateAdded,
|
||||||
@ -223,10 +172,15 @@ namespace MediaBrowser.Api.Reports
|
|||||||
HeaderMetadata.Genres
|
HeaderMetadata.Genres
|
||||||
};
|
};
|
||||||
|
|
||||||
case ReportViewType.Game:
|
case ReportIncludeItemTypes.Game:
|
||||||
return new List<HeaderMetadata>
|
return new List<HeaderMetadata>
|
||||||
{
|
{
|
||||||
HeaderMetadata.StatusImage,
|
HeaderMetadata.Status,
|
||||||
|
HeaderMetadata.Locked,
|
||||||
|
HeaderMetadata.Unidentified,
|
||||||
|
HeaderMetadata.ImagePrimary,
|
||||||
|
HeaderMetadata.ImageBackdrop,
|
||||||
|
HeaderMetadata.ImageLogo,
|
||||||
HeaderMetadata.Name,
|
HeaderMetadata.Name,
|
||||||
HeaderMetadata.GameSystem,
|
HeaderMetadata.GameSystem,
|
||||||
HeaderMetadata.DateAdded,
|
HeaderMetadata.DateAdded,
|
||||||
@ -239,10 +193,15 @@ namespace MediaBrowser.Api.Reports
|
|||||||
HeaderMetadata.Trailers
|
HeaderMetadata.Trailers
|
||||||
};
|
};
|
||||||
|
|
||||||
case ReportViewType.Movie:
|
case ReportIncludeItemTypes.Movie:
|
||||||
return new List<HeaderMetadata>
|
return new List<HeaderMetadata>
|
||||||
{
|
{
|
||||||
HeaderMetadata.StatusImage,
|
HeaderMetadata.Status,
|
||||||
|
HeaderMetadata.Locked,
|
||||||
|
HeaderMetadata.Unidentified,
|
||||||
|
HeaderMetadata.ImagePrimary,
|
||||||
|
HeaderMetadata.ImageBackdrop,
|
||||||
|
HeaderMetadata.ImageLogo,
|
||||||
HeaderMetadata.Name,
|
HeaderMetadata.Name,
|
||||||
HeaderMetadata.DateAdded,
|
HeaderMetadata.DateAdded,
|
||||||
HeaderMetadata.ReleaseDate,
|
HeaderMetadata.ReleaseDate,
|
||||||
@ -259,10 +218,15 @@ namespace MediaBrowser.Api.Reports
|
|||||||
HeaderMetadata.Specials
|
HeaderMetadata.Specials
|
||||||
};
|
};
|
||||||
|
|
||||||
case ReportViewType.Book:
|
case ReportIncludeItemTypes.Book:
|
||||||
return new List<HeaderMetadata>
|
return new List<HeaderMetadata>
|
||||||
{
|
{
|
||||||
HeaderMetadata.StatusImage,
|
HeaderMetadata.Status,
|
||||||
|
HeaderMetadata.Locked,
|
||||||
|
HeaderMetadata.Unidentified,
|
||||||
|
HeaderMetadata.ImagePrimary,
|
||||||
|
HeaderMetadata.ImageBackdrop,
|
||||||
|
HeaderMetadata.ImageLogo,
|
||||||
HeaderMetadata.Name,
|
HeaderMetadata.Name,
|
||||||
HeaderMetadata.DateAdded,
|
HeaderMetadata.DateAdded,
|
||||||
HeaderMetadata.ReleaseDate,
|
HeaderMetadata.ReleaseDate,
|
||||||
@ -272,10 +236,15 @@ namespace MediaBrowser.Api.Reports
|
|||||||
HeaderMetadata.CommunityRating
|
HeaderMetadata.CommunityRating
|
||||||
};
|
};
|
||||||
|
|
||||||
case ReportViewType.BoxSet:
|
case ReportIncludeItemTypes.BoxSet:
|
||||||
return new List<HeaderMetadata>
|
return new List<HeaderMetadata>
|
||||||
{
|
{
|
||||||
HeaderMetadata.StatusImage,
|
HeaderMetadata.Status,
|
||||||
|
HeaderMetadata.Locked,
|
||||||
|
HeaderMetadata.Unidentified,
|
||||||
|
HeaderMetadata.ImagePrimary,
|
||||||
|
HeaderMetadata.ImageBackdrop,
|
||||||
|
HeaderMetadata.ImageLogo,
|
||||||
HeaderMetadata.Name,
|
HeaderMetadata.Name,
|
||||||
HeaderMetadata.DateAdded,
|
HeaderMetadata.DateAdded,
|
||||||
HeaderMetadata.ReleaseDate,
|
HeaderMetadata.ReleaseDate,
|
||||||
@ -286,10 +255,15 @@ namespace MediaBrowser.Api.Reports
|
|||||||
HeaderMetadata.Trailers
|
HeaderMetadata.Trailers
|
||||||
};
|
};
|
||||||
|
|
||||||
case ReportViewType.Audio:
|
case ReportIncludeItemTypes.Audio:
|
||||||
return new List<HeaderMetadata>
|
return new List<HeaderMetadata>
|
||||||
{
|
{
|
||||||
HeaderMetadata.StatusImage,
|
HeaderMetadata.Status,
|
||||||
|
HeaderMetadata.Locked,
|
||||||
|
HeaderMetadata.Unidentified,
|
||||||
|
HeaderMetadata.ImagePrimary,
|
||||||
|
HeaderMetadata.ImageBackdrop,
|
||||||
|
HeaderMetadata.ImageLogo,
|
||||||
HeaderMetadata.Name,
|
HeaderMetadata.Name,
|
||||||
HeaderMetadata.AudioAlbumArtist,
|
HeaderMetadata.AudioAlbumArtist,
|
||||||
HeaderMetadata.AudioAlbum,
|
HeaderMetadata.AudioAlbum,
|
||||||
@ -305,10 +279,15 @@ namespace MediaBrowser.Api.Reports
|
|||||||
HeaderMetadata.Audio
|
HeaderMetadata.Audio
|
||||||
};
|
};
|
||||||
|
|
||||||
case ReportViewType.Episode:
|
case ReportIncludeItemTypes.Episode:
|
||||||
return new List<HeaderMetadata>
|
return new List<HeaderMetadata>
|
||||||
{
|
{
|
||||||
HeaderMetadata.StatusImage,
|
HeaderMetadata.Status,
|
||||||
|
HeaderMetadata.Locked,
|
||||||
|
HeaderMetadata.Unidentified,
|
||||||
|
HeaderMetadata.ImagePrimary,
|
||||||
|
HeaderMetadata.ImageBackdrop,
|
||||||
|
HeaderMetadata.ImageLogo,
|
||||||
HeaderMetadata.Name,
|
HeaderMetadata.Name,
|
||||||
HeaderMetadata.EpisodeSeries,
|
HeaderMetadata.EpisodeSeries,
|
||||||
HeaderMetadata.Season,
|
HeaderMetadata.Season,
|
||||||
@ -327,14 +306,23 @@ namespace MediaBrowser.Api.Reports
|
|||||||
HeaderMetadata.Specials
|
HeaderMetadata.Specials
|
||||||
};
|
};
|
||||||
|
|
||||||
case ReportViewType.Video:
|
case ReportIncludeItemTypes.Video:
|
||||||
case ReportViewType.MusicVideo:
|
case ReportIncludeItemTypes.MusicVideo:
|
||||||
case ReportViewType.Trailer:
|
case ReportIncludeItemTypes.Trailer:
|
||||||
case ReportViewType.BaseItem:
|
case ReportIncludeItemTypes.BaseItem:
|
||||||
default:
|
default:
|
||||||
return new List<HeaderMetadata>
|
return new List<HeaderMetadata>
|
||||||
{
|
{
|
||||||
HeaderMetadata.StatusImage,
|
HeaderMetadata.Status,
|
||||||
|
HeaderMetadata.Locked,
|
||||||
|
HeaderMetadata.Unidentified,
|
||||||
|
HeaderMetadata.ImagePrimary,
|
||||||
|
HeaderMetadata.ImageBackdrop,
|
||||||
|
HeaderMetadata.ImageLogo,
|
||||||
|
HeaderMetadata.Unidentified,
|
||||||
|
HeaderMetadata.ImagePrimary,
|
||||||
|
HeaderMetadata.ImageBackdrop,
|
||||||
|
HeaderMetadata.ImageLogo,
|
||||||
HeaderMetadata.Name,
|
HeaderMetadata.Name,
|
||||||
HeaderMetadata.DateAdded,
|
HeaderMetadata.DateAdded,
|
||||||
HeaderMetadata.ReleaseDate,
|
HeaderMetadata.ReleaseDate,
|
||||||
@ -351,239 +339,313 @@ namespace MediaBrowser.Api.Reports
|
|||||||
HeaderMetadata.Specials
|
HeaderMetadata.Specials
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Gets report option. </summary>
|
/// <summary> Gets report option. </summary>
|
||||||
/// <param name="header"> The header. </param>
|
/// <param name="header"> The header. </param>
|
||||||
/// <param name="sortField"> The sort field. </param>
|
/// <param name="sortField"> The sort field. </param>
|
||||||
/// <returns> The report option. </returns>
|
/// <returns> The report option. </returns>
|
||||||
private ReportOptions<BaseItem> GetReportOption(HeaderMetadata header, string sortField = "")
|
private ReportOptions<BaseItem> GetOption(HeaderMetadata header, string sortField = "")
|
||||||
{
|
{
|
||||||
ReportHeader reportHeader = new ReportHeader
|
HeaderMetadata internalHeader = header;
|
||||||
{
|
|
||||||
HeaderFieldType = ReportFieldType.String,
|
|
||||||
SortField = sortField,
|
|
||||||
Type = "",
|
|
||||||
ItemViewType = ItemViewType.None
|
|
||||||
};
|
|
||||||
|
|
||||||
Func<BaseItem, ReportRow, object> column = null;
|
ReportOptions<BaseItem> option = new ReportOptions<BaseItem>()
|
||||||
Func<BaseItem, object> itemId = null;
|
{
|
||||||
HeaderMetadata internalHeader = header;
|
Header = new ReportHeader
|
||||||
|
{
|
||||||
|
HeaderFieldType = ReportFieldType.String,
|
||||||
|
SortField = sortField,
|
||||||
|
Type = "",
|
||||||
|
ItemViewType = ItemViewType.None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
switch (header)
|
switch (header)
|
||||||
{
|
{
|
||||||
case HeaderMetadata.StatusImage:
|
case HeaderMetadata.Status:
|
||||||
reportHeader.ItemViewType = ItemViewType.StatusImage;
|
option.Header.ItemViewType = ItemViewType.StatusImage;
|
||||||
internalHeader = HeaderMetadata.Status;
|
internalHeader = HeaderMetadata.Status;
|
||||||
reportHeader.CanGroup = false;
|
option.Header.CanGroup = false;
|
||||||
break;
|
option.Header.DisplayType = ReportDisplayType.Screen;
|
||||||
|
break;
|
||||||
|
case HeaderMetadata.Locked:
|
||||||
|
option.Column = (i, r) => this.GetBoolString(r.HasLockData);
|
||||||
|
option.Header.ItemViewType = ItemViewType.LockDataImage;
|
||||||
|
option.Header.CanGroup = false;
|
||||||
|
option.Header.DisplayType = ReportDisplayType.Export;
|
||||||
|
break;
|
||||||
|
case HeaderMetadata.Unidentified:
|
||||||
|
option.Column = (i, r) => this.GetBoolString(r.IsUnidentified);
|
||||||
|
option.Header.ItemViewType = ItemViewType.UnidentifiedImage;
|
||||||
|
option.Header.CanGroup = false;
|
||||||
|
option.Header.DisplayType = ReportDisplayType.Export;
|
||||||
|
break;
|
||||||
|
case HeaderMetadata.ImagePrimary:
|
||||||
|
option.Column = (i, r) => this.GetBoolString(r.HasImageTagsPrimary);
|
||||||
|
option.Header.ItemViewType = ItemViewType.TagsPrimaryImage;
|
||||||
|
option.Header.CanGroup = false;
|
||||||
|
option.Header.DisplayType = ReportDisplayType.Export;
|
||||||
|
break;
|
||||||
|
case HeaderMetadata.ImageBackdrop:
|
||||||
|
option.Column = (i, r) => this.GetBoolString(r.HasImageTagsBackdrop);
|
||||||
|
option.Header.ItemViewType = ItemViewType.TagsBackdropImage;
|
||||||
|
option.Header.CanGroup = false;
|
||||||
|
option.Header.DisplayType = ReportDisplayType.Export;
|
||||||
|
break;
|
||||||
|
case HeaderMetadata.ImageLogo:
|
||||||
|
option.Column = (i, r) => this.GetBoolString(r.HasImageTagsLogo);
|
||||||
|
option.Header.ItemViewType = ItemViewType.TagsLogoImage;
|
||||||
|
option.Header.CanGroup = false;
|
||||||
|
option.Header.DisplayType = ReportDisplayType.Export;
|
||||||
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.Name:
|
case HeaderMetadata.Name:
|
||||||
column = (i, r) => i.Name;
|
option.Column = (i, r) => i.Name;
|
||||||
reportHeader.ItemViewType = ItemViewType.Detail;
|
option.Header.ItemViewType = ItemViewType.Detail;
|
||||||
reportHeader.SortField = "SortName";
|
option.Header.SortField = "SortName";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.DateAdded:
|
case HeaderMetadata.DateAdded:
|
||||||
column = (i, r) => i.DateCreated;
|
option.Column = (i, r) => i.DateCreated;
|
||||||
reportHeader.SortField = "DateCreated,SortName";
|
option.Header.SortField = "DateCreated,SortName";
|
||||||
reportHeader.HeaderFieldType = ReportFieldType.DateTime;
|
option.Header.HeaderFieldType = ReportFieldType.DateTime;
|
||||||
reportHeader.Type = "";
|
option.Header.Type = "";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.PremiereDate:
|
case HeaderMetadata.PremiereDate:
|
||||||
case HeaderMetadata.ReleaseDate:
|
case HeaderMetadata.ReleaseDate:
|
||||||
column = (i, r) => i.PremiereDate;
|
option.Column = (i, r) => i.PremiereDate;
|
||||||
reportHeader.HeaderFieldType = ReportFieldType.DateTime;
|
option.Header.HeaderFieldType = ReportFieldType.DateTime;
|
||||||
reportHeader.SortField = "ProductionYear,PremiereDate,SortName";
|
option.Header.SortField = "ProductionYear,PremiereDate,SortName";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.Runtime:
|
case HeaderMetadata.Runtime:
|
||||||
column = (i, r) => this.GetRuntimeDateTime(i.RunTimeTicks);
|
option.Column = (i, r) => this.GetRuntimeDateTime(i.RunTimeTicks);
|
||||||
reportHeader.HeaderFieldType = ReportFieldType.Minutes;
|
option.Header.HeaderFieldType = ReportFieldType.Minutes;
|
||||||
reportHeader.SortField = "Runtime,SortName";
|
option.Header.SortField = "Runtime,SortName";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.PlayCount:
|
case HeaderMetadata.PlayCount:
|
||||||
reportHeader.HeaderFieldType = ReportFieldType.Int;
|
option.Header.HeaderFieldType = ReportFieldType.Int;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.Season:
|
case HeaderMetadata.Season:
|
||||||
column = (i, r) => this.GetEpisode(i);
|
option.Column = (i, r) => this.GetEpisode(i);
|
||||||
reportHeader.ItemViewType = ItemViewType.Detail;
|
option.Header.ItemViewType = ItemViewType.Detail;
|
||||||
reportHeader.SortField = "SortName";
|
option.Header.SortField = "SortName";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.SeasonNumber:
|
case HeaderMetadata.SeasonNumber:
|
||||||
column = (i, r) => this.GetObject<Season, string>(i, (x) => x.IndexNumber == null ? "" : x.IndexNumber.ToString());
|
option.Column = (i, r) => this.GetObject<Season, string>(i, (x) => x.IndexNumber == null ? "" : x.IndexNumber.ToString());
|
||||||
reportHeader.SortField = "IndexNumber";
|
option.Header.SortField = "IndexNumber";
|
||||||
reportHeader.HeaderFieldType = ReportFieldType.Int;
|
option.Header.HeaderFieldType = ReportFieldType.Int;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.Series:
|
case HeaderMetadata.Series:
|
||||||
column = (i, r) => this.GetObject<IHasSeries, string>(i, (x) => x.SeriesName);
|
option.Column = (i, r) => this.GetObject<IHasSeries, string>(i, (x) => x.SeriesName);
|
||||||
reportHeader.ItemViewType = ItemViewType.Detail;
|
option.Header.ItemViewType = ItemViewType.Detail;
|
||||||
reportHeader.SortField = "SeriesSortName,SortName";
|
option.Header.SortField = "SeriesSortName,SortName";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.EpisodeSeries:
|
case HeaderMetadata.EpisodeSeries:
|
||||||
column = (i, r) => this.GetObject<IHasSeries, string>(i, (x) => x.SeriesName);
|
option.Column = (i, r) => this.GetObject<IHasSeries, string>(i, (x) => x.SeriesName);
|
||||||
reportHeader.ItemViewType = ItemViewType.Detail;
|
option.Header.ItemViewType = ItemViewType.Detail;
|
||||||
itemId = (i) =>
|
option.ItemID = (i) =>
|
||||||
{
|
{
|
||||||
Series series = this.GetObject<Episode, Series>(i, (x) => x.Series);
|
Series series = this.GetObject<Episode, Series>(i, (x) => x.Series);
|
||||||
if (series == null)
|
if (series == null)
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
return series.Id;
|
return series.Id;
|
||||||
};
|
};
|
||||||
reportHeader.SortField = "SeriesSortName,SortName";
|
option.Header.SortField = "SeriesSortName,SortName";
|
||||||
internalHeader = HeaderMetadata.Series;
|
internalHeader = HeaderMetadata.Series;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.EpisodeSeason:
|
case HeaderMetadata.EpisodeSeason:
|
||||||
column = (i, r) => this.GetObject<IHasSeries, string>(i, (x) => x.SeriesName);
|
option.Column = (i, r) => this.GetObject<IHasSeries, string>(i, (x) => x.SeriesName);
|
||||||
reportHeader.ItemViewType = ItemViewType.Detail;
|
option.Header.ItemViewType = ItemViewType.Detail;
|
||||||
itemId = (i) =>
|
option.ItemID = (i) =>
|
||||||
{
|
{
|
||||||
Season season = this.GetObject<Episode, Season>(i, (x) => x.Season);
|
Season season = this.GetObject<Episode, Season>(i, (x) => x.Season);
|
||||||
if (season == null)
|
if (season == null)
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
return season.Id;
|
return season.Id;
|
||||||
};
|
};
|
||||||
reportHeader.SortField = "SortName";
|
option.Header.SortField = "SortName";
|
||||||
internalHeader = HeaderMetadata.Season;
|
internalHeader = HeaderMetadata.Season;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.Network:
|
case HeaderMetadata.Network:
|
||||||
column = (i, r) => this.GetListAsString(i.Studios);
|
option.Column = (i, r) => this.GetListAsString(i.Studios);
|
||||||
itemId = (i) => this.GetStudioID(i.Studios.FirstOrDefault());
|
option.ItemID = (i) => this.GetStudioID(i.Studios.FirstOrDefault());
|
||||||
reportHeader.ItemViewType = ItemViewType.ItemByNameDetails;
|
option.Header.ItemViewType = ItemViewType.ItemByNameDetails;
|
||||||
reportHeader.SortField = "Studio,SortName";
|
option.Header.SortField = "Studio,SortName";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.Year:
|
case HeaderMetadata.Year:
|
||||||
column = (i, r) => this.GetSeriesProductionYear(i);
|
option.Column = (i, r) => this.GetSeriesProductionYear(i);
|
||||||
reportHeader.SortField = "ProductionYear,PremiereDate,SortName";
|
option.Header.SortField = "ProductionYear,PremiereDate,SortName";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.ParentalRating:
|
case HeaderMetadata.ParentalRating:
|
||||||
column = (i, r) => i.OfficialRating;
|
option.Column = (i, r) => i.OfficialRating;
|
||||||
reportHeader.SortField = "OfficialRating,SortName";
|
option.Header.SortField = "OfficialRating,SortName";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.CommunityRating:
|
case HeaderMetadata.CommunityRating:
|
||||||
column = (i, r) => i.CommunityRating;
|
option.Column = (i, r) => i.CommunityRating;
|
||||||
reportHeader.SortField = "CommunityRating,SortName";
|
option.Header.SortField = "CommunityRating,SortName";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.Trailers:
|
case HeaderMetadata.Trailers:
|
||||||
column = (i, r) => this.GetBoolString(r.HasLocalTrailer);
|
option.Column = (i, r) => this.GetBoolString(r.HasLocalTrailer);
|
||||||
reportHeader.ItemViewType = ItemViewType.TrailersImage;
|
option.Header.ItemViewType = ItemViewType.TrailersImage;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.Specials:
|
case HeaderMetadata.Specials:
|
||||||
column = (i, r) => this.GetBoolString(r.HasSpecials);
|
option.Column = (i, r) => this.GetBoolString(r.HasSpecials);
|
||||||
reportHeader.ItemViewType = ItemViewType.SpecialsImage;
|
option.Header.ItemViewType = ItemViewType.SpecialsImage;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.GameSystem:
|
case HeaderMetadata.GameSystem:
|
||||||
column = (i, r) => this.GetObject<Game, string>(i, (x) => x.GameSystem);
|
option.Column = (i, r) => this.GetObject<Game, string>(i, (x) => x.GameSystem);
|
||||||
reportHeader.SortField = "GameSystem,SortName";
|
option.Header.SortField = "GameSystem,SortName";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.Players:
|
case HeaderMetadata.Players:
|
||||||
column = (i, r) => this.GetObject<Game, int?>(i, (x) => x.PlayersSupported);
|
option.Column = (i, r) => this.GetObject<Game, int?>(i, (x) => x.PlayersSupported);
|
||||||
reportHeader.SortField = "Players,GameSystem,SortName";
|
option.Header.SortField = "Players,GameSystem,SortName";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.AlbumArtist:
|
case HeaderMetadata.AlbumArtist:
|
||||||
column = (i, r) => this.GetObject<MusicAlbum, string>(i, (x) => x.AlbumArtist);
|
option.Column = (i, r) => this.GetObject<MusicAlbum, string>(i, (x) => x.AlbumArtist);
|
||||||
itemId = (i) => this.GetPersonID(this.GetObject<MusicAlbum, string>(i, (x) => x.AlbumArtist));
|
option.ItemID = (i) => this.GetPersonID(this.GetObject<MusicAlbum, string>(i, (x) => x.AlbumArtist));
|
||||||
reportHeader.ItemViewType = ItemViewType.Detail;
|
option.Header.ItemViewType = ItemViewType.Detail;
|
||||||
reportHeader.SortField = "AlbumArtist,Album,SortName";
|
option.Header.SortField = "AlbumArtist,Album,SortName";
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case HeaderMetadata.MusicArtist:
|
case HeaderMetadata.MusicArtist:
|
||||||
column = (i, r) => this.GetObject<MusicArtist, string>(i, (x) => x.GetLookupInfo().Name);
|
option.Column = (i, r) => this.GetObject<MusicArtist, string>(i, (x) => x.GetLookupInfo().Name);
|
||||||
reportHeader.ItemViewType = ItemViewType.Detail;
|
option.Header.ItemViewType = ItemViewType.Detail;
|
||||||
reportHeader.SortField = "AlbumArtist,Album,SortName";
|
option.Header.SortField = "AlbumArtist,Album,SortName";
|
||||||
internalHeader = HeaderMetadata.AlbumArtist;
|
internalHeader = HeaderMetadata.AlbumArtist;
|
||||||
break;
|
break;
|
||||||
case HeaderMetadata.AudioAlbumArtist:
|
case HeaderMetadata.AudioAlbumArtist:
|
||||||
column = (i, r) => this.GetListAsString(this.GetObject<Audio, List<string>>(i, (x) => x.AlbumArtists));
|
option.Column = (i, r) => this.GetListAsString(this.GetObject<Audio, List<string>>(i, (x) => x.AlbumArtists));
|
||||||
reportHeader.SortField = "AlbumArtist,Album,SortName";
|
option.Header.SortField = "AlbumArtist,Album,SortName";
|
||||||
internalHeader = HeaderMetadata.AlbumArtist;
|
internalHeader = HeaderMetadata.AlbumArtist;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.AudioAlbum:
|
case HeaderMetadata.AudioAlbum:
|
||||||
column = (i, r) => this.GetObject<Audio, string>(i, (x) => x.Album);
|
option.Column = (i, r) => this.GetObject<Audio, string>(i, (x) => x.Album);
|
||||||
reportHeader.SortField = "Album,SortName";
|
option.Header.SortField = "Album,SortName";
|
||||||
internalHeader = HeaderMetadata.Album;
|
internalHeader = HeaderMetadata.Album;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.Countries:
|
case HeaderMetadata.Countries:
|
||||||
column = (i, r) => this.GetListAsString(this.GetObject<IHasProductionLocations, List<string>>(i, (x) => x.ProductionLocations));
|
option.Column = (i, r) => this.GetListAsString(this.GetObject<IHasProductionLocations, List<string>>(i, (x) => x.ProductionLocations));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.Disc:
|
case HeaderMetadata.Disc:
|
||||||
column = (i, r) => i.ParentIndexNumber;
|
option.Column = (i, r) => i.ParentIndexNumber;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.Track:
|
case HeaderMetadata.Track:
|
||||||
column = (i, r) => i.IndexNumber;
|
option.Column = (i, r) => i.IndexNumber;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.Tracks:
|
case HeaderMetadata.Tracks:
|
||||||
column = (i, r) => this.GetObject<MusicAlbum, List<Audio>>(i, (x) => x.Tracks.ToList(), new List<Audio>()).Count();
|
option.Column = (i, r) => this.GetObject<MusicAlbum, List<Audio>>(i, (x) => x.Tracks.ToList(), new List<Audio>()).Count();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.Audio:
|
case HeaderMetadata.Audio:
|
||||||
column = (i, r) => this.GetAudioStream(i);
|
option.Column = (i, r) => this.GetAudioStream(i);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.EmbeddedImage:
|
case HeaderMetadata.EmbeddedImage:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.Video:
|
case HeaderMetadata.Video:
|
||||||
column = (i, r) => this.GetVideoStream(i);
|
option.Column = (i, r) => this.GetVideoStream(i);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.Resolution:
|
case HeaderMetadata.Resolution:
|
||||||
column = (i, r) => this.GetVideoResolution(i);
|
option.Column = (i, r) => this.GetVideoResolution(i);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.Subtitles:
|
case HeaderMetadata.Subtitles:
|
||||||
column = (i, r) => this.GetBoolString(r.HasSubtitles);
|
option.Column = (i, r) => this.GetBoolString(r.HasSubtitles);
|
||||||
reportHeader.ItemViewType = ItemViewType.SubtitleImage;
|
option.Header.ItemViewType = ItemViewType.SubtitleImage;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.Genres:
|
case HeaderMetadata.Genres:
|
||||||
column = (i, r) => this.GetListAsString(i.Genres);
|
option.Column = (i, r) => this.GetListAsString(i.Genres);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string headerName = "";
|
option.Header.Name = GetLocalizedHeader(internalHeader);
|
||||||
if (internalHeader != HeaderMetadata.None)
|
option.Header.FieldName = header;
|
||||||
{
|
|
||||||
string localHeader = "Header" + internalHeader.ToString();
|
|
||||||
headerName = internalHeader != HeaderMetadata.None ? ReportHelper.GetJavaScriptLocalizedString(localHeader) : "";
|
|
||||||
if (string.Compare(localHeader, headerName, StringComparison.CurrentCultureIgnoreCase) == 0)
|
|
||||||
headerName = ReportHelper.GetServerLocalizedString(localHeader);
|
|
||||||
}
|
|
||||||
|
|
||||||
reportHeader.Name = headerName;
|
return option;
|
||||||
reportHeader.FieldName = header;
|
}
|
||||||
ReportOptions<BaseItem> option = new ReportOptions<BaseItem>()
|
|
||||||
{
|
/// <summary> Gets report rows. </summary>
|
||||||
Header = reportHeader,
|
/// <param name="items"> The items. </param>
|
||||||
Column = column,
|
/// <param name="options"> Options for controlling the operation. </param>
|
||||||
ItemID = itemId
|
/// <returns> The report rows. </returns>
|
||||||
};
|
private List<ReportRow> GetReportRows(IEnumerable<BaseItem> items, List<ReportOptions<BaseItem>> options)
|
||||||
return option;
|
{
|
||||||
}
|
var rows = new List<ReportRow>();
|
||||||
}
|
|
||||||
|
foreach (BaseItem item in items)
|
||||||
|
{
|
||||||
|
ReportRow rRow = GetRow(item);
|
||||||
|
foreach (ReportOptions<BaseItem> option in options)
|
||||||
|
{
|
||||||
|
object itemColumn = option.Column != null ? option.Column(item, rRow) : "";
|
||||||
|
object itemId = option.ItemID != null ? option.ItemID(item) : "";
|
||||||
|
ReportItem rItem = new ReportItem
|
||||||
|
{
|
||||||
|
Name = ReportHelper.ConvertToString(itemColumn, option.Header.HeaderFieldType),
|
||||||
|
Id = ReportHelper.ConvertToString(itemId, ReportFieldType.Object)
|
||||||
|
};
|
||||||
|
rRow.Columns.Add(rItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
rows.Add(rRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Gets a row. </summary>
|
||||||
|
/// <param name="item"> The item. </param>
|
||||||
|
/// <returns> The row. </returns>
|
||||||
|
private ReportRow GetRow(BaseItem item)
|
||||||
|
{
|
||||||
|
var hasTrailers = item as IHasTrailers;
|
||||||
|
var hasSpecialFeatures = item as IHasSpecialFeatures;
|
||||||
|
var video = item as Video;
|
||||||
|
ReportRow rRow = new ReportRow
|
||||||
|
{
|
||||||
|
Id = item.Id.ToString("N"),
|
||||||
|
HasLockData = item.IsLocked,
|
||||||
|
IsUnidentified = item.IsUnidentified,
|
||||||
|
HasLocalTrailer = hasTrailers != null ? hasTrailers.GetTrailerIds().Count() > 0 : false,
|
||||||
|
HasImageTagsPrimary = (item.ImageInfos != null && item.ImageInfos.Count(n => n.Type == ImageType.Primary) > 0),
|
||||||
|
HasImageTagsBackdrop = (item.ImageInfos != null && item.ImageInfos.Count(n => n.Type == ImageType.Backdrop) > 0),
|
||||||
|
HasImageTagsLogo = (item.ImageInfos != null && item.ImageInfos.Count(n => n.Type == ImageType.Logo) > 0),
|
||||||
|
HasSpecials = hasSpecialFeatures != null ? hasSpecialFeatures.SpecialFeatureIds.Count > 0 : false,
|
||||||
|
HasSubtitles = video != null ? video.HasSubtitles : false,
|
||||||
|
RowType = ReportHelper.GetRowType(item.GetClientTypeName())
|
||||||
|
};
|
||||||
|
return rRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,9 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace MediaBrowser.Api.Reports
|
namespace MediaBrowser.Api.Reports
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary> A report options. </summary>
|
/// <summary> A report options. </summary>
|
||||||
internal class ReportOptions<I>
|
public class ReportOptions<I>
|
||||||
{
|
{
|
||||||
/// <summary> Initializes a new instance of the ReportOptions class. </summary>
|
/// <summary> Initializes a new instance of the ReportOptions class. </summary>
|
||||||
public ReportOptions()
|
public ReportOptions()
|
||||||
|
@ -16,6 +16,8 @@ namespace MediaBrowser.Api.Reports
|
|||||||
ItemViewType = ItemViewType.None;
|
ItemViewType = ItemViewType.None;
|
||||||
Visible = true;
|
Visible = true;
|
||||||
CanGroup = true;
|
CanGroup = true;
|
||||||
|
ShowHeaderLabel = true;
|
||||||
|
DisplayType = ReportDisplayType.ScreenExport;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Gets or sets the type of the header field. </summary>
|
/// <summary> Gets or sets the type of the header field. </summary>
|
||||||
@ -46,6 +48,14 @@ namespace MediaBrowser.Api.Reports
|
|||||||
/// <value> true if visible, false if not. </value>
|
/// <value> true if visible, false if not. </value>
|
||||||
public bool Visible { get; set; }
|
public bool Visible { get; set; }
|
||||||
|
|
||||||
|
/// <summary> Gets or sets the type of the display. </summary>
|
||||||
|
/// <value> The type of the display. </value>
|
||||||
|
public ReportDisplayType DisplayType { get; set; }
|
||||||
|
|
||||||
|
/// <summary> Gets or sets a value indicating whether the header label is shown. </summary>
|
||||||
|
/// <value> true if show header label, false if not. </value>
|
||||||
|
public bool ShowHeaderLabel { get; set; }
|
||||||
|
|
||||||
/// <summary> Gets or sets a value indicating whether we can group. </summary>
|
/// <summary> Gets or sets a value indicating whether we can group. </summary>
|
||||||
/// <value> true if we can group, false if not. </value>
|
/// <value> true if we can group, false if not. </value>
|
||||||
public bool CanGroup { get; set; }
|
public bool CanGroup { get; set; }
|
@ -66,6 +66,10 @@ namespace MediaBrowser.Api.Reports
|
|||||||
|
|
||||||
/// <summary> Gets or sets the type. </summary>
|
/// <summary> Gets or sets the type. </summary>
|
||||||
/// <value> The type. </value>
|
/// <value> The type. </value>
|
||||||
public ReportViewType RowType { get; set; }
|
public ReportIncludeItemTypes RowType { get; set; }
|
||||||
|
|
||||||
|
/// <summary> Gets or sets the identifier of the user. </summary>
|
||||||
|
/// <value> The identifier of the user. </value>
|
||||||
|
public string UserId { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -7,251 +7,90 @@ using System.Linq;
|
|||||||
|
|
||||||
namespace MediaBrowser.Api.Reports
|
namespace MediaBrowser.Api.Reports
|
||||||
{
|
{
|
||||||
public class BaseReportRequest : BaseItemsRequest
|
public interface IReportsDownload : IReportsQuery
|
||||||
{
|
{
|
||||||
|
/// <summary> Gets or sets the minimum date. </summary>
|
||||||
|
/// <value> The minimum date. </value>
|
||||||
|
string MinDate { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Interface for reports query. </summary>
|
||||||
|
public interface IReportsQuery : IReportsHeader
|
||||||
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the user id.
|
/// Gets or sets a value indicating whether this MediaBrowser.Api.Reports.GetActivityLogs has
|
||||||
/// </summary>
|
/// query limit. </summary>
|
||||||
/// <value>The user id.</value>
|
/// <value>
|
||||||
[ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")]
|
/// true if this MediaBrowser.Api.Reports.GetActivityLogs has query limit, false if not. </value>
|
||||||
public string UserId { get; set; }
|
bool HasQueryLimit { get; set; }
|
||||||
|
/// <summary> Gets or sets who group this MediaBrowser.Api.Reports.GetActivityLogs. </summary>
|
||||||
|
/// <value> Describes who group this MediaBrowser.Api.Reports.GetActivityLogs. </value>
|
||||||
|
string GroupBy { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Limit results to items containing a specific person
|
/// Skips over a given number of items within the results. Use for paging.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The person.</value>
|
/// <value>The start index.</value>
|
||||||
[ApiMember(Name = "Person", Description = "Optional. If specified, results will be filtered to include only those containing the specified person.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
int? StartIndex { get; set; }
|
||||||
public string Person { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "PersonIds", Description = "Optional. If specified, results will be filtered to include only those containing the specified person.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public string PersonIds { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If the Person filter is used, this can also be used to restrict to a specific person type
|
/// The maximum number of items to return
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The type of the person.</value>
|
/// <value>The limit.</value>
|
||||||
[ApiMember(Name = "PersonTypes", Description = "Optional. If specified, along with Person, results will be filtered to include only those containing the specified person and PersonType. Allows multiple, comma-delimited", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
int? Limit { get; set; }
|
||||||
public string PersonTypes { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
}
|
||||||
/// Limit results to items containing specific studios
|
public interface IReportsHeader
|
||||||
/// </summary>
|
{
|
||||||
/// <value>The studios.</value>
|
/// <summary> Gets or sets the report view. </summary>
|
||||||
[ApiMember(Name = "Studios", Description = "Optional. If specified, results will be filtered based on studio. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
/// <value> The report view. </value>
|
||||||
public string Studios { get; set; }
|
string ReportView { get; set; }
|
||||||
|
|
||||||
[ApiMember(Name = "StudioIds", Description = "Optional. If specified, results will be filtered based on studio. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
/// <summary> Gets or sets the report columns. </summary>
|
||||||
public string StudioIds { get; set; }
|
/// <value> The report columns. </value>
|
||||||
|
string ReportColumns { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary> Gets or sets a list of types of the include items. </summary>
|
||||||
/// Gets or sets the studios.
|
/// <value> A list of types of the include items. </value>
|
||||||
/// </summary>
|
string IncludeItemTypes { get; set; }
|
||||||
/// <value>The studios.</value>
|
|
||||||
[ApiMember(Name = "Artists", Description = "Optional. If specified, results will be filtered based on artist. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
|
||||||
public string Artists { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "ArtistIds", Description = "Optional. If specified, results will be filtered based on artist. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
/// <summary> Gets or sets a list of types of the displays. </summary>
|
||||||
public string ArtistIds { get; set; }
|
/// <value> A list of types of the displays. </value>
|
||||||
|
string DisplayType { get; set; }
|
||||||
|
|
||||||
[ApiMember(Name = "Albums", Description = "Optional. If specified, results will be filtered based on album. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
}
|
||||||
public string Albums { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
public class BaseReportRequest : BaseItemsRequest, IReportsQuery
|
||||||
/// Gets or sets the item ids.
|
{
|
||||||
/// </summary>
|
/// <summary> Gets or sets the report view. </summary>
|
||||||
/// <value>The item ids.</value>
|
/// <value> The report view. </value>
|
||||||
[ApiMember(Name = "Ids", Description = "Optional. If specific items are needed, specify a list of item id's to retrieve. This allows multiple, comma delimited.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
[ApiMember(Name = "ReportView", Description = "The report view. Values (ReportData, ReportStatistics, ReportActivities)", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
public string Ids { get; set; }
|
public string ReportView { get; set; }
|
||||||
|
|
||||||
|
/// <summary> Gets or sets the report view. </summary>
|
||||||
|
/// <value> The report view. </value>
|
||||||
|
[ApiMember(Name = "DisplayType", Description = "The report display type. Values (None, Screen, Export, ScreenExport)", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string DisplayType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether this MediaBrowser.Api.Reports.BaseReportRequest has
|
||||||
|
/// query limit. </summary>
|
||||||
|
/// <value>
|
||||||
|
/// true if this MediaBrowser.Api.Reports.BaseReportRequest has query limit, false if not. </value>
|
||||||
|
[ApiMember(Name = "HasQueryLimit", Description = "Optional. If specified, results will include all records.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
public bool HasQueryLimit { get; set; }
|
public bool HasQueryLimit { get; set; }
|
||||||
public string GroupBy { get; set; }
|
|
||||||
|
|
||||||
public string ReportColumns { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the video types.
|
/// Gets or sets who group this MediaBrowser.Api.Reports.BaseReportRequest. </summary>
|
||||||
/// </summary>
|
/// <value> Describes who group this MediaBrowser.Api.Reports.BaseReportRequest. </value>
|
||||||
/// <value>The video types.</value>
|
[ApiMember(Name = "GroupBy", Description = "Optional. If specified, results will include grouped records.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
[ApiMember(Name = "VideoTypes", Description = "Optional filter by VideoType (videofile, dvd, bluray, iso). Allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
public string GroupBy { get; set; }
|
||||||
public string VideoTypes { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary> Gets or sets the report columns. </summary>
|
||||||
/// Gets or sets the video formats.
|
/// <value> The report columns. </value>
|
||||||
/// </summary>
|
[ApiMember(Name = "ReportColumns", Description = "Optional. The columns to show.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
/// <value>The video formats.</value>
|
public string ReportColumns { get; set; }
|
||||||
[ApiMember(Name = "Is3D", Description = "Optional filter by items that are 3D, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? Is3D { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the series status.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The series status.</value>
|
|
||||||
[ApiMember(Name = "SeriesStatus", Description = "Optional filter by Series Status. Allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
|
||||||
public string SeriesStatus { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "NameStartsWithOrGreater", Description = "Optional filter by items whose name is sorted equally or greater than a given input string.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public string NameStartsWithOrGreater { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "NameStartsWith", Description = "Optional filter by items whose name is sorted equally than a given input string.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public string NameStartsWith { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "NameLessThan", Description = "Optional filter by items whose name is equally or lesser than a given input string.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public string NameLessThan { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "AlbumArtistStartsWithOrGreater", Description = "Optional filter by items whose album artist is sorted equally or greater than a given input string.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public string AlbumArtistStartsWithOrGreater { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the air days.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The air days.</value>
|
|
||||||
[ApiMember(Name = "AirDays", Description = "Optional filter by Series Air Days. Allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
|
||||||
public string AirDays { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the min offical rating.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The min offical rating.</value>
|
|
||||||
[ApiMember(Name = "MinOfficialRating", Description = "Optional filter by minimum official rating (PG, PG-13, TV-MA, etc).", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public string MinOfficialRating { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the max offical rating.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The max offical rating.</value>
|
|
||||||
[ApiMember(Name = "MaxOfficialRating", Description = "Optional filter by maximum official rating (PG, PG-13, TV-MA, etc).", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public string MaxOfficialRating { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "HasThemeSong", Description = "Optional filter by items with theme songs.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? HasThemeSong { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "HasThemeVideo", Description = "Optional filter by items with theme videos.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? HasThemeVideo { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "HasSubtitles", Description = "Optional filter by items with subtitles.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? HasSubtitles { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "HasSpecialFeature", Description = "Optional filter by items with special features.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? HasSpecialFeature { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "HasTrailer", Description = "Optional filter by items with trailers.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? HasTrailer { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "AdjacentTo", Description = "Optional. Return items that are siblings of a supplied item.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public string AdjacentTo { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "MinIndexNumber", Description = "Optional filter by minimum index number.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
|
||||||
public int? MinIndexNumber { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "MinPlayers", Description = "Optional filter by minimum number of game players.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
|
||||||
public int? MinPlayers { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "MaxPlayers", Description = "Optional filter by maximum number of game players.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
|
||||||
public int? MaxPlayers { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "ParentIndexNumber", Description = "Optional filter by parent index number.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
|
||||||
public int? ParentIndexNumber { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "HasParentalRating", Description = "Optional filter by items that have or do not have a parental rating", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? HasParentalRating { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "IsHD", Description = "Optional filter by items that are HD or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? IsHD { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "LocationTypes", Description = "Optional. If specified, results will be filtered based on LocationType. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
|
||||||
public string LocationTypes { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "ExcludeLocationTypes", Description = "Optional. If specified, results will be filtered based on LocationType. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
|
||||||
public string ExcludeLocationTypes { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "IsMissing", Description = "Optional filter by items that are missing episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? IsMissing { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "IsUnaired", Description = "Optional filter by items that are unaired episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? IsUnaired { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "IsVirtualUnaired", Description = "Optional filter by items that are virtual unaired episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? IsVirtualUnaired { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "MinCommunityRating", Description = "Optional filter by minimum community rating.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
|
||||||
public double? MinCommunityRating { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "MinCriticRating", Description = "Optional filter by minimum critic rating.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
|
||||||
public double? MinCriticRating { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "AiredDuringSeason", Description = "Gets all episodes that aired during a season, including specials.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
|
||||||
public int? AiredDuringSeason { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "MinPremiereDate", Description = "Optional. The minimum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
|
|
||||||
public string MinPremiereDate { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "MaxPremiereDate", Description = "Optional. The maximum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
|
|
||||||
public string MaxPremiereDate { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "HasOverview", Description = "Optional filter by items that have an overview or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? HasOverview { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "HasImdbId", Description = "Optional filter by items that have an imdb id or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? HasImdbId { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "HasTmdbId", Description = "Optional filter by items that have a tmdb id or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? HasTmdbId { get; set; }
|
|
||||||
|
|
||||||
[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; }
|
|
||||||
|
|
||||||
[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")]
|
|
||||||
public bool? IsInBoxSet { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "IsLocked", Description = "Optional filter by items that are locked.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? IsLocked { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "IsUnidentified", Description = "Optional filter by items that are unidentified by internet metadata providers.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? IsUnidentified { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "IsPlaceHolder", Description = "Optional filter by items that are placeholders", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? IsPlaceHolder { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "HasOfficialRating", Description = "Optional filter by items that have official ratings", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? HasOfficialRating { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "CollapseBoxSetItems", Description = "Whether or not to hide items behind their boxsets.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? CollapseBoxSetItems { get; set; }
|
|
||||||
|
|
||||||
public string[] GetStudios()
|
|
||||||
{
|
|
||||||
return (Studios ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string[] GetStudioIds()
|
|
||||||
{
|
|
||||||
return (StudioIds ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string[] GetPersonTypes()
|
|
||||||
{
|
|
||||||
return (PersonTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string[] GetPersonIds()
|
|
||||||
{
|
|
||||||
return (PersonIds ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
}
|
|
||||||
|
|
||||||
public VideoType[] GetVideoTypes()
|
|
||||||
{
|
|
||||||
var val = VideoTypes;
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(val))
|
|
||||||
{
|
|
||||||
return new VideoType[] { };
|
|
||||||
}
|
|
||||||
|
|
||||||
return val.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(v => (VideoType)Enum.Parse(typeof(VideoType), v, true)).ToArray();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/Reports/Items", "GET", Summary = "Gets reports based on library items")]
|
[Route("/Reports/Items", "GET", Summary = "Gets reports based on library items")]
|
||||||
@ -261,8 +100,27 @@ namespace MediaBrowser.Api.Reports
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Route("/Reports/Headers", "GET", Summary = "Gets reports headers based on library items")]
|
[Route("/Reports/Headers", "GET", Summary = "Gets reports headers based on library items")]
|
||||||
public class GetReportHeaders : BaseReportRequest, IReturn<List<ReportHeader>>
|
public class GetReportHeaders : IReturn<List<ReportHeader>>, IReportsHeader
|
||||||
{
|
{
|
||||||
|
/// <summary> Gets or sets the report view. </summary>
|
||||||
|
/// <value> The report view. </value>
|
||||||
|
[ApiMember(Name = "ReportView", Description = "The report view. Values (ReportData, ReportStatistics, ReportActivities)", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string ReportView { get; set; }
|
||||||
|
|
||||||
|
/// <summary> Gets or sets the report view. </summary>
|
||||||
|
/// <value> The report view. </value>
|
||||||
|
[ApiMember(Name = "DisplayType", Description = "The report display type. Values (None, Screen, Export, ScreenExport)", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string DisplayType { get; set; }
|
||||||
|
|
||||||
|
/// <summary> Gets or sets a list of types of the include items. </summary>
|
||||||
|
/// <value> A list of types of the include items. </value>
|
||||||
|
[ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
|
public string IncludeItemTypes { get; set; }
|
||||||
|
|
||||||
|
/// <summary> Gets or sets the report columns. </summary>
|
||||||
|
/// <value> The report columns. </value>
|
||||||
|
[ApiMember(Name = "ReportColumns", Description = "Optional. The columns to show.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string ReportColumns { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/Reports/Statistics", "GET", Summary = "Gets reports statistics based on library items")]
|
[Route("/Reports/Statistics", "GET", Summary = "Gets reports statistics based on library items")]
|
||||||
@ -273,7 +131,7 @@ namespace MediaBrowser.Api.Reports
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Route("/Reports/Items/Download", "GET", Summary = "Downloads report")]
|
[Route("/Reports/Items/Download", "GET", Summary = "Downloads report")]
|
||||||
public class GetReportDownload : BaseReportRequest
|
public class GetReportDownload : BaseReportRequest, IReportsDownload
|
||||||
{
|
{
|
||||||
public GetReportDownload()
|
public GetReportDownload()
|
||||||
{
|
{
|
||||||
@ -281,6 +139,66 @@ namespace MediaBrowser.Api.Reports
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ReportExportType ExportType { get; set; }
|
public ReportExportType ExportType { get; set; }
|
||||||
|
|
||||||
|
/// <summary> Gets or sets the minimum date. </summary>
|
||||||
|
/// <value> The minimum date. </value>
|
||||||
|
[ApiMember(Name = "MinDate", Description = "Optional. The minimum date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
|
||||||
|
public string MinDate { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Route("/Reports/Activities", "GET", Summary = "Gets activities entries")]
|
||||||
|
public class GetActivityLogs : IReturn<ReportResult>, IReportsQuery, IReportsDownload
|
||||||
|
{
|
||||||
|
/// <summary> Gets or sets the report view. </summary>
|
||||||
|
/// <value> The report view. </value>
|
||||||
|
[ApiMember(Name = "ReportView", Description = "The report view. Values (ReportData, ReportStatistics, ReportActivities)", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string ReportView { get; set; }
|
||||||
|
|
||||||
|
/// <summary> Gets or sets the report view. </summary>
|
||||||
|
/// <value> The report view. </value>
|
||||||
|
[ApiMember(Name = "DisplayType", Description = "The report display type. Values (None, Screen, Export, ScreenExport)", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string DisplayType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether this MediaBrowser.Api.Reports.GetActivityLogs has
|
||||||
|
/// query limit. </summary>
|
||||||
|
/// <value>
|
||||||
|
/// true if this MediaBrowser.Api.Reports.GetActivityLogs has query limit, false if not. </value>
|
||||||
|
[ApiMember(Name = "HasQueryLimit", Description = "Optional. If specified, results will include all records.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool HasQueryLimit { get; set; }
|
||||||
|
|
||||||
|
/// <summary> Gets or sets who group this MediaBrowser.Api.Reports.GetActivityLogs. </summary>
|
||||||
|
/// <value> Describes who group this MediaBrowser.Api.Reports.GetActivityLogs. </value>
|
||||||
|
[ApiMember(Name = "GroupBy", Description = "Optional. If specified, results will include grouped records.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string GroupBy { get; set; }
|
||||||
|
|
||||||
|
/// <summary> Gets or sets the report columns. </summary>
|
||||||
|
/// <value> The report columns. </value>
|
||||||
|
[ApiMember(Name = "ReportColumns", Description = "Optional. The columns to show.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string ReportColumns { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Skips over a given number of items within the results. Use for paging.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The start index.</value>
|
||||||
|
[ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
||||||
|
public int? StartIndex { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The maximum number of items to return
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The limit.</value>
|
||||||
|
[ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
||||||
|
public int? Limit { get; set; }
|
||||||
|
|
||||||
|
/// <summary> Gets or sets the minimum date. </summary>
|
||||||
|
/// <value> The minimum date. </value>
|
||||||
|
[ApiMember(Name = "MinDate", Description = "Optional. The minimum date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
|
||||||
|
public string MinDate { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
|
public string IncludeItemTypes { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -9,206 +9,276 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace MediaBrowser.Api.Reports
|
namespace MediaBrowser.Api.Reports
|
||||||
{
|
{
|
||||||
/// <summary> A report stat builder. </summary>
|
/// <summary> A report stat builder. </summary>
|
||||||
/// <seealso cref="T:MediaBrowser.Api.Reports.ReportBuilderBase"/>
|
/// <seealso cref="T:MediaBrowser.Api.Reports.ReportBuilderBase"/>
|
||||||
public class ReportStatBuilder : ReportBuilderBase
|
public class ReportStatBuilder : ReportBuilderBase
|
||||||
{
|
{
|
||||||
/// <summary>
|
#region [Constructors]
|
||||||
/// Initializes a new instance of the MediaBrowser.Api.Reports.ReportStatBuilder class. </summary>
|
|
||||||
/// <param name="libraryManager"> Manager for library. </param>
|
|
||||||
public ReportStatBuilder(ILibraryManager libraryManager)
|
|
||||||
: base(libraryManager)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary> Gets report stat result. </summary>
|
/// <summary>
|
||||||
/// <param name="items"> The items. </param>
|
/// Initializes a new instance of the MediaBrowser.Api.Reports.ReportStatBuilder class. </summary>
|
||||||
/// <param name="reportRowType"> Type of the report row. </param>
|
/// <param name="libraryManager"> Manager for library. </param>
|
||||||
/// <param name="topItem"> The top item. </param>
|
public ReportStatBuilder(ILibraryManager libraryManager)
|
||||||
/// <returns> The report stat result. </returns>
|
: base(libraryManager)
|
||||||
public ReportStatResult GetReportStatResult(BaseItem[] items, ReportViewType reportRowType, int topItem = 5)
|
{
|
||||||
{
|
}
|
||||||
ReportStatResult result = new ReportStatResult();
|
|
||||||
result = this.GetResultGenres(result, items, topItem);
|
|
||||||
result = this.GetResultStudios(result, items, topItem);
|
|
||||||
result = this.GetResultPersons(result, items, topItem);
|
|
||||||
result = this.GetResultProductionYears(result, items, topItem);
|
|
||||||
result = this.GetResulProductionLocations(result, items, topItem);
|
|
||||||
result = this.GetResultCommunityRatings(result, items, topItem);
|
|
||||||
result = this.GetResultParentalRatings(result, items, topItem);
|
|
||||||
|
|
||||||
switch (reportRowType)
|
#endregion
|
||||||
{
|
|
||||||
case ReportViewType.Season:
|
|
||||||
case ReportViewType.Series:
|
|
||||||
case ReportViewType.MusicAlbum:
|
|
||||||
case ReportViewType.MusicArtist:
|
|
||||||
case ReportViewType.Game:
|
|
||||||
break;
|
|
||||||
case ReportViewType.Movie:
|
|
||||||
case ReportViewType.BoxSet:
|
|
||||||
|
|
||||||
break;
|
#region [Public Methods]
|
||||||
case ReportViewType.Book:
|
|
||||||
case ReportViewType.Episode:
|
|
||||||
case ReportViewType.Video:
|
|
||||||
case ReportViewType.MusicVideo:
|
|
||||||
case ReportViewType.Trailer:
|
|
||||||
case ReportViewType.Audio:
|
|
||||||
case ReportViewType.BaseItem:
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.Groups = result.Groups.OrderByDescending(n => n.Items.Count()).ToList();
|
/// <summary> Gets report stat result. </summary>
|
||||||
|
/// <param name="items"> The items. </param>
|
||||||
|
/// <param name="reportIncludeItemTypes"> List of types of the report include items. </param>
|
||||||
|
/// <param name="topItem"> The top item. </param>
|
||||||
|
/// <returns> The report stat result. </returns>
|
||||||
|
public ReportStatResult GetResult(BaseItem[] items, ReportIncludeItemTypes reportIncludeItemTypes, int topItem = 5)
|
||||||
|
{
|
||||||
|
ReportStatResult result = new ReportStatResult();
|
||||||
|
result = this.GetResultGenres(result, items, topItem);
|
||||||
|
result = this.GetResultStudios(result, items, topItem);
|
||||||
|
result = this.GetResultPersons(result, items, topItem);
|
||||||
|
result = this.GetResultProductionYears(result, items, topItem);
|
||||||
|
result = this.GetResulProductionLocations(result, items, topItem);
|
||||||
|
result = this.GetResultCommunityRatings(result, items, topItem);
|
||||||
|
result = this.GetResultParentalRatings(result, items, topItem);
|
||||||
|
|
||||||
return result;
|
switch (reportIncludeItemTypes)
|
||||||
}
|
{
|
||||||
|
case ReportIncludeItemTypes.Season:
|
||||||
|
case ReportIncludeItemTypes.Series:
|
||||||
|
case ReportIncludeItemTypes.MusicAlbum:
|
||||||
|
case ReportIncludeItemTypes.MusicArtist:
|
||||||
|
case ReportIncludeItemTypes.Game:
|
||||||
|
break;
|
||||||
|
case ReportIncludeItemTypes.Movie:
|
||||||
|
case ReportIncludeItemTypes.BoxSet:
|
||||||
|
|
||||||
private ReportStatResult GetResultGenres(ReportStatResult result, BaseItem[] items, int topItem = 5)
|
break;
|
||||||
{
|
case ReportIncludeItemTypes.Book:
|
||||||
this.GetGroups(result, ReportHelper.GetServerLocalizedString("HeaderGenres"), topItem,
|
case ReportIncludeItemTypes.Episode:
|
||||||
items.SelectMany(x => x.Genres)
|
case ReportIncludeItemTypes.Video:
|
||||||
.GroupBy(x => x)
|
case ReportIncludeItemTypes.MusicVideo:
|
||||||
.OrderByDescending(x => x.Count())
|
case ReportIncludeItemTypes.Trailer:
|
||||||
.Take(topItem)
|
case ReportIncludeItemTypes.Audio:
|
||||||
.Select(x => new ReportStatItem
|
case ReportIncludeItemTypes.BaseItem:
|
||||||
{
|
default:
|
||||||
Name = x.Key,
|
break;
|
||||||
Value = x.Count().ToString(),
|
}
|
||||||
Id = GetGenreID(x.Key)
|
|
||||||
}));
|
|
||||||
return result;
|
|
||||||
|
|
||||||
}
|
result.Groups = result.Groups.OrderByDescending(n => n.Items.Count()).ToList();
|
||||||
|
|
||||||
private ReportStatResult GetResultStudios(ReportStatResult result, BaseItem[] items, int topItem = 5)
|
return result;
|
||||||
{
|
}
|
||||||
this.GetGroups(result, ReportHelper.GetServerLocalizedString("HeaderStudios"), topItem,
|
|
||||||
items.SelectMany(x => x.Studios)
|
|
||||||
.GroupBy(x => x)
|
|
||||||
.OrderByDescending(x => x.Count())
|
|
||||||
.Take(topItem)
|
|
||||||
.Select(x => new ReportStatItem
|
|
||||||
{
|
|
||||||
Name = x.Key,
|
|
||||||
Value = x.Count().ToString(),
|
|
||||||
Id = GetStudioID(x.Key)
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
return result;
|
#endregion
|
||||||
|
|
||||||
}
|
#region [Protected Internal Methods]
|
||||||
|
/// <summary> Gets the headers. </summary>
|
||||||
|
/// <typeparam name="H"> Type of the header. </typeparam>
|
||||||
|
/// <param name="request"> The request. </param>
|
||||||
|
/// <returns> The headers. </returns>
|
||||||
|
/// <seealso cref="M:MediaBrowser.Api.Reports.ReportBuilderBase.GetHeaders{H}(H)"/>
|
||||||
|
protected internal override List<ReportHeader> GetHeaders<H>(H request)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
private ReportStatResult GetResultPersons(ReportStatResult result, BaseItem[] items, int topItem = 5)
|
#endregion
|
||||||
{
|
|
||||||
List<string> t = new List<string> { PersonType.Actor, PersonType.Composer, PersonType.Director, PersonType.GuestStar, PersonType.Producer, PersonType.Writer, "Artist", "AlbumArtist" };
|
|
||||||
foreach (var item in t)
|
|
||||||
{
|
|
||||||
this.GetGroups(result, ReportHelper.GetServerLocalizedString("Option" + item), topItem,
|
|
||||||
items.SelectMany(x => _libraryManager.GetPeople(x))
|
|
||||||
.Where(n => n.Type == item)
|
|
||||||
.GroupBy(x => x.Name)
|
|
||||||
.OrderByDescending(x => x.Count())
|
|
||||||
.Take(topItem)
|
|
||||||
.Select(x => new ReportStatItem
|
|
||||||
{
|
|
||||||
Name = x.Key,
|
|
||||||
Value = x.Count().ToString(),
|
|
||||||
Id = GetPersonID(x.Key)
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
#region [Private Methods]
|
||||||
}
|
|
||||||
|
|
||||||
private ReportStatResult GetResultCommunityRatings(ReportStatResult result, BaseItem[] items, int topItem = 5)
|
/// <summary> Gets the groups. </summary>
|
||||||
{
|
/// <param name="result"> The result. </param>
|
||||||
this.GetGroups(result, ReportHelper.GetServerLocalizedString("LabelCommunityRating"), topItem,
|
/// <param name="header"> The header. </param>
|
||||||
items.Where(x => x.CommunityRating != null && x.CommunityRating > 0)
|
/// <param name="topItem"> The top item. </param>
|
||||||
.GroupBy(x => x.CommunityRating)
|
/// <param name="top"> The top. </param>
|
||||||
.OrderByDescending(x => x.Count())
|
private void GetGroups(ReportStatResult result, string header, int topItem, IEnumerable<ReportStatItem> top)
|
||||||
.Take(topItem)
|
{
|
||||||
.Select(x => new ReportStatItem
|
if (top != null && top.Count() > 0)
|
||||||
{
|
{
|
||||||
Name = x.Key.ToString(),
|
var group = new ReportStatGroup { Header = ReportStatGroup.FormatedHeader(header, topItem) };
|
||||||
Value = x.Count().ToString()
|
group.Items.AddRange(top);
|
||||||
})
|
result.Groups.Add(group);
|
||||||
);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
/// <summary> Gets resul production locations. </summary>
|
||||||
}
|
/// <param name="result"> The result. </param>
|
||||||
|
/// <param name="items"> The items. </param>
|
||||||
|
/// <param name="topItem"> The top item. </param>
|
||||||
|
/// <returns> The resul production locations. </returns>
|
||||||
|
private ReportStatResult GetResulProductionLocations(ReportStatResult result, BaseItem[] items, int topItem = 5)
|
||||||
|
{
|
||||||
|
this.GetGroups(result, GetLocalizedHeader(HeaderMetadata.Countries), topItem,
|
||||||
|
items.OfType<IHasProductionLocations>()
|
||||||
|
.Where(x => x.ProductionLocations != null)
|
||||||
|
.SelectMany(x => x.ProductionLocations)
|
||||||
|
.GroupBy(x => x)
|
||||||
|
.OrderByDescending(x => x.Count())
|
||||||
|
.Take(topItem)
|
||||||
|
.Select(x => new ReportStatItem
|
||||||
|
{
|
||||||
|
Name = x.Key.ToString(),
|
||||||
|
Value = x.Count().ToString()
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
private ReportStatResult GetResultParentalRatings(ReportStatResult result, BaseItem[] items, int topItem = 5)
|
return result;
|
||||||
{
|
}
|
||||||
this.GetGroups(result, ReportHelper.GetServerLocalizedString("HeaderParentalRatings"), topItem,
|
|
||||||
items.Where(x => x.OfficialRating != null)
|
|
||||||
.GroupBy(x => x.OfficialRating)
|
|
||||||
.OrderByDescending(x => x.Count())
|
|
||||||
.Take(topItem)
|
|
||||||
.Select(x => new ReportStatItem
|
|
||||||
{
|
|
||||||
Name = x.Key.ToString(),
|
|
||||||
Value = x.Count().ToString()
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
return result;
|
/// <summary> Gets result community ratings. </summary>
|
||||||
}
|
/// <param name="result"> The result. </param>
|
||||||
|
/// <param name="items"> The items. </param>
|
||||||
|
/// <param name="topItem"> The top item. </param>
|
||||||
|
/// <returns> The result community ratings. </returns>
|
||||||
|
private ReportStatResult GetResultCommunityRatings(ReportStatResult result, BaseItem[] items, int topItem = 5)
|
||||||
|
{
|
||||||
|
this.GetGroups(result, GetLocalizedHeader(HeaderMetadata.CommunityRating), topItem,
|
||||||
|
items.Where(x => x.CommunityRating != null && x.CommunityRating > 0)
|
||||||
|
.GroupBy(x => x.CommunityRating)
|
||||||
|
.OrderByDescending(x => x.Count())
|
||||||
|
.Take(topItem)
|
||||||
|
.Select(x => new ReportStatItem
|
||||||
|
{
|
||||||
|
Name = x.Key.ToString(),
|
||||||
|
Value = x.Count().ToString()
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private ReportStatResult GetResultProductionYears(ReportStatResult result, BaseItem[] items, int topItem = 5)
|
/// <summary> Gets result genres. </summary>
|
||||||
{
|
/// <param name="result"> The result. </param>
|
||||||
this.GetGroups(result, ReportHelper.GetServerLocalizedString("HeaderYears"), topItem,
|
/// <param name="items"> The items. </param>
|
||||||
items.Where(x => x.ProductionYear != null && x.ProductionYear > 0)
|
/// <param name="topItem"> The top item. </param>
|
||||||
.GroupBy(x => x.ProductionYear)
|
/// <returns> The result genres. </returns>
|
||||||
.OrderByDescending(x => x.Count())
|
private ReportStatResult GetResultGenres(ReportStatResult result, BaseItem[] items, int topItem = 5)
|
||||||
.Take(topItem)
|
{
|
||||||
.Select(x => new ReportStatItem
|
this.GetGroups(result, GetLocalizedHeader(HeaderMetadata.Genres), topItem,
|
||||||
{
|
items.SelectMany(x => x.Genres)
|
||||||
Name = x.Key.ToString(),
|
.GroupBy(x => x)
|
||||||
Value = x.Count().ToString()
|
.OrderByDescending(x => x.Count())
|
||||||
})
|
.Take(topItem)
|
||||||
);
|
.Select(x => new ReportStatItem
|
||||||
|
{
|
||||||
|
Name = x.Key,
|
||||||
|
Value = x.Count().ToString(),
|
||||||
|
Id = GetGenreID(x.Key)
|
||||||
|
}));
|
||||||
|
return result;
|
||||||
|
|
||||||
return result;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private ReportStatResult GetResulProductionLocations(ReportStatResult result, BaseItem[] items, int topItem = 5)
|
/// <summary> Gets result parental ratings. </summary>
|
||||||
{
|
/// <param name="result"> The result. </param>
|
||||||
this.GetGroups(result, ReportHelper.GetServerLocalizedString("HeaderCountries"), topItem,
|
/// <param name="items"> The items. </param>
|
||||||
items.OfType<IHasProductionLocations>()
|
/// <param name="topItem"> The top item. </param>
|
||||||
.Where(x => x.ProductionLocations != null)
|
/// <returns> The result parental ratings. </returns>
|
||||||
.SelectMany(x => x.ProductionLocations)
|
private ReportStatResult GetResultParentalRatings(ReportStatResult result, BaseItem[] items, int topItem = 5)
|
||||||
.GroupBy(x => x)
|
{
|
||||||
.OrderByDescending(x => x.Count())
|
this.GetGroups(result, GetLocalizedHeader(HeaderMetadata.ParentalRatings), topItem,
|
||||||
.Take(topItem)
|
items.Where(x => x.OfficialRating != null)
|
||||||
.Select(x => new ReportStatItem
|
.GroupBy(x => x.OfficialRating)
|
||||||
{
|
.OrderByDescending(x => x.Count())
|
||||||
Name = x.Key.ToString(),
|
.Take(topItem)
|
||||||
Value = x.Count().ToString()
|
.Select(x => new ReportStatItem
|
||||||
})
|
{
|
||||||
);
|
Name = x.Key.ToString(),
|
||||||
|
Value = x.Count().ToString()
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary> Gets result persons. </summary>
|
||||||
|
/// <param name="result"> The result. </param>
|
||||||
|
/// <param name="items"> The items. </param>
|
||||||
|
/// <param name="topItem"> The top item. </param>
|
||||||
|
/// <returns> The result persons. </returns>
|
||||||
|
private ReportStatResult GetResultPersons(ReportStatResult result, BaseItem[] items, int topItem = 5)
|
||||||
|
{
|
||||||
|
List<HeaderMetadata> t = new List<HeaderMetadata>
|
||||||
|
{
|
||||||
|
HeaderMetadata.Actor,
|
||||||
|
HeaderMetadata.Composer,
|
||||||
|
HeaderMetadata.Director,
|
||||||
|
HeaderMetadata.GuestStar,
|
||||||
|
HeaderMetadata.Producer,
|
||||||
|
HeaderMetadata.Writer,
|
||||||
|
HeaderMetadata.Artist,
|
||||||
|
HeaderMetadata.AlbumArtist
|
||||||
|
};
|
||||||
|
foreach (var item in t)
|
||||||
|
{
|
||||||
|
var ps = items.Where(x => x.People != null && x.SupportsPeople).SelectMany(x => x.People)
|
||||||
|
.Where(n => n.Type == item.ToString())
|
||||||
|
.GroupBy(x => x.Name)
|
||||||
|
.OrderByDescending(x => x.Count())
|
||||||
|
.Take(topItem);
|
||||||
|
if (ps != null && ps.Count() > 0)
|
||||||
|
this.GetGroups(result, GetLocalizedHeader(item), topItem,
|
||||||
|
ps.Select(x => new ReportStatItem
|
||||||
|
{
|
||||||
|
Name = x.Key,
|
||||||
|
Value = x.Count().ToString(),
|
||||||
|
Id = GetPersonID(x.Key)
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary> Gets the groups. </summary>
|
return result;
|
||||||
/// <param name="result"> The result. </param>
|
}
|
||||||
/// <param name="header"> The header. </param>
|
|
||||||
/// <param name="topItem"> The top item. </param>
|
/// <summary> Gets result production years. </summary>
|
||||||
/// <param name="top"> The top. </param>
|
/// <param name="result"> The result. </param>
|
||||||
private void GetGroups(ReportStatResult result, string header, int topItem, IEnumerable<ReportStatItem> top)
|
/// <param name="items"> The items. </param>
|
||||||
{
|
/// <param name="topItem"> The top item. </param>
|
||||||
if (top.Count() > 0)
|
/// <returns> The result production years. </returns>
|
||||||
{
|
private ReportStatResult GetResultProductionYears(ReportStatResult result, BaseItem[] items, int topItem = 5)
|
||||||
var group = new ReportStatGroup { Header = ReportStatGroup.FormatedHeader(header, topItem) };
|
{
|
||||||
group.Items.AddRange(top);
|
this.GetGroups(result, GetLocalizedHeader(HeaderMetadata.Year), topItem,
|
||||||
result.Groups.Add(group);
|
items.Where(x => x.ProductionYear != null && x.ProductionYear > 0)
|
||||||
}
|
.GroupBy(x => x.ProductionYear)
|
||||||
}
|
.OrderByDescending(x => x.Count())
|
||||||
}
|
.Take(topItem)
|
||||||
|
.Select(x => new ReportStatItem
|
||||||
|
{
|
||||||
|
Name = x.Key.ToString(),
|
||||||
|
Value = x.Count().ToString()
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Gets result studios. </summary>
|
||||||
|
/// <param name="result"> The result. </param>
|
||||||
|
/// <param name="items"> The items. </param>
|
||||||
|
/// <param name="topItem"> The top item. </param>
|
||||||
|
/// <returns> The result studios. </returns>
|
||||||
|
private ReportStatResult GetResultStudios(ReportStatResult result, BaseItem[] items, int topItem = 5)
|
||||||
|
{
|
||||||
|
this.GetGroups(result, GetLocalizedHeader(HeaderMetadata.Studios), topItem,
|
||||||
|
items.SelectMany(x => x.Studios)
|
||||||
|
.GroupBy(x => x)
|
||||||
|
.OrderByDescending(x => x.Count())
|
||||||
|
.Take(topItem)
|
||||||
|
.Select(x => new ReportStatItem
|
||||||
|
{
|
||||||
|
Name = x.Key,
|
||||||
|
Value = x.Count().ToString(),
|
||||||
|
Id = GetStudioID(x.Key)
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ using MediaBrowser.Controller.Entities;
|
|||||||
using MediaBrowser.Controller.Entities.Audio;
|
using MediaBrowser.Controller.Entities.Audio;
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
|
using MediaBrowser.Controller.LiveTv;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Search;
|
using MediaBrowser.Model.Search;
|
||||||
@ -171,6 +172,8 @@ namespace MediaBrowser.Api
|
|||||||
ProductionYear = item.ProductionYear
|
ProductionYear = item.ProductionYear
|
||||||
};
|
};
|
||||||
|
|
||||||
|
result.ChannelId = item.ChannelId;
|
||||||
|
|
||||||
var primaryImageTag = _imageProcessor.GetImageCacheTag(item, ImageType.Primary);
|
var primaryImageTag = _imageProcessor.GetImageCacheTag(item, ImageType.Primary);
|
||||||
|
|
||||||
if (primaryImageTag != null)
|
if (primaryImageTag != null)
|
||||||
@ -181,24 +184,19 @@ namespace MediaBrowser.Api
|
|||||||
SetThumbImageInfo(result, item);
|
SetThumbImageInfo(result, item);
|
||||||
SetBackdropImageInfo(result, item);
|
SetBackdropImageInfo(result, item);
|
||||||
|
|
||||||
var episode = item as Episode;
|
var hasSeries = item as IHasSeries;
|
||||||
|
if (hasSeries != null)
|
||||||
if (episode != null)
|
|
||||||
{
|
{
|
||||||
result.Series = episode.Series.Name;
|
result.Series = hasSeries.SeriesName;
|
||||||
}
|
}
|
||||||
|
|
||||||
var season = item as Season;
|
var season = item as Season;
|
||||||
|
|
||||||
if (season != null)
|
if (season != null)
|
||||||
{
|
{
|
||||||
result.Series = season.Series.Name;
|
|
||||||
|
|
||||||
result.EpisodeCount = season.GetRecursiveChildren(i => i is Episode).Count;
|
result.EpisodeCount = season.GetRecursiveChildren(i => i is Episode).Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
var series = item as Series;
|
var series = item as Series;
|
||||||
|
|
||||||
if (series != null)
|
if (series != null)
|
||||||
{
|
{
|
||||||
result.EpisodeCount = series.GetRecursiveChildren(i => i is Episode).Count;
|
result.EpisodeCount = series.GetRecursiveChildren(i => i is Episode).Count;
|
||||||
@ -223,6 +221,12 @@ namespace MediaBrowser.Api
|
|||||||
result.Artists = song.Artists.ToArray();
|
result.Artists = song.Artists.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(item.ChannelId))
|
||||||
|
{
|
||||||
|
var channel = _libraryManager.GetItemById(item.ChannelId);
|
||||||
|
result.ChannelName = channel == null ? null : channel.Name;
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,8 +3,10 @@ using MediaBrowser.Controller;
|
|||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Connect;
|
using MediaBrowser.Controller.Connect;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
|
using MediaBrowser.Controller.LiveTv;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
|
using MediaBrowser.Model.LiveTv;
|
||||||
using ServiceStack;
|
using ServiceStack;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -49,13 +51,15 @@ namespace MediaBrowser.Api
|
|||||||
private readonly IServerApplicationHost _appHost;
|
private readonly IServerApplicationHost _appHost;
|
||||||
private readonly IUserManager _userManager;
|
private readonly IUserManager _userManager;
|
||||||
private readonly IConnectManager _connectManager;
|
private readonly IConnectManager _connectManager;
|
||||||
|
private readonly ILiveTvManager _liveTvManager;
|
||||||
|
|
||||||
public StartupWizardService(IServerConfigurationManager config, IServerApplicationHost appHost, IUserManager userManager, IConnectManager connectManager)
|
public StartupWizardService(IServerConfigurationManager config, IServerApplicationHost appHost, IUserManager userManager, IConnectManager connectManager, ILiveTvManager liveTvManager)
|
||||||
{
|
{
|
||||||
_config = config;
|
_config = config;
|
||||||
_appHost = appHost;
|
_appHost = appHost;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
_connectManager = connectManager;
|
_connectManager = connectManager;
|
||||||
|
_liveTvManager = liveTvManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Post(ReportStartupWizardComplete request)
|
public void Post(ReportStartupWizardComplete request)
|
||||||
@ -67,6 +71,8 @@ namespace MediaBrowser.Api
|
|||||||
_config.Configuration.EnableLibraryMetadataSubFolder = true;
|
_config.Configuration.EnableLibraryMetadataSubFolder = true;
|
||||||
_config.Configuration.EnableUserSpecificUserViews = true;
|
_config.Configuration.EnableUserSpecificUserViews = true;
|
||||||
_config.Configuration.EnableCustomPathSubFolders = true;
|
_config.Configuration.EnableCustomPathSubFolders = true;
|
||||||
|
_config.Configuration.DisableXmlSavers = true;
|
||||||
|
_config.Configuration.DisableStartupScan = true;
|
||||||
_config.SaveConfiguration();
|
_config.SaveConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +88,7 @@ namespace MediaBrowser.Api
|
|||||||
|
|
||||||
public object Get(GetStartupConfiguration request)
|
public object Get(GetStartupConfiguration request)
|
||||||
{
|
{
|
||||||
return new StartupConfiguration
|
var result = new StartupConfiguration
|
||||||
{
|
{
|
||||||
UICulture = _config.Configuration.UICulture,
|
UICulture = _config.Configuration.UICulture,
|
||||||
EnableInternetProviders = _config.Configuration.EnableInternetProviders,
|
EnableInternetProviders = _config.Configuration.EnableInternetProviders,
|
||||||
@ -90,6 +96,22 @@ namespace MediaBrowser.Api
|
|||||||
MetadataCountryCode = _config.Configuration.MetadataCountryCode,
|
MetadataCountryCode = _config.Configuration.MetadataCountryCode,
|
||||||
PreferredMetadataLanguage = _config.Configuration.PreferredMetadataLanguage
|
PreferredMetadataLanguage = _config.Configuration.PreferredMetadataLanguage
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var tvConfig = GetLiveTVConfiguration();
|
||||||
|
|
||||||
|
if (tvConfig.TunerHosts.Count > 0)
|
||||||
|
{
|
||||||
|
result.LiveTvTunerPath = tvConfig.TunerHosts[0].Url;
|
||||||
|
result.LiveTvTunerType = tvConfig.TunerHosts[0].Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tvConfig.ListingProviders.Count > 0)
|
||||||
|
{
|
||||||
|
result.LiveTvGuideProviderId = tvConfig.ListingProviders[0].Id;
|
||||||
|
result.LiveTvGuideProviderType = tvConfig.ListingProviders[0].Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Post(UpdateStartupConfiguration request)
|
public void Post(UpdateStartupConfiguration request)
|
||||||
@ -100,6 +122,9 @@ namespace MediaBrowser.Api
|
|||||||
_config.Configuration.MetadataCountryCode = request.MetadataCountryCode;
|
_config.Configuration.MetadataCountryCode = request.MetadataCountryCode;
|
||||||
_config.Configuration.PreferredMetadataLanguage = request.PreferredMetadataLanguage;
|
_config.Configuration.PreferredMetadataLanguage = request.PreferredMetadataLanguage;
|
||||||
_config.SaveConfiguration();
|
_config.SaveConfiguration();
|
||||||
|
|
||||||
|
var task = UpdateTuners(request);
|
||||||
|
Task.WaitAll(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetStartupUser request)
|
public object Get(GetStartupUser request)
|
||||||
@ -140,6 +165,51 @@ namespace MediaBrowser.Api
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task UpdateTuners(UpdateStartupConfiguration request)
|
||||||
|
{
|
||||||
|
var config = GetLiveTVConfiguration();
|
||||||
|
var save = false;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(request.LiveTvTunerPath) ||
|
||||||
|
string.IsNullOrWhiteSpace(request.LiveTvTunerType))
|
||||||
|
{
|
||||||
|
if (config.TunerHosts.Count > 0)
|
||||||
|
{
|
||||||
|
config.TunerHosts.Clear();
|
||||||
|
save = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!config.TunerHosts.Any(i => string.Equals(i.Type, request.LiveTvTunerType, StringComparison.OrdinalIgnoreCase) && string.Equals(i.Url, request.LiveTvTunerPath, StringComparison.OrdinalIgnoreCase)))
|
||||||
|
{
|
||||||
|
// Add tuner
|
||||||
|
await _liveTvManager.SaveTunerHost(new TunerHostInfo
|
||||||
|
{
|
||||||
|
IsEnabled = true,
|
||||||
|
Type = request.LiveTvTunerType,
|
||||||
|
Url = request.LiveTvTunerPath
|
||||||
|
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (save)
|
||||||
|
{
|
||||||
|
SaveLiveTVConfiguration(config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveLiveTVConfiguration(LiveTvOptions config)
|
||||||
|
{
|
||||||
|
_config.SaveConfiguration("livetv", config);
|
||||||
|
}
|
||||||
|
|
||||||
|
private LiveTvOptions GetLiveTVConfiguration()
|
||||||
|
{
|
||||||
|
return _config.GetConfiguration<LiveTvOptions>("livetv");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class StartupConfiguration
|
public class StartupConfiguration
|
||||||
@ -149,6 +219,10 @@ namespace MediaBrowser.Api
|
|||||||
public bool SaveLocalMeta { get; set; }
|
public bool SaveLocalMeta { get; set; }
|
||||||
public string MetadataCountryCode { get; set; }
|
public string MetadataCountryCode { get; set; }
|
||||||
public string PreferredMetadataLanguage { get; set; }
|
public string PreferredMetadataLanguage { get; set; }
|
||||||
|
public string LiveTvTunerType { get; set; }
|
||||||
|
public string LiveTvTunerPath { get; set; }
|
||||||
|
public string LiveTvGuideProviderId { get; set; }
|
||||||
|
public string LiveTvGuideProviderType { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class StartupInfo
|
public class StartupInfo
|
||||||
|
@ -10,11 +10,6 @@ namespace MediaBrowser.Api.Sync
|
|||||||
{
|
{
|
||||||
List<SyncJobOption> options = new List<SyncJobOption>();
|
List<SyncJobOption> options = new List<SyncJobOption>();
|
||||||
|
|
||||||
if (items.Count > 1)
|
|
||||||
{
|
|
||||||
options.Add(SyncJobOption.Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (BaseItemDto item in items)
|
foreach (BaseItemDto item in items)
|
||||||
{
|
{
|
||||||
if (item.SupportsSync ?? false)
|
if (item.SupportsSync ?? false)
|
||||||
@ -65,7 +60,6 @@ namespace MediaBrowser.Api.Sync
|
|||||||
{
|
{
|
||||||
List<SyncJobOption> options = new List<SyncJobOption>();
|
List<SyncJobOption> options = new List<SyncJobOption>();
|
||||||
|
|
||||||
options.Add(SyncJobOption.Name);
|
|
||||||
options.Add(SyncJobOption.Quality);
|
options.Add(SyncJobOption.Quality);
|
||||||
options.Add(SyncJobOption.Profile);
|
options.Add(SyncJobOption.Profile);
|
||||||
options.Add(SyncJobOption.UnwatchedOnly);
|
options.Add(SyncJobOption.UnwatchedOnly);
|
||||||
|
@ -6,7 +6,6 @@ using MediaBrowser.Controller.Net;
|
|||||||
using MediaBrowser.Controller.Persistence;
|
using MediaBrowser.Controller.Persistence;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using ServiceStack;
|
using ServiceStack;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
@ -124,48 +123,18 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
/// <param name="items">The items.</param>
|
/// <param name="items">The items.</param>
|
||||||
/// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
|
/// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
|
||||||
protected override IEnumerable<MusicArtist> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items)
|
protected override IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items)
|
||||||
{
|
{
|
||||||
if (request is GetAlbumArtists)
|
if (request is GetAlbumArtists)
|
||||||
{
|
{
|
||||||
return items
|
return LibraryManager.GetAlbumArtists(items
|
||||||
.Where(i => !i.IsFolder)
|
.Where(i => !i.IsFolder)
|
||||||
.OfType<IHasAlbumArtist>()
|
.OfType<IHasAlbumArtist>());
|
||||||
.SelectMany(i => i.AlbumArtists)
|
|
||||||
.DistinctNames()
|
|
||||||
.Select(name =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return LibraryManager.GetArtist(name);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.ErrorException("Error getting artist {0}", ex, name);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}).Where(i => i != null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return items
|
return LibraryManager.GetArtists(items
|
||||||
.Where(i => !i.IsFolder)
|
.Where(i => !i.IsFolder)
|
||||||
.OfType<IHasArtist>()
|
.OfType<IHasArtist>());
|
||||||
.SelectMany(i => i.AllArtists)
|
|
||||||
.DistinctNames()
|
|
||||||
.Select(name =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return LibraryManager.GetArtist(name);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.ErrorException("Error getting artist {0}", ex, name);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}).Where(i => i != null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,42 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
DtoService = dtoService;
|
DtoService = dtoService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected BaseItem GetParentItem(GetItemsByName request)
|
||||||
|
{
|
||||||
|
BaseItem parentItem;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(request.UserId))
|
||||||
|
{
|
||||||
|
var 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parentItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected string GetParentItemViewType(GetItemsByName request)
|
||||||
|
{
|
||||||
|
var parent = GetParentItem(request);
|
||||||
|
|
||||||
|
var collectionFolder = parent as ICollectionFolder;
|
||||||
|
if (collectionFolder != null)
|
||||||
|
{
|
||||||
|
return collectionFolder.CollectionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
var view = parent as UserView;
|
||||||
|
if (view != null)
|
||||||
|
{
|
||||||
|
return view.ViewType;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the specified request.
|
/// Gets the specified request.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -114,13 +150,13 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
|
|
||||||
var filteredItems = FilterItems(request, extractedItems, user);
|
var filteredItems = FilterItems(request, extractedItems, user);
|
||||||
|
|
||||||
filteredItems = FilterByLibraryItems(request, filteredItems, user, libraryItems);
|
filteredItems = FilterByLibraryItems(request, filteredItems.Cast<IItemByName>(), user, libraryItems).Cast<BaseItem>();
|
||||||
|
|
||||||
filteredItems = LibraryManager.Sort(filteredItems, user, request.GetOrderBy(), request.SortOrder ?? SortOrder.Ascending).Cast<TItemType>();
|
filteredItems = LibraryManager.Sort(filteredItems, user, request.GetOrderBy(), request.SortOrder ?? SortOrder.Ascending);
|
||||||
|
|
||||||
var ibnItemsArray = filteredItems.ToList();
|
var ibnItemsArray = filteredItems.ToList();
|
||||||
|
|
||||||
IEnumerable<TItemType> ibnItems = ibnItemsArray;
|
IEnumerable<BaseItem> ibnItems = ibnItemsArray;
|
||||||
|
|
||||||
var result = new ItemsResult
|
var result = new ItemsResult
|
||||||
{
|
{
|
||||||
@ -141,14 +177,14 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerable<Tuple<TItemType, List<BaseItem>>> tuples;
|
IEnumerable<Tuple<BaseItem, List<BaseItem>>> tuples;
|
||||||
if (dtoOptions.Fields.Contains(ItemFields.ItemCounts))
|
if (dtoOptions.Fields.Contains(ItemFields.ItemCounts))
|
||||||
{
|
{
|
||||||
tuples = ibnItems.Select(i => new Tuple<TItemType, List<BaseItem>>(i, i.GetTaggedItems(libraryItems).ToList()));
|
tuples = ibnItems.Select(i => new Tuple<BaseItem, List<BaseItem>>(i, ((IItemByName)i).GetTaggedItems(libraryItems).ToList()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tuples = ibnItems.Select(i => new Tuple<TItemType, List<BaseItem>>(i, new List<BaseItem>()));
|
tuples = ibnItems.Select(i => new Tuple<BaseItem, List<BaseItem>>(i, new List<BaseItem>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
var dtos = tuples.Select(i => DtoService.GetItemByNameDto(i.Item1, dtoOptions, i.Item2, user));
|
var dtos = tuples.Select(i => DtoService.GetItemByNameDto(i.Item1, dtoOptions, i.Item2, user));
|
||||||
@ -180,7 +216,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
return options.Fields.Contains(ItemFields.ItemCounts);
|
return options.Fields.Contains(ItemFields.ItemCounts);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<TItemType> FilterByLibraryItems(GetItemsByName request, IEnumerable<TItemType> items, User user, IEnumerable<BaseItem> libraryItems)
|
private IEnumerable<IItemByName> FilterByLibraryItems(GetItemsByName request, IEnumerable<IItemByName> items, User user, IEnumerable<BaseItem> libraryItems)
|
||||||
{
|
{
|
||||||
var filters = request.GetFilters().ToList();
|
var filters = request.GetFilters().ToList();
|
||||||
|
|
||||||
@ -211,7 +247,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// <param name="items">The items.</param>
|
/// <param name="items">The items.</param>
|
||||||
/// <param name="user">The user.</param>
|
/// <param name="user">The user.</param>
|
||||||
/// <returns>IEnumerable{`0}.</returns>
|
/// <returns>IEnumerable{`0}.</returns>
|
||||||
private IEnumerable<TItemType> FilterItems(GetItemsByName request, IEnumerable<TItemType> items, User user)
|
private IEnumerable<BaseItem> FilterItems(GetItemsByName request, IEnumerable<BaseItem> items, User user)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(request.NameStartsWithOrGreater))
|
if (!string.IsNullOrEmpty(request.NameStartsWithOrGreater))
|
||||||
{
|
{
|
||||||
@ -375,7 +411,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
/// <param name="items">The items.</param>
|
/// <param name="items">The items.</param>
|
||||||
/// <returns>IEnumerable{Task{`0}}.</returns>
|
/// <returns>IEnumerable{Task{`0}}.</returns>
|
||||||
protected abstract IEnumerable<TItemType> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items);
|
protected abstract IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -383,22 +419,6 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetItemsByName : BaseItemsRequest, IReturn<ItemsResult>
|
public class GetItemsByName : BaseItemsRequest, IReturn<ItemsResult>
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the user id.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The user id.</value>
|
|
||||||
[ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public string UserId { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "NameStartsWithOrGreater", Description = "Optional filter by items whose name is sorted equally or greater than a given input string.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public string NameStartsWithOrGreater { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "NameStartsWith", Description = "Optional filter by items whose name is sorted equally than a given input string.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public string NameStartsWith { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "NameLessThan", Description = "Optional filter by items whose name is sorted less than a given input string.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public string NameLessThan { get; set; }
|
|
||||||
|
|
||||||
public GetItemsByName()
|
public GetItemsByName()
|
||||||
{
|
{
|
||||||
Recursive = true;
|
Recursive = true;
|
||||||
|
@ -14,6 +14,97 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
EnableImages = true;
|
EnableImages = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the max offical rating.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The max offical rating.</value>
|
||||||
|
[ApiMember(Name = "MaxOfficialRating", Description = "Optional filter by maximum official rating (PG, PG-13, TV-MA, etc).", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string MaxOfficialRating { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "HasThemeSong", Description = "Optional filter by items with theme songs.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool? HasThemeSong { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "HasThemeVideo", Description = "Optional filter by items with theme videos.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool? HasThemeVideo { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "HasSubtitles", Description = "Optional filter by items with subtitles.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool? HasSubtitles { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "HasSpecialFeature", Description = "Optional filter by items with special features.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool? HasSpecialFeature { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "HasTrailer", Description = "Optional filter by items with trailers.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool? HasTrailer { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "AdjacentTo", Description = "Optional. Return items that are siblings of a supplied item.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string AdjacentTo { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "MinIndexNumber", Description = "Optional filter by minimum index number.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
||||||
|
public int? MinIndexNumber { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "MinPlayers", Description = "Optional filter by minimum number of game players.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
||||||
|
public int? MinPlayers { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "MaxPlayers", Description = "Optional filter by maximum number of game players.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
||||||
|
public int? MaxPlayers { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "ParentIndexNumber", Description = "Optional filter by parent index number.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
||||||
|
public int? ParentIndexNumber { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "HasParentalRating", Description = "Optional filter by items that have or do not have a parental rating", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool? HasParentalRating { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "IsHD", Description = "Optional filter by items that are HD or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool? IsHD { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "LocationTypes", Description = "Optional. If specified, results will be filtered based on LocationType. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
|
public string LocationTypes { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "ExcludeLocationTypes", Description = "Optional. If specified, results will be filtered based on LocationType. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
|
public string ExcludeLocationTypes { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "IsMissing", Description = "Optional filter by items that are missing episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool? IsMissing { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "IsUnaired", Description = "Optional filter by items that are unaired episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool? IsUnaired { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "IsVirtualUnaired", Description = "Optional filter by items that are virtual unaired episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool? IsVirtualUnaired { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "MinCommunityRating", Description = "Optional filter by minimum community rating.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
||||||
|
public double? MinCommunityRating { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "MinCriticRating", Description = "Optional filter by minimum critic rating.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
||||||
|
public double? MinCriticRating { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "AiredDuringSeason", Description = "Gets all episodes that aired during a season, including specials.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
||||||
|
public int? AiredDuringSeason { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "MinPremiereDate", Description = "Optional. The minimum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
|
||||||
|
public string MinPremiereDate { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "MaxPremiereDate", Description = "Optional. The maximum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
|
||||||
|
public string MaxPremiereDate { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "HasOverview", Description = "Optional filter by items that have an overview or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool? HasOverview { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "HasImdbId", Description = "Optional filter by items that have an imdb id or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool? HasImdbId { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "HasTmdbId", Description = "Optional filter by items that have a tmdb id or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool? HasTmdbId { get; set; }
|
||||||
|
|
||||||
|
[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; }
|
||||||
|
|
||||||
|
[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")]
|
||||||
|
public bool? IsInBoxSet { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Skips over a given number of items within the results. Use for paging.
|
/// Skips over a given number of items within the results. Use for paging.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -130,6 +221,121 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
[ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
public string EnableImageTypes { get; set; }
|
public string EnableImageTypes { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Limit results to items containing a specific person
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The person.</value>
|
||||||
|
[ApiMember(Name = "Person", Description = "Optional. If specified, results will be filtered to include only those containing the specified person.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string Person { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "PersonIds", Description = "Optional. If specified, results will be filtered to include only those containing the specified person.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string PersonIds { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If the Person filter is used, this can also be used to restrict to a specific person type
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The type of the person.</value>
|
||||||
|
[ApiMember(Name = "PersonTypes", Description = "Optional. If specified, along with Person, results will be filtered to include only those containing the specified person and PersonType. Allows multiple, comma-delimited", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string PersonTypes { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Limit results to items containing specific studios
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The studios.</value>
|
||||||
|
[ApiMember(Name = "Studios", Description = "Optional. If specified, results will be filtered based on studio. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
|
public string Studios { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "StudioIds", Description = "Optional. If specified, results will be filtered based on studio. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
|
public string StudioIds { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the studios.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The studios.</value>
|
||||||
|
[ApiMember(Name = "Artists", Description = "Optional. If specified, results will be filtered based on artist. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
|
public string Artists { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "ArtistIds", Description = "Optional. If specified, results will be filtered based on artist. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
|
public string ArtistIds { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "Albums", Description = "Optional. If specified, results will be filtered based on album. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
|
public string Albums { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the item ids.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The item ids.</value>
|
||||||
|
[ApiMember(Name = "Ids", Description = "Optional. If specific items are needed, specify a list of item id's to retrieve. This allows multiple, comma delimited.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
|
public string Ids { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the video types.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The video types.</value>
|
||||||
|
[ApiMember(Name = "VideoTypes", Description = "Optional filter by VideoType (videofile, dvd, bluray, iso). Allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
|
public string VideoTypes { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the air days.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The air days.</value>
|
||||||
|
[ApiMember(Name = "AirDays", Description = "Optional filter by Series Air Days. Allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
|
public string AirDays { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the user id.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The user id.</value>
|
||||||
|
[ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||||
|
public string UserId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the min offical rating.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The min offical rating.</value>
|
||||||
|
[ApiMember(Name = "MinOfficialRating", Description = "Optional filter by minimum official rating (PG, PG-13, TV-MA, etc).", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string MinOfficialRating { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "IsLocked", Description = "Optional filter by items that are locked.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool? IsLocked { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "IsUnidentified", Description = "Optional filter by items that are unidentified by internet metadata providers.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool? IsUnidentified { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "IsPlaceHolder", Description = "Optional filter by items that are placeholders", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool? IsPlaceHolder { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "HasOfficialRating", Description = "Optional filter by items that have official ratings", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool? HasOfficialRating { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "CollapseBoxSetItems", Description = "Whether or not to hide items behind their boxsets.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool? CollapseBoxSetItems { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the video formats.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The video formats.</value>
|
||||||
|
[ApiMember(Name = "Is3D", Description = "Optional filter by items that are 3D, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool? Is3D { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the series status.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The series status.</value>
|
||||||
|
[ApiMember(Name = "SeriesStatus", Description = "Optional filter by Series Status. Allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
|
public string SeriesStatus { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "NameStartsWithOrGreater", Description = "Optional filter by items whose name is sorted equally or greater than a given input string.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string NameStartsWithOrGreater { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "NameStartsWith", Description = "Optional filter by items whose name is sorted equally than a given input string.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string NameStartsWith { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "NameLessThan", Description = "Optional filter by items whose name is equally or lesser than a given input string.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string NameLessThan { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "AlbumArtistStartsWithOrGreater", Description = "Optional filter by items whose album artist is sorted equally or greater than a given input string.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string AlbumArtistStartsWithOrGreater { get; set; }
|
||||||
|
|
||||||
public string[] GetGenres()
|
public string[] GetGenres()
|
||||||
{
|
{
|
||||||
return (Genres ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
|
return (Genres ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
@ -164,6 +370,43 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
{
|
{
|
||||||
return (Years ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();
|
return (Years ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string[] GetStudios()
|
||||||
|
{
|
||||||
|
return (Studios ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string[] GetStudioIds()
|
||||||
|
{
|
||||||
|
return (StudioIds ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string[] GetPersonTypes()
|
||||||
|
{
|
||||||
|
return (PersonTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string[] GetPersonIds()
|
||||||
|
{
|
||||||
|
return (PersonIds ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string[] GetItemIds()
|
||||||
|
{
|
||||||
|
return (Ids ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
}
|
||||||
|
|
||||||
|
public VideoType[] GetVideoTypes()
|
||||||
|
{
|
||||||
|
var val = VideoTypes;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(val))
|
||||||
|
{
|
||||||
|
return new VideoType[] { };
|
||||||
|
}
|
||||||
|
|
||||||
|
return val.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(v => (VideoType)Enum.Parse(typeof(VideoType), v, true)).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the filters.
|
/// Gets the filters.
|
||||||
|
@ -99,14 +99,24 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
/// <param name="items">The items.</param>
|
/// <param name="items">The items.</param>
|
||||||
/// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
|
/// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
|
||||||
protected override IEnumerable<GameGenre> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items)
|
protected override IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items)
|
||||||
{
|
{
|
||||||
var itemsList = items.Where(i => i.Genres != null).ToList();
|
return items
|
||||||
|
|
||||||
return itemsList
|
|
||||||
.SelectMany(i => i.Genres)
|
.SelectMany(i => i.Genres)
|
||||||
.DistinctNames()
|
.DistinctNames()
|
||||||
.Select(name => LibraryManager.GetGameGenre(name));
|
.Select(name =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return LibraryManager.GetGameGenre(name);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.ErrorException("Error getting genre {0}", ex, name);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.Where(i => i != null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.Audio;
|
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
using MediaBrowser.Controller.Persistence;
|
using MediaBrowser.Controller.Persistence;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Entities;
|
||||||
using ServiceStack;
|
using ServiceStack;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -104,8 +103,38 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
/// <param name="items">The items.</param>
|
/// <param name="items">The items.</param>
|
||||||
/// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
|
/// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
|
||||||
protected override IEnumerable<Genre> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items)
|
protected override IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items)
|
||||||
{
|
{
|
||||||
|
var viewType = GetParentItemViewType(request);
|
||||||
|
|
||||||
|
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
|
return items
|
||||||
.SelectMany(i => i.Genres)
|
.SelectMany(i => i.Genres)
|
||||||
.DistinctNames()
|
.DistinctNames()
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
using MediaBrowser.Controller.Dto;
|
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.Entities.Movies;
|
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Localization;
|
using MediaBrowser.Controller.Localization;
|
||||||
@ -25,249 +24,6 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
[Route("/Users/{UserId}/Items", "GET", Summary = "Gets items based on a query.")]
|
[Route("/Users/{UserId}/Items", "GET", Summary = "Gets items based on a query.")]
|
||||||
public class GetItems : BaseItemsRequest, IReturn<ItemsResult>
|
public class GetItems : BaseItemsRequest, IReturn<ItemsResult>
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the user id.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The user id.</value>
|
|
||||||
[ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")]
|
|
||||||
public string UserId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Limit results to items containing a specific person
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The person.</value>
|
|
||||||
[ApiMember(Name = "Person", Description = "Optional. If specified, results will be filtered to include only those containing the specified person.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public string Person { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "PersonIds", Description = "Optional. If specified, results will be filtered to include only those containing the specified person.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public string PersonIds { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If the Person filter is used, this can also be used to restrict to a specific person type
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The type of the person.</value>
|
|
||||||
[ApiMember(Name = "PersonTypes", Description = "Optional. If specified, along with Person, results will be filtered to include only those containing the specified person and PersonType. Allows multiple, comma-delimited", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public string PersonTypes { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Limit results to items containing specific studios
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The studios.</value>
|
|
||||||
[ApiMember(Name = "Studios", Description = "Optional. If specified, results will be filtered based on studio. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
|
||||||
public string Studios { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "StudioIds", Description = "Optional. If specified, results will be filtered based on studio. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
|
||||||
public string StudioIds { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the studios.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The studios.</value>
|
|
||||||
[ApiMember(Name = "Artists", Description = "Optional. If specified, results will be filtered based on artist. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
|
||||||
public string Artists { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "ArtistIds", Description = "Optional. If specified, results will be filtered based on artist. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
|
||||||
public string ArtistIds { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "Albums", Description = "Optional. If specified, results will be filtered based on album. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
|
||||||
public string Albums { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the item ids.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The item ids.</value>
|
|
||||||
[ApiMember(Name = "Ids", Description = "Optional. If specific items are needed, specify a list of item id's to retrieve. This allows multiple, comma delimited.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
|
||||||
public string Ids { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the video types.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The video types.</value>
|
|
||||||
[ApiMember(Name = "VideoTypes", Description = "Optional filter by VideoType (videofile, dvd, bluray, iso). Allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
|
||||||
public string VideoTypes { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the video formats.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The video formats.</value>
|
|
||||||
[ApiMember(Name = "Is3D", Description = "Optional filter by items that are 3D, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? Is3D { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the series status.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The series status.</value>
|
|
||||||
[ApiMember(Name = "SeriesStatus", Description = "Optional filter by Series Status. Allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
|
||||||
public string SeriesStatus { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "NameStartsWithOrGreater", Description = "Optional filter by items whose name is sorted equally or greater than a given input string.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public string NameStartsWithOrGreater { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "NameStartsWith", Description = "Optional filter by items whose name is sorted equally than a given input string.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public string NameStartsWith { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "NameLessThan", Description = "Optional filter by items whose name is equally or lesser than a given input string.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public string NameLessThan { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "AlbumArtistStartsWithOrGreater", Description = "Optional filter by items whose album artist is sorted equally or greater than a given input string.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public string AlbumArtistStartsWithOrGreater { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the air days.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The air days.</value>
|
|
||||||
[ApiMember(Name = "AirDays", Description = "Optional filter by Series Air Days. Allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
|
||||||
public string AirDays { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the min offical rating.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The min offical rating.</value>
|
|
||||||
[ApiMember(Name = "MinOfficialRating", Description = "Optional filter by minimum official rating (PG, PG-13, TV-MA, etc).", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public string MinOfficialRating { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the max offical rating.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The max offical rating.</value>
|
|
||||||
[ApiMember(Name = "MaxOfficialRating", Description = "Optional filter by maximum official rating (PG, PG-13, TV-MA, etc).", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public string MaxOfficialRating { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "HasThemeSong", Description = "Optional filter by items with theme songs.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? HasThemeSong { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "HasThemeVideo", Description = "Optional filter by items with theme videos.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? HasThemeVideo { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "HasSubtitles", Description = "Optional filter by items with subtitles.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? HasSubtitles { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "HasSpecialFeature", Description = "Optional filter by items with special features.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? HasSpecialFeature { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "HasTrailer", Description = "Optional filter by items with trailers.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? HasTrailer { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "AdjacentTo", Description = "Optional. Return items that are siblings of a supplied item.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public string AdjacentTo { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "MinIndexNumber", Description = "Optional filter by minimum index number.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
|
||||||
public int? MinIndexNumber { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "MinPlayers", Description = "Optional filter by minimum number of game players.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
|
||||||
public int? MinPlayers { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "MaxPlayers", Description = "Optional filter by maximum number of game players.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
|
||||||
public int? MaxPlayers { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "ParentIndexNumber", Description = "Optional filter by parent index number.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
|
||||||
public int? ParentIndexNumber { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "HasParentalRating", Description = "Optional filter by items that have or do not have a parental rating", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? HasParentalRating { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "IsHD", Description = "Optional filter by items that are HD or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? IsHD { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "LocationTypes", Description = "Optional. If specified, results will be filtered based on LocationType. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
|
||||||
public string LocationTypes { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "ExcludeLocationTypes", Description = "Optional. If specified, results will be filtered based on LocationType. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
|
||||||
public string ExcludeLocationTypes { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "IsMissing", Description = "Optional filter by items that are missing episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? IsMissing { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "IsUnaired", Description = "Optional filter by items that are unaired episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? IsUnaired { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "IsVirtualUnaired", Description = "Optional filter by items that are virtual unaired episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? IsVirtualUnaired { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "MinCommunityRating", Description = "Optional filter by minimum community rating.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
|
||||||
public double? MinCommunityRating { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "MinCriticRating", Description = "Optional filter by minimum critic rating.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
|
||||||
public double? MinCriticRating { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "AiredDuringSeason", Description = "Gets all episodes that aired during a season, including specials.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
|
||||||
public int? AiredDuringSeason { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "MinPremiereDate", Description = "Optional. The minimum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
|
|
||||||
public string MinPremiereDate { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "MaxPremiereDate", Description = "Optional. The maximum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
|
|
||||||
public string MaxPremiereDate { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "HasOverview", Description = "Optional filter by items that have an overview or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? HasOverview { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "HasImdbId", Description = "Optional filter by items that have an imdb id or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? HasImdbId { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "HasTmdbId", Description = "Optional filter by items that have a tmdb id or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? HasTmdbId { get; set; }
|
|
||||||
|
|
||||||
[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; }
|
|
||||||
|
|
||||||
[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")]
|
|
||||||
public bool? IsInBoxSet { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "IsLocked", Description = "Optional filter by items that are locked.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? IsLocked { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "IsUnidentified", Description = "Optional filter by items that are unidentified by internet metadata providers.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? IsUnidentified { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "IsPlaceHolder", Description = "Optional filter by items that are placeholders", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? IsPlaceHolder { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "HasOfficialRating", Description = "Optional filter by items that have official ratings", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? HasOfficialRating { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "CollapseBoxSetItems", Description = "Whether or not to hide items behind their boxsets.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? CollapseBoxSetItems { get; set; }
|
|
||||||
|
|
||||||
public string[] GetStudios()
|
|
||||||
{
|
|
||||||
return (Studios ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string[] GetStudioIds()
|
|
||||||
{
|
|
||||||
return (StudioIds ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string[] GetPersonTypes()
|
|
||||||
{
|
|
||||||
return (PersonTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string[] GetPersonIds()
|
|
||||||
{
|
|
||||||
return (PersonIds ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string[] GetItemIds()
|
|
||||||
{
|
|
||||||
return (Ids ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
}
|
|
||||||
|
|
||||||
public VideoType[] GetVideoTypes()
|
|
||||||
{
|
|
||||||
var val = VideoTypes;
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(val))
|
|
||||||
{
|
|
||||||
return new VideoType[] { };
|
|
||||||
}
|
|
||||||
|
|
||||||
return val.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(v => (VideoType)Enum.Parse(typeof(VideoType), v, true)).ToArray();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -361,7 +117,16 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
if (!string.IsNullOrEmpty(request.Ids))
|
if (!string.IsNullOrEmpty(request.Ids))
|
||||||
{
|
{
|
||||||
request.Recursive = true;
|
request.Recursive = true;
|
||||||
var result = await ((Folder)item).GetItems(GetItemsQuery(request, user)).ConfigureAwait(false);
|
var query = GetItemsQuery(request, user);
|
||||||
|
var result = await ((Folder)item).GetItems(query).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(request.SortBy))
|
||||||
|
{
|
||||||
|
var ids = query.ItemIds.ToList();
|
||||||
|
|
||||||
|
// Try to preserve order
|
||||||
|
result.Items = result.Items.OrderBy(i => ids.IndexOf(i.Id.ToString("N"))).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
return new Tuple<QueryResult<BaseItem>, bool>(result, true);
|
return new Tuple<QueryResult<BaseItem>, bool>(result, true);
|
||||||
}
|
}
|
||||||
|
@ -99,11 +99,9 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
/// <param name="items">The items.</param>
|
/// <param name="items">The items.</param>
|
||||||
/// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
|
/// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
|
||||||
protected override IEnumerable<MusicGenre> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items)
|
protected override IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items)
|
||||||
{
|
{
|
||||||
var itemsList = items.ToList();
|
return items
|
||||||
|
|
||||||
return itemsList
|
|
||||||
.SelectMany(i => i.Genres)
|
.SelectMany(i => i.Genres)
|
||||||
.DistinctNames()
|
.DistinctNames()
|
||||||
.Select(name => LibraryManager.GetMusicGenre(name));
|
.Select(name => LibraryManager.GetMusicGenre(name));
|
||||||
|
@ -16,12 +16,6 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
[Route("/Persons", "GET", Summary = "Gets all persons from a given item, folder, or the entire library")]
|
[Route("/Persons", "GET", Summary = "Gets all persons from a given item, folder, or the entire library")]
|
||||||
public class GetPersons : GetItemsByName
|
public class GetPersons : GetItemsByName
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the person types.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The person types.</value>
|
|
||||||
[ApiMember(Name = "PersonTypes", Description = "Optional filter by person type. Accepts multiple, comma-delimited.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
|
||||||
public string PersonTypes { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -114,7 +108,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
/// <param name="items">The items.</param>
|
/// <param name="items">The items.</param>
|
||||||
/// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
|
/// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
|
||||||
protected override IEnumerable<Person> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items)
|
protected override IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items)
|
||||||
{
|
{
|
||||||
var inputPersonTypes = ((GetPersons)request).PersonTypes;
|
var inputPersonTypes = ((GetPersons)request).PersonTypes;
|
||||||
var personTypes = string.IsNullOrEmpty(inputPersonTypes) ? new string[] { } : inputPersonTypes.Split(',');
|
var personTypes = string.IsNullOrEmpty(inputPersonTypes) ? new string[] { } : inputPersonTypes.Split(',');
|
||||||
|
@ -185,6 +185,9 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
|
|
||||||
[ApiMember(Name = "PlaySessionId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
|
[ApiMember(Name = "PlaySessionId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
|
||||||
public string PlaySessionId { get; set; }
|
public string PlaySessionId { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "RepeatMode", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
|
||||||
|
public RepeatMode RepeatMode { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -325,7 +328,8 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
VolumeLevel = request.VolumeLevel,
|
VolumeLevel = request.VolumeLevel,
|
||||||
PlayMethod = request.PlayMethod,
|
PlayMethod = request.PlayMethod,
|
||||||
PlaySessionId = request.PlaySessionId,
|
PlaySessionId = request.PlaySessionId,
|
||||||
LiveStreamId = request.LiveStreamId
|
LiveStreamId = request.LiveStreamId,
|
||||||
|
RepeatMode = request.RepeatMode
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
/// <param name="items">The items.</param>
|
/// <param name="items">The items.</param>
|
||||||
/// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
|
/// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
|
||||||
protected override IEnumerable<Studio> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items)
|
protected override IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items)
|
||||||
{
|
{
|
||||||
var itemsList = items.Where(i => i.Studios != null).ToList();
|
var itemsList = items.Where(i => i.Studios != null).ToList();
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
var views = user.RootFolder
|
var views = user.RootFolder
|
||||||
.GetChildren(user, true)
|
.GetChildren(user, true)
|
||||||
.OfType<ICollectionFolder>()
|
.OfType<ICollectionFolder>()
|
||||||
.Where(i => IsEligibleForSpecialView(i))
|
.Where(IsEligibleForSpecialView)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var list = views
|
var list = views
|
||||||
|
@ -103,7 +103,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
/// <param name="items">The items.</param>
|
/// <param name="items">The items.</param>
|
||||||
/// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
|
/// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
|
||||||
protected override IEnumerable<Year> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items)
|
protected override IEnumerable<BaseItem> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items)
|
||||||
{
|
{
|
||||||
var itemsList = items.Where(i => i.ProductionYear != null).ToList();
|
var itemsList = items.Where(i => i.ProductionYear != null).ToList();
|
||||||
|
|
||||||
|
@ -68,6 +68,9 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
|
|
||||||
// http://stackoverflow.com/questions/566437/http-post-returns-the-error-417-expectation-failed-c
|
// http://stackoverflow.com/questions/566437/http-post-returns-the-error-417-expectation-failed-c
|
||||||
ServicePointManager.Expect100Continue = false;
|
ServicePointManager.Expect100Continue = false;
|
||||||
|
|
||||||
|
// Trakt requests sometimes fail without this
|
||||||
|
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -124,7 +127,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
|
|
||||||
private WebRequest GetRequest(HttpRequestOptions options, string method, bool enableHttpCompression)
|
private WebRequest GetRequest(HttpRequestOptions options, string method, bool enableHttpCompression)
|
||||||
{
|
{
|
||||||
var request = WebRequest.Create(options.Url);
|
var request = CreateWebRequest(options.Url);
|
||||||
var httpWebRequest = request as HttpWebRequest;
|
var httpWebRequest = request as HttpWebRequest;
|
||||||
|
|
||||||
if (httpWebRequest != null)
|
if (httpWebRequest != null)
|
||||||
@ -432,7 +435,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
|
|
||||||
var httpResponse = (HttpWebResponse)response;
|
var httpResponse = (HttpWebResponse)response;
|
||||||
|
|
||||||
EnsureSuccessStatusCode(httpResponse, options);
|
EnsureSuccessStatusCode(client, httpResponse, options);
|
||||||
|
|
||||||
options.CancellationToken.ThrowIfCancellationRequested();
|
options.CancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
@ -443,7 +446,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
{
|
{
|
||||||
var httpResponse = (HttpWebResponse)response;
|
var httpResponse = (HttpWebResponse)response;
|
||||||
|
|
||||||
EnsureSuccessStatusCode(httpResponse, options);
|
EnsureSuccessStatusCode(client, httpResponse, options);
|
||||||
|
|
||||||
options.CancellationToken.ThrowIfCancellationRequested();
|
options.CancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
@ -629,7 +632,8 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
{
|
{
|
||||||
var httpResponse = (HttpWebResponse)response;
|
var httpResponse = (HttpWebResponse)response;
|
||||||
|
|
||||||
EnsureSuccessStatusCode(httpResponse, options);
|
var client = GetHttpClient(GetHostFromUrl(options.Url), options.EnableHttpCompression);
|
||||||
|
EnsureSuccessStatusCode(client, httpResponse, options);
|
||||||
|
|
||||||
options.CancellationToken.ThrowIfCancellationRequested();
|
options.CancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
@ -803,13 +807,20 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
return exception;
|
return exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EnsureSuccessStatusCode(HttpWebResponse response, HttpRequestOptions options)
|
private void EnsureSuccessStatusCode(HttpClientInfo client, HttpWebResponse response, HttpRequestOptions options)
|
||||||
{
|
{
|
||||||
var statusCode = response.StatusCode;
|
var statusCode = response.StatusCode;
|
||||||
|
|
||||||
var isSuccessful = statusCode >= HttpStatusCode.OK && statusCode <= (HttpStatusCode)299;
|
var isSuccessful = statusCode >= HttpStatusCode.OK && statusCode <= (HttpStatusCode)299;
|
||||||
|
|
||||||
if (!isSuccessful)
|
if (!isSuccessful)
|
||||||
{
|
{
|
||||||
|
if ((int) statusCode == 429)
|
||||||
|
{
|
||||||
|
client.LastTimeout = DateTime.UtcNow;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (statusCode == HttpStatusCode.RequestEntityTooLarge)
|
||||||
if (options.LogErrorResponseBody)
|
if (options.LogErrorResponseBody)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -234,10 +234,10 @@ namespace MediaBrowser.Common.Implementations.IO
|
|||||||
{
|
{
|
||||||
if (_supportsAsyncFileStreams && isAsync)
|
if (_supportsAsyncFileStreams && isAsync)
|
||||||
{
|
{
|
||||||
return new FileStream(path, mode, access, share, 4096, true);
|
return new FileStream(path, mode, access, share, StreamDefaults.DefaultFileStreamBufferSize, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new FileStream(path, mode, access, share);
|
return new FileStream(path, mode, access, share, StreamDefaults.DefaultFileStreamBufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -312,7 +312,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
|
|||||||
|
|
||||||
trigger.Triggered -= trigger_Triggered;
|
trigger.Triggered -= trigger_Triggered;
|
||||||
trigger.Triggered += trigger_Triggered;
|
trigger.Triggered += trigger_Triggered;
|
||||||
trigger.Start(isApplicationStartup);
|
trigger.Start(LastExecutionResult, isApplicationStartup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -340,7 +340,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
|
|||||||
|
|
||||||
await Task.Delay(1000).ConfigureAwait(false);
|
await Task.Delay(1000).ConfigureAwait(false);
|
||||||
|
|
||||||
trigger.Start(false);
|
trigger.Start(LastExecutionResult, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task _currentTask;
|
private Task _currentTask;
|
||||||
|
@ -45,9 +45,6 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
|
|||||||
// Until we can vary these default triggers per server and MBT, we need something that makes sense for both
|
// Until we can vary these default triggers per server and MBT, we need something that makes sense for both
|
||||||
return new ITaskTrigger[] {
|
return new ITaskTrigger[] {
|
||||||
|
|
||||||
// At startup
|
|
||||||
new StartupTrigger {DelayMs = 60000},
|
|
||||||
|
|
||||||
// Every so often
|
// Every so often
|
||||||
new IntervalTrigger { Interval = TimeSpan.FromHours(24)}
|
new IntervalTrigger { Interval = TimeSpan.FromHours(24)}
|
||||||
};
|
};
|
||||||
|
@ -42,9 +42,6 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
|
|||||||
// Until we can vary these default triggers per server and MBT, we need something that makes sense for both
|
// Until we can vary these default triggers per server and MBT, we need something that makes sense for both
|
||||||
return new ITaskTrigger[] {
|
return new ITaskTrigger[] {
|
||||||
|
|
||||||
// At startup
|
|
||||||
new StartupTrigger {DelayMs = 30000},
|
|
||||||
|
|
||||||
// Every so often
|
// Every so often
|
||||||
new IntervalTrigger { Interval = TimeSpan.FromHours(24)}
|
new IntervalTrigger { Interval = TimeSpan.FromHours(24)}
|
||||||
};
|
};
|
||||||
|
@ -61,7 +61,7 @@ namespace MediaBrowser.Common.Implementations.Serialization
|
|||||||
|
|
||||||
private Stream OpenFile(string path)
|
private Stream OpenFile(string path)
|
||||||
{
|
{
|
||||||
return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
|
return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 131072);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -149,10 +149,12 @@ namespace MediaBrowser.Common.Implementations.Updates
|
|||||||
/// Gets all available packages.
|
/// Gets all available packages.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="withRegistration">if set to <c>true</c> [with registration].</param>
|
||||||
/// <param name="packageType">Type of the package.</param>
|
/// <param name="packageType">Type of the package.</param>
|
||||||
/// <param name="applicationVersion">The application version.</param>
|
/// <param name="applicationVersion">The application version.</param>
|
||||||
/// <returns>Task{List{PackageInfo}}.</returns>
|
/// <returns>Task{List{PackageInfo}}.</returns>
|
||||||
public async Task<IEnumerable<PackageInfo>> GetAvailablePackages(CancellationToken cancellationToken,
|
public async Task<IEnumerable<PackageInfo>> GetAvailablePackages(CancellationToken cancellationToken,
|
||||||
|
bool withRegistration = true,
|
||||||
PackageType? packageType = null,
|
PackageType? packageType = null,
|
||||||
Version applicationVersion = null)
|
Version applicationVersion = null)
|
||||||
{
|
{
|
||||||
@ -163,13 +165,22 @@ namespace MediaBrowser.Common.Implementations.Updates
|
|||||||
{ "systemid", _applicationHost.SystemId }
|
{ "systemid", _applicationHost.SystemId }
|
||||||
};
|
};
|
||||||
|
|
||||||
using (var json = await _httpClient.Post(MbAdmin.HttpsUrl + "service/package/retrieveall", data, cancellationToken).ConfigureAwait(false))
|
if (withRegistration)
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
using (var json = await _httpClient.Post(MbAdmin.HttpsUrl + "service/package/retrieveall", data, cancellationToken).ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
var packages = _jsonSerializer.DeserializeFromStream<List<PackageInfo>>(json).ToList();
|
var packages = _jsonSerializer.DeserializeFromStream<List<PackageInfo>>(json).ToList();
|
||||||
|
|
||||||
return FilterPackages(packages, packageType, applicationVersion);
|
return FilterPackages(packages, packageType, applicationVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var packages = await GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return FilterPackages(packages.ToList(), packageType, applicationVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,11 +9,11 @@ namespace MediaBrowser.Common.IO
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The default copy to buffer size
|
/// The default copy to buffer size
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const int DefaultCopyToBufferSize = 81920;
|
public const int DefaultCopyToBufferSize = 262144;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The default file stream buffer size
|
/// The default file stream buffer size
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const int DefaultFileStreamBufferSize = 4096;
|
public const int DefaultFileStreamBufferSize = 262144;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using MediaBrowser.Model.Events;
|
||||||
|
using MediaBrowser.Model.Tasks;
|
||||||
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Common.ScheduledTasks
|
namespace MediaBrowser.Common.ScheduledTasks
|
||||||
{
|
{
|
||||||
@ -32,8 +33,9 @@ namespace MediaBrowser.Common.ScheduledTasks
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stars waiting for the trigger action
|
/// Stars waiting for the trigger action
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="lastResult">The last result.</param>
|
||||||
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
||||||
public void Start(bool isApplicationStartup)
|
public void Start(TaskResult lastResult, bool isApplicationStartup)
|
||||||
{
|
{
|
||||||
DisposeTimer();
|
DisposeTimer();
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using MediaBrowser.Model.Events;
|
||||||
using MediaBrowser.Model.Events;
|
using MediaBrowser.Model.Tasks;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace MediaBrowser.Common.ScheduledTasks
|
namespace MediaBrowser.Common.ScheduledTasks
|
||||||
{
|
{
|
||||||
@ -16,8 +17,9 @@ namespace MediaBrowser.Common.ScheduledTasks
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stars waiting for the trigger action
|
/// Stars waiting for the trigger action
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="lastResult">The last result.</param>
|
||||||
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
||||||
void Start(bool isApplicationStartup);
|
void Start(TaskResult lastResult, bool isApplicationStartup);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stops waiting for the trigger action
|
/// Stops waiting for the trigger action
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using MediaBrowser.Model.Events;
|
||||||
|
using MediaBrowser.Model.Tasks;
|
||||||
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Common.ScheduledTasks
|
namespace MediaBrowser.Common.ScheduledTasks
|
||||||
{
|
{
|
||||||
@ -29,15 +30,43 @@ namespace MediaBrowser.Common.ScheduledTasks
|
|||||||
/// </value>
|
/// </value>
|
||||||
public TaskExecutionOptions TaskOptions { get; set; }
|
public TaskExecutionOptions TaskOptions { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the first run delay.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The first run delay.</value>
|
||||||
|
public TimeSpan FirstRunDelay { get; set; }
|
||||||
|
|
||||||
|
public IntervalTrigger()
|
||||||
|
{
|
||||||
|
FirstRunDelay = TimeSpan.FromHours(1);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stars waiting for the trigger action
|
/// Stars waiting for the trigger action
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="lastResult">The last result.</param>
|
||||||
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
||||||
public void Start(bool isApplicationStartup)
|
public void Start(TaskResult lastResult, bool isApplicationStartup)
|
||||||
{
|
{
|
||||||
DisposeTimer();
|
DisposeTimer();
|
||||||
|
|
||||||
Timer = new Timer(state => OnTriggered(), null, Interval, TimeSpan.FromMilliseconds(-1));
|
var triggerDate = lastResult != null ?
|
||||||
|
lastResult.EndTimeUtc.Add(Interval) :
|
||||||
|
DateTime.UtcNow.Add(FirstRunDelay);
|
||||||
|
|
||||||
|
if (DateTime.UtcNow > triggerDate)
|
||||||
|
{
|
||||||
|
if (isApplicationStartup)
|
||||||
|
{
|
||||||
|
triggerDate = DateTime.UtcNow.AddMinutes(5);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
triggerDate = DateTime.UtcNow.Add(Interval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer = new Timer(state => OnTriggered(), null, triggerDate - DateTime.UtcNow, TimeSpan.FromMilliseconds(-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using MediaBrowser.Model.Events;
|
||||||
|
using MediaBrowser.Model.Tasks;
|
||||||
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Common.ScheduledTasks
|
namespace MediaBrowser.Common.ScheduledTasks
|
||||||
{
|
{
|
||||||
@ -27,8 +28,9 @@ namespace MediaBrowser.Common.ScheduledTasks
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stars waiting for the trigger action
|
/// Stars waiting for the trigger action
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="lastResult">The last result.</param>
|
||||||
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
||||||
public async void Start(bool isApplicationStartup)
|
public async void Start(TaskResult lastResult, bool isApplicationStartup)
|
||||||
{
|
{
|
||||||
if (isApplicationStartup)
|
if (isApplicationStartup)
|
||||||
{
|
{
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
using MediaBrowser.Model.Tasks;
|
using MediaBrowser.Model.Events;
|
||||||
|
using MediaBrowser.Model.Tasks;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Common.ScheduledTasks
|
namespace MediaBrowser.Common.ScheduledTasks
|
||||||
{
|
{
|
||||||
@ -28,8 +28,9 @@ namespace MediaBrowser.Common.ScheduledTasks
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stars waiting for the trigger action
|
/// Stars waiting for the trigger action
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="lastResult">The last result.</param>
|
||||||
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
||||||
public void Start(bool isApplicationStartup)
|
public void Start(TaskResult lastResult, bool isApplicationStartup)
|
||||||
{
|
{
|
||||||
switch (SystemEvent)
|
switch (SystemEvent)
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using MediaBrowser.Model.Events;
|
using MediaBrowser.Model.Events;
|
||||||
|
using MediaBrowser.Model.Tasks;
|
||||||
|
|
||||||
namespace MediaBrowser.Common.ScheduledTasks
|
namespace MediaBrowser.Common.ScheduledTasks
|
||||||
{
|
{
|
||||||
@ -38,8 +39,9 @@ namespace MediaBrowser.Common.ScheduledTasks
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stars waiting for the trigger action
|
/// Stars waiting for the trigger action
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="lastResult">The last result.</param>
|
||||||
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
||||||
public void Start(bool isApplicationStartup)
|
public void Start(TaskResult lastResult, bool isApplicationStartup)
|
||||||
{
|
{
|
||||||
DisposeTimer();
|
DisposeTimer();
|
||||||
|
|
||||||
|
@ -45,10 +45,12 @@ namespace MediaBrowser.Common.Updates
|
|||||||
/// Gets all available packages.
|
/// Gets all available packages.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="withRegistration">if set to <c>true</c> [with registration].</param>
|
||||||
/// <param name="packageType">Type of the package.</param>
|
/// <param name="packageType">Type of the package.</param>
|
||||||
/// <param name="applicationVersion">The application version.</param>
|
/// <param name="applicationVersion">The application version.</param>
|
||||||
/// <returns>Task{List{PackageInfo}}.</returns>
|
/// <returns>Task{List{PackageInfo}}.</returns>
|
||||||
Task<IEnumerable<PackageInfo>> GetAvailablePackages(CancellationToken cancellationToken,
|
Task<IEnumerable<PackageInfo>> GetAvailablePackages(CancellationToken cancellationToken,
|
||||||
|
bool withRegistration = true,
|
||||||
PackageType? packageType = null,
|
PackageType? packageType = null,
|
||||||
Version applicationVersion = null);
|
Version applicationVersion = null);
|
||||||
|
|
||||||
|
@ -121,10 +121,9 @@ namespace MediaBrowser.Controller.Channels
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the channel folder.
|
/// Gets the channel folder.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="userId">The user identifier.</param>
|
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>BaseItemDto.</returns>
|
/// <returns>BaseItemDto.</returns>
|
||||||
Task<Folder> GetInternalChannelFolder(string userId, CancellationToken cancellationToken);
|
Task<Folder> GetInternalChannelFolder(CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the channel folder.
|
/// Gets the channel folder.
|
||||||
|
10
MediaBrowser.Controller/Dlna/IDeviceDiscovery.cs
Normal file
10
MediaBrowser.Controller/Dlna/IDeviceDiscovery.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.Dlna
|
||||||
|
{
|
||||||
|
public interface IDeviceDiscovery
|
||||||
|
{
|
||||||
|
event EventHandler<SsdpMessageEventArgs> DeviceDiscovered;
|
||||||
|
event EventHandler<SsdpMessageEventArgs> DeviceLeft;
|
||||||
|
}
|
||||||
|
}
|
@ -81,13 +81,11 @@ namespace MediaBrowser.Controller.Dto
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the item by name dto.
|
/// Gets the item by name dto.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T"></typeparam>
|
|
||||||
/// <param name="item">The item.</param>
|
/// <param name="item">The item.</param>
|
||||||
/// <param name="options">The options.</param>
|
/// <param name="options">The options.</param>
|
||||||
/// <param name="taggedItems">The tagged items.</param>
|
/// <param name="taggedItems">The tagged items.</param>
|
||||||
/// <param name="user">The user.</param>
|
/// <param name="user">The user.</param>
|
||||||
/// <returns>BaseItemDto.</returns>
|
/// <returns>BaseItemDto.</returns>
|
||||||
BaseItemDto GetItemByNameDto<T>(T item, DtoOptions options, List<BaseItem> taggedItems, User user = null)
|
BaseItemDto GetItemByNameDto(BaseItem item, DtoOptions options, List<BaseItem> taggedItems, User user = null);
|
||||||
where T : BaseItem, IItemByName;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,12 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
get { return AlbumArtists.FirstOrDefault(); }
|
get { return AlbumArtists.FirstOrDefault(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override bool SupportsPeople
|
||||||
|
{
|
||||||
|
get { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
public List<string> AlbumArtists { get; set; }
|
public List<string> AlbumArtists { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -142,7 +142,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
public virtual string Path { get; set; }
|
public virtual string Path { get; set; }
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
protected internal bool IsOffline { get; set; }
|
public bool IsOffline { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the folder containing the item.
|
/// Returns the folder containing the item.
|
||||||
@ -419,6 +419,10 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
return _sortName ?? (_sortName = CreateSortName());
|
return _sortName ?? (_sortName = CreateSortName());
|
||||||
}
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_sortName = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetInternalMetadataPath()
|
public string GetInternalMetadataPath()
|
||||||
@ -485,6 +489,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// Gets or sets the parent.
|
/// Gets or sets the parent.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The parent.</value>
|
/// <value>The parent.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
public Folder Parent
|
public Folder Parent
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -1115,6 +1120,23 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return value.Value <= maxAllowedRating.Value;
|
return value.Value <= maxAllowedRating.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int? GetParentalRatingValue()
|
||||||
|
{
|
||||||
|
var rating = CustomRatingForComparison;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(rating))
|
||||||
|
{
|
||||||
|
rating = OfficialRatingForComparison;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(rating))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LocalizationManager.GetRatingLevel(rating);
|
||||||
|
}
|
||||||
|
|
||||||
private bool IsVisibleViaTags(User user)
|
private bool IsVisibleViaTags(User user)
|
||||||
{
|
{
|
||||||
var hasTags = this as IHasTags;
|
var hasTags = this as IHasTags;
|
||||||
|
@ -35,6 +35,15 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
protected override bool SupportsShortcutChildren
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override bool CanDelete()
|
public override bool CanDelete()
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
using MediaBrowser.Common.Progress;
|
using MediaBrowser.Common.Progress;
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Localization;
|
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
@ -14,7 +13,6 @@ 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.Users;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
@ -50,7 +48,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public virtual bool IsPreSorted
|
public virtual bool IsPreSorted
|
||||||
{
|
{
|
||||||
get { return false; }
|
get { return ConfigurationManager.Configuration.EnableWindowsShortcuts; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -122,7 +120,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
protected virtual bool SupportsShortcutChildren
|
protected virtual bool SupportsShortcutChildren
|
||||||
{
|
{
|
||||||
get { return true; }
|
get { return false; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -176,7 +174,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
protected void AddChildInternal(BaseItem child)
|
protected void AddChildInternal(BaseItem child)
|
||||||
{
|
{
|
||||||
var actualChildren = ActualChildren;
|
var actualChildren = ActualChildren;
|
||||||
|
|
||||||
lock (_childrenSyncLock)
|
lock (_childrenSyncLock)
|
||||||
{
|
{
|
||||||
var newChildren = actualChildren.ToList();
|
var newChildren = actualChildren.ToList();
|
||||||
@ -1070,7 +1068,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
var changesFound = false;
|
var changesFound = false;
|
||||||
|
|
||||||
if (SupportsShortcutChildren && LocationType == LocationType.FileSystem)
|
if (LocationType == LocationType.FileSystem)
|
||||||
{
|
{
|
||||||
if (RefreshLinkedChildren(fileSystemChildren))
|
if (RefreshLinkedChildren(fileSystemChildren))
|
||||||
{
|
{
|
||||||
@ -1092,37 +1090,43 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
var currentManualLinks = LinkedChildren.Where(i => i.Type == LinkedChildType.Manual).ToList();
|
var currentManualLinks = LinkedChildren.Where(i => i.Type == LinkedChildType.Manual).ToList();
|
||||||
var currentShortcutLinks = LinkedChildren.Where(i => i.Type == LinkedChildType.Shortcut).ToList();
|
var currentShortcutLinks = LinkedChildren.Where(i => i.Type == LinkedChildType.Shortcut).ToList();
|
||||||
|
|
||||||
var newShortcutLinks = fileSystemChildren
|
List<LinkedChild> newShortcutLinks;
|
||||||
.Where(i => (i.Attributes & FileAttributes.Directory) != FileAttributes.Directory && FileSystem.IsShortcut(i.FullName))
|
|
||||||
.Select(i =>
|
if (SupportsShortcutChildren)
|
||||||
{
|
{
|
||||||
try
|
newShortcutLinks = fileSystemChildren
|
||||||
|
.Where(i => (i.Attributes & FileAttributes.Directory) != FileAttributes.Directory && FileSystem.IsShortcut(i.FullName))
|
||||||
|
.Select(i =>
|
||||||
{
|
{
|
||||||
Logger.Debug("Found shortcut at {0}", i.FullName);
|
try
|
||||||
|
|
||||||
var resolvedPath = FileSystem.ResolveShortcut(i.FullName);
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(resolvedPath))
|
|
||||||
{
|
{
|
||||||
return new LinkedChild
|
Logger.Debug("Found shortcut at {0}", i.FullName);
|
||||||
|
|
||||||
|
var resolvedPath = FileSystem.ResolveShortcut(i.FullName);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(resolvedPath))
|
||||||
{
|
{
|
||||||
Path = resolvedPath,
|
return new LinkedChild
|
||||||
Type = LinkedChildType.Shortcut
|
{
|
||||||
};
|
Path = resolvedPath,
|
||||||
|
Type = LinkedChildType.Shortcut
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.Error("Error resolving shortcut {0}", i.FullName);
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
catch (IOException ex)
|
||||||
Logger.Error("Error resolving shortcut {0}", i.FullName);
|
{
|
||||||
|
Logger.ErrorException("Error resolving shortcut {0}", ex, i.FullName);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
catch (IOException ex)
|
})
|
||||||
{
|
.Where(i => i != null)
|
||||||
Logger.ErrorException("Error resolving shortcut {0}", ex, i.FullName);
|
.ToList();
|
||||||
return null;
|
}
|
||||||
}
|
else { newShortcutLinks = new List<LinkedChild>(); }
|
||||||
})
|
|
||||||
.Where(i => i != null)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
if (!newShortcutLinks.SequenceEqual(currentShortcutLinks, new LinkedChildComparer()))
|
if (!newShortcutLinks.SequenceEqual(currentShortcutLinks, new LinkedChildComparer()))
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
@ -14,4 +15,17 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
Guid Id { get; }
|
Guid Id { get; }
|
||||||
IEnumerable<string> PhysicalLocations { get; }
|
IEnumerable<string> PhysicalLocations { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class CollectionFolderExtensions
|
||||||
|
{
|
||||||
|
public static string GetViewType(this ICollectionFolder folder, User user)
|
||||||
|
{
|
||||||
|
if (user.Configuration.PlainFolderViews.Contains(folder.Id.ToString("N"), StringComparer.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return folder.CollectionType;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
bool IsKids { get; set; }
|
bool IsKids { get; set; }
|
||||||
bool IsRepeat { get; set; }
|
bool IsRepeat { get; set; }
|
||||||
bool? IsHD { get; set; }
|
bool? IsHD { get; set; }
|
||||||
|
bool IsSeries { get; set; }
|
||||||
bool IsLive { get; set; }
|
bool IsLive { get; set; }
|
||||||
bool IsPremiere { get; set; }
|
bool IsPremiere { get; set; }
|
||||||
ProgramAudio? Audio { get; set; }
|
ProgramAudio? Audio { get; set; }
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
using System.Collections.Generic;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Entities;
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
@ -40,6 +40,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
public string NameStartsWithOrGreater { get; set; }
|
public string NameStartsWithOrGreater { get; set; }
|
||||||
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 Person { get; set; }
|
public string Person { get; set; }
|
||||||
public string[] PersonIds { get; set; }
|
public string[] PersonIds { get; set; }
|
||||||
@ -93,7 +94,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
public string[] ChannelIds { get; set; }
|
public string[] ChannelIds { get; set; }
|
||||||
|
|
||||||
internal List<Guid> ItemIdsFromPersonFilters { get; set; }
|
internal List<Guid> ItemIdsFromPersonFilters { get; set; }
|
||||||
|
public int? MaxParentalRating { get; set; }
|
||||||
|
|
||||||
|
public bool? IsCurrentSchema { get; set; }
|
||||||
|
public bool? HasDeadParentId { get; set; }
|
||||||
|
|
||||||
public InternalItemsQuery()
|
public InternalItemsQuery()
|
||||||
{
|
{
|
||||||
Tags = new string[] { };
|
Tags = new string[] { };
|
||||||
|
@ -74,6 +74,15 @@ namespace MediaBrowser.Controller.Entities.Movies
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
protected override bool SupportsShortcutChildren
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override bool IsAuthorizedToDelete(User user)
|
public override bool IsAuthorizedToDelete(User user)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
@ -100,12 +100,7 @@ namespace MediaBrowser.Controller.Entities.Movies
|
|||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
protected override string CreateUserDataKey()
|
protected override string CreateUserDataKey()
|
||||||
{
|
{
|
||||||
var key = this.GetProviderId(MetadataProviders.Tmdb);
|
var key = GetMovieUserDataKey(this);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(key))
|
|
||||||
{
|
|
||||||
key = this.GetProviderId(MetadataProviders.Imdb);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(key))
|
if (string.IsNullOrWhiteSpace(key))
|
||||||
{
|
{
|
||||||
@ -115,6 +110,18 @@ namespace MediaBrowser.Controller.Entities.Movies
|
|||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string GetMovieUserDataKey(BaseItem movie)
|
||||||
|
{
|
||||||
|
var key = movie.GetProviderId(MetadataProviders.Tmdb);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(key))
|
||||||
|
{
|
||||||
|
key = movie.GetProviderId(MetadataProviders.Imdb);
|
||||||
|
}
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemInfo> fileSystemChildren, CancellationToken cancellationToken)
|
protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemInfo> fileSystemChildren, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var hasChanges = await base.RefreshedOwnedItems(options, fileSystemChildren, cancellationToken).ConfigureAwait(false);
|
var hasChanges = await base.RefreshedOwnedItems(options, fileSystemChildren, cancellationToken).ConfigureAwait(false);
|
||||||
|
@ -150,7 +150,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
{
|
{
|
||||||
var series = Series;
|
var series = Series;
|
||||||
|
|
||||||
if (ParentIndexNumber.HasValue)
|
if (series != null && ParentIndexNumber.HasValue)
|
||||||
{
|
{
|
||||||
var findNumber = ParentIndexNumber.Value;
|
var findNumber = ParentIndexNumber.Value;
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using MediaBrowser.Controller.Providers;
|
using System.Runtime.Serialization;
|
||||||
|
using MediaBrowser.Controller.Providers;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Library;
|
using MediaBrowser.Model.Library;
|
||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Querying;
|
||||||
@ -36,6 +37,16 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return PostFilterAndSort(result.Where(filter), query);
|
return PostFilterAndSort(result.Where(filter), query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
protected override bool SupportsShortcutChildren
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
public override bool IsPreSorted
|
public override bool IsPreSorted
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
using System.Runtime.Serialization;
|
using MediaBrowser.Controller.Playlists;
|
||||||
using MediaBrowser.Controller.Playlists;
|
|
||||||
using MediaBrowser.Controller.TV;
|
using MediaBrowser.Controller.TV;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Querying;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
@ -15,7 +15,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
public Guid ParentId { get; set; }
|
public Guid ParentId { get; set; }
|
||||||
|
|
||||||
public Guid? UserId { get; set; }
|
public Guid? UserId { get; set; }
|
||||||
|
|
||||||
public static ITVSeriesManager TVSeriesManager;
|
public static ITVSeriesManager TVSeriesManager;
|
||||||
public static IPlaylistManager PlaylistManager;
|
public static IPlaylistManager PlaylistManager;
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
var result = await _channelManager.GetChannelsInternal(new ChannelQuery
|
var result = await _channelManager.GetChannelsInternal(new ChannelQuery
|
||||||
{
|
{
|
||||||
UserId = user.Id.ToString("N"),
|
UserId = user == null ? null : user.Id.ToString("N"),
|
||||||
Limit = query.Limit,
|
Limit = query.Limit,
|
||||||
StartIndex = query.StartIndex
|
StartIndex = query.StartIndex
|
||||||
|
|
||||||
@ -264,10 +264,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
private async Task<QueryResult<BaseItem>> FindPlaylists(Folder parent, User user, InternalItemsQuery query)
|
private async Task<QueryResult<BaseItem>> FindPlaylists(Folder parent, User user, InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
var collectionFolders = user.RootFolder.GetChildren(user, true).Select(i => i.Id).ToList();
|
var list = _playlistManager.GetPlaylists(user.Id.ToString("N"));
|
||||||
|
|
||||||
var list = _playlistManager.GetPlaylists(user.Id.ToString("N"))
|
|
||||||
.Where(i => i.GetChildren(user, true).Any(media => _libraryManager.GetCollectionFolders(media).Select(c => c.Id).Any(collectionFolders.Contains)));
|
|
||||||
|
|
||||||
return GetResult(list, parent, query);
|
return GetResult(list, parent, query);
|
||||||
}
|
}
|
||||||
@ -288,14 +285,14 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
var list = new List<BaseItem>();
|
var list = new List<BaseItem>();
|
||||||
|
|
||||||
list.Add(await GetUserView(SpecialFolder.MusicLatest, user, "0", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.MusicLatest, "0", parent).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.MusicPlaylists, user, "1", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.MusicPlaylists, "1", parent).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.MusicAlbums, user, "2", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.MusicAlbums, "2", parent).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.MusicAlbumArtists, user, "3", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.MusicAlbumArtists, "3", parent).ConfigureAwait(false));
|
||||||
//list.Add(await GetUserView(SpecialFolder.MusicArtists, user, "4", parent).ConfigureAwait(false));
|
//list.Add(await GetUserView(SpecialFolder.MusicArtists, user, "4", parent).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.MusicSongs, user, "5", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.MusicSongs, "5", parent).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.MusicGenres, user, "6", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.MusicGenres, "6", parent).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.MusicFavorites, user, "7", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.MusicFavorites, "7", parent).ConfigureAwait(false));
|
||||||
|
|
||||||
return GetResult(list, parent, query);
|
return GetResult(list, parent, query);
|
||||||
}
|
}
|
||||||
@ -304,9 +301,9 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
var list = new List<BaseItem>();
|
var list = new List<BaseItem>();
|
||||||
|
|
||||||
list.Add(await GetUserView(SpecialFolder.MusicFavoriteAlbums, user, "0", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.MusicFavoriteAlbums, "0", parent).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.MusicFavoriteArtists, user, "1", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.MusicFavoriteArtists, "1", parent).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.MusicFavoriteSongs, user, "2", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.MusicFavoriteSongs, "2", parent).ConfigureAwait(false));
|
||||||
|
|
||||||
return GetResult(list, parent, query);
|
return GetResult(list, parent, query);
|
||||||
}
|
}
|
||||||
@ -332,7 +329,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
})
|
})
|
||||||
.Where(i => i != null)
|
.Where(i => i != null)
|
||||||
.Select(i => GetUserView(i.Name, SpecialFolder.MusicGenre, user, i.SortName, parent));
|
.Select(i => GetUserView(i.Name, SpecialFolder.MusicGenre, i.SortName, parent));
|
||||||
|
|
||||||
var genres = await Task.WhenAll(tasks).ConfigureAwait(false);
|
var genres = await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||||
|
|
||||||
@ -344,94 +341,42 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
var items = GetRecursiveChildren(queryParent, user, new[] { CollectionType.Music, CollectionType.MusicVideos })
|
var items = GetRecursiveChildren(queryParent, user, new[] { CollectionType.Music, CollectionType.MusicVideos })
|
||||||
.Where(i => !i.IsFolder)
|
.Where(i => !i.IsFolder)
|
||||||
.Where(i => i.Genres.Contains(displayParent.Name, StringComparer.OrdinalIgnoreCase))
|
.Where(i => i.Genres.Contains(displayParent.Name, StringComparer.OrdinalIgnoreCase))
|
||||||
.OfType<IHasAlbumArtist>()
|
.OfType<IHasAlbumArtist>();
|
||||||
.SelectMany(i => i.AlbumArtists)
|
|
||||||
.DistinctNames()
|
|
||||||
.Select(i =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return _libraryManager.GetArtist(i);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// Already logged at lower levels
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.Where(i => i != null);
|
|
||||||
|
|
||||||
return GetResult(items, queryParent, query);
|
var artists = _libraryManager.GetAlbumArtists(items);
|
||||||
|
|
||||||
|
return GetResult(artists, queryParent, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
private QueryResult<BaseItem> GetMusicAlbumArtists(Folder parent, User user, InternalItemsQuery query)
|
private QueryResult<BaseItem> GetMusicAlbumArtists(Folder parent, User user, InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
var artists = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos })
|
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos })
|
||||||
.Where(i => !i.IsFolder)
|
.Where(i => !i.IsFolder)
|
||||||
.OfType<IHasAlbumArtist>()
|
.OfType<IHasAlbumArtist>();
|
||||||
.SelectMany(i => i.AlbumArtists)
|
|
||||||
.DistinctNames()
|
var artists = _libraryManager.GetAlbumArtists(items);
|
||||||
.Select(i =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return _libraryManager.GetArtist(i);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// Already logged at lower levels
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.Where(i => i != null);
|
|
||||||
|
|
||||||
return GetResult(artists, parent, query);
|
return GetResult(artists, parent, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
private QueryResult<BaseItem> GetMusicArtists(Folder parent, User user, InternalItemsQuery query)
|
private QueryResult<BaseItem> GetMusicArtists(Folder parent, User user, InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
var artists = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos })
|
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos })
|
||||||
.Where(i => !i.IsFolder)
|
.Where(i => !i.IsFolder)
|
||||||
.OfType<IHasArtist>()
|
.OfType<IHasArtist>();
|
||||||
.SelectMany(i => i.Artists)
|
|
||||||
.DistinctNames()
|
var artists = _libraryManager.GetArtists(items);
|
||||||
.Select(i =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return _libraryManager.GetArtist(i);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// Already logged at lower levels
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.Where(i => i != null);
|
|
||||||
|
|
||||||
return GetResult(artists, parent, query);
|
return GetResult(artists, parent, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
private QueryResult<BaseItem> GetFavoriteArtists(Folder parent, User user, InternalItemsQuery query)
|
private QueryResult<BaseItem> GetFavoriteArtists(Folder parent, User user, InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
var artists = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos })
|
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos })
|
||||||
.Where(i => !i.IsFolder)
|
.Where(i => !i.IsFolder)
|
||||||
.OfType<IHasAlbumArtist>()
|
.OfType<IHasAlbumArtist>();
|
||||||
.SelectMany(i => i.AlbumArtists)
|
|
||||||
.DistinctNames()
|
var artists = _libraryManager.GetAlbumArtists(items).Where(i => _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).IsFavorite);
|
||||||
.Select(i =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return _libraryManager.GetArtist(i);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// Already logged at lower levels
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.Where(i => i != null && _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).IsFavorite);
|
|
||||||
|
|
||||||
return GetResult(artists, parent, query);
|
return GetResult(artists, parent, query);
|
||||||
}
|
}
|
||||||
@ -498,12 +443,12 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
var list = new List<BaseItem>();
|
var list = new List<BaseItem>();
|
||||||
|
|
||||||
list.Add(await GetUserView(SpecialFolder.MovieResume, user, "0", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.MovieResume, "0", parent).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.MovieLatest, user, "1", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.MovieLatest, "1", parent).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.MovieMovies, user, "2", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.MovieMovies, "2", parent).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.MovieCollections, user, "3", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.MovieCollections, "3", parent).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.MovieFavorites, user, "4", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.MovieFavorites, "4", parent).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.MovieGenres, user, "5", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.MovieGenres, "5", parent).ConfigureAwait(false));
|
||||||
|
|
||||||
return GetResult(list, parent, query);
|
return GetResult(list, parent, query);
|
||||||
}
|
}
|
||||||
@ -609,7 +554,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
})
|
})
|
||||||
.Where(i => i != null)
|
.Where(i => i != null)
|
||||||
.Select(i => GetUserView(i.Name, SpecialFolder.MovieGenre, user, i.SortName, parent));
|
.Select(i => GetUserView(i.Name, SpecialFolder.MovieGenre, i.SortName, parent));
|
||||||
|
|
||||||
var genres = await Task.WhenAll(tasks).ConfigureAwait(false);
|
var genres = await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||||
|
|
||||||
@ -671,13 +616,13 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
var list = new List<BaseItem>();
|
var list = new List<BaseItem>();
|
||||||
|
|
||||||
list.Add(await GetUserView(SpecialFolder.TvResume, user, "0", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.TvResume, "0", parent).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.TvNextUp, user, "1", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.TvNextUp, "1", parent).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.TvLatest, user, "2", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.TvLatest, "2", parent).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.TvShowSeries, user, "3", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.TvShowSeries, "3", parent).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.TvFavoriteSeries, user, "4", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.TvFavoriteSeries, "4", parent).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.TvFavoriteEpisodes, user, "5", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.TvFavoriteEpisodes, "5", parent).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.TvGenres, user, "6", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.TvGenres, "6", parent).ConfigureAwait(false));
|
||||||
|
|
||||||
return GetResult(list, parent, query);
|
return GetResult(list, parent, query);
|
||||||
}
|
}
|
||||||
@ -692,11 +637,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
var list = new List<BaseItem>();
|
var list = new List<BaseItem>();
|
||||||
|
|
||||||
list.Add(await GetUserView(SpecialFolder.LatestGames, user, "0", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.LatestGames, "0", parent).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.RecentlyPlayedGames, user, "1", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.RecentlyPlayedGames, "1", parent).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.GameFavorites, user, "2", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.GameFavorites, "2", parent).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.GameSystems, user, "3", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.GameSystems, "3", parent).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.GameGenres, user, "4", parent).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.GameGenres, "4", parent).ConfigureAwait(false));
|
||||||
|
|
||||||
return GetResult(list, parent, query);
|
return GetResult(list, parent, query);
|
||||||
}
|
}
|
||||||
@ -794,7 +739,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
})
|
})
|
||||||
.Where(i => i != null)
|
.Where(i => i != null)
|
||||||
.Select(i => GetUserView(i.Name, SpecialFolder.TvGenre, user, i.SortName, parent));
|
.Select(i => GetUserView(i.Name, SpecialFolder.TvGenre, i.SortName, parent));
|
||||||
|
|
||||||
var genres = await Task.WhenAll(tasks).ConfigureAwait(false);
|
var genres = await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||||
|
|
||||||
@ -846,7 +791,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
})
|
})
|
||||||
.Where(i => i != null)
|
.Where(i => i != null)
|
||||||
.Select(i => GetUserView(i.Name, SpecialFolder.GameGenre, user, i.SortName, parent));
|
.Select(i => GetUserView(i.Name, SpecialFolder.GameGenre, i.SortName, parent));
|
||||||
|
|
||||||
var genres = await Task.WhenAll(tasks).ConfigureAwait(false);
|
var genres = await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||||
|
|
||||||
@ -1926,26 +1871,20 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
var list = new List<BaseItem>();
|
var list = new List<BaseItem>();
|
||||||
|
|
||||||
//list.Add(await GetUserSubView(SpecialFolder.LiveTvNowPlaying, user, "0", parent).ConfigureAwait(false));
|
//list.Add(await GetUserSubView(SpecialFolder.LiveTvNowPlaying, user, "0", parent).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.LiveTvChannels, user, string.Empty, user.RootFolder).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.LiveTvChannels, string.Empty, user.RootFolder).ConfigureAwait(false));
|
||||||
list.Add(await GetUserView(SpecialFolder.LiveTvRecordingGroups, user, string.Empty, user.RootFolder).ConfigureAwait(false));
|
list.Add(await GetUserView(SpecialFolder.LiveTvRecordingGroups, string.Empty, user.RootFolder).ConfigureAwait(false));
|
||||||
|
|
||||||
return GetResult(list, queryParent, query);
|
return GetResult(list, queryParent, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<UserView> GetUserView(string name, string type, User user, string sortName, BaseItem parent)
|
private Task<UserView> GetUserView(string name, string type, string sortName, BaseItem parent)
|
||||||
{
|
{
|
||||||
var view = await _userViewManager.GetUserSubView(name, parent.Id.ToString("N"), type, user, sortName, CancellationToken.None)
|
return _userViewManager.GetUserSubView(name, parent.Id.ToString("N"), type, sortName, CancellationToken.None);
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
return view;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<UserView> GetUserView(string type, User user, string sortName, BaseItem parent)
|
private Task<UserView> GetUserView(string type, string sortName, BaseItem parent)
|
||||||
{
|
{
|
||||||
var view = await _userViewManager.GetUserSubView(parent.Id.ToString("N"), type, user, sortName, CancellationToken.None)
|
return _userViewManager.GetUserSubView(parent.Id.ToString("N"), type, sortName, CancellationToken.None);
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
return view;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsYearMismatched(BaseItem item, ILibraryManager libraryManager)
|
public static bool IsYearMismatched(BaseItem item, ILibraryManager libraryManager)
|
||||||
|
@ -5,12 +5,12 @@ using MediaBrowser.Controller.Providers;
|
|||||||
using MediaBrowser.Controller.Resolvers;
|
using MediaBrowser.Controller.Resolvers;
|
||||||
using MediaBrowser.Controller.Sorting;
|
using MediaBrowser.Controller.Sorting;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
|
using MediaBrowser.Model.Querying;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.Querying;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Library
|
namespace MediaBrowser.Controller.Library
|
||||||
{
|
{
|
||||||
@ -61,7 +61,18 @@ namespace MediaBrowser.Controller.Library
|
|||||||
/// <param name="name">The name.</param>
|
/// <param name="name">The name.</param>
|
||||||
/// <returns>Task{Artist}.</returns>
|
/// <returns>Task{Artist}.</returns>
|
||||||
MusicArtist GetArtist(string name);
|
MusicArtist GetArtist(string name);
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the album artists.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="items">The items.</param>
|
||||||
|
/// <returns>IEnumerable<MusicArtist>.</returns>
|
||||||
|
IEnumerable<MusicArtist> GetAlbumArtists(IEnumerable<IHasAlbumArtist> items);
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the artists.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="items">The items.</param>
|
||||||
|
/// <returns>IEnumerable<MusicArtist>.</returns>
|
||||||
|
IEnumerable<MusicArtist> GetArtists(IEnumerable<IHasArtist> items);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a Studio
|
/// Gets a Studio
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -340,7 +351,37 @@ namespace MediaBrowser.Controller.Library
|
|||||||
Task<UserView> GetNamedView(User user,
|
Task<UserView> GetNamedView(User user,
|
||||||
string name,
|
string name,
|
||||||
string viewType,
|
string viewType,
|
||||||
string sortName,
|
string sortName,
|
||||||
|
CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the named view.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The name.</param>
|
||||||
|
/// <param name="viewType">Type of the view.</param>
|
||||||
|
/// <param name="sortName">Name of the sort.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>Task<UserView>.</returns>
|
||||||
|
Task<UserView> GetNamedView(string name,
|
||||||
|
string viewType,
|
||||||
|
string sortName,
|
||||||
|
CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the named view.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The name.</param>
|
||||||
|
/// <param name="parentId">The parent identifier.</param>
|
||||||
|
/// <param name="viewType">Type of the view.</param>
|
||||||
|
/// <param name="sortName">Name of the sort.</param>
|
||||||
|
/// <param name="uniqueId">The unique identifier.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>Task<UserView>.</returns>
|
||||||
|
Task<UserView> GetNamedView(string name,
|
||||||
|
string parentId,
|
||||||
|
string viewType,
|
||||||
|
string sortName,
|
||||||
|
string uniqueId,
|
||||||
CancellationToken cancellationToken);
|
CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -461,5 +502,12 @@ namespace MediaBrowser.Controller.Library
|
|||||||
/// <param name="query">The query.</param>
|
/// <param name="query">The query.</param>
|
||||||
/// <returns>List<System.String>.</returns>
|
/// <returns>List<System.String>.</returns>
|
||||||
List<string> GetPeopleNames(InternalPeopleQuery query);
|
List<string> GetPeopleNames(InternalPeopleQuery query);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queries the items.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="query">The query.</param>
|
||||||
|
/// <returns>QueryResult<BaseItem>.</returns>
|
||||||
|
QueryResult<BaseItem> QueryItems(InternalItemsQuery query);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,4 +11,9 @@ namespace MediaBrowser.Controller.Library
|
|||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
string GetSavePath(IHasMetadata item);
|
string GetSavePath(IHasMetadata item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface IConfigurableProvider
|
||||||
|
{
|
||||||
|
bool IsEnabled { get; }
|
||||||
|
}
|
||||||
}
|
}
|
@ -16,10 +16,10 @@ namespace MediaBrowser.Controller.Library
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the instant mix from artist.
|
/// Gets the instant mix from artist.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="name">The name.</param>
|
/// <param name="artist">The artist.</param>
|
||||||
/// <param name="user">The user.</param>
|
/// <param name="user">The user.</param>
|
||||||
/// <returns>IEnumerable{Audio}.</returns>
|
/// <returns>IEnumerable{Audio}.</returns>
|
||||||
IEnumerable<Audio> GetInstantMixFromArtist(string name, User user);
|
IEnumerable<Audio> GetInstantMixFromArtist(MusicArtist artist, User user);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the instant mix from genre.
|
/// Gets the instant mix from genre.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -12,10 +12,9 @@ namespace MediaBrowser.Controller.Library
|
|||||||
{
|
{
|
||||||
Task<IEnumerable<Folder>> GetUserViews(UserViewQuery query, CancellationToken cancellationToken);
|
Task<IEnumerable<Folder>> GetUserViews(UserViewQuery query, CancellationToken cancellationToken);
|
||||||
|
|
||||||
Task<UserView> GetUserSubView(string name, string parentId, string type, User user, string sortName,
|
Task<UserView> GetUserSubView(string name, string parentId, string type, string sortName, CancellationToken cancellationToken);
|
||||||
CancellationToken cancellationToken);
|
|
||||||
|
|
||||||
Task<UserView> GetUserSubView(string category, string type, User user, string sortName, CancellationToken cancellationToken);
|
Task<UserView> GetUserSubView(string category, string type, string sortName, CancellationToken cancellationToken);
|
||||||
|
|
||||||
List<Tuple<BaseItem, List<BaseItem>>> GetLatestItems(LatestItemsQuery request);
|
List<Tuple<BaseItem, List<BaseItem>>> GetLatestItems(LatestItemsQuery request);
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,10 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value><c>null</c> if [has image] contains no value, <c>true</c> if [has image]; otherwise, <c>false</c>.</value>
|
/// <value><c>null</c> if [has image] contains no value, <c>true</c> if [has image]; otherwise, <c>false</c>.</value>
|
||||||
public bool? HasImage { get; set; }
|
public bool? HasImage { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether this instance is favorite.
|
||||||
|
/// </summary>
|
||||||
|
/// <value><c>null</c> if [is favorite] contains no value, <c>true</c> if [is favorite]; otherwise, <c>false</c>.</value>
|
||||||
|
public bool? IsFavorite { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
15
MediaBrowser.Controller/LiveTv/IHasRegistrationInfo.cs
Normal file
15
MediaBrowser.Controller/LiveTv/IHasRegistrationInfo.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using MediaBrowser.Model.Entities;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
|
{
|
||||||
|
public interface IHasRegistrationInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the registration information.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="feature">The feature.</param>
|
||||||
|
/// <returns>Task<MBRegistrationRecord>.</returns>
|
||||||
|
Task<MBRegistrationRecord> GetRegistrationInfo(string feature);
|
||||||
|
}
|
||||||
|
}
|
19
MediaBrowser.Controller/LiveTv/IListingsProvider.cs
Normal file
19
MediaBrowser.Controller/LiveTv/IListingsProvider.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using MediaBrowser.Model.Dto;
|
||||||
|
using MediaBrowser.Model.LiveTv;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
|
{
|
||||||
|
public interface IListingsProvider
|
||||||
|
{
|
||||||
|
string Name { get; }
|
||||||
|
string Type { get; }
|
||||||
|
Task<IEnumerable<ProgramInfo>> GetProgramsAsync(ListingsProviderInfo info, string channelNumber, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken);
|
||||||
|
Task AddMetadata(ListingsProviderInfo info, List<ChannelInfo> channels, CancellationToken cancellationToken);
|
||||||
|
Task Validate(ListingsProviderInfo info, bool validateLogin, bool validateListings);
|
||||||
|
Task<List<NameIdPair>> GetLineups(ListingsProviderInfo info, string country, string location);
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.LiveTv;
|
using MediaBrowser.Model.LiveTv;
|
||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Querying;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -56,20 +57,23 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
/// <param name="id">The identifier.</param>
|
/// <param name="id">The identifier.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task CancelSeriesTimer(string id);
|
Task CancelSeriesTimer(string id);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the parts.
|
/// Adds the parts.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="services">The services.</param>
|
/// <param name="services">The services.</param>
|
||||||
void AddParts(IEnumerable<ILiveTvService> services);
|
/// <param name="tunerHosts">The tuner hosts.</param>
|
||||||
|
/// <param name="listingProviders">The listing providers.</param>
|
||||||
|
void AddParts(IEnumerable<ILiveTvService> services, IEnumerable<ITunerHost> tunerHosts, IEnumerable<IListingsProvider> listingProviders);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the channels.
|
/// Gets the channels.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="query">The query.</param>
|
/// <param name="query">The query.</param>
|
||||||
|
/// <param name="options">The options.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>IEnumerable{Channel}.</returns>
|
/// <returns>IEnumerable{Channel}.</returns>
|
||||||
Task<QueryResult<ChannelInfoDto>> GetChannels(LiveTvChannelQuery query, CancellationToken cancellationToken);
|
Task<QueryResult<ChannelInfoDto>> GetChannels(LiveTvChannelQuery query, DtoOptions options, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the recording.
|
/// Gets the recording.
|
||||||
@ -171,14 +175,15 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
/// <param name="user">The user.</param>
|
/// <param name="user">The user.</param>
|
||||||
/// <returns>Task{ProgramInfoDto}.</returns>
|
/// <returns>Task{ProgramInfoDto}.</returns>
|
||||||
Task<BaseItemDto> GetProgram(string id, CancellationToken cancellationToken, User user = null);
|
Task<BaseItemDto> GetProgram(string id, CancellationToken cancellationToken, User user = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the programs.
|
/// Gets the programs.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="query">The query.</param>
|
/// <param name="query">The query.</param>
|
||||||
|
/// <param name="options">The options.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>IEnumerable{ProgramInfo}.</returns>
|
/// <returns>IEnumerable{ProgramInfo}.</returns>
|
||||||
Task<QueryResult<BaseItemDto>> GetPrograms(ProgramQuery query, CancellationToken cancellationToken);
|
Task<QueryResult<BaseItemDto>> GetPrograms(ProgramQuery query, DtoOptions options, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the timer.
|
/// Updates the timer.
|
||||||
@ -238,10 +243,10 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
/// Gets the recommended programs.
|
/// Gets the recommended programs.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="query">The query.</param>
|
/// <param name="query">The query.</param>
|
||||||
|
/// <param name="options">The options.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task{QueryResult{ProgramInfoDto}}.</returns>
|
/// <returns>Task{QueryResult{ProgramInfoDto}}.</returns>
|
||||||
Task<QueryResult<BaseItemDto>> GetRecommendedPrograms(RecommendedProgramQuery query,
|
Task<QueryResult<BaseItemDto>> GetRecommendedPrograms(RecommendedProgramQuery query, DtoOptions options, CancellationToken cancellationToken);
|
||||||
CancellationToken cancellationToken);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the recommended programs internal.
|
/// Gets the recommended programs internal.
|
||||||
@ -249,8 +254,7 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
/// <param name="query">The query.</param>
|
/// <param name="query">The query.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task<QueryResult<LiveTvProgram>>.</returns>
|
/// <returns>Task<QueryResult<LiveTvProgram>>.</returns>
|
||||||
Task<QueryResult<LiveTvProgram>> GetRecommendedProgramsInternal(RecommendedProgramQuery query,
|
Task<QueryResult<LiveTvProgram>> GetRecommendedProgramsInternal(RecommendedProgramQuery query, CancellationToken cancellationToken);
|
||||||
CancellationToken cancellationToken);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the live tv information.
|
/// Gets the live tv information.
|
||||||
@ -270,10 +274,9 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the live tv folder.
|
/// Gets the live tv folder.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="userId">The user identifier.</param>
|
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>BaseItemDto.</returns>
|
/// <returns>BaseItemDto.</returns>
|
||||||
Task<Folder> GetInternalLiveTvFolder(string userId, CancellationToken cancellationToken);
|
Task<Folder> GetInternalLiveTvFolder(CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the live tv folder.
|
/// Gets the live tv folder.
|
||||||
@ -337,5 +340,46 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
/// <param name="dto">The dto.</param>
|
/// <param name="dto">The dto.</param>
|
||||||
/// <param name="user">The user.</param>
|
/// <param name="user">The user.</param>
|
||||||
void AddInfoToProgramDto(BaseItem item, BaseItemDto dto, User user = null);
|
void AddInfoToProgramDto(BaseItem item, BaseItemDto dto, User user = null);
|
||||||
|
/// <summary>
|
||||||
|
/// Saves the tuner host.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="info">The information.</param>
|
||||||
|
/// <returns>Task.</returns>
|
||||||
|
Task<TunerHostInfo> SaveTunerHost(TunerHostInfo info);
|
||||||
|
/// <summary>
|
||||||
|
/// Saves the listing provider.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="info">The information.</param>
|
||||||
|
/// <param name="validateLogin">if set to <c>true</c> [validate login].</param>
|
||||||
|
/// <param name="validateListings">if set to <c>true</c> [validate listings].</param>
|
||||||
|
/// <returns>Task.</returns>
|
||||||
|
Task<ListingsProviderInfo> SaveListingProvider(ListingsProviderInfo info, bool validateLogin, bool validateListings);
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the lineups.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="providerType">Type of the provider.</param>
|
||||||
|
/// <param name="providerId">The provider identifier.</param>
|
||||||
|
/// <param name="country">The country.</param>
|
||||||
|
/// <param name="location">The location.</param>
|
||||||
|
/// <returns>Task<List<NameIdPair>>.</returns>
|
||||||
|
Task<List<NameIdPair>> GetLineups(string providerType, string providerId, string country, string location);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the registration information.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="channelId">The channel identifier.</param>
|
||||||
|
/// <param name="programId">The program identifier.</param>
|
||||||
|
/// <param name="feature">The feature.</param>
|
||||||
|
/// <returns>Task<MBRegistrationRecord>.</returns>
|
||||||
|
Task<MBRegistrationRecord> GetRegistrationInfo(string channelId, string programId, string feature);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the channel information.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dto">The dto.</param>
|
||||||
|
/// <param name="channel">The channel.</param>
|
||||||
|
/// <param name="options">The options.</param>
|
||||||
|
/// <param name="user">The user.</param>
|
||||||
|
void AddChannelInfo(BaseItemDto dto, LiveTvChannel channel, DtoOptions options, User user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,10 +37,12 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
|
|
||||||
string ExternalId { get; set; }
|
string ExternalId { get; set; }
|
||||||
string EpisodeTitle { get; set; }
|
string EpisodeTitle { get; set; }
|
||||||
bool IsSeries { get; set; }
|
|
||||||
string SeriesTimerId { get; set; }
|
string SeriesTimerId { get; set; }
|
||||||
RecordingStatus Status { get; set; }
|
RecordingStatus Status { get; set; }
|
||||||
DateTime? EndDate { get; set; }
|
DateTime? EndDate { get; set; }
|
||||||
ChannelType ChannelType { get; set; }
|
ChannelType ChannelType { get; set; }
|
||||||
|
DateTime DateLastSaved { get; set; }
|
||||||
|
DateTime DateCreated { get; set; }
|
||||||
|
DateTime DateModified { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
55
MediaBrowser.Controller/LiveTv/ITunerHost.cs
Normal file
55
MediaBrowser.Controller/LiveTv/ITunerHost.cs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
using MediaBrowser.Model.Dto;
|
||||||
|
using MediaBrowser.Model.LiveTv;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
|
{
|
||||||
|
public interface ITunerHost
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The name.</value>
|
||||||
|
string Name { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the type.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The type.</value>
|
||||||
|
string Type { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the channels.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>Task<IEnumerable<ChannelInfo>>.</returns>
|
||||||
|
Task<IEnumerable<ChannelInfo>> GetChannels(CancellationToken cancellationToken);
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the tuner infos.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>Task<List<LiveTvTunerInfo>>.</returns>
|
||||||
|
Task<List<LiveTvTunerInfo>> GetTunerInfos(CancellationToken cancellationToken);
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the channel stream.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="channelId">The channel identifier.</param>
|
||||||
|
/// <param name="streamId">The stream identifier.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>Task<MediaSourceInfo>.</returns>
|
||||||
|
Task<MediaSourceInfo> GetChannelStream(string channelId, string streamId, CancellationToken cancellationToken);
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the channel stream media sources.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="channelId">The channel identifier.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>Task<List<MediaSourceInfo>>.</returns>
|
||||||
|
Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(string channelId, CancellationToken cancellationToken);
|
||||||
|
/// <summary>
|
||||||
|
/// Validates the specified information.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="info">The information.</param>
|
||||||
|
/// <returns>Task.</returns>
|
||||||
|
Task Validate(TunerHostInfo info);
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
|
using MediaBrowser.Controller.Entities.Movies;
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.LiveTv;
|
using MediaBrowser.Model.LiveTv;
|
||||||
@ -17,9 +18,24 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
protected override string CreateUserDataKey()
|
protected override string CreateUserDataKey()
|
||||||
{
|
{
|
||||||
|
if (IsMovie)
|
||||||
|
{
|
||||||
|
var key = Movie.GetMovieUserDataKey(this);
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(key))
|
||||||
|
{
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
||||||
return GetClientTypeName() + "-" + Name;
|
return GetClientTypeName() + "-" + Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the etag.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The etag.</value>
|
||||||
|
public string Etag { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Id of the program.
|
/// Id of the program.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -227,5 +243,19 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
info.IsMovie = IsMovie;
|
info.IsMovie = IsMovie;
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool SupportsPeople
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
// Optimization
|
||||||
|
if (IsNews || IsSports)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.SupportsPeople;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,10 +34,16 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The tuners.</value>
|
/// <value>The tuners.</value>
|
||||||
public List<LiveTvTunerInfo> Tuners { get; set; }
|
public List<LiveTvTunerInfo> Tuners { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether this instance is visible.
|
||||||
|
/// </summary>
|
||||||
|
/// <value><c>true</c> if this instance is visible; otherwise, <c>false</c>.</value>
|
||||||
|
public bool IsVisible { get; set; }
|
||||||
|
|
||||||
public LiveTvServiceStatusInfo()
|
public LiveTvServiceStatusInfo()
|
||||||
{
|
{
|
||||||
Tuners = new List<LiveTvTunerInfo>();
|
Tuners = new List<LiveTvTunerInfo>();
|
||||||
|
IsVisible = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
|
using MediaBrowser.Controller.Entities.Movies;
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
@ -40,6 +41,16 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
protected override string CreateUserDataKey()
|
protected override string CreateUserDataKey()
|
||||||
{
|
{
|
||||||
|
if (IsMovie)
|
||||||
|
{
|
||||||
|
var key = Movie.GetMovieUserDataKey(this);
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(key))
|
||||||
|
{
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var name = GetClientTypeName();
|
var name = GetClientTypeName();
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(ProgramId))
|
if (!string.IsNullOrEmpty(ProgramId))
|
||||||
|
@ -33,6 +33,11 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The overview.</value>
|
/// <value>The overview.</value>
|
||||||
public string Overview { get; set; }
|
public string Overview { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the short overview.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The short overview.</value>
|
||||||
|
public string ShortOverview { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The start date of the program, in UTC.
|
/// The start date of the program, in UTC.
|
||||||
@ -150,6 +155,36 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The production year.</value>
|
/// <value>The production year.</value>
|
||||||
public int? ProductionYear { get; set; }
|
public int? ProductionYear { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the home page URL.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The home page URL.</value>
|
||||||
|
public string HomePageUrl { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the series identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The series identifier.</value>
|
||||||
|
public string SeriesId { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the show identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The show identifier.</value>
|
||||||
|
public string ShowId { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the season number.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The season number.</value>
|
||||||
|
public int? SeasonNumber { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the episode number.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The episode number.</value>
|
||||||
|
public int? EpisodeNumber { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the etag.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The etag.</value>
|
||||||
|
public string Etag { get; set; }
|
||||||
|
|
||||||
public ProgramInfo()
|
public ProgramInfo()
|
||||||
{
|
{
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user