mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-07-09 03:04:24 -04:00
Merge branch 'master' of https://github.com/MediaBrowser/MediaBrowser
This commit is contained in:
commit
6819be8160
@ -92,7 +92,7 @@ namespace MediaBrowser.Api
|
|||||||
private readonly char[] _dashReplaceChars = new[] { '?', '/' };
|
private readonly char[] _dashReplaceChars = new[] { '?', '/' };
|
||||||
private const char SlugChar = '-';
|
private const char SlugChar = '-';
|
||||||
|
|
||||||
protected Artist GetArtist(string name, ILibraryManager libraryManager)
|
protected MusicArtist GetArtist(string name, ILibraryManager libraryManager)
|
||||||
{
|
{
|
||||||
return libraryManager.GetArtist(DeSlugArtistName(name, libraryManager));
|
return libraryManager.GetArtist(DeSlugArtistName(name, libraryManager));
|
||||||
}
|
}
|
||||||
@ -147,21 +147,7 @@ namespace MediaBrowser.Api
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
return libraryManager.RootFolder.GetRecursiveChildren()
|
return libraryManager.GetAllArtists()
|
||||||
.OfType<Audio>()
|
|
||||||
.SelectMany(i =>
|
|
||||||
{
|
|
||||||
var list = new List<string>();
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(i.AlbumArtist))
|
|
||||||
{
|
|
||||||
list.Add(i.AlbumArtist);
|
|
||||||
}
|
|
||||||
list.AddRange(i.Artists);
|
|
||||||
|
|
||||||
return list;
|
|
||||||
})
|
|
||||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
|
||||||
.FirstOrDefault(i =>
|
.FirstOrDefault(i =>
|
||||||
{
|
{
|
||||||
i = _dashReplaceChars.Aggregate(i, (current, c) => current.Replace(c, SlugChar));
|
i = _dashReplaceChars.Aggregate(i, (current, c) => current.Replace(c, SlugChar));
|
||||||
|
@ -194,20 +194,7 @@ namespace MediaBrowser.Api.DefaultTheme
|
|||||||
.Select(i => _dtoService.GetBaseItemDto(i, fields, user))
|
.Select(i => _dtoService.GetBaseItemDto(i, fields, user))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var artists = allItems.OfType<Audio>()
|
var artists = _libraryManager.GetAllArtists(allItems)
|
||||||
.SelectMany(i =>
|
|
||||||
{
|
|
||||||
var list = new List<string>();
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(i.AlbumArtist))
|
|
||||||
{
|
|
||||||
list.Add(i.AlbumArtist);
|
|
||||||
}
|
|
||||||
list.AddRange(i.Artists);
|
|
||||||
|
|
||||||
return list;
|
|
||||||
})
|
|
||||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
|
||||||
.Randomize()
|
.Randomize()
|
||||||
.Select(i =>
|
.Select(i =>
|
||||||
{
|
{
|
||||||
@ -650,7 +637,7 @@ namespace MediaBrowser.Api.DefaultTheme
|
|||||||
public static IEnumerable<T> Randomize<T>(this IEnumerable<T> sequence, string type = "none")
|
public static IEnumerable<T> Randomize<T>(this IEnumerable<T> sequence, string type = "none")
|
||||||
where T : BaseItem
|
where T : BaseItem
|
||||||
{
|
{
|
||||||
var hour = DateTime.Now.Hour + 2;
|
var hour = DateTime.Now.Hour + DateTime.Now.Day + 2;
|
||||||
|
|
||||||
var typeCode = type.GetHashCode();
|
var typeCode = type.GetHashCode();
|
||||||
|
|
||||||
|
52
MediaBrowser.Api/IHasItemFields.cs
Normal file
52
MediaBrowser.Api/IHasItemFields.cs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
using MediaBrowser.Model.Querying;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Api
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interface IHasItemFields
|
||||||
|
/// </summary>
|
||||||
|
public interface IHasItemFields
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the fields.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The fields.</value>
|
||||||
|
string Fields { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Class ItemFieldsExtensions.
|
||||||
|
/// </summary>
|
||||||
|
public static class ItemFieldsExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the item fields.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">The request.</param>
|
||||||
|
/// <returns>IEnumerable{ItemFields}.</returns>
|
||||||
|
public static IEnumerable<ItemFields> GetItemFields(this IHasItemFields request)
|
||||||
|
{
|
||||||
|
var val = request.Fields;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(val))
|
||||||
|
{
|
||||||
|
return new ItemFields[] { };
|
||||||
|
}
|
||||||
|
|
||||||
|
return val.Split(',').Select(v =>
|
||||||
|
{
|
||||||
|
ItemFields value;
|
||||||
|
|
||||||
|
if (Enum.TryParse(v, true, out value))
|
||||||
|
{
|
||||||
|
return (ItemFields?)value;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}).Where(i => i.HasValue).Select(i => i.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@ using MediaBrowser.Controller.Drawing;
|
|||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
|
using MediaBrowser.Controller.LiveTv;
|
||||||
using MediaBrowser.Controller.Persistence;
|
using MediaBrowser.Controller.Persistence;
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
using MediaBrowser.Model.Drawing;
|
using MediaBrowser.Model.Drawing;
|
||||||
@ -37,6 +38,18 @@ namespace MediaBrowser.Api.Images
|
|||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Route("/LiveTv/Channels/{Id}/Images", "GET")]
|
||||||
|
[Api(Description = "Gets information about an item's images")]
|
||||||
|
public class GetChannelImageInfos : IReturn<List<ImageInfo>>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the id.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The id.</value>
|
||||||
|
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||||
|
public string Id { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
[Route("/Artists/{Name}/Images", "GET")]
|
[Route("/Artists/{Name}/Images", "GET")]
|
||||||
[Route("/Genres/{Name}/Images", "GET")]
|
[Route("/Genres/{Name}/Images", "GET")]
|
||||||
[Route("/GameGenres/{Name}/Images", "GET")]
|
[Route("/GameGenres/{Name}/Images", "GET")]
|
||||||
@ -67,6 +80,19 @@ namespace MediaBrowser.Api.Images
|
|||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Route("/LiveTv/Channels/{Id}/Images/{Type}", "GET")]
|
||||||
|
[Route("/LiveTv/Channels/{Id}/Images/{Type}/{Index}", "GET")]
|
||||||
|
[Api(Description = "Gets an item image")]
|
||||||
|
public class GetChannelImage : ImageRequest
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the id.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The id.</value>
|
||||||
|
[ApiMember(Name = "Id", Description = "Channel Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||||
|
public string Id { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class UpdateItemImageIndex
|
/// Class UpdateItemImageIndex
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -243,6 +269,19 @@ namespace MediaBrowser.Api.Images
|
|||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Route("/LiveTv/Channels/{Id}/Images/{Type}", "DELETE")]
|
||||||
|
[Route("/LiveTv/Channels/{Id}/Images/{Type}/{Index}", "DELETE")]
|
||||||
|
[Api(Description = "Deletes an item image")]
|
||||||
|
public class DeleteChannelImage : DeleteImageRequest, IReturnVoid
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the id.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The id.</value>
|
||||||
|
[ApiMember(Name = "Id", Description = "Channel Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
|
||||||
|
public string Id { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class PostUserImage
|
/// Class PostUserImage
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -318,6 +357,25 @@ namespace MediaBrowser.Api.Images
|
|||||||
public Stream RequestStream { get; set; }
|
public Stream RequestStream { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Route("/LiveTv/Channels/{Id}/Images/{Type}", "POST")]
|
||||||
|
[Route("/LiveTv/Channels/{Id}/Images/{Type}/{Index}", "POST")]
|
||||||
|
[Api(Description = "Posts an item image")]
|
||||||
|
public class PostChannelImage : DeleteImageRequest, IRequiresRequestStream, IReturnVoid
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the id.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The id.</value>
|
||||||
|
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The raw Http Request Input Stream
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The request stream.</value>
|
||||||
|
public Stream RequestStream { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class ImageService
|
/// Class ImageService
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -341,10 +399,12 @@ namespace MediaBrowser.Api.Images
|
|||||||
private readonly IDtoService _dtoService;
|
private readonly IDtoService _dtoService;
|
||||||
private readonly IImageProcessor _imageProcessor;
|
private readonly IImageProcessor _imageProcessor;
|
||||||
|
|
||||||
|
private readonly ILiveTvManager _liveTv;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ImageService" /> class.
|
/// Initializes a new instance of the <see cref="ImageService" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ImageService(IUserManager userManager, ILibraryManager libraryManager, IApplicationPaths appPaths, IProviderManager providerManager, IItemRepository itemRepo, IDtoService dtoService, IImageProcessor imageProcessor)
|
public ImageService(IUserManager userManager, ILibraryManager libraryManager, IApplicationPaths appPaths, IProviderManager providerManager, IItemRepository itemRepo, IDtoService dtoService, IImageProcessor imageProcessor, ILiveTvManager liveTv)
|
||||||
{
|
{
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
@ -353,6 +413,7 @@ namespace MediaBrowser.Api.Images
|
|||||||
_itemRepo = itemRepo;
|
_itemRepo = itemRepo;
|
||||||
_dtoService = dtoService;
|
_dtoService = dtoService;
|
||||||
_imageProcessor = imageProcessor;
|
_imageProcessor = imageProcessor;
|
||||||
|
_liveTv = liveTv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -369,6 +430,15 @@ namespace MediaBrowser.Api.Images
|
|||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public object Get(GetChannelImageInfos request)
|
||||||
|
{
|
||||||
|
var item = _liveTv.GetChannel(request.Id);
|
||||||
|
|
||||||
|
var result = GetItemImageInfos(item);
|
||||||
|
|
||||||
|
return ToOptimizedResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
public object Get(GetItemByNameImageInfos request)
|
public object Get(GetItemByNameImageInfos request)
|
||||||
{
|
{
|
||||||
var result = GetItemByNameImageInfos(request);
|
var result = GetItemByNameImageInfos(request);
|
||||||
@ -484,7 +554,7 @@ namespace MediaBrowser.Api.Images
|
|||||||
Height = Convert.ToInt32(size.Height)
|
Height = Convert.ToInt32(size.Height)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
catch (IOException ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.ErrorException("Error getting image information for {0}", ex, path);
|
Logger.ErrorException("Error getting image information for {0}", ex, path);
|
||||||
|
|
||||||
@ -492,6 +562,13 @@ namespace MediaBrowser.Api.Images
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public object Get(GetChannelImage request)
|
||||||
|
{
|
||||||
|
var item = _liveTv.GetChannel(request.Id);
|
||||||
|
|
||||||
|
return GetImage(request, item);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the specified request.
|
/// Gets the specified request.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -577,6 +654,20 @@ namespace MediaBrowser.Api.Images
|
|||||||
Task.WaitAll(task);
|
Task.WaitAll(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Post(PostChannelImage request)
|
||||||
|
{
|
||||||
|
var pathInfo = PathInfo.Parse(RequestContext.PathInfo);
|
||||||
|
var id = pathInfo.GetArgumentValue<string>(2);
|
||||||
|
|
||||||
|
request.Type = (ImageType)Enum.Parse(typeof(ImageType), pathInfo.GetArgumentValue<string>(4), true);
|
||||||
|
|
||||||
|
var item = _liveTv.GetChannel(id);
|
||||||
|
|
||||||
|
var task = PostImage(item, request.RequestStream, request.Type, RequestContext.ContentType);
|
||||||
|
|
||||||
|
Task.WaitAll(task);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Deletes the specified request.
|
/// Deletes the specified request.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -603,6 +694,15 @@ namespace MediaBrowser.Api.Images
|
|||||||
Task.WaitAll(task);
|
Task.WaitAll(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Delete(DeleteChannelImage request)
|
||||||
|
{
|
||||||
|
var item = _liveTv.GetChannel(request.Id);
|
||||||
|
|
||||||
|
var task = item.DeleteImage(request.Type, request.Index);
|
||||||
|
|
||||||
|
Task.WaitAll(task);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Deletes the specified request.
|
/// Deletes the specified request.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -264,16 +264,14 @@ namespace MediaBrowser.Api
|
|||||||
{
|
{
|
||||||
var item = _dtoService.GetItemByDtoId(request.Id);
|
var item = _dtoService.GetItemByDtoId(request.Id);
|
||||||
|
|
||||||
var folder = item as Folder;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await item.RefreshMetadata(CancellationToken.None, forceRefresh: request.Forced).ConfigureAwait(false);
|
await item.RefreshMetadata(CancellationToken.None, forceRefresh: request.Forced).ConfigureAwait(false);
|
||||||
|
|
||||||
if (folder != null)
|
if (item.IsFolder)
|
||||||
{
|
{
|
||||||
// Collection folders don't validate their children so we'll have to simulate that here
|
// Collection folders don't validate their children so we'll have to simulate that here
|
||||||
var collectionFolder = folder as CollectionFolder;
|
var collectionFolder = item as CollectionFolder;
|
||||||
|
|
||||||
if (collectionFolder != null)
|
if (collectionFolder != null)
|
||||||
{
|
{
|
||||||
@ -281,6 +279,8 @@ namespace MediaBrowser.Api
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
var folder = (Folder)item;
|
||||||
|
|
||||||
await folder.ValidateChildren(new Progress<double>(), CancellationToken.None, request.Recursive, request.Forced).ConfigureAwait(false);
|
await folder.ValidateChildren(new Progress<double>(), CancellationToken.None, request.Recursive, request.Forced).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -303,10 +303,10 @@ namespace MediaBrowser.Api
|
|||||||
{
|
{
|
||||||
await child.RefreshMetadata(CancellationToken.None, forceRefresh: request.Forced).ConfigureAwait(false);
|
await child.RefreshMetadata(CancellationToken.None, forceRefresh: request.Forced).ConfigureAwait(false);
|
||||||
|
|
||||||
var folder = child as Folder;
|
if (child.IsFolder)
|
||||||
|
|
||||||
if (folder != null)
|
|
||||||
{
|
{
|
||||||
|
var folder = (Folder)child;
|
||||||
|
|
||||||
await folder.ValidateChildren(new Progress<double>(), CancellationToken.None, request.Recursive, request.Forced).ConfigureAwait(false);
|
await folder.ValidateChildren(new Progress<double>(), CancellationToken.None, request.Recursive, request.Forced).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,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.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using ServiceStack.ServiceHost;
|
using ServiceStack.ServiceHost;
|
||||||
@ -13,6 +14,14 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace MediaBrowser.Api
|
namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
|
[Route("/LiveTv/Channels/{ChannelId}", "POST")]
|
||||||
|
[Api(("Updates an item"))]
|
||||||
|
public class UpdateChannel : BaseItemDto, IReturnVoid
|
||||||
|
{
|
||||||
|
[ApiMember(Name = "ChannelId", Description = "The id of the channel", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
|
||||||
|
public string ChannelId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
[Route("/Items/{ItemId}", "POST")]
|
[Route("/Items/{ItemId}", "POST")]
|
||||||
[Api(("Updates an item"))]
|
[Api(("Updates an item"))]
|
||||||
public class UpdateItem : BaseItemDto, IReturnVoid
|
public class UpdateItem : BaseItemDto, IReturnVoid
|
||||||
@ -73,11 +82,13 @@ namespace MediaBrowser.Api
|
|||||||
{
|
{
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly IDtoService _dtoService;
|
private readonly IDtoService _dtoService;
|
||||||
|
private readonly ILiveTvManager _liveTv;
|
||||||
|
|
||||||
public ItemUpdateService(ILibraryManager libraryManager, IDtoService dtoService)
|
public ItemUpdateService(ILibraryManager libraryManager, IDtoService dtoService, ILiveTvManager liveTv)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_dtoService = dtoService;
|
_dtoService = dtoService;
|
||||||
|
_liveTv = liveTv;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Post(UpdateItem request)
|
public void Post(UpdateItem request)
|
||||||
@ -87,13 +98,34 @@ namespace MediaBrowser.Api
|
|||||||
Task.WaitAll(task);
|
Task.WaitAll(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task UpdateItem(UpdateItem request)
|
public void Post(UpdateChannel request)
|
||||||
|
{
|
||||||
|
var task = UpdateItem(request);
|
||||||
|
|
||||||
|
Task.WaitAll(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task UpdateItem(UpdateItem request)
|
||||||
{
|
{
|
||||||
var item = _dtoService.GetItemByDtoId(request.ItemId);
|
var item = _dtoService.GetItemByDtoId(request.ItemId);
|
||||||
|
|
||||||
|
var newEnableInternetProviders = request.EnableInternetProviders ?? true;
|
||||||
|
var dontFetchMetaChanged = item.DontFetchMeta != !newEnableInternetProviders;
|
||||||
|
|
||||||
UpdateItem(request, item);
|
UpdateItem(request, item);
|
||||||
|
|
||||||
return _libraryManager.UpdateItem(item, ItemUpdateType.MetadataEdit, CancellationToken.None);
|
await _libraryManager.UpdateItem(item, ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (dontFetchMetaChanged && item.IsFolder)
|
||||||
|
{
|
||||||
|
var folder = (Folder)item;
|
||||||
|
|
||||||
|
foreach (var child in folder.RecursiveChildren.ToList())
|
||||||
|
{
|
||||||
|
child.DontFetchMeta = !newEnableInternetProviders;
|
||||||
|
await _libraryManager.UpdateItem(child, ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Post(UpdatePerson request)
|
public void Post(UpdatePerson request)
|
||||||
@ -112,6 +144,15 @@ namespace MediaBrowser.Api
|
|||||||
await _libraryManager.UpdateItem(item, ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
await _libraryManager.UpdateItem(item, ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task UpdateItem(UpdateChannel request)
|
||||||
|
{
|
||||||
|
var item = _liveTv.GetChannel(request.Id);
|
||||||
|
|
||||||
|
UpdateItem(request, item);
|
||||||
|
|
||||||
|
await _libraryManager.UpdateItem(item, ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
public void Post(UpdateArtist request)
|
public void Post(UpdateArtist request)
|
||||||
{
|
{
|
||||||
var task = UpdateItem(request);
|
var task = UpdateItem(request);
|
||||||
@ -126,15 +167,6 @@ namespace MediaBrowser.Api
|
|||||||
UpdateItem(request, item);
|
UpdateItem(request, item);
|
||||||
|
|
||||||
await _libraryManager.UpdateItem(item, ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
await _libraryManager.UpdateItem(item, ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
var musicArtist = Artist.FindMusicArtist(item, _libraryManager);
|
|
||||||
|
|
||||||
if (musicArtist != null)
|
|
||||||
{
|
|
||||||
UpdateItem(request, musicArtist);
|
|
||||||
|
|
||||||
await _libraryManager.UpdateItem(musicArtist, ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Post(UpdateStudio request)
|
public void Post(UpdateStudio request)
|
||||||
@ -216,8 +248,12 @@ namespace MediaBrowser.Api
|
|||||||
item.ForcedSortName = request.SortName;
|
item.ForcedSortName = request.SortName;
|
||||||
}
|
}
|
||||||
|
|
||||||
item.Budget = request.Budget;
|
var hasBudget = item as IHasBudget;
|
||||||
item.Revenue = request.Revenue;
|
if (hasBudget != null)
|
||||||
|
{
|
||||||
|
hasBudget.Budget = request.Budget;
|
||||||
|
hasBudget.Revenue = request.Revenue;
|
||||||
|
}
|
||||||
|
|
||||||
var hasCriticRating = item as IHasCriticRating;
|
var hasCriticRating = item as IHasCriticRating;
|
||||||
if (hasCriticRating != null)
|
if (hasCriticRating != null)
|
||||||
@ -235,8 +271,16 @@ namespace MediaBrowser.Api
|
|||||||
item.Overview = request.Overview;
|
item.Overview = request.Overview;
|
||||||
item.Genres = request.Genres;
|
item.Genres = request.Genres;
|
||||||
item.Tags = request.Tags;
|
item.Tags = request.Tags;
|
||||||
|
|
||||||
|
if (request.Studios != null)
|
||||||
|
{
|
||||||
item.Studios = request.Studios.Select(x => x.Name).ToList();
|
item.Studios = request.Studios.Select(x => x.Name).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.People != null)
|
||||||
|
{
|
||||||
item.People = request.People.Select(x => new PersonInfo { Name = x.Name, Role = x.Role, Type = x.Type }).ToList();
|
item.People = request.People.Select(x => new PersonInfo { Name = x.Name, Role = x.Role, Type = x.Type }).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
if (request.DateCreated.HasValue)
|
if (request.DateCreated.HasValue)
|
||||||
{
|
{
|
||||||
@ -247,11 +291,16 @@ namespace MediaBrowser.Api
|
|||||||
item.PremiereDate = request.PremiereDate.HasValue ? request.PremiereDate.Value.ToUniversalTime() : (DateTime?)null;
|
item.PremiereDate = request.PremiereDate.HasValue ? request.PremiereDate.Value.ToUniversalTime() : (DateTime?)null;
|
||||||
item.ProductionYear = request.ProductionYear;
|
item.ProductionYear = request.ProductionYear;
|
||||||
item.ProductionLocations = request.ProductionLocations;
|
item.ProductionLocations = request.ProductionLocations;
|
||||||
item.AspectRatio = request.AspectRatio;
|
|
||||||
item.Language = request.Language;
|
item.Language = request.Language;
|
||||||
item.OfficialRating = request.OfficialRating;
|
item.OfficialRating = request.OfficialRating;
|
||||||
item.CustomRating = request.CustomRating;
|
item.CustomRating = request.CustomRating;
|
||||||
|
|
||||||
|
var hasAspectRatio = item as IHasAspectRatio;
|
||||||
|
if (hasAspectRatio != null)
|
||||||
|
{
|
||||||
|
hasAspectRatio.AspectRatio = request.AspectRatio;
|
||||||
|
}
|
||||||
|
|
||||||
item.DontFetchMeta = !(request.EnableInternetProviders ?? true);
|
item.DontFetchMeta = !(request.EnableInternetProviders ?? true);
|
||||||
if (request.EnableInternetProviders ?? true)
|
if (request.EnableInternetProviders ?? true)
|
||||||
{
|
{
|
||||||
|
@ -285,8 +285,13 @@ namespace MediaBrowser.Api.Library
|
|||||||
Task.WaitAll(task);
|
Task.WaitAll(task);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
{
|
||||||
|
// No need to start if scanning the library because it will handle it
|
||||||
|
if (!request.RefreshLibrary)
|
||||||
{
|
{
|
||||||
_directoryWatchers.Start();
|
_directoryWatchers.Start();
|
||||||
|
}
|
||||||
|
|
||||||
_directoryWatchers.RemoveTempIgnore(virtualFolderPath);
|
_directoryWatchers.RemoveTempIgnore(virtualFolderPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,8 +357,13 @@ namespace MediaBrowser.Api.Library
|
|||||||
Task.WaitAll(task);
|
Task.WaitAll(task);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
{
|
||||||
|
// No need to start if scanning the library because it will handle it
|
||||||
|
if (!request.RefreshLibrary)
|
||||||
{
|
{
|
||||||
_directoryWatchers.Start();
|
_directoryWatchers.Start();
|
||||||
|
}
|
||||||
|
|
||||||
_directoryWatchers.RemoveTempIgnore(currentPath);
|
_directoryWatchers.RemoveTempIgnore(currentPath);
|
||||||
_directoryWatchers.RemoveTempIgnore(newPath);
|
_directoryWatchers.RemoveTempIgnore(newPath);
|
||||||
}
|
}
|
||||||
@ -403,8 +413,13 @@ namespace MediaBrowser.Api.Library
|
|||||||
Task.WaitAll(delayTask);
|
Task.WaitAll(delayTask);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
{
|
||||||
|
// No need to start if scanning the library because it will handle it
|
||||||
|
if (!request.RefreshLibrary)
|
||||||
{
|
{
|
||||||
_directoryWatchers.Start();
|
_directoryWatchers.Start();
|
||||||
|
}
|
||||||
|
|
||||||
_directoryWatchers.RemoveTempIgnore(path);
|
_directoryWatchers.RemoveTempIgnore(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -441,9 +456,13 @@ namespace MediaBrowser.Api.Library
|
|||||||
Task.WaitAll(task);
|
Task.WaitAll(task);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
{
|
||||||
|
// No need to start if scanning the library because it will handle it
|
||||||
|
if (!request.RefreshLibrary)
|
||||||
{
|
{
|
||||||
_directoryWatchers.Start();
|
_directoryWatchers.Start();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (request.RefreshLibrary)
|
if (request.RefreshLibrary)
|
||||||
{
|
{
|
||||||
@ -478,9 +497,13 @@ namespace MediaBrowser.Api.Library
|
|||||||
Task.WaitAll(task);
|
Task.WaitAll(task);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
{
|
||||||
|
// No need to start if scanning the library because it will handle it
|
||||||
|
if (!request.RefreshLibrary)
|
||||||
{
|
{
|
||||||
_directoryWatchers.Start();
|
_directoryWatchers.Start();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (request.RefreshLibrary)
|
if (request.RefreshLibrary)
|
||||||
{
|
{
|
||||||
|
@ -37,7 +37,7 @@ namespace MediaBrowser.Api
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/Items/{Id}/CriticReviews", "GET")]
|
[Route("/Items/{Id}/CriticReviews", "GET")]
|
||||||
[Api(Description = "Gets critic reviews for an item")]
|
[Api(Description = "Gets critic reviews for an item")]
|
||||||
public class GetCriticReviews : IReturn<ItemReviewsResult>
|
public class GetCriticReviews : IReturn<QueryResult<ItemReview>>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the id.
|
/// Gets or sets the id.
|
||||||
@ -367,7 +367,7 @@ namespace MediaBrowser.Api
|
|||||||
BoxSetCount = boxsets.Count,
|
BoxSetCount = boxsets.Count,
|
||||||
BookCount = books.Count,
|
BookCount = books.Count,
|
||||||
|
|
||||||
UniqueTypes = items.Select(i => i.GetType().Name).Distinct().ToList()
|
UniqueTypes = items.Select(i => i.GetClientTypeName()).Distinct().ToList()
|
||||||
};
|
};
|
||||||
|
|
||||||
var people = items.SelectMany(i => i.People)
|
var people = items.SelectMany(i => i.People)
|
||||||
@ -390,19 +390,7 @@ namespace MediaBrowser.Api
|
|||||||
people = request.UserId.HasValue ? FilterItems(people, request, request.UserId.Value).ToList() : people;
|
people = request.UserId.HasValue ? FilterItems(people, request, request.UserId.Value).ToList() : people;
|
||||||
counts.PersonCount = people.Count;
|
counts.PersonCount = people.Count;
|
||||||
|
|
||||||
var artists = items.OfType<Audio>().SelectMany(i =>
|
var artists = _libraryManager.GetAllArtists(items)
|
||||||
{
|
|
||||||
var list = new List<string>();
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(i.AlbumArtist))
|
|
||||||
{
|
|
||||||
list.Add(i.AlbumArtist);
|
|
||||||
}
|
|
||||||
list.AddRange(i.Artists);
|
|
||||||
|
|
||||||
return list;
|
|
||||||
})
|
|
||||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
|
||||||
.Select(i =>
|
.Select(i =>
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -477,13 +465,16 @@ namespace MediaBrowser.Api
|
|||||||
|
|
||||||
if (item.LocationType == LocationType.FileSystem)
|
if (item.LocationType == LocationType.FileSystem)
|
||||||
{
|
{
|
||||||
if (Directory.Exists(item.Path))
|
foreach (var path in item.GetDeletePaths().ToList())
|
||||||
{
|
{
|
||||||
Directory.Delete(item.Path, true);
|
if (Directory.Exists(path))
|
||||||
|
{
|
||||||
|
Directory.Delete(path, true);
|
||||||
}
|
}
|
||||||
else if (File.Exists(item.Path))
|
else if (File.Exists(path))
|
||||||
{
|
{
|
||||||
File.Delete(item.Path);
|
File.Delete(path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parent != null)
|
if (parent != null)
|
||||||
@ -521,13 +512,13 @@ namespace MediaBrowser.Api
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
/// <returns>Task{ItemReviewsResult}.</returns>
|
/// <returns>Task{ItemReviewsResult}.</returns>
|
||||||
private ItemReviewsResult GetCriticReviews(GetCriticReviews request)
|
private QueryResult<ItemReview> GetCriticReviews(GetCriticReviews request)
|
||||||
{
|
{
|
||||||
var reviews = _itemRepo.GetCriticReviews(new Guid(request.Id));
|
var reviews = _itemRepo.GetCriticReviews(new Guid(request.Id));
|
||||||
|
|
||||||
var reviewsArray = reviews.ToArray();
|
var reviewsArray = reviews.ToArray();
|
||||||
|
|
||||||
var result = new ItemReviewsResult
|
var result = new QueryResult<ItemReview>
|
||||||
{
|
{
|
||||||
TotalRecordCount = reviewsArray.Length
|
TotalRecordCount = reviewsArray.Length
|
||||||
};
|
};
|
||||||
@ -541,7 +532,7 @@ namespace MediaBrowser.Api
|
|||||||
reviewsArray = reviewsArray.Take(request.Limit.Value).ToArray();
|
reviewsArray = reviewsArray.Take(request.Limit.Value).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
result.ItemReviews = reviewsArray;
|
result.Items = reviewsArray;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -681,6 +672,11 @@ namespace MediaBrowser.Api
|
|||||||
{
|
{
|
||||||
var album = originalItem as MusicAlbum;
|
var album = originalItem as MusicAlbum;
|
||||||
|
|
||||||
|
if (album == null)
|
||||||
|
{
|
||||||
|
album = originalItem.Parents.OfType<MusicAlbum>().FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
if (album != null)
|
if (album != null)
|
||||||
{
|
{
|
||||||
var linkedItemWithThemes = album.SoundtrackIds
|
var linkedItemWithThemes = album.SoundtrackIds
|
||||||
@ -744,17 +740,12 @@ namespace MediaBrowser.Api
|
|||||||
: (Folder)_libraryManager.RootFolder)
|
: (Folder)_libraryManager.RootFolder)
|
||||||
: _dtoService.GetItemByDtoId(id, userId);
|
: _dtoService.GetItemByDtoId(id, userId);
|
||||||
|
|
||||||
while (GetSoundtrackSongIds(item).Count == 0 && inheritFromParent && item.Parent != null)
|
|
||||||
{
|
|
||||||
item = item.Parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get everything
|
// Get everything
|
||||||
var fields = Enum.GetNames(typeof(ItemFields))
|
var fields = Enum.GetNames(typeof(ItemFields))
|
||||||
.Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
|
.Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var dtos = GetSoundtrackSongIds(item)
|
var dtos = GetSoundtrackSongIds(item, inheritFromParent)
|
||||||
.Select(_libraryManager.GetItemById)
|
.Select(_libraryManager.GetItemById)
|
||||||
.OfType<MusicAlbum>()
|
.OfType<MusicAlbum>()
|
||||||
.SelectMany(i => i.RecursiveChildren)
|
.SelectMany(i => i.RecursiveChildren)
|
||||||
@ -772,7 +763,7 @@ namespace MediaBrowser.Api
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Guid> GetSoundtrackSongIds(BaseItem item)
|
private IEnumerable<Guid> GetSoundtrackSongIds(BaseItem item, bool inherit)
|
||||||
{
|
{
|
||||||
var hasSoundtracks = item as IHasSoundtracks;
|
var hasSoundtracks = item as IHasSoundtracks;
|
||||||
|
|
||||||
@ -781,7 +772,14 @@ namespace MediaBrowser.Api
|
|||||||
return hasSoundtracks.SoundtrackIds;
|
return hasSoundtracks.SoundtrackIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new List<Guid>();
|
if (!inherit)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasSoundtracks = item.Parents.OfType<IHasSoundtracks>().FirstOrDefault();
|
||||||
|
|
||||||
|
return hasSoundtracks != null ? hasSoundtracks.SoundtrackIds : new List<Guid>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
using MediaBrowser.Controller.LiveTv;
|
using MediaBrowser.Controller.LiveTv;
|
||||||
using MediaBrowser.Model.LiveTv;
|
using MediaBrowser.Model.LiveTv;
|
||||||
|
using MediaBrowser.Model.Querying;
|
||||||
using ServiceStack.ServiceHost;
|
using ServiceStack.ServiceHost;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@ -18,29 +20,99 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
|
|
||||||
[Route("/LiveTv/Channels", "GET")]
|
[Route("/LiveTv/Channels", "GET")]
|
||||||
[Api(Description = "Gets available live tv channels.")]
|
[Api(Description = "Gets available live tv channels.")]
|
||||||
public class GetChannels : IReturn<List<ChannelInfoDto>>
|
public class GetChannels : IReturn<QueryResult<ChannelInfoDto>>
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "ServiceName", Description = "Optional filter by service.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "ServiceName", Description = "Optional filter by service.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
public string ServiceName { get; set; }
|
public string ServiceName { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "Type", Description = "Optional filter by channel type.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public ChannelType? Type { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "UserId", Description = "Optional filter by user id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string UserId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Route("/LiveTv/Channels/{Id}", "GET")]
|
||||||
|
[Api(Description = "Gets a live tv channel")]
|
||||||
|
public class GetChannel : IReturn<ChannelInfoDto>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the id.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The id.</value>
|
||||||
|
[ApiMember(Name = "Id", Description = "Channel Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "UserId", Description = "Optional user id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string UserId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Recordings", "GET")]
|
[Route("/LiveTv/Recordings", "GET")]
|
||||||
[Api(Description = "Gets available live tv recordings.")]
|
[Api(Description = "Gets live tv recordings")]
|
||||||
public class GetRecordings : IReturn<List<RecordingInfo>>
|
public class GetRecordings : IReturn<QueryResult<RecordingInfoDto>>
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "ServiceName", Description = "Optional filter by service.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "ServiceName", Description = "Optional filter by service.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
public string ServiceName { get; set; }
|
public string ServiceName { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "ChannelId", Description = "Optional filter by channel id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string ChannelId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Guide", "GET")]
|
[Route("/LiveTv/Recordings/{Id}", "GET")]
|
||||||
[Api(Description = "Gets available live tv epgs..")]
|
[Api(Description = "Gets a live tv recording")]
|
||||||
public class GetGuide : IReturn<List<ChannelGuide>>
|
public class GetRecording : IReturn<RecordingInfoDto>
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "ServiceName", Description = "Live tv service name", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "Id", Description = "Recording Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||||
|
public string Id { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Route("/LiveTv/Timers/{Id}", "GET")]
|
||||||
|
[Api(Description = "Gets a live tv timer")]
|
||||||
|
public class GetTimer : IReturn<TimerInfoDto>
|
||||||
|
{
|
||||||
|
[ApiMember(Name = "Id", Description = "Timer Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||||
|
public string Id { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Route("/LiveTv/Timers", "GET")]
|
||||||
|
[Api(Description = "Gets live tv timers")]
|
||||||
|
public class GetTimers : IReturn<QueryResult<TimerInfoDto>>
|
||||||
|
{
|
||||||
|
[ApiMember(Name = "ServiceName", Description = "Optional filter by service.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
public string ServiceName { get; set; }
|
public string ServiceName { get; set; }
|
||||||
|
|
||||||
[ApiMember(Name = "ChannelIds", Description = "The channels to return guide information for.", IsRequired = true, 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; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Route("/LiveTv/Programs", "GET")]
|
||||||
|
[Api(Description = "Gets available live tv epgs..")]
|
||||||
|
public class GetPrograms : IReturn<QueryResult<ProgramInfoDto>>
|
||||||
|
{
|
||||||
|
[ApiMember(Name = "ServiceName", Description = "Live tv service name", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string ServiceName { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "ChannelIds", Description = "The channels to return guide information for.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
public string ChannelIds { get; set; }
|
public string ChannelIds { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "UserId", Description = "Optional filter by user id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string UserId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Route("/LiveTv/Recordings/{Id}", "DELETE")]
|
||||||
|
[Api(Description = "Deletes a live tv recording")]
|
||||||
|
public class DeleteRecording : IReturnVoid
|
||||||
|
{
|
||||||
|
[ApiMember(Name = "Id", Description = "Recording Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||||
|
public string Id { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Route("/LiveTv/Timers/{Id}", "DELETE")]
|
||||||
|
[Api(Description = "Cancels a live tv timer")]
|
||||||
|
public class CancelTimer : IReturnVoid
|
||||||
|
{
|
||||||
|
[ApiMember(Name = "Id", Description = "Timer Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||||
|
public string Id { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LiveTvService : BaseApiService
|
public class LiveTvService : BaseApiService
|
||||||
@ -58,7 +130,7 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
|
|
||||||
if (!string.IsNullOrEmpty(serviceName))
|
if (!string.IsNullOrEmpty(serviceName))
|
||||||
{
|
{
|
||||||
services = services.Where(i => string.Equals(i.Name, serviceName, System.StringComparison.OrdinalIgnoreCase));
|
services = services.Where(i => string.Equals(i.Name, serviceName, StringComparison.OrdinalIgnoreCase));
|
||||||
}
|
}
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
@ -83,62 +155,87 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
|
|
||||||
public object Get(GetChannels request)
|
public object Get(GetChannels request)
|
||||||
{
|
{
|
||||||
var result = GetChannelsAsync(request).Result;
|
var result = _liveTvManager.GetChannels(new ChannelQuery
|
||||||
|
|
||||||
return ToOptimizedResult(result.ToList());
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<IEnumerable<ChannelInfoDto>> GetChannelsAsync(GetChannels request)
|
|
||||||
{
|
{
|
||||||
var services = GetServices(request.ServiceName);
|
ChannelType = request.Type,
|
||||||
|
ServiceName = request.ServiceName,
|
||||||
|
UserId = request.UserId
|
||||||
|
|
||||||
var tasks = services.Select(i => i.GetChannelsAsync(CancellationToken.None));
|
});
|
||||||
|
|
||||||
var channelLists = await Task.WhenAll(tasks).ConfigureAwait(false);
|
|
||||||
|
|
||||||
// Aggregate all channels from all services
|
|
||||||
return channelLists.SelectMany(i => i)
|
|
||||||
.Select(_liveTvManager.GetChannelInfoDto);
|
|
||||||
}
|
|
||||||
|
|
||||||
public object Get(GetRecordings request)
|
|
||||||
{
|
|
||||||
var result = GetRecordingsAsync(request).Result;
|
|
||||||
|
|
||||||
return ToOptimizedResult(result.ToList());
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<IEnumerable<RecordingInfo>> GetRecordingsAsync(GetRecordings request)
|
|
||||||
{
|
|
||||||
var services = GetServices(request.ServiceName);
|
|
||||||
|
|
||||||
var query = new RecordingQuery
|
|
||||||
{
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
var tasks = services.Select(i => i.GetRecordingsAsync(query, CancellationToken.None));
|
|
||||||
|
|
||||||
var recordings = await Task.WhenAll(tasks).ConfigureAwait(false);
|
|
||||||
|
|
||||||
return recordings.SelectMany(i => i);
|
|
||||||
}
|
|
||||||
|
|
||||||
public object Get(GetGuide request)
|
|
||||||
{
|
|
||||||
var result = GetGuideAsync(request).Result;
|
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<IEnumerable<ChannelGuide>> GetGuideAsync(GetGuide request)
|
public object Get(GetChannel request)
|
||||||
{
|
{
|
||||||
var service = GetServices(request.ServiceName)
|
var result = _liveTvManager.GetChannelInfoDto(request.Id, request.UserId);
|
||||||
.First();
|
|
||||||
|
|
||||||
var channels = request.ChannelIds.Split(',');
|
return ToOptimizedResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
return await service.GetChannelGuidesAsync(channels, CancellationToken.None).ConfigureAwait(false);
|
public object Get(GetPrograms request)
|
||||||
|
{
|
||||||
|
var result = _liveTvManager.GetPrograms(new ProgramQuery
|
||||||
|
{
|
||||||
|
ServiceName = request.ServiceName,
|
||||||
|
ChannelIdList = (request.ChannelIds ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToArray(),
|
||||||
|
UserId = request.UserId
|
||||||
|
|
||||||
|
}, CancellationToken.None).Result;
|
||||||
|
|
||||||
|
return ToOptimizedResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Get(GetRecordings request)
|
||||||
|
{
|
||||||
|
var result = _liveTvManager.GetRecordings(new RecordingQuery
|
||||||
|
{
|
||||||
|
ChannelId = request.ChannelId,
|
||||||
|
ServiceName = request.ServiceName
|
||||||
|
|
||||||
|
}, CancellationToken.None).Result;
|
||||||
|
|
||||||
|
return ToOptimizedResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Get(GetRecording request)
|
||||||
|
{
|
||||||
|
var result = _liveTvManager.GetRecording(request.Id, CancellationToken.None).Result;
|
||||||
|
|
||||||
|
return ToOptimizedResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Get(GetTimer request)
|
||||||
|
{
|
||||||
|
var result = _liveTvManager.GetTimer(request.Id, CancellationToken.None).Result;
|
||||||
|
|
||||||
|
return ToOptimizedResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Get(GetTimers request)
|
||||||
|
{
|
||||||
|
var result = _liveTvManager.GetTimers(new TimerQuery
|
||||||
|
{
|
||||||
|
ChannelId = request.ChannelId,
|
||||||
|
ServiceName = request.ServiceName
|
||||||
|
|
||||||
|
}, CancellationToken.None).Result;
|
||||||
|
|
||||||
|
return ToOptimizedResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Delete(DeleteRecording request)
|
||||||
|
{
|
||||||
|
var task = _liveTvManager.DeleteRecording(request.Id);
|
||||||
|
|
||||||
|
Task.WaitAll(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Delete(CancelTimer request)
|
||||||
|
{
|
||||||
|
var task = _liveTvManager.CancelTimer(request.Id);
|
||||||
|
|
||||||
|
Task.WaitAll(task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -38,6 +38,18 @@
|
|||||||
<RunPostBuildEvent>Always</RunPostBuildEvent>
|
<RunPostBuildEvent>Always</RunPostBuildEvent>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Reference Include="ServiceStack.Common, Version=3.9.70.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>..\packages\ServiceStack.Common.3.9.70\lib\net35\ServiceStack.Common.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="ServiceStack.Interfaces, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>..\packages\ServiceStack.Common.3.9.70\lib\net35\ServiceStack.Interfaces.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="ServiceStack.Text, Version=3.9.70.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>..\packages\ServiceStack.Text.3.9.70\lib\net35\ServiceStack.Text.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
@ -47,15 +59,6 @@
|
|||||||
<Reference Include="MoreLinq">
|
<Reference Include="MoreLinq">
|
||||||
<HintPath>..\packages\morelinq.1.0.16006\lib\net35\MoreLinq.dll</HintPath>
|
<HintPath>..\packages\morelinq.1.0.16006\lib\net35\MoreLinq.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="ServiceStack.Common">
|
|
||||||
<HintPath>..\packages\ServiceStack.Common.3.9.62\lib\net35\ServiceStack.Common.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="ServiceStack.Interfaces">
|
|
||||||
<HintPath>..\packages\ServiceStack.Common.3.9.62\lib\net35\ServiceStack.Interfaces.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="ServiceStack.Text">
|
|
||||||
<HintPath>..\packages\ServiceStack.Text.3.9.62\lib\net35\ServiceStack.Text.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -70,6 +73,7 @@
|
|||||||
<Compile Include="EnvironmentService.cs" />
|
<Compile Include="EnvironmentService.cs" />
|
||||||
<Compile Include="AuthorizationRequestFilterAttribute.cs" />
|
<Compile Include="AuthorizationRequestFilterAttribute.cs" />
|
||||||
<Compile Include="GamesService.cs" />
|
<Compile Include="GamesService.cs" />
|
||||||
|
<Compile Include="IHasItemFields.cs" />
|
||||||
<Compile Include="Images\ImageByNameService.cs" />
|
<Compile Include="Images\ImageByNameService.cs" />
|
||||||
<Compile Include="Images\ImageRequest.cs" />
|
<Compile Include="Images\ImageRequest.cs" />
|
||||||
<Compile Include="Images\ImageService.cs" />
|
<Compile Include="Images\ImageService.cs" />
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using System.Globalization;
|
using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Common.Extensions;
|
|
||||||
using MediaBrowser.Common.IO;
|
using MediaBrowser.Common.IO;
|
||||||
using MediaBrowser.Common.MediaInfo;
|
using MediaBrowser.Common.MediaInfo;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
@ -11,15 +10,15 @@ using MediaBrowser.Controller.MediaInfo;
|
|||||||
using MediaBrowser.Model.Drawing;
|
using MediaBrowser.Model.Drawing;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
|
using MediaBrowser.Model.IO;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.IO;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Api.Playback
|
namespace MediaBrowser.Api.Playback
|
||||||
{
|
{
|
||||||
@ -696,7 +695,7 @@ namespace MediaBrowser.Api.Playback
|
|||||||
// This is arbitrary, but add a little buffer time when internet streaming
|
// This is arbitrary, but add a little buffer time when internet streaming
|
||||||
if (state.Item.LocationType == LocationType.Remote)
|
if (state.Item.LocationType == LocationType.Remote)
|
||||||
{
|
{
|
||||||
await Task.Delay(2000).ConfigureAwait(false);
|
await Task.Delay(4000).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
}
|
}
|
||||||
|
|
||||||
var volParam = string.Empty;
|
var volParam = string.Empty;
|
||||||
var AudioSampleRate = string.Empty;
|
var audioSampleRate = string.Empty;
|
||||||
|
|
||||||
// Boost volume to 200% when downsampling from 6ch to 2ch
|
// Boost volume to 200% when downsampling from 6ch to 2ch
|
||||||
if (channels.HasValue && channels.Value <= 2 && state.AudioStream.Channels.HasValue && state.AudioStream.Channels.Value > 5)
|
if (channels.HasValue && channels.Value <= 2 && state.AudioStream.Channels.HasValue && state.AudioStream.Channels.Value > 5)
|
||||||
@ -98,10 +98,10 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
|
|
||||||
if (state.Request.AudioSampleRate.HasValue)
|
if (state.Request.AudioSampleRate.HasValue)
|
||||||
{
|
{
|
||||||
AudioSampleRate= state.Request.AudioSampleRate.Value + ":";
|
audioSampleRate= state.Request.AudioSampleRate.Value + ":";
|
||||||
}
|
}
|
||||||
|
|
||||||
args += string.Format(" -af \"adelay=1,aresample={0}async=1000{1}\"",AudioSampleRate, volParam);
|
args += string.Format(" -af \"adelay=1,aresample={0}async=1000{1}\"",audioSampleRate, volParam);
|
||||||
|
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
@ -127,6 +127,10 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
|
|
||||||
const string keyFrameArg = " -force_key_frames expr:if(isnan(prev_forced_t),gte(t,.1),gte(t,prev_forced_t+5))";
|
const string keyFrameArg = " -force_key_frames expr:if(isnan(prev_forced_t),gte(t,.1),gte(t,prev_forced_t+5))";
|
||||||
|
|
||||||
|
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsExternal &&
|
||||||
|
(state.SubtitleStream.Codec.IndexOf("pgs", StringComparison.OrdinalIgnoreCase) != -1 ||
|
||||||
|
state.SubtitleStream.Codec.IndexOf("dvd", StringComparison.OrdinalIgnoreCase) != -1);
|
||||||
|
|
||||||
var args = "-codec:v:0 " + codec + " -preset superfast" + keyFrameArg;
|
var args = "-codec:v:0 " + codec + " -preset superfast" + keyFrameArg;
|
||||||
|
|
||||||
var bitrate = GetVideoBitrateParam(state);
|
var bitrate = GetVideoBitrateParam(state);
|
||||||
@ -137,10 +141,13 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add resolution params, if specified
|
// Add resolution params, if specified
|
||||||
|
if (!hasGraphicalSubs)
|
||||||
|
{
|
||||||
if (state.VideoRequest.Width.HasValue || state.VideoRequest.Height.HasValue || state.VideoRequest.MaxHeight.HasValue || state.VideoRequest.MaxWidth.HasValue)
|
if (state.VideoRequest.Width.HasValue || state.VideoRequest.Height.HasValue || state.VideoRequest.MaxHeight.HasValue || state.VideoRequest.MaxWidth.HasValue)
|
||||||
{
|
{
|
||||||
args += GetOutputSizeParam(state, codec, performSubtitleConversion);
|
args += GetOutputSizeParam(state, codec, performSubtitleConversion);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (state.VideoRequest.Framerate.HasValue)
|
if (state.VideoRequest.Framerate.HasValue)
|
||||||
{
|
{
|
||||||
@ -159,14 +166,11 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
args += " -level " + state.VideoRequest.Level;
|
args += " -level " + state.VideoRequest.Level;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.SubtitleStream != null)
|
|
||||||
{
|
|
||||||
// This is for internal graphical subs
|
// This is for internal graphical subs
|
||||||
if (!state.SubtitleStream.IsExternal && (state.SubtitleStream.Codec.IndexOf("pgs", StringComparison.OrdinalIgnoreCase) != -1 || state.SubtitleStream.Codec.IndexOf("dvd", StringComparison.OrdinalIgnoreCase) != -1))
|
if (hasGraphicalSubs)
|
||||||
{
|
{
|
||||||
args += GetInternalGraphicalSubtitleParam(state, codec);
|
args += GetInternalGraphicalSubtitleParam(state, codec);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
@ -127,44 +127,44 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
|
|
||||||
const string dlnaflags = ";DLNA.ORG_FLAGS=01500000000000000000000000000000";
|
const string dlnaflags = ";DLNA.ORG_FLAGS=01500000000000000000000000000000";
|
||||||
|
|
||||||
if (string.Equals(extension, ".mp3", StringComparison.OrdinalIgnoreCase))
|
//if (string.Equals(extension, ".mp3", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
//{
|
||||||
contentFeatures = "DLNA.ORG_PN=MP3";
|
// contentFeatures = "DLNA.ORG_PN=MP3";
|
||||||
}
|
//}
|
||||||
else if (string.Equals(extension, ".aac", StringComparison.OrdinalIgnoreCase))
|
//else if (string.Equals(extension, ".aac", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
//{
|
||||||
contentFeatures = "DLNA.ORG_PN=AAC_ISO";
|
// contentFeatures = "DLNA.ORG_PN=AAC_ISO";
|
||||||
}
|
//}
|
||||||
else if (string.Equals(extension, ".wma", StringComparison.OrdinalIgnoreCase))
|
//else if (string.Equals(extension, ".wma", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
//{
|
||||||
contentFeatures = "DLNA.ORG_PN=WMABASE";
|
// contentFeatures = "DLNA.ORG_PN=WMABASE";
|
||||||
}
|
//}
|
||||||
else if (string.Equals(extension, ".avi", StringComparison.OrdinalIgnoreCase))
|
//else if (string.Equals(extension, ".avi", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
//{
|
||||||
contentFeatures = "DLNA.ORG_PN=AVI";
|
// contentFeatures = "DLNA.ORG_PN=AVI";
|
||||||
}
|
//}
|
||||||
else if (string.Equals(extension, ".mp4", StringComparison.OrdinalIgnoreCase))
|
//else if (string.Equals(extension, ".mp4", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
//{
|
||||||
contentFeatures = "DLNA.ORG_PN=MPEG4_P2_SP_AAC";
|
// contentFeatures = "DLNA.ORG_PN=MPEG4_P2_SP_AAC";
|
||||||
}
|
//}
|
||||||
else if (string.Equals(extension, ".mpeg", StringComparison.OrdinalIgnoreCase))
|
//else if (string.Equals(extension, ".mpeg", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
//{
|
||||||
contentFeatures = "DLNA.ORG_PN=MPEG_PS_PAL";
|
// contentFeatures = "DLNA.ORG_PN=MPEG_PS_PAL";
|
||||||
}
|
//}
|
||||||
else if (string.Equals(extension, ".wmv", StringComparison.OrdinalIgnoreCase))
|
//else if (string.Equals(extension, ".wmv", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
//{
|
||||||
contentFeatures = "DLNA.ORG_PN=WMVHIGH_BASE";
|
// contentFeatures = "DLNA.ORG_PN=WMVHIGH_BASE";
|
||||||
}
|
//}
|
||||||
else if (string.Equals(extension, ".asf", StringComparison.OrdinalIgnoreCase))
|
//else if (string.Equals(extension, ".asf", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
//{
|
||||||
// ??
|
// // ??
|
||||||
contentFeatures = "DLNA.ORG_PN=WMVHIGH_BASE";
|
// contentFeatures = "DLNA.ORG_PN=WMVHIGH_BASE";
|
||||||
}
|
//}
|
||||||
else if (string.Equals(extension, ".mkv", StringComparison.OrdinalIgnoreCase))
|
//else if (string.Equals(extension, ".mkv", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
//{
|
||||||
// ??
|
// // ??
|
||||||
contentFeatures = "";
|
// contentFeatures = "";
|
||||||
}
|
//}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(contentFeatures))
|
if (!string.IsNullOrEmpty(contentFeatures))
|
||||||
{
|
{
|
||||||
@ -206,10 +206,10 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
var outputPath = GetOutputFilePath(state);
|
var outputPath = GetOutputFilePath(state);
|
||||||
var outputPathExists = File.Exists(outputPath);
|
var outputPathExists = File.Exists(outputPath);
|
||||||
|
|
||||||
//var isStatic = request.Static ||
|
var isStatic = request.Static ||
|
||||||
// (outputPathExists && !ApiEntryPoint.Instance.HasActiveTranscodingJob(outputPath, TranscodingJobType.Progressive));
|
(outputPathExists && !ApiEntryPoint.Instance.HasActiveTranscodingJob(outputPath, TranscodingJobType.Progressive));
|
||||||
|
|
||||||
//AddDlnaHeaders(state, responseHeaders, isStatic);
|
AddDlnaHeaders(state, responseHeaders, isStatic);
|
||||||
|
|
||||||
if (request.Static)
|
if (request.Static)
|
||||||
{
|
{
|
||||||
@ -307,7 +307,7 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ImageService(UserManager, LibraryManager, ApplicationPaths, null, ItemRepository, DtoService, ImageProcessor)
|
return new ImageService(UserManager, LibraryManager, ApplicationPaths, null, ItemRepository, DtoService, ImageProcessor, null)
|
||||||
{
|
{
|
||||||
Logger = Logger,
|
Logger = Logger,
|
||||||
RequestContext = RequestContext,
|
RequestContext = RequestContext,
|
||||||
|
@ -143,13 +143,20 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
|
|
||||||
args += keyFrameArg;
|
args += keyFrameArg;
|
||||||
|
|
||||||
|
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsExternal &&
|
||||||
|
(state.SubtitleStream.Codec.IndexOf("pgs", StringComparison.OrdinalIgnoreCase) != -1 ||
|
||||||
|
state.SubtitleStream.Codec.IndexOf("dvd", StringComparison.OrdinalIgnoreCase) != -1);
|
||||||
|
|
||||||
var request = state.VideoRequest;
|
var request = state.VideoRequest;
|
||||||
|
|
||||||
// Add resolution params, if specified
|
// Add resolution params, if specified
|
||||||
|
if (!hasGraphicalSubs)
|
||||||
|
{
|
||||||
if (request.Width.HasValue || request.Height.HasValue || request.MaxHeight.HasValue || request.MaxWidth.HasValue)
|
if (request.Width.HasValue || request.Height.HasValue || request.MaxHeight.HasValue || request.MaxWidth.HasValue)
|
||||||
{
|
{
|
||||||
args += GetOutputSizeParam(state, codec, performSubtitleConversion);
|
args += GetOutputSizeParam(state, codec, performSubtitleConversion);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (request.Framerate.HasValue)
|
if (request.Framerate.HasValue)
|
||||||
{
|
{
|
||||||
@ -175,14 +182,11 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
args += " -level " + state.VideoRequest.Level;
|
args += " -level " + state.VideoRequest.Level;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.SubtitleStream != null)
|
|
||||||
{
|
|
||||||
// This is for internal graphical subs
|
// This is for internal graphical subs
|
||||||
if (!state.SubtitleStream.IsExternal && (state.SubtitleStream.Codec.IndexOf("pgs", StringComparison.OrdinalIgnoreCase) != -1 || state.SubtitleStream.Codec.IndexOf("dvd", StringComparison.OrdinalIgnoreCase) != -1))
|
if (hasGraphicalSubs)
|
||||||
{
|
{
|
||||||
args += GetInternalGraphicalSubtitleParam(state, codec);
|
args += GetInternalGraphicalSubtitleParam(state, codec);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,8 @@ namespace MediaBrowser.Api.ScheduledTasks
|
|||||||
[Api(Description = "Gets scheduled tasks")]
|
[Api(Description = "Gets scheduled tasks")]
|
||||||
public class GetScheduledTasks : IReturn<List<TaskInfo>>
|
public class GetScheduledTasks : IReturn<List<TaskInfo>>
|
||||||
{
|
{
|
||||||
|
[ApiMember(Name = "IsHidden", Description = "Optional filter tasks that are hidden, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool? IsHidden { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -112,10 +113,33 @@ namespace MediaBrowser.Api.ScheduledTasks
|
|||||||
/// <returns>IEnumerable{TaskInfo}.</returns>
|
/// <returns>IEnumerable{TaskInfo}.</returns>
|
||||||
public object Get(GetScheduledTasks request)
|
public object Get(GetScheduledTasks request)
|
||||||
{
|
{
|
||||||
var result = TaskManager.ScheduledTasks.OrderBy(i => i.Name)
|
IEnumerable<IScheduledTaskWorker> result = TaskManager.ScheduledTasks
|
||||||
.Select(ScheduledTaskHelpers.GetTaskInfo).ToList();
|
.OrderBy(i => i.Name);
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
if (request.IsHidden.HasValue)
|
||||||
|
{
|
||||||
|
var val = request.IsHidden.Value;
|
||||||
|
|
||||||
|
result = result.Where(i =>
|
||||||
|
{
|
||||||
|
var isHidden = false;
|
||||||
|
|
||||||
|
var configurableTask = i.ScheduledTask as IConfigurableScheduledTask;
|
||||||
|
|
||||||
|
if (configurableTask != null)
|
||||||
|
{
|
||||||
|
isHidden = configurableTask.IsHidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isHidden == val;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var infos = result
|
||||||
|
.Select(ScheduledTaskHelpers.GetTaskInfo)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
return ToOptimizedResult(infos);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -46,8 +46,10 @@ namespace MediaBrowser.Api.ScheduledTasks
|
|||||||
/// <returns>Task{IEnumerable{TaskInfo}}.</returns>
|
/// <returns>Task{IEnumerable{TaskInfo}}.</returns>
|
||||||
protected override Task<IEnumerable<TaskInfo>> GetDataToSend(object state)
|
protected override Task<IEnumerable<TaskInfo>> GetDataToSend(object state)
|
||||||
{
|
{
|
||||||
return Task.FromResult(TaskManager.ScheduledTasks.OrderBy(i => i.Name)
|
return Task.FromResult(TaskManager.ScheduledTasks
|
||||||
.Select(ScheduledTaskHelpers.GetTaskInfo));
|
.OrderBy(i => i.Name)
|
||||||
|
.Select(ScheduledTaskHelpers.GetTaskInfo)
|
||||||
|
.Where(i => !i.IsHidden));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,7 +144,7 @@ namespace MediaBrowser.Api
|
|||||||
IndexNumber = item.IndexNumber,
|
IndexNumber = item.IndexNumber,
|
||||||
ParentIndexNumber = item.ParentIndexNumber,
|
ParentIndexNumber = item.ParentIndexNumber,
|
||||||
ItemId = _dtoService.GetDtoId(item),
|
ItemId = _dtoService.GetDtoId(item),
|
||||||
Type = item.GetType().Name,
|
Type = item.GetClientTypeName(),
|
||||||
MediaType = item.MediaType,
|
MediaType = item.MediaType,
|
||||||
MatchedTerm = hintInfo.MatchedTerm,
|
MatchedTerm = hintInfo.MatchedTerm,
|
||||||
DisplayMediaType = item.DisplayMediaType,
|
DisplayMediaType = item.DisplayMediaType,
|
||||||
@ -187,9 +187,7 @@ namespace MediaBrowser.Api
|
|||||||
|
|
||||||
result.SongCount = songs.Count;
|
result.SongCount = songs.Count;
|
||||||
|
|
||||||
result.Artists = songs
|
result.Artists = _libraryManager.GetAllArtists(songs)
|
||||||
.SelectMany(i => i.Artists)
|
|
||||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
result.AlbumArtist = songs.Select(i => i.AlbumArtist).FirstOrDefault(i => !string.IsNullOrEmpty(i));
|
result.AlbumArtist = songs.Select(i => i.AlbumArtist).FirstOrDefault(i => !string.IsNullOrEmpty(i));
|
||||||
|
@ -25,7 +25,7 @@ namespace MediaBrowser.Api
|
|||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BaseGetSimilarItems : IReturn<ItemsResult>
|
public class BaseGetSimilarItems : IReturn<ItemsResult>, IHasItemFields
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the user id.
|
/// Gets or sets the user id.
|
||||||
@ -47,32 +47,6 @@ namespace MediaBrowser.Api
|
|||||||
/// <value>The fields.</value>
|
/// <value>The fields.</value>
|
||||||
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, OverviewHtml, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, OverviewHtml, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
public string Fields { get; set; }
|
public string Fields { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the item fields.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>IEnumerable{ItemFields}.</returns>
|
|
||||||
public IEnumerable<ItemFields> GetItemFields()
|
|
||||||
{
|
|
||||||
var val = Fields;
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(val))
|
|
||||||
{
|
|
||||||
return new ItemFields[] { };
|
|
||||||
}
|
|
||||||
|
|
||||||
return val.Split(',').Select(v =>
|
|
||||||
{
|
|
||||||
ItemFields value;
|
|
||||||
|
|
||||||
if (Enum.TryParse(v, true, out value))
|
|
||||||
{
|
|
||||||
return (ItemFields?)value;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
|
|
||||||
}).Where(i => i.HasValue).Select(i => i.Value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Api.UserLibrary;
|
||||||
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
@ -17,7 +18,7 @@ namespace MediaBrowser.Api
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/Shows/NextUp", "GET")]
|
[Route("/Shows/NextUp", "GET")]
|
||||||
[Api(("Gets a list of currently installed plugins"))]
|
[Api(("Gets a list of currently installed plugins"))]
|
||||||
public class GetNextUpEpisodes : IReturn<ItemsResult>
|
public class GetNextUpEpisodes : IReturn<ItemsResult>, IHasItemFields
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the user id.
|
/// Gets or sets the user id.
|
||||||
@ -49,32 +50,6 @@ namespace MediaBrowser.Api
|
|||||||
|
|
||||||
[ApiMember(Name = "SeriesId", Description = "Optional. Filter by series id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "SeriesId", Description = "Optional. Filter by series id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
public string SeriesId { get; set; }
|
public string SeriesId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the item fields.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>IEnumerable{ItemFields}.</returns>
|
|
||||||
public IEnumerable<ItemFields> GetItemFields()
|
|
||||||
{
|
|
||||||
var val = Fields;
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(val))
|
|
||||||
{
|
|
||||||
return new ItemFields[] { };
|
|
||||||
}
|
|
||||||
|
|
||||||
return val.Split(',').Select(v =>
|
|
||||||
{
|
|
||||||
ItemFields value;
|
|
||||||
|
|
||||||
if (Enum.TryParse(v, true, out value))
|
|
||||||
{
|
|
||||||
return (ItemFields?)value;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
|
|
||||||
}).Where(i => i.HasValue).Select(i => i.Value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/Shows/{Id}/Similar", "GET")]
|
[Route("/Shows/{Id}/Similar", "GET")]
|
||||||
@ -83,6 +58,77 @@ namespace MediaBrowser.Api
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Route("/Shows/{Id}/Episodes", "GET")]
|
||||||
|
[Api(Description = "Gets episodes for a tv season")]
|
||||||
|
public class GetEpisodes : IReturn<ItemsResult>, IHasItemFields
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the user id.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The user id.</value>
|
||||||
|
[ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public Guid UserId { 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, OverviewHtml, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
|
public string Fields { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "Id", Description = "The series id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "Season", Description = "Optional filter by season number.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public int? Season { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "SeasonId", Description = "Optional. Filter by season id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string SeasonId { 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 = "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 = "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; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Route("/Shows/{Id}/Seasons", "GET")]
|
||||||
|
[Api(Description = "Gets seasons for a tv series")]
|
||||||
|
public class GetSeasons : IReturn<ItemsResult>, IHasItemFields
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the user id.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The user id.</value>
|
||||||
|
[ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public Guid UserId { 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, OverviewHtml, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
|
public string Fields { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "Id", Description = "The series id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "IsSpecialSeason", Description = "Optional. Filter by special season.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool? IsSpecialSeason { 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 = "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 = "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; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class TvShowsService
|
/// Class TvShowsService
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -311,5 +357,196 @@ namespace MediaBrowser.Api
|
|||||||
|
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public object Get(GetSeasons request)
|
||||||
|
{
|
||||||
|
var user = _userManager.GetUserById(request.UserId);
|
||||||
|
|
||||||
|
var series = _libraryManager.GetItemById(request.Id) as Series;
|
||||||
|
|
||||||
|
var fields = request.GetItemFields().ToList();
|
||||||
|
|
||||||
|
var seasons = series.GetChildren(user, true)
|
||||||
|
.OfType<Season>();
|
||||||
|
|
||||||
|
var sortOrder = ItemSortBy.SortName;
|
||||||
|
|
||||||
|
if (request.IsSpecialSeason.HasValue)
|
||||||
|
{
|
||||||
|
var val = request.IsSpecialSeason.Value;
|
||||||
|
|
||||||
|
seasons = seasons.Where(i => i.IsSpecialSeason == val);
|
||||||
|
}
|
||||||
|
|
||||||
|
var config = user.Configuration;
|
||||||
|
|
||||||
|
if (!config.DisplayMissingEpisodes && !config.DisplayUnairedEpisodes)
|
||||||
|
{
|
||||||
|
seasons = seasons.Where(i => !i.IsMissingOrVirtualUnaired);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!config.DisplayMissingEpisodes)
|
||||||
|
{
|
||||||
|
seasons = seasons.Where(i => !i.IsMissingSeason);
|
||||||
|
}
|
||||||
|
if (!config.DisplayUnairedEpisodes)
|
||||||
|
{
|
||||||
|
seasons = seasons.Where(i => !i.IsVirtualUnaired);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
seasons = FilterVirtualSeasons(request, seasons);
|
||||||
|
|
||||||
|
seasons = _libraryManager.Sort(seasons, user, new[] { sortOrder }, SortOrder.Ascending)
|
||||||
|
.Cast<Season>();
|
||||||
|
|
||||||
|
// This must be the last filter
|
||||||
|
if (!string.IsNullOrEmpty(request.AdjacentTo))
|
||||||
|
{
|
||||||
|
seasons = ItemsService.FilterForAdjacency(seasons, request.AdjacentTo)
|
||||||
|
.Cast<Season>();
|
||||||
|
}
|
||||||
|
|
||||||
|
var returnItems = seasons.Select(i => _dtoService.GetBaseItemDto(i, fields, user))
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
return new ItemsResult
|
||||||
|
{
|
||||||
|
TotalRecordCount = returnItems.Length,
|
||||||
|
Items = returnItems
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<Season> FilterVirtualSeasons(GetSeasons request, IEnumerable<Season> items)
|
||||||
|
{
|
||||||
|
if (request.IsMissing.HasValue && request.IsVirtualUnaired.HasValue)
|
||||||
|
{
|
||||||
|
var isMissing = request.IsMissing.Value;
|
||||||
|
var isVirtualUnaired = request.IsVirtualUnaired.Value;
|
||||||
|
|
||||||
|
if (!isMissing && !isVirtualUnaired)
|
||||||
|
{
|
||||||
|
return items.Where(i => !i.IsMissingOrVirtualUnaired);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.IsMissing.HasValue)
|
||||||
|
{
|
||||||
|
var val = request.IsMissing.Value;
|
||||||
|
items = items.Where(i => i.IsMissingSeason == val);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.IsVirtualUnaired.HasValue)
|
||||||
|
{
|
||||||
|
var val = request.IsVirtualUnaired.Value;
|
||||||
|
items = items.Where(i => i.IsVirtualUnaired == val);
|
||||||
|
}
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Get(GetEpisodes request)
|
||||||
|
{
|
||||||
|
var user = _userManager.GetUserById(request.UserId);
|
||||||
|
|
||||||
|
var series = _libraryManager.GetItemById(request.Id) as Series;
|
||||||
|
|
||||||
|
var fields = request.GetItemFields().ToList();
|
||||||
|
|
||||||
|
var episodes = series.GetRecursiveChildren(user)
|
||||||
|
.OfType<Episode>();
|
||||||
|
|
||||||
|
var sortOrder = ItemSortBy.SortName;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(request.SeasonId))
|
||||||
|
{
|
||||||
|
var season = _libraryManager.GetItemById(new Guid(request.SeasonId)) as Season;
|
||||||
|
|
||||||
|
if (season.IndexNumber.HasValue)
|
||||||
|
{
|
||||||
|
episodes = FilterEpisodesBySeason(episodes, season.IndexNumber.Value, true);
|
||||||
|
|
||||||
|
sortOrder = ItemSortBy.AiredEpisodeOrder;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
episodes = season.RecursiveChildren.OfType<Episode>();
|
||||||
|
|
||||||
|
sortOrder = ItemSortBy.SortName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (request.Season.HasValue)
|
||||||
|
{
|
||||||
|
episodes = FilterEpisodesBySeason(episodes, request.Season.Value, true);
|
||||||
|
|
||||||
|
sortOrder = ItemSortBy.AiredEpisodeOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
var config = user.Configuration;
|
||||||
|
|
||||||
|
if (!config.DisplayMissingEpisodes)
|
||||||
|
{
|
||||||
|
episodes = episodes.Where(i => !i.IsMissingEpisode);
|
||||||
|
}
|
||||||
|
if (!config.DisplayUnairedEpisodes)
|
||||||
|
{
|
||||||
|
episodes = episodes.Where(i => !i.IsVirtualUnaired);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.IsMissing.HasValue)
|
||||||
|
{
|
||||||
|
var val = request.IsMissing.Value;
|
||||||
|
episodes = episodes.Where(i => i.IsMissingEpisode == val);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.IsVirtualUnaired.HasValue)
|
||||||
|
{
|
||||||
|
var val = request.IsVirtualUnaired.Value;
|
||||||
|
episodes = episodes.Where(i => i.IsVirtualUnaired == val);
|
||||||
|
}
|
||||||
|
|
||||||
|
episodes = _libraryManager.Sort(episodes, user, new[] { sortOrder }, SortOrder.Ascending)
|
||||||
|
.Cast<Episode>();
|
||||||
|
|
||||||
|
// This must be the last filter
|
||||||
|
if (!string.IsNullOrEmpty(request.AdjacentTo))
|
||||||
|
{
|
||||||
|
episodes = ItemsService.FilterForAdjacency(episodes, request.AdjacentTo)
|
||||||
|
.Cast<Episode>();
|
||||||
|
}
|
||||||
|
|
||||||
|
var returnItems = episodes.Select(i => _dtoService.GetBaseItemDto(i, fields, user))
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
return new ItemsResult
|
||||||
|
{
|
||||||
|
TotalRecordCount = returnItems.Length,
|
||||||
|
Items = returnItems
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static IEnumerable<Episode> FilterEpisodesBySeason(IEnumerable<Episode> episodes, int seasonNumber, bool includeSpecials)
|
||||||
|
{
|
||||||
|
if (!includeSpecials || seasonNumber < 1)
|
||||||
|
{
|
||||||
|
return episodes.Where(i => (i.PhysicalSeasonNumber ?? -1) == seasonNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
return episodes.Where(i =>
|
||||||
|
{
|
||||||
|
var episode = i;
|
||||||
|
|
||||||
|
if (episode != null)
|
||||||
|
{
|
||||||
|
var currentSeasonNumber = episode.AiredSeasonNumber;
|
||||||
|
|
||||||
|
return currentSeasonNumber.HasValue && currentSeasonNumber.Value == seasonNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class ArtistsService
|
/// Class ArtistsService
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ArtistsService : BaseItemsByNameService<Artist>
|
public class ArtistsService : BaseItemsByNameService<MusicArtist>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ArtistsService" /> class.
|
/// Initializes a new instance of the <see cref="ArtistsService" /> class.
|
||||||
@ -109,24 +109,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<Artist> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items)
|
protected override IEnumerable<MusicArtist> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items)
|
||||||
{
|
{
|
||||||
var itemsList = items.OfType<Audio>().ToList();
|
return LibraryManager.GetAllArtists(items)
|
||||||
|
|
||||||
return itemsList
|
|
||||||
.SelectMany(i =>
|
|
||||||
{
|
|
||||||
var list = new List<string>();
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(i.AlbumArtist))
|
|
||||||
{
|
|
||||||
list.Add(i.AlbumArtist);
|
|
||||||
}
|
|
||||||
list.AddRange(i.Artists);
|
|
||||||
|
|
||||||
return list;
|
|
||||||
})
|
|
||||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
|
||||||
.Select(name => LibraryManager.GetArtist(name));
|
.Select(name => LibraryManager.GetArtist(name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ using System;
|
|||||||
|
|
||||||
namespace MediaBrowser.Api.UserLibrary
|
namespace MediaBrowser.Api.UserLibrary
|
||||||
{
|
{
|
||||||
public abstract class BaseItemsRequest
|
public abstract class BaseItemsRequest : IHasItemFields
|
||||||
{
|
{
|
||||||
/// <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.
|
||||||
@ -109,32 +109,6 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
return val.Split(',').Select(v => (ItemFilter)Enum.Parse(typeof(ItemFilter), v, true));
|
return val.Split(',').Select(v => (ItemFilter)Enum.Parse(typeof(ItemFilter), v, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the item fields.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>IEnumerable{ItemFields}.</returns>
|
|
||||||
public IEnumerable<ItemFields> GetItemFields()
|
|
||||||
{
|
|
||||||
var val = Fields;
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(val))
|
|
||||||
{
|
|
||||||
return new ItemFields[] { };
|
|
||||||
}
|
|
||||||
|
|
||||||
return val.Split(',').Select(v =>
|
|
||||||
{
|
|
||||||
ItemFields value;
|
|
||||||
|
|
||||||
if (Enum.TryParse(v, true, out value))
|
|
||||||
{
|
|
||||||
return (ItemFields?)value;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
|
|
||||||
}).Where(i => i.HasValue).Select(i => i.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the image types.
|
/// Gets the image types.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
using MediaBrowser.Controller.Dto;
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
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.Localization;
|
using MediaBrowser.Controller.Localization;
|
||||||
|
using MediaBrowser.Controller.Providers;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Querying;
|
||||||
using ServiceStack.ServiceHost;
|
using ServiceStack.ServiceHost;
|
||||||
@ -205,6 +208,27 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
|
|
||||||
[ApiMember(Name = "AiredDuringSeason", Description = "Gets all episodes that aired during a season, including specials.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
[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; }
|
public int? AiredDuringSeason { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "MinPremiereDate", Description = "Optional. The minimum premiere date. Format = yyyyMMddHHmmss", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
|
||||||
|
public string MinPremiereDate { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "MaxPremiereDate", Description = "Optional. The maximum premiere date. Format = yyyyMMddHHmmss", 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; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -286,6 +310,12 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
|
|
||||||
items = ApplySortOrder(request, items, user, _libraryManager);
|
items = ApplySortOrder(request, items, user, _libraryManager);
|
||||||
|
|
||||||
|
// This must be the last filter
|
||||||
|
if (!string.IsNullOrEmpty(request.AdjacentTo))
|
||||||
|
{
|
||||||
|
items = FilterForAdjacency(items, request.AdjacentTo);
|
||||||
|
}
|
||||||
|
|
||||||
var itemsArray = items.ToList();
|
var itemsArray = items.ToList();
|
||||||
|
|
||||||
var pagedItems = ApplyPaging(request, itemsArray);
|
var pagedItems = ApplyPaging(request, itemsArray);
|
||||||
@ -642,30 +672,6 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(request.AdjacentTo))
|
|
||||||
{
|
|
||||||
var item = _dtoService.GetItemByDtoId(request.AdjacentTo);
|
|
||||||
|
|
||||||
var allSiblings = item.Parent.GetChildren(user, true).OrderBy(i => i.SortName).ToList();
|
|
||||||
|
|
||||||
var index = allSiblings.IndexOf(item);
|
|
||||||
|
|
||||||
var previousId = Guid.Empty;
|
|
||||||
var nextId = Guid.Empty;
|
|
||||||
|
|
||||||
if (index > 0)
|
|
||||||
{
|
|
||||||
previousId = allSiblings[index - 1].Id;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index < allSiblings.Count - 1)
|
|
||||||
{
|
|
||||||
nextId = allSiblings[index + 1].Id;
|
|
||||||
}
|
|
||||||
|
|
||||||
items = items.Where(i => i.Id == previousId || i.Id == nextId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Min index number
|
// Min index number
|
||||||
if (request.MinIndexNumber.HasValue)
|
if (request.MinIndexNumber.HasValue)
|
||||||
{
|
{
|
||||||
@ -861,7 +867,19 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
|
|
||||||
if (request.HasTrailer.HasValue)
|
if (request.HasTrailer.HasValue)
|
||||||
{
|
{
|
||||||
items = items.Where(i => request.HasTrailer.Value ? i.LocalTrailerIds.Count > 0 : i.LocalTrailerIds.Count == 0);
|
var val = request.HasTrailer.Value;
|
||||||
|
items = items.Where(i =>
|
||||||
|
{
|
||||||
|
var trailerCount = 0;
|
||||||
|
|
||||||
|
var hasTrailers = i as IHasTrailers;
|
||||||
|
if (hasTrailers != null)
|
||||||
|
{
|
||||||
|
trailerCount = hasTrailers.LocalTrailerIds.Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return val ? trailerCount > 0 : trailerCount == 0;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.HasThemeSong.HasValue)
|
if (request.HasThemeSong.HasValue)
|
||||||
@ -1005,26 +1023,134 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
|
|
||||||
if (request.AiredDuringSeason.HasValue)
|
if (request.AiredDuringSeason.HasValue)
|
||||||
{
|
{
|
||||||
var val = request.AiredDuringSeason.Value;
|
items = TvShowsService.FilterEpisodesBySeason(items.OfType<Episode>(), request.AiredDuringSeason.Value, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(request.MinPremiereDate))
|
||||||
|
{
|
||||||
|
var date = DateTime.ParseExact(request.MinPremiereDate, "yyyyMMddHHmmss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
|
||||||
|
|
||||||
|
items = items.Where(i => i.PremiereDate.HasValue && i.PremiereDate.Value >= date);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(request.MaxPremiereDate))
|
||||||
|
{
|
||||||
|
var date = DateTime.ParseExact(request.MaxPremiereDate, "yyyyMMddHHmmss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
|
||||||
|
|
||||||
|
items = items.Where(i => i.PremiereDate.HasValue && i.PremiereDate.Value <= date);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.HasOverview.HasValue)
|
||||||
|
{
|
||||||
|
var filterValue = request.HasOverview.Value;
|
||||||
|
|
||||||
items = items.Where(i =>
|
items = items.Where(i =>
|
||||||
{
|
{
|
||||||
var episode = i as Episode;
|
var hasValue = !string.IsNullOrEmpty(i.Overview);
|
||||||
|
|
||||||
if (episode != null)
|
return hasValue == filterValue;
|
||||||
{
|
|
||||||
var seasonNumber = episode.AirsAfterSeasonNumber ?? episode.AirsBeforeEpisodeNumber ?? episode.ParentIndexNumber;
|
|
||||||
|
|
||||||
return episode.PremiereDate.HasValue && seasonNumber.HasValue && seasonNumber.Value == val;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (request.HasImdbId.HasValue)
|
||||||
|
{
|
||||||
|
var filterValue = request.HasImdbId.Value;
|
||||||
|
|
||||||
|
items = items.Where(i =>
|
||||||
|
{
|
||||||
|
var hasValue = !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Imdb));
|
||||||
|
|
||||||
|
return hasValue == filterValue;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.HasTmdbId.HasValue)
|
||||||
|
{
|
||||||
|
var filterValue = request.HasTmdbId.Value;
|
||||||
|
|
||||||
|
items = items.Where(i =>
|
||||||
|
{
|
||||||
|
var hasValue = !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Tmdb));
|
||||||
|
|
||||||
|
return hasValue == filterValue;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.HasTvdbId.HasValue)
|
||||||
|
{
|
||||||
|
var filterValue = request.HasTvdbId.Value;
|
||||||
|
|
||||||
|
items = items.Where(i =>
|
||||||
|
{
|
||||||
|
var hasValue = !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Tvdb));
|
||||||
|
|
||||||
|
return hasValue == filterValue;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.IsYearMismatched.HasValue)
|
||||||
|
{
|
||||||
|
var filterValue = request.IsYearMismatched.Value;
|
||||||
|
|
||||||
|
items = items.Where(i => IsYearMismatched(i) == filterValue);
|
||||||
|
}
|
||||||
|
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IsYearMismatched(BaseItem item)
|
||||||
|
{
|
||||||
|
if (item.ProductionYear.HasValue)
|
||||||
|
{
|
||||||
|
var path = item.Path;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(path))
|
||||||
|
{
|
||||||
|
int? yearInName;
|
||||||
|
string name;
|
||||||
|
NameParser.ParseName(Path.GetFileName(path), out name, out yearInName);
|
||||||
|
|
||||||
|
// Go up a level if we didn't get a year
|
||||||
|
if (!yearInName.HasValue)
|
||||||
|
{
|
||||||
|
NameParser.ParseName(Path.GetFileName(Path.GetDirectoryName(path)), out name, out yearInName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (yearInName.HasValue)
|
||||||
|
{
|
||||||
|
return yearInName.Value != item.ProductionYear.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static IEnumerable<BaseItem> FilterForAdjacency(IEnumerable<BaseItem> items, string adjacentToId)
|
||||||
|
{
|
||||||
|
var list = items.ToList();
|
||||||
|
|
||||||
|
var adjacentToIdGuid = new Guid(adjacentToId);
|
||||||
|
var adjacentToItem = list.FirstOrDefault(i => i.Id == adjacentToIdGuid);
|
||||||
|
|
||||||
|
var index = list.IndexOf(adjacentToItem);
|
||||||
|
|
||||||
|
var previousId = Guid.Empty;
|
||||||
|
var nextId = Guid.Empty;
|
||||||
|
|
||||||
|
if (index > 0)
|
||||||
|
{
|
||||||
|
previousId = list[index - 1].Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index < list.Count - 1)
|
||||||
|
{
|
||||||
|
nextId = list[index + 1].Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return list.Where(i => i.Id == previousId || i.Id == nextId);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether the specified item has image.
|
/// Determines whether the specified item has image.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -155,7 +155,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// <returns>IEnumerable{PersonInfo}.</returns>
|
/// <returns>IEnumerable{PersonInfo}.</returns>
|
||||||
private IEnumerable<PersonInfo> GetAllPeople(IEnumerable<BaseItem> itemsList, string[] personTypes)
|
private IEnumerable<PersonInfo> GetAllPeople(IEnumerable<BaseItem> itemsList, string[] personTypes)
|
||||||
{
|
{
|
||||||
var people = itemsList.SelectMany(i => i.People.OrderBy(p => p.Type));
|
var people = itemsList.SelectMany(i => i.People.OrderBy(p => p.SortOrder ?? int.MaxValue).ThenBy(p => p.Type));
|
||||||
|
|
||||||
return personTypes.Length == 0 ?
|
return personTypes.Length == 0 ?
|
||||||
|
|
||||||
|
@ -489,7 +489,15 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
// Get everything
|
// Get everything
|
||||||
var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)).ToList();
|
var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)).ToList();
|
||||||
|
|
||||||
var dtos = item.LocalTrailerIds
|
var trailerIds = new List<Guid>();
|
||||||
|
|
||||||
|
var hasTrailers = item as IHasTrailers;
|
||||||
|
if (hasTrailers != null)
|
||||||
|
{
|
||||||
|
trailerIds = hasTrailers.LocalTrailerIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
var dtos = trailerIds
|
||||||
.Select(_libraryManager.GetItemById)
|
.Select(_libraryManager.GetItemById)
|
||||||
.OrderBy(i => i.SortName)
|
.OrderBy(i => i.SortName)
|
||||||
.Select(i => _dtoService.GetBaseItemDto(i, fields, user, item));
|
.Select(i => _dtoService.GetBaseItemDto(i, fields, user, item));
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="morelinq" version="1.0.16006" targetFramework="net45" />
|
<package id="morelinq" version="1.0.16006" targetFramework="net45" />
|
||||||
<package id="ServiceStack.Common" version="3.9.62" targetFramework="net45" />
|
<package id="ServiceStack.Common" version="3.9.70" targetFramework="net45" />
|
||||||
<package id="ServiceStack.Text" version="3.9.62" targetFramework="net45" />
|
<package id="ServiceStack.Text" version="3.9.70" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
@ -22,7 +22,6 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -34,7 +33,7 @@ namespace MediaBrowser.Common.Implementations
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TApplicationPathsType">The type of the T application paths type.</typeparam>
|
/// <typeparam name="TApplicationPathsType">The type of the T application paths type.</typeparam>
|
||||||
public abstract class BaseApplicationHost<TApplicationPathsType> : IApplicationHost
|
public abstract class BaseApplicationHost<TApplicationPathsType> : IApplicationHost
|
||||||
where TApplicationPathsType : class, IApplicationPaths, new()
|
where TApplicationPathsType : class, IApplicationPaths
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when [has pending restart changed].
|
/// Occurs when [has pending restart changed].
|
||||||
@ -84,7 +83,7 @@ namespace MediaBrowser.Common.Implementations
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The json serializer
|
/// The json serializer
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly IJsonSerializer JsonSerializer = new JsonSerializer();
|
public IJsonSerializer JsonSerializer { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The _XML serializer
|
/// The _XML serializer
|
||||||
@ -182,6 +181,8 @@ namespace MediaBrowser.Common.Implementations
|
|||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
public virtual async Task Init()
|
public virtual async Task Init()
|
||||||
{
|
{
|
||||||
|
JsonSerializer = CreateJsonSerializer();
|
||||||
|
|
||||||
IsFirstRun = !ConfigurationManager.CommonConfiguration.IsStartupWizardCompleted;
|
IsFirstRun = !ConfigurationManager.CommonConfiguration.IsStartupWizardCompleted;
|
||||||
|
|
||||||
Logger = LogManager.GetLogger("App");
|
Logger = LogManager.GetLogger("App");
|
||||||
@ -213,12 +214,17 @@ namespace MediaBrowser.Common.Implementations
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual IJsonSerializer CreateJsonSerializer()
|
||||||
|
{
|
||||||
|
return new JsonSerializer();
|
||||||
|
}
|
||||||
|
|
||||||
private void SetHttpLimit()
|
private void SetHttpLimit()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Increase the max http request limit
|
// Increase the max http request limit
|
||||||
ServicePointManager.DefaultConnectionLimit = Math.Max(48, ServicePointManager.DefaultConnectionLimit);
|
ServicePointManager.DefaultConnectionLimit = Math.Max(96, ServicePointManager.DefaultConnectionLimit);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -353,7 +359,7 @@ namespace MediaBrowser.Common.Implementations
|
|||||||
FileSystemManager = CreateFileSystemManager();
|
FileSystemManager = CreateFileSystemManager();
|
||||||
RegisterSingleInstance(FileSystemManager);
|
RegisterSingleInstance(FileSystemManager);
|
||||||
|
|
||||||
HttpClient = new HttpClientManager.HttpClientManager(ApplicationPaths, Logger, CreateHttpClient, FileSystemManager);
|
HttpClient = new HttpClientManager.HttpClientManager(ApplicationPaths, Logger, FileSystemManager);
|
||||||
RegisterSingleInstance(HttpClient);
|
RegisterSingleInstance(HttpClient);
|
||||||
|
|
||||||
NetworkManager = CreateNetworkManager();
|
NetworkManager = CreateNetworkManager();
|
||||||
@ -378,8 +384,6 @@ namespace MediaBrowser.Common.Implementations
|
|||||||
return new CommonFileSystem(Logger, true);
|
return new CommonFileSystem(Logger, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract HttpClient CreateHttpClient(bool enableHttpCompression);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a list of types within an assembly
|
/// Gets a list of types within an assembly
|
||||||
/// This will handle situations that would normally throw an exception - such as a type within the assembly that depends on some other non-existant reference
|
/// This will handle situations that would normally throw an exception - such as a type within the assembly that depends on some other non-existant reference
|
||||||
|
@ -20,21 +20,23 @@ namespace MediaBrowser.Common.Implementations
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="BaseApplicationPaths" /> class.
|
/// Initializes a new instance of the <see cref="BaseApplicationPaths" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="useDebugPath">if set to <c>true</c> [use debug paths].</param>
|
protected BaseApplicationPaths(bool useDebugPath, string applicationPath)
|
||||||
protected BaseApplicationPaths(bool useDebugPath)
|
|
||||||
{
|
{
|
||||||
_useDebugPath = useDebugPath;
|
_useDebugPath = useDebugPath;
|
||||||
|
ApplicationPath = applicationPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="BaseApplicationPaths"/> class.
|
/// Initializes a new instance of the <see cref="BaseApplicationPaths"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="programDataPath">The program data path.</param>
|
protected BaseApplicationPaths(string programDataPath, string applicationPath)
|
||||||
protected BaseApplicationPaths(string programDataPath)
|
|
||||||
{
|
{
|
||||||
_programDataPath = programDataPath;
|
_programDataPath = programDataPath;
|
||||||
|
ApplicationPath = applicationPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string ApplicationPath { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The _program data path
|
/// The _program data path
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Net.Http;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Common.Implementations.HttpClientManager
|
namespace MediaBrowser.Common.Implementations.HttpClientManager
|
||||||
{
|
{
|
||||||
@ -8,11 +7,6 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class HttpClientInfo
|
public class HttpClientInfo
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the HTTP client.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The HTTP client.</value>
|
|
||||||
public HttpClient HttpClient { get; set; }
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the last timeout.
|
/// Gets or sets the last timeout.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -9,7 +9,10 @@ using System.Collections.Generic;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Cache;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -21,6 +24,11 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class HttpClientManager : IHttpClient
|
public class HttpClientManager : IHttpClient
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// When one request to a host times out, we'll ban all other requests for this period of time, to prevent scans from stalling
|
||||||
|
/// </summary>
|
||||||
|
private const int TimeoutSeconds = 30;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The _logger
|
/// The _logger
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -31,23 +39,18 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly IApplicationPaths _appPaths;
|
private readonly IApplicationPaths _appPaths;
|
||||||
|
|
||||||
public delegate HttpClient GetHttpClientHandler(bool enableHttpCompression);
|
|
||||||
|
|
||||||
private readonly GetHttpClientHandler _getHttpClientHandler;
|
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="HttpClientManager"/> class.
|
/// Initializes a new instance of the <see cref="HttpClientManager" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="appPaths">The app paths.</param>
|
/// <param name="appPaths">The app paths.</param>
|
||||||
/// <param name="logger">The logger.</param>
|
/// <param name="logger">The logger.</param>
|
||||||
/// <param name="getHttpClientHandler">The get HTTP client handler.</param>
|
/// <param name="fileSystem">The file system.</param>
|
||||||
/// <exception cref="System.ArgumentNullException">
|
/// <exception cref="System.ArgumentNullException">appPaths
|
||||||
/// appPaths
|
|
||||||
/// or
|
/// or
|
||||||
/// logger
|
/// logger</exception>
|
||||||
/// </exception>
|
public HttpClientManager(IApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem)
|
||||||
public HttpClientManager(IApplicationPaths appPaths, ILogger logger, GetHttpClientHandler getHttpClientHandler, IFileSystem fileSystem)
|
|
||||||
{
|
{
|
||||||
if (appPaths == null)
|
if (appPaths == null)
|
||||||
{
|
{
|
||||||
@ -59,7 +62,6 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_getHttpClientHandler = getHttpClientHandler;
|
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
_appPaths = appPaths;
|
_appPaths = appPaths;
|
||||||
}
|
}
|
||||||
@ -91,17 +93,82 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
|
|
||||||
if (!_httpClients.TryGetValue(key, out client))
|
if (!_httpClients.TryGetValue(key, out client))
|
||||||
{
|
{
|
||||||
client = new HttpClientInfo
|
client = new HttpClientInfo();
|
||||||
{
|
|
||||||
|
|
||||||
HttpClient = _getHttpClientHandler(enableHttpCompression)
|
|
||||||
};
|
|
||||||
_httpClients.TryAdd(key, client);
|
_httpClients.TryAdd(key, client);
|
||||||
}
|
}
|
||||||
|
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private WebRequest GetMonoRequest(HttpRequestOptions options, string method, bool enableHttpCompression)
|
||||||
|
{
|
||||||
|
var request = WebRequest.Create(options.Url);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(options.AcceptHeader))
|
||||||
|
{
|
||||||
|
request.Headers.Add("Accept", options.AcceptHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.Revalidate);
|
||||||
|
request.ConnectionGroupName = GetHostFromUrl(options.Url);
|
||||||
|
request.Method = method;
|
||||||
|
request.Timeout = 20000;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(options.UserAgent))
|
||||||
|
{
|
||||||
|
request.Headers.Add("User-Agent", options.UserAgent);
|
||||||
|
}
|
||||||
|
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PropertyInfo _httpBehaviorPropertyInfo;
|
||||||
|
private WebRequest GetRequest(HttpRequestOptions options, string method, bool enableHttpCompression)
|
||||||
|
{
|
||||||
|
#if __MonoCS__
|
||||||
|
return GetMonoRequest(options, method, enableHttpCompression);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var request = HttpWebRequest.CreateHttp(options.Url);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(options.AcceptHeader))
|
||||||
|
{
|
||||||
|
request.Accept = options.AcceptHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
request.AutomaticDecompression = enableHttpCompression ? DecompressionMethods.Deflate : DecompressionMethods.None;
|
||||||
|
request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.Revalidate);
|
||||||
|
request.ConnectionGroupName = GetHostFromUrl(options.Url);
|
||||||
|
request.KeepAlive = true;
|
||||||
|
request.Method = method;
|
||||||
|
request.Pipelined = true;
|
||||||
|
request.Timeout = 20000;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(options.UserAgent))
|
||||||
|
{
|
||||||
|
request.UserAgent = options.UserAgent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a hack to prevent KeepAlive from getting disabled internally by the HttpWebRequest
|
||||||
|
// May need to remove this for mono
|
||||||
|
var sp = request.ServicePoint;
|
||||||
|
if (_httpBehaviorPropertyInfo == null)
|
||||||
|
{
|
||||||
|
_httpBehaviorPropertyInfo = sp.GetType().GetProperty("HttpBehaviour", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||||
|
}
|
||||||
|
_httpBehaviorPropertyInfo.SetValue(sp, (byte)0, null);
|
||||||
|
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the response internal.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="options">The options.</param>
|
||||||
|
/// <returns>Task{HttpResponseInfo}.</returns>
|
||||||
|
/// <exception cref="HttpException">
|
||||||
|
/// </exception>
|
||||||
public async Task<HttpResponseInfo> GetResponse(HttpRequestOptions options)
|
public async Task<HttpResponseInfo> GetResponse(HttpRequestOptions options)
|
||||||
{
|
{
|
||||||
ValidateParams(options.Url, options.CancellationToken);
|
ValidateParams(options.Url, options.CancellationToken);
|
||||||
@ -110,19 +177,19 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
|
|
||||||
var client = GetHttpClient(GetHostFromUrl(options.Url), options.EnableHttpCompression);
|
var client = GetHttpClient(GetHostFromUrl(options.Url), options.EnableHttpCompression);
|
||||||
|
|
||||||
if ((DateTime.UtcNow - client.LastTimeout).TotalSeconds < 30)
|
if ((DateTime.UtcNow - client.LastTimeout).TotalSeconds < TimeoutSeconds)
|
||||||
{
|
{
|
||||||
throw new HttpException(string.Format("Cancelling connection to {0} due to a previous timeout.", options.Url)) { IsTimedOut = true };
|
throw new HttpException(string.Format("Cancelling connection to {0} due to a previous timeout.", options.Url)) { IsTimedOut = true };
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var message = GetHttpRequestMessage(options))
|
var httpWebRequest = GetRequest(options, "GET", options.EnableHttpCompression);
|
||||||
{
|
|
||||||
if (options.ResourcePool != null)
|
if (options.ResourcePool != null)
|
||||||
{
|
{
|
||||||
await options.ResourcePool.WaitAsync(options.CancellationToken).ConfigureAwait(false);
|
await options.ResourcePool.WaitAsync(options.CancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((DateTime.UtcNow - client.LastTimeout).TotalSeconds < 30)
|
if ((DateTime.UtcNow - client.LastTimeout).TotalSeconds < TimeoutSeconds)
|
||||||
{
|
{
|
||||||
if (options.ResourcePool != null)
|
if (options.ResourcePool != null)
|
||||||
{
|
{
|
||||||
@ -132,27 +199,39 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
throw new HttpException(string.Format("Connection to {0} timed out", options.Url)) { IsTimedOut = true };
|
throw new HttpException(string.Format("Connection to {0} timed out", options.Url)) { IsTimedOut = true };
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Info("HttpClientManager.Get url: {0}", options.Url);
|
_logger.Info("HttpClientManager.GET url: {0}", options.Url);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
options.CancellationToken.ThrowIfCancellationRequested();
|
options.CancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
var response = await client.HttpClient.SendAsync(message, HttpCompletionOption.ResponseContentRead, options.CancellationToken).ConfigureAwait(false);
|
using (var response = await httpWebRequest.GetResponseAsync().ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
var httpResponse = (HttpWebResponse)response;
|
||||||
|
|
||||||
EnsureSuccessStatusCode(response);
|
EnsureSuccessStatusCode(httpResponse);
|
||||||
|
|
||||||
options.CancellationToken.ThrowIfCancellationRequested();
|
options.CancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
using (var stream = httpResponse.GetResponseStream())
|
||||||
|
{
|
||||||
|
var memoryStream = new MemoryStream();
|
||||||
|
|
||||||
|
await stream.CopyToAsync(memoryStream).ConfigureAwait(false);
|
||||||
|
|
||||||
|
memoryStream.Position = 0;
|
||||||
|
|
||||||
return new HttpResponseInfo
|
return new HttpResponseInfo
|
||||||
{
|
{
|
||||||
Content = await response.Content.ReadAsStreamAsync().ConfigureAwait(false),
|
Content = memoryStream,
|
||||||
|
|
||||||
StatusCode = response.StatusCode,
|
StatusCode = httpResponse.StatusCode,
|
||||||
|
|
||||||
ContentType = response.Content.Headers.ContentType.MediaType
|
ContentType = httpResponse.ContentType
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
catch (OperationCanceledException ex)
|
catch (OperationCanceledException ex)
|
||||||
{
|
{
|
||||||
var exception = GetCancellationException(options.Url, options.CancellationToken, ex);
|
var exception = GetCancellationException(options.Url, options.CancellationToken, ex);
|
||||||
@ -172,6 +251,12 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
|
|
||||||
throw new HttpException(ex.Message, ex);
|
throw new HttpException(ex.Message, ex);
|
||||||
}
|
}
|
||||||
|
catch (WebException ex)
|
||||||
|
{
|
||||||
|
_logger.ErrorException("Error getting response from " + options.Url, ex);
|
||||||
|
|
||||||
|
throw new HttpException(ex.Message, ex);
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.ErrorException("Error getting response from " + options.Url, ex);
|
_logger.ErrorException("Error getting response from " + options.Url, ex);
|
||||||
@ -186,7 +271,6 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Performs a GET request and returns the resulting stream
|
/// Performs a GET request and returns the resulting stream
|
||||||
@ -197,81 +281,9 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
/// <exception cref="MediaBrowser.Model.Net.HttpException"></exception>
|
/// <exception cref="MediaBrowser.Model.Net.HttpException"></exception>
|
||||||
public async Task<Stream> Get(HttpRequestOptions options)
|
public async Task<Stream> Get(HttpRequestOptions options)
|
||||||
{
|
{
|
||||||
ValidateParams(options.Url, options.CancellationToken);
|
var response = await GetResponse(options).ConfigureAwait(false);
|
||||||
|
|
||||||
options.CancellationToken.ThrowIfCancellationRequested();
|
return response.Content;
|
||||||
|
|
||||||
var client = GetHttpClient(GetHostFromUrl(options.Url), options.EnableHttpCompression);
|
|
||||||
|
|
||||||
if ((DateTime.UtcNow - client.LastTimeout).TotalSeconds < 30)
|
|
||||||
{
|
|
||||||
throw new HttpException(string.Format("Cancelling connection to {0} due to a previous timeout.", options.Url)) { IsTimedOut = true };
|
|
||||||
}
|
|
||||||
|
|
||||||
using (var message = GetHttpRequestMessage(options))
|
|
||||||
{
|
|
||||||
if (options.ResourcePool != null)
|
|
||||||
{
|
|
||||||
await options.ResourcePool.WaitAsync(options.CancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((DateTime.UtcNow - client.LastTimeout).TotalSeconds < 30)
|
|
||||||
{
|
|
||||||
if (options.ResourcePool != null)
|
|
||||||
{
|
|
||||||
options.ResourcePool.Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new HttpException(string.Format("Connection to {0} timed out", options.Url)) { IsTimedOut = true };
|
|
||||||
}
|
|
||||||
|
|
||||||
_logger.Info("HttpClientManager.Get url: {0}", options.Url);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
options.CancellationToken.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
var response = await client.HttpClient.SendAsync(message, HttpCompletionOption.ResponseContentRead, options.CancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
EnsureSuccessStatusCode(response);
|
|
||||||
|
|
||||||
options.CancellationToken.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
return await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (OperationCanceledException ex)
|
|
||||||
{
|
|
||||||
var exception = GetCancellationException(options.Url, options.CancellationToken, ex);
|
|
||||||
|
|
||||||
var httpException = exception as HttpException;
|
|
||||||
|
|
||||||
if (httpException != null && httpException.IsTimedOut)
|
|
||||||
{
|
|
||||||
client.LastTimeout = DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw exception;
|
|
||||||
}
|
|
||||||
catch (HttpRequestException ex)
|
|
||||||
{
|
|
||||||
_logger.ErrorException("Error getting response from " + options.Url, ex);
|
|
||||||
|
|
||||||
throw new HttpException(ex.Message, ex);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.ErrorException("Error getting response from " + options.Url, ex);
|
|
||||||
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (options.ResourcePool != null)
|
|
||||||
{
|
|
||||||
options.ResourcePool.Release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -302,6 +314,96 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
return Get(url, null, cancellationToken);
|
return Get(url, null, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs a POST request
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="options">The options.</param>
|
||||||
|
/// <param name="postData">Params to add to the POST data.</param>
|
||||||
|
/// <returns>stream on success, null on failure</returns>
|
||||||
|
/// <exception cref="HttpException">
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentNullException">postData</exception>
|
||||||
|
/// <exception cref="MediaBrowser.Model.Net.HttpException"></exception>
|
||||||
|
public async Task<Stream> Post(HttpRequestOptions options, Dictionary<string, string> postData)
|
||||||
|
{
|
||||||
|
ValidateParams(options.Url, options.CancellationToken);
|
||||||
|
|
||||||
|
options.CancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
var httpWebRequest = GetRequest(options, "POST", options.EnableHttpCompression);
|
||||||
|
|
||||||
|
var strings = postData.Keys.Select(key => string.Format("{0}={1}", key, postData[key]));
|
||||||
|
var postContent = string.Join("&", strings.ToArray());
|
||||||
|
var bytes = Encoding.UTF8.GetBytes(postContent);
|
||||||
|
|
||||||
|
httpWebRequest.ContentType = "application/x-www-form-urlencoded";
|
||||||
|
httpWebRequest.ContentLength = bytes.Length;
|
||||||
|
httpWebRequest.GetRequestStream().Write(bytes, 0, bytes.Length);
|
||||||
|
|
||||||
|
if (options.ResourcePool != null)
|
||||||
|
{
|
||||||
|
await options.ResourcePool.WaitAsync(options.CancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.Info("HttpClientManager.POST url: {0}", options.Url);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
options.CancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
using (var response = await httpWebRequest.GetResponseAsync().ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
var httpResponse = (HttpWebResponse)response;
|
||||||
|
|
||||||
|
EnsureSuccessStatusCode(httpResponse);
|
||||||
|
|
||||||
|
options.CancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
using (var stream = httpResponse.GetResponseStream())
|
||||||
|
{
|
||||||
|
var memoryStream = new MemoryStream();
|
||||||
|
|
||||||
|
await stream.CopyToAsync(memoryStream).ConfigureAwait(false);
|
||||||
|
|
||||||
|
memoryStream.Position = 0;
|
||||||
|
|
||||||
|
return memoryStream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException ex)
|
||||||
|
{
|
||||||
|
var exception = GetCancellationException(options.Url, options.CancellationToken, ex);
|
||||||
|
|
||||||
|
throw exception;
|
||||||
|
}
|
||||||
|
catch (HttpRequestException ex)
|
||||||
|
{
|
||||||
|
_logger.ErrorException("Error getting response from " + options.Url, ex);
|
||||||
|
|
||||||
|
throw new HttpException(ex.Message, ex);
|
||||||
|
}
|
||||||
|
catch (WebException ex)
|
||||||
|
{
|
||||||
|
_logger.ErrorException("Error getting response from " + options.Url, ex);
|
||||||
|
|
||||||
|
throw new HttpException(ex.Message, ex);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.ErrorException("Error getting response from " + options.Url, ex);
|
||||||
|
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (options.ResourcePool != null)
|
||||||
|
{
|
||||||
|
options.ResourcePool.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Performs a POST request
|
/// Performs a POST request
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -310,57 +412,15 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
/// <param name="resourcePool">The resource pool.</param>
|
/// <param name="resourcePool">The resource pool.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>stream on success, null on failure</returns>
|
/// <returns>stream on success, null on failure</returns>
|
||||||
/// <exception cref="System.ArgumentNullException">postData</exception>
|
public Task<Stream> Post(string url, Dictionary<string, string> postData, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
|
||||||
/// <exception cref="MediaBrowser.Model.Net.HttpException"></exception>
|
|
||||||
public async Task<Stream> Post(string url, Dictionary<string, string> postData, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
|
|
||||||
{
|
{
|
||||||
ValidateParams(url, cancellationToken);
|
return Post(new HttpRequestOptions
|
||||||
|
|
||||||
if (postData == null)
|
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException("postData");
|
Url = url,
|
||||||
}
|
ResourcePool = resourcePool,
|
||||||
|
CancellationToken = cancellationToken
|
||||||
|
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
}, postData);
|
||||||
|
|
||||||
var strings = postData.Keys.Select(key => string.Format("{0}={1}", key, postData[key]));
|
|
||||||
var postContent = string.Join("&", strings.ToArray());
|
|
||||||
var content = new StringContent(postContent, Encoding.UTF8, "application/x-www-form-urlencoded");
|
|
||||||
|
|
||||||
if (resourcePool != null)
|
|
||||||
{
|
|
||||||
await resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
_logger.Info("HttpClientManager.Post url: {0}", url);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
var msg = await GetHttpClient(GetHostFromUrl(url), true).HttpClient.PostAsync(url, content, cancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
EnsureSuccessStatusCode(msg);
|
|
||||||
|
|
||||||
return await msg.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (OperationCanceledException ex)
|
|
||||||
{
|
|
||||||
throw GetCancellationException(url, cancellationToken, ex);
|
|
||||||
}
|
|
||||||
catch (HttpRequestException ex)
|
|
||||||
{
|
|
||||||
_logger.ErrorException("Error getting response from " + url, ex);
|
|
||||||
|
|
||||||
throw new HttpException(ex.Message, ex);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (resourcePool != null)
|
|
||||||
{
|
|
||||||
resourcePool.Release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -391,6 +451,8 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
|
|
||||||
options.CancellationToken.ThrowIfCancellationRequested();
|
options.CancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
var httpWebRequest = GetRequest(options, "GET", options.EnableHttpCompression);
|
||||||
|
|
||||||
if (options.ResourcePool != null)
|
if (options.ResourcePool != null)
|
||||||
{
|
{
|
||||||
await options.ResourcePool.WaitAsync(options.CancellationToken).ConfigureAwait(false);
|
await options.ResourcePool.WaitAsync(options.CancellationToken).ConfigureAwait(false);
|
||||||
@ -398,26 +460,26 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
|
|
||||||
options.Progress.Report(0);
|
options.Progress.Report(0);
|
||||||
|
|
||||||
_logger.Info("HttpClientManager.GetTempFile url: {0}, temp file: {1}", options.Url, tempFile);
|
_logger.Info("HttpClientManager.GetTempFileResponse url: {0}", options.Url);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
options.CancellationToken.ThrowIfCancellationRequested();
|
options.CancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
using (var message = GetHttpRequestMessage(options))
|
using (var response = await httpWebRequest.GetResponseAsync().ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
using (var response = await GetHttpClient(GetHostFromUrl(options.Url), options.EnableHttpCompression).HttpClient.SendAsync(message, HttpCompletionOption.ResponseHeadersRead, options.CancellationToken).ConfigureAwait(false))
|
var httpResponse = (HttpWebResponse)response;
|
||||||
{
|
|
||||||
EnsureSuccessStatusCode(response);
|
EnsureSuccessStatusCode(httpResponse);
|
||||||
|
|
||||||
options.CancellationToken.ThrowIfCancellationRequested();
|
options.CancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
var contentLength = GetContentLength(response);
|
var contentLength = GetContentLength(httpResponse);
|
||||||
|
|
||||||
if (!contentLength.HasValue)
|
if (!contentLength.HasValue)
|
||||||
{
|
{
|
||||||
// We're not able to track progress
|
// We're not able to track progress
|
||||||
using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
|
using (var stream = httpResponse.GetResponseStream())
|
||||||
{
|
{
|
||||||
using (var fs = _fileSystem.GetFileStream(tempFile, FileMode.Create, FileAccess.Write, FileShare.Read, true))
|
using (var fs = _fileSystem.GetFileStream(tempFile, FileMode.Create, FileAccess.Write, FileShare.Read, true))
|
||||||
{
|
{
|
||||||
@ -427,7 +489,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
using (var stream = ProgressStream.CreateReadProgressStream(await response.Content.ReadAsStreamAsync().ConfigureAwait(false), options.Progress.Report, contentLength.Value))
|
using (var stream = ProgressStream.CreateReadProgressStream(httpResponse.GetResponseStream(), options.Progress.Report, contentLength.Value))
|
||||||
{
|
{
|
||||||
using (var fs = _fileSystem.GetFileStream(tempFile, FileMode.Create, FileAccess.Write, FileShare.Read, true))
|
using (var fs = _fileSystem.GetFileStream(tempFile, FileMode.Create, FileAccess.Write, FileShare.Read, true))
|
||||||
{
|
{
|
||||||
@ -442,12 +504,23 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
{
|
{
|
||||||
TempFilePath = tempFile,
|
TempFilePath = tempFile,
|
||||||
|
|
||||||
StatusCode = response.StatusCode,
|
StatusCode = httpResponse.StatusCode,
|
||||||
|
|
||||||
ContentType = response.Content.Headers.ContentType.MediaType
|
ContentType = httpResponse.ContentType
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (OperationCanceledException ex)
|
||||||
|
{
|
||||||
|
throw GetTempFileException(ex, options, tempFile);
|
||||||
|
}
|
||||||
|
catch (HttpRequestException ex)
|
||||||
|
{
|
||||||
|
throw GetTempFileException(ex, options, tempFile);
|
||||||
|
}
|
||||||
|
catch (WebException ex)
|
||||||
|
{
|
||||||
|
throw GetTempFileException(ex, options, tempFile);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -462,63 +535,16 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
private long? GetContentLength(HttpWebResponse response)
|
||||||
/// Gets the message.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="options">The options.</param>
|
|
||||||
/// <returns>HttpResponseMessage.</returns>
|
|
||||||
private HttpRequestMessage GetHttpRequestMessage(HttpRequestOptions options)
|
|
||||||
{
|
{
|
||||||
var message = new HttpRequestMessage(HttpMethod.Get, options.Url);
|
var length = response.ContentLength;
|
||||||
|
|
||||||
foreach (var pair in options.RequestHeaders.ToList())
|
if (length == 0)
|
||||||
{
|
|
||||||
if (!message.Headers.TryAddWithoutValidation(pair.Key, pair.Value))
|
|
||||||
{
|
|
||||||
_logger.Error("Unable to add request header {0} with value {1}", pair.Key, pair.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the length of the content.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="response">The response.</param>
|
|
||||||
/// <returns>System.Nullable{System.Int64}.</returns>
|
|
||||||
private long? GetContentLength(HttpResponseMessage response)
|
|
||||||
{
|
|
||||||
IEnumerable<string> lengthValues = null;
|
|
||||||
|
|
||||||
// Seeing some InvalidOperationException here under mono
|
|
||||||
try
|
|
||||||
{
|
|
||||||
response.Headers.TryGetValues("content-length", out lengthValues);
|
|
||||||
}
|
|
||||||
catch (InvalidOperationException ex)
|
|
||||||
{
|
|
||||||
_logger.ErrorException("Error accessing response.Headers.TryGetValues Content-Length", ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lengthValues == null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
response.Content.Headers.TryGetValues("content-length", out lengthValues);
|
|
||||||
}
|
|
||||||
catch (InvalidOperationException ex)
|
|
||||||
{
|
|
||||||
_logger.ErrorException("Error accessing response.Content.Headers.TryGetValues Content-Length", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lengthValues == null)
|
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return long.Parse(string.Join(string.Empty, lengthValues.ToArray()), UsCulture);
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
protected static readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
||||||
@ -545,16 +571,23 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
|
|
||||||
_logger.ErrorException("Error getting response from " + options.Url, ex);
|
_logger.ErrorException("Error getting response from " + options.Url, ex);
|
||||||
|
|
||||||
var httpRequestException = ex as HttpRequestException;
|
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
DeleteTempFile(tempFile);
|
DeleteTempFile(tempFile);
|
||||||
|
|
||||||
|
var httpRequestException = ex as HttpRequestException;
|
||||||
|
|
||||||
if (httpRequestException != null)
|
if (httpRequestException != null)
|
||||||
{
|
{
|
||||||
return new HttpException(ex.Message, ex);
|
return new HttpException(ex.Message, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var webException = ex as WebException;
|
||||||
|
|
||||||
|
if (webException != null)
|
||||||
|
{
|
||||||
|
return new HttpException(ex.Message, ex);
|
||||||
|
}
|
||||||
|
|
||||||
return ex;
|
return ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -613,11 +646,6 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
{
|
{
|
||||||
if (dispose)
|
if (dispose)
|
||||||
{
|
{
|
||||||
foreach (var client in _httpClients.Values.ToList())
|
|
||||||
{
|
|
||||||
client.HttpClient.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
_httpClients.Clear();
|
_httpClients.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -645,16 +673,14 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
return exception;
|
return exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
private void EnsureSuccessStatusCode(HttpWebResponse response)
|
||||||
/// Ensures the success status code.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="response">The response.</param>
|
|
||||||
/// <exception cref="MediaBrowser.Model.Net.HttpException"></exception>
|
|
||||||
private void EnsureSuccessStatusCode(HttpResponseMessage response)
|
|
||||||
{
|
{
|
||||||
if (!response.IsSuccessStatusCode)
|
var statusCode = response.StatusCode;
|
||||||
|
var isSuccessful = statusCode >= HttpStatusCode.OK && statusCode <= (HttpStatusCode)299;
|
||||||
|
|
||||||
|
if (!isSuccessful)
|
||||||
{
|
{
|
||||||
throw new HttpException(response.ReasonPhrase) { StatusCode = response.StatusCode };
|
throw new HttpException(response.StatusDescription) { StatusCode = response.StatusCode };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,6 +41,10 @@
|
|||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\packages\NLog.2.1.0\lib\net45\NLog.dll</HintPath>
|
<HintPath>..\packages\NLog.2.1.0\lib\net45\NLog.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="ServiceStack.Text, Version=3.9.70.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>..\packages\ServiceStack.Text.3.9.70\lib\net35\ServiceStack.Text.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="SharpCompress">
|
<Reference Include="SharpCompress">
|
||||||
<HintPath>..\packages\sharpcompress.0.10.1.3\lib\net40\SharpCompress.dll</HintPath>
|
<HintPath>..\packages\sharpcompress.0.10.1.3\lib\net40\SharpCompress.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
@ -55,9 +59,6 @@
|
|||||||
<Reference Include="System.Net" />
|
<Reference Include="System.Net" />
|
||||||
<Reference Include="System.Net.Http" />
|
<Reference Include="System.Net.Http" />
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
<Reference Include="ServiceStack.Text">
|
|
||||||
<HintPath>..\packages\ServiceStack.Text.3.9.62\lib\net35\ServiceStack.Text.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="..\SharedVersion.cs">
|
<Compile Include="..\SharedVersion.cs">
|
||||||
|
@ -29,7 +29,6 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="DeleteCacheFileTask" /> class.
|
/// Initializes a new instance of the <see cref="DeleteCacheFileTask" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="appPaths">The app paths.</param>
|
|
||||||
public DeleteCacheFileTask(IApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem)
|
public DeleteCacheFileTask(IApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem)
|
||||||
{
|
{
|
||||||
ApplicationPaths = appPaths;
|
ApplicationPaths = appPaths;
|
||||||
|
@ -80,7 +80,7 @@ namespace MediaBrowser.Common.Implementations.Serialization
|
|||||||
|
|
||||||
using (Stream stream = File.OpenRead(file))
|
using (Stream stream = File.OpenRead(file))
|
||||||
{
|
{
|
||||||
return ServiceStack.Text.JsonSerializer.DeserializeFromStream(type, stream);
|
return DeserializeFromStream(stream, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ namespace MediaBrowser.Common.Implementations.Serialization
|
|||||||
|
|
||||||
using (Stream stream = File.OpenRead(file))
|
using (Stream stream = File.OpenRead(file))
|
||||||
{
|
{
|
||||||
return ServiceStack.Text.JsonSerializer.DeserializeFromStream<T>(stream);
|
return DeserializeFromStream<T>(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,6 +169,8 @@ namespace MediaBrowser.Common.Implementations.Serialization
|
|||||||
ServiceStack.Text.JsConfig.DateHandler = ServiceStack.Text.JsonDateHandler.ISO8601;
|
ServiceStack.Text.JsConfig.DateHandler = ServiceStack.Text.JsonDateHandler.ISO8601;
|
||||||
ServiceStack.Text.JsConfig.ExcludeTypeInfo = true;
|
ServiceStack.Text.JsConfig.ExcludeTypeInfo = true;
|
||||||
ServiceStack.Text.JsConfig.IncludeNullValues = false;
|
ServiceStack.Text.JsConfig.IncludeNullValues = false;
|
||||||
|
ServiceStack.Text.JsConfig.AlwaysUseUtc = true;
|
||||||
|
ServiceStack.Text.JsConfig.AssumeUtc = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -168,7 +168,7 @@ namespace MediaBrowser.Common.Implementations.Updates
|
|||||||
{
|
{
|
||||||
// Let dev users get results more often for testing purposes
|
// Let dev users get results more often for testing purposes
|
||||||
var cacheLength = _config.CommonConfiguration.SystemUpdateLevel == PackageVersionClass.Dev
|
var cacheLength = _config.CommonConfiguration.SystemUpdateLevel == PackageVersionClass.Dev
|
||||||
? TimeSpan.FromMinutes(15)
|
? TimeSpan.FromMinutes(5)
|
||||||
: TimeSpan.FromHours(12);
|
: TimeSpan.FromHours(12);
|
||||||
|
|
||||||
if ((DateTime.UtcNow - _lastPackageListResult.Item2) < cacheLength)
|
if ((DateTime.UtcNow - _lastPackageListResult.Item2) < cacheLength)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="NLog" version="2.1.0" targetFramework="net45" />
|
<package id="NLog" version="2.1.0" targetFramework="net45" />
|
||||||
<package id="ServiceStack.Text" version="3.9.62" targetFramework="net45" />
|
<package id="ServiceStack.Text" version="3.9.70" targetFramework="net45" />
|
||||||
<package id="sharpcompress" version="0.10.1.3" targetFramework="net45" />
|
<package id="sharpcompress" version="0.10.1.3" targetFramework="net45" />
|
||||||
<package id="SimpleInjector" version="2.3.6" targetFramework="net45" />
|
<package id="SimpleInjector" version="2.3.6" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
@ -6,6 +6,12 @@ namespace MediaBrowser.Common.Configuration
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IApplicationPaths
|
public interface IApplicationPaths
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the application path.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The application path.</value>
|
||||||
|
string ApplicationPath { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the path to the program data folder
|
/// Gets the path to the program data folder
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -35,18 +35,21 @@
|
|||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Reference Include="ServiceStack.Common, Version=3.9.70.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>..\packages\ServiceStack.Common.3.9.70\lib\net35\ServiceStack.Common.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="ServiceStack.Interfaces, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>..\packages\ServiceStack.Common.3.9.70\lib\net35\ServiceStack.Interfaces.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="ServiceStack.Text, Version=3.9.70.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>..\packages\ServiceStack.Text.3.9.70\lib\net35\ServiceStack.Text.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
<Reference Include="ServiceStack.Common">
|
|
||||||
<HintPath>..\packages\ServiceStack.Common.3.9.62\lib\net35\ServiceStack.Common.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="ServiceStack.Interfaces">
|
|
||||||
<HintPath>..\packages\ServiceStack.Common.3.9.62\lib\net35\ServiceStack.Interfaces.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="ServiceStack.Text">
|
|
||||||
<HintPath>..\packages\ServiceStack.Text.3.9.62\lib\net35\ServiceStack.Text.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="..\SharedVersion.cs">
|
<Compile Include="..\SharedVersion.cs">
|
||||||
|
@ -73,6 +73,11 @@ namespace MediaBrowser.Common.Net
|
|||||||
/// <exception cref="MediaBrowser.Model.Net.HttpException"></exception>
|
/// <exception cref="MediaBrowser.Model.Net.HttpException"></exception>
|
||||||
Task<string> GetTempFile(HttpRequestOptions options);
|
Task<string> GetTempFile(HttpRequestOptions options);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the temporary file response.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="options">The options.</param>
|
||||||
|
/// <returns>Task{HttpResponseInfo}.</returns>
|
||||||
Task<HttpResponseInfo> GetTempFileResponse(HttpRequestOptions options);
|
Task<HttpResponseInfo> GetTempFileResponse(HttpRequestOptions options);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -42,4 +42,9 @@ namespace MediaBrowser.Common.ScheduledTasks
|
|||||||
/// <returns>IEnumerable{BaseTaskTrigger}.</returns>
|
/// <returns>IEnumerable{BaseTaskTrigger}.</returns>
|
||||||
IEnumerable<ITaskTrigger> GetDefaultTriggers();
|
IEnumerable<ITaskTrigger> GetDefaultTriggers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface IConfigurableScheduledTask
|
||||||
|
{
|
||||||
|
bool IsHidden { get; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,15 @@ namespace MediaBrowser.Common.ScheduledTasks
|
|||||||
/// <returns>TaskInfo.</returns>
|
/// <returns>TaskInfo.</returns>
|
||||||
public static TaskInfo GetTaskInfo(IScheduledTaskWorker task)
|
public static TaskInfo GetTaskInfo(IScheduledTaskWorker task)
|
||||||
{
|
{
|
||||||
|
var isHidden = false;
|
||||||
|
|
||||||
|
var configurableTask = task.ScheduledTask as IConfigurableScheduledTask;
|
||||||
|
|
||||||
|
if (configurableTask != null)
|
||||||
|
{
|
||||||
|
isHidden = configurableTask.IsHidden;
|
||||||
|
}
|
||||||
|
|
||||||
return new TaskInfo
|
return new TaskInfo
|
||||||
{
|
{
|
||||||
Name = task.Name,
|
Name = task.Name,
|
||||||
@ -25,7 +34,8 @@ namespace MediaBrowser.Common.ScheduledTasks
|
|||||||
LastExecutionResult = task.LastExecutionResult,
|
LastExecutionResult = task.LastExecutionResult,
|
||||||
Triggers = task.Triggers.Select(GetTriggerInfo).ToList(),
|
Triggers = task.Triggers.Select(GetTriggerInfo).ToList(),
|
||||||
Description = task.Description,
|
Description = task.Description,
|
||||||
Category = task.Category
|
Category = task.Category,
|
||||||
|
IsHidden = isHidden
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="ServiceStack.Common" version="3.9.62" targetFramework="net45" />
|
<package id="ServiceStack.Common" version="3.9.70" targetFramework="net45" />
|
||||||
<package id="ServiceStack.Text" version="3.9.62" targetFramework="net45" />
|
<package id="ServiceStack.Text" version="3.9.70" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
@ -1,86 +0,0 @@
|
|||||||
using MediaBrowser.Controller.Library;
|
|
||||||
using MediaBrowser.Model.Dto;
|
|
||||||
using MediaBrowser.Model.Entities;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.Serialization;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities.Audio
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Class Artist
|
|
||||||
/// </summary>
|
|
||||||
public class Artist : BaseItem, IItemByName, IHasMusicGenres
|
|
||||||
{
|
|
||||||
public Artist()
|
|
||||||
{
|
|
||||||
UserItemCounts = new Dictionary<Guid, ItemByNameCounts>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public string LastFmImageUrl { get; set; }
|
|
||||||
public string LastFmImageSize { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the user data key.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>System.String.</returns>
|
|
||||||
public override string GetUserDataKey()
|
|
||||||
{
|
|
||||||
return GetUserDataKey(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
|
||||||
public Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Finds the music artist.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="artist">The artist.</param>
|
|
||||||
/// <param name="libraryManager">The library manager.</param>
|
|
||||||
/// <returns>MusicArtist.</returns>
|
|
||||||
public static MusicArtist FindMusicArtist(Artist artist, ILibraryManager libraryManager)
|
|
||||||
{
|
|
||||||
return FindMusicArtist(artist, libraryManager.RootFolder.RecursiveChildren.OfType<MusicArtist>());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Finds the music artist.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="artist">The artist.</param>
|
|
||||||
/// <param name="allMusicArtists">All music artists.</param>
|
|
||||||
/// <returns>MusicArtist.</returns>
|
|
||||||
public static MusicArtist FindMusicArtist(Artist artist, IEnumerable<MusicArtist> allMusicArtists)
|
|
||||||
{
|
|
||||||
var musicBrainzId = artist.GetProviderId(MetadataProviders.Musicbrainz);
|
|
||||||
|
|
||||||
return allMusicArtists.FirstOrDefault(i =>
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrWhiteSpace(musicBrainzId) && string.Equals(musicBrainzId, i.GetProviderId(MetadataProviders.Musicbrainz), StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return string.Compare(i.Name, artist.Name, CultureInfo.CurrentCulture, CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols) == 0;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the user data key.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="item">The item.</param>
|
|
||||||
/// <returns>System.String.</returns>
|
|
||||||
public static string GetUserDataKey(BaseItem item)
|
|
||||||
{
|
|
||||||
var id = item.GetProviderId(MetadataProviders.Musicbrainz);
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(id))
|
|
||||||
{
|
|
||||||
return "Artist-Musicbrainz-" + id;
|
|
||||||
}
|
|
||||||
|
|
||||||
return "Artist-" + item.Name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +1,65 @@
|
|||||||
|
using MediaBrowser.Model.Dto;
|
||||||
|
using MediaBrowser.Model.Entities;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities.Audio
|
namespace MediaBrowser.Controller.Entities.Audio
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class MusicArtist
|
/// Class MusicArtist
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MusicArtist : Folder
|
public class MusicArtist : Folder, IItemByName, IHasMusicGenres, IHasDualAccess
|
||||||
{
|
{
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public List<ItemByNameCounts> UserItemCountList { get; set; }
|
||||||
|
|
||||||
|
public bool IsAccessedByName { get; set; }
|
||||||
|
|
||||||
|
public override bool IsFolder
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return !IsAccessedByName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override IEnumerable<BaseItem> ActualChildren
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (IsAccessedByName)
|
||||||
|
{
|
||||||
|
return new List<BaseItem>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.ActualChildren;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool? recursive = null, bool forceRefreshMetadata = false)
|
||||||
|
{
|
||||||
|
if (IsAccessedByName)
|
||||||
|
{
|
||||||
|
// Should never get in here anyway
|
||||||
|
return Task.FromResult(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.ValidateChildrenInternal(progress, cancellationToken, recursive, forceRefreshMetadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetClientTypeName()
|
||||||
|
{
|
||||||
|
if (IsAccessedByName)
|
||||||
|
{
|
||||||
|
//return "Artist";
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.GetClientTypeName();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the last fm image URL.
|
/// Gets or sets the last fm image URL.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -13,13 +67,35 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
public string LastFmImageUrl { get; set; }
|
public string LastFmImageUrl { get; set; }
|
||||||
public string LastFmImageSize { get; set; }
|
public string LastFmImageSize { get; set; }
|
||||||
|
|
||||||
|
public MusicArtist()
|
||||||
|
{
|
||||||
|
UserItemCountList = new List<ItemByNameCounts>();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the user data key.
|
/// Gets the user data key.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
public override string GetUserDataKey()
|
public override string GetUserDataKey()
|
||||||
{
|
{
|
||||||
return Artist.GetUserDataKey(this);
|
return GetUserDataKey(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the user data key.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">The item.</param>
|
||||||
|
/// <returns>System.String.</returns>
|
||||||
|
public static string GetUserDataKey(BaseItem item)
|
||||||
|
{
|
||||||
|
var id = item.GetProviderId(MetadataProviders.Musicbrainz);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(id))
|
||||||
|
{
|
||||||
|
return "Artist-Musicbrainz-" + id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Artist-" + item.Name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
{
|
{
|
||||||
public MusicGenre()
|
public MusicGenre()
|
||||||
{
|
{
|
||||||
UserItemCounts = new Dictionary<Guid, ItemByNameCounts>();
|
UserItemCountList = new List<ItemByNameCounts>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -25,6 +25,6 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; }
|
public List<ItemByNameCounts> UserItemCountList { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Common.IO;
|
using MediaBrowser.Common.IO;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
|
||||||
using MediaBrowser.Controller.IO;
|
using MediaBrowser.Controller.IO;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Localization;
|
using MediaBrowser.Controller.Localization;
|
||||||
@ -38,10 +37,8 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
Tags = new List<string>();
|
Tags = new List<string>();
|
||||||
ThemeSongIds = new List<Guid>();
|
ThemeSongIds = new List<Guid>();
|
||||||
ThemeVideoIds = new List<Guid>();
|
ThemeVideoIds = new List<Guid>();
|
||||||
LocalTrailerIds = new List<Guid>();
|
|
||||||
LockedFields = new List<MetadataFields>();
|
LockedFields = new List<MetadataFields>();
|
||||||
Taglines = new List<string>();
|
Taglines = new List<string>();
|
||||||
RemoteTrailers = new List<MediaUrl>();
|
|
||||||
ImageSources = new List<ImageSourceInfo>();
|
ImageSources = new List<ImageSourceInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,30 +84,12 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <value>The id.</value>
|
/// <value>The id.</value>
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the budget.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The budget.</value>
|
|
||||||
public double? Budget { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the taglines.
|
/// Gets or sets the taglines.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The taglines.</value>
|
/// <value>The taglines.</value>
|
||||||
public List<string> Taglines { get; set; }
|
public List<string> Taglines { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the revenue.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The revenue.</value>
|
|
||||||
public double? Revenue { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the trailer URL.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The trailer URL.</value>
|
|
||||||
public List<MediaUrl> RemoteTrailers { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Return the id that should be used to key display prefs for this item.
|
/// Return the id that should be used to key display prefs for this item.
|
||||||
/// Default is based on the type for everything except actual generic folders.
|
/// Default is based on the type for everything except actual generic folders.
|
||||||
@ -139,6 +118,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// Gets or sets the type of the location.
|
/// Gets or sets the type of the location.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The type of the location.</value>
|
/// <value>The type of the location.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
public virtual LocationType LocationType
|
public virtual LocationType LocationType
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -483,6 +463,22 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public Folder Parent { get; set; }
|
public Folder Parent { get; set; }
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public IEnumerable<Folder> Parents
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var parent = Parent;
|
||||||
|
|
||||||
|
while (parent != null)
|
||||||
|
{
|
||||||
|
yield return parent;
|
||||||
|
|
||||||
|
parent = parent.Parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When the item first debuted. For movies this could be premiere date, episodes would be first aired
|
/// When the item first debuted. For movies this could be premiere date, episodes would be first aired
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -630,11 +626,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <value>The original run time ticks.</value>
|
/// <value>The original run time ticks.</value>
|
||||||
public long? OriginalRunTimeTicks { get; set; }
|
public long? OriginalRunTimeTicks { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the aspect ratio.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The aspect ratio.</value>
|
|
||||||
public string AspectRatio { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the production year.
|
/// Gets or sets the production year.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The production year.</value>
|
/// <value>The production year.</value>
|
||||||
@ -655,7 +646,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
public List<Guid> ThemeSongIds { get; set; }
|
public List<Guid> ThemeSongIds { get; set; }
|
||||||
public List<Guid> ThemeVideoIds { get; set; }
|
public List<Guid> ThemeVideoIds { get; set; }
|
||||||
public List<Guid> LocalTrailerIds { get; set; }
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public virtual string OfficialRatingForComparison
|
public virtual string OfficialRatingForComparison
|
||||||
@ -898,7 +888,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
themeVideosChanged = await RefreshThemeVideos(cancellationToken, forceSave, forceRefresh, allowSlowProviders).ConfigureAwait(false);
|
themeVideosChanged = await RefreshThemeVideos(cancellationToken, forceSave, forceRefresh, allowSlowProviders).ConfigureAwait(false);
|
||||||
|
|
||||||
localTrailersChanged = await RefreshLocalTrailers(cancellationToken, forceSave, forceRefresh, allowSlowProviders).ConfigureAwait(false);
|
var hasTrailers = this as IHasTrailers;
|
||||||
|
if (hasTrailers != null)
|
||||||
|
{
|
||||||
|
localTrailersChanged = await RefreshLocalTrailers(hasTrailers, cancellationToken, forceSave, forceRefresh, allowSlowProviders).ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
@ -918,18 +912,18 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> RefreshLocalTrailers(CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false, bool allowSlowProviders = true)
|
private async Task<bool> RefreshLocalTrailers(IHasTrailers item, CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false, bool allowSlowProviders = true)
|
||||||
{
|
{
|
||||||
var newItems = LoadLocalTrailers().ToList();
|
var newItems = LoadLocalTrailers().ToList();
|
||||||
var newItemIds = newItems.Select(i => i.Id).ToList();
|
var newItemIds = newItems.Select(i => i.Id).ToList();
|
||||||
|
|
||||||
var itemsChanged = !LocalTrailerIds.SequenceEqual(newItemIds);
|
var itemsChanged = !item.LocalTrailerIds.SequenceEqual(newItemIds);
|
||||||
|
|
||||||
var tasks = newItems.Select(i => i.RefreshMetadata(cancellationToken, forceSave, forceRefresh, allowSlowProviders, resetResolveArgs: false));
|
var tasks = newItems.Select(i => i.RefreshMetadata(cancellationToken, forceSave, forceRefresh, allowSlowProviders, resetResolveArgs: false));
|
||||||
|
|
||||||
var results = await Task.WhenAll(tasks).ConfigureAwait(false);
|
var results = await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||||
|
|
||||||
LocalTrailerIds = newItemIds;
|
item.LocalTrailerIds = newItemIds;
|
||||||
|
|
||||||
return itemsChanged || results.Contains(true);
|
return itemsChanged || results.Contains(true);
|
||||||
}
|
}
|
||||||
@ -1134,6 +1128,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual string GetClientTypeName()
|
||||||
|
{
|
||||||
|
return GetType().Name;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines if the item is considered new based on user settings
|
/// Determines if the item is considered new based on user settings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -1187,6 +1186,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
if (existing != null)
|
if (existing != null)
|
||||||
{
|
{
|
||||||
existing.Type = PersonType.GuestStar;
|
existing.Type = PersonType.GuestStar;
|
||||||
|
existing.SortOrder = person.SortOrder ?? existing.SortOrder;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1203,23 +1203,35 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Was there, if no role and we have one - fill it in
|
// Was there, if no role and we have one - fill it in
|
||||||
if (string.IsNullOrWhiteSpace(existing.Role) && !string.IsNullOrWhiteSpace(person.Role)) existing.Role = person.Role;
|
if (string.IsNullOrWhiteSpace(existing.Role) && !string.IsNullOrWhiteSpace(person.Role))
|
||||||
|
{
|
||||||
|
existing.Role = person.Role;
|
||||||
|
}
|
||||||
|
|
||||||
|
existing.SortOrder = person.SortOrder ?? existing.SortOrder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
var existing = People.FirstOrDefault(p =>
|
||||||
|
string.Equals(p.Name, person.Name, StringComparison.OrdinalIgnoreCase) &&
|
||||||
|
string.Equals(p.Type, person.Type, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
// Check for dupes based on the combination of Name and Type
|
// Check for dupes based on the combination of Name and Type
|
||||||
if (!People.Any(p => string.Equals(p.Name, person.Name, StringComparison.OrdinalIgnoreCase) && string.Equals(p.Type, person.Type, StringComparison.OrdinalIgnoreCase)))
|
if (existing == null)
|
||||||
{
|
{
|
||||||
People.Add(person);
|
People.Add(person);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
existing.SortOrder = person.SortOrder ?? existing.SortOrder;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the tagline.
|
/// Adds the tagline.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">The item.</param>
|
|
||||||
/// <param name="tagline">The tagline.</param>
|
/// <param name="tagline">The tagline.</param>
|
||||||
/// <exception cref="System.ArgumentNullException">tagline</exception>
|
/// <exception cref="System.ArgumentNullException">tagline</exception>
|
||||||
public void AddTagline(string tagline)
|
public void AddTagline(string tagline)
|
||||||
@ -1737,5 +1749,14 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
// See if we can avoid a file system lookup by looking for the file in ResolveArgs
|
// See if we can avoid a file system lookup by looking for the file in ResolveArgs
|
||||||
return metaFileEntry == null ? FileSystem.GetLastWriteTimeUtc(imagePath) : FileSystem.GetLastWriteTimeUtc(metaFileEntry);
|
return metaFileEntry == null ? FileSystem.GetLastWriteTimeUtc(imagePath) : FileSystem.GetLastWriteTimeUtc(metaFileEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the file system path to delete when the item is to be deleted
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual IEnumerable<string> GetDeletePaths()
|
||||||
|
{
|
||||||
|
return new[] { Path };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <param name="url">The URL.</param>
|
/// <param name="url">The URL.</param>
|
||||||
/// <param name="isDirectLink">if set to <c>true</c> [is direct link].</param>
|
/// <param name="isDirectLink">if set to <c>true</c> [is direct link].</param>
|
||||||
/// <exception cref="System.ArgumentNullException">url</exception>
|
/// <exception cref="System.ArgumentNullException">url</exception>
|
||||||
public static void AddTrailerUrl(this BaseItem item, string url, bool isDirectLink)
|
public static void AddTrailerUrl(this IHasTrailers item, string url, bool isDirectLink)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(url))
|
if (string.IsNullOrWhiteSpace(url))
|
||||||
{
|
{
|
||||||
|
@ -90,7 +90,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
item.Id = item.Path.GetMBId(item.GetType());
|
item.Id = item.Path.GetMBId(item.GetType());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_children.Any(i => i.Id == item.Id))
|
if (ActualChildren.Any(i => i.Id == item.Id))
|
||||||
{
|
{
|
||||||
throw new ArgumentException(string.Format("A child with the Id {0} already exists.", item.Id));
|
throw new ArgumentException(string.Format("A child with the Id {0} already exists.", item.Id));
|
||||||
}
|
}
|
||||||
@ -108,14 +108,14 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
|
await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
await ItemRepository.SaveChildren(Id, _children.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
|
await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void AddChildrenInternal(IEnumerable<BaseItem> children)
|
protected void AddChildrenInternal(IEnumerable<BaseItem> children)
|
||||||
{
|
{
|
||||||
lock (_childrenSyncLock)
|
lock (_childrenSyncLock)
|
||||||
{
|
{
|
||||||
var newChildren = _children.ToList();
|
var newChildren = ActualChildren.ToList();
|
||||||
newChildren.AddRange(children);
|
newChildren.AddRange(children);
|
||||||
_children = newChildren;
|
_children = newChildren;
|
||||||
}
|
}
|
||||||
@ -124,7 +124,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
lock (_childrenSyncLock)
|
lock (_childrenSyncLock)
|
||||||
{
|
{
|
||||||
var newChildren = _children.ToList();
|
var newChildren = ActualChildren.ToList();
|
||||||
newChildren.Add(child);
|
newChildren.Add(child);
|
||||||
_children = newChildren;
|
_children = newChildren;
|
||||||
}
|
}
|
||||||
@ -134,7 +134,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
lock (_childrenSyncLock)
|
lock (_childrenSyncLock)
|
||||||
{
|
{
|
||||||
_children = _children.Except(children).ToList();
|
_children = ActualChildren.Except(children).ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -519,7 +519,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The children
|
/// The children
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private IReadOnlyList<BaseItem> _children = new List<BaseItem>();
|
private IReadOnlyList<BaseItem> _children;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The _children sync lock
|
/// The _children sync lock
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -532,15 +532,10 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return _children;
|
return _children ?? (_children = LoadChildrenInternal());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadSavedChildren()
|
|
||||||
{
|
|
||||||
_children = LoadChildrenInternal();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// thread-safe access to the actual children of this folder - without regard to user
|
/// thread-safe access to the actual children of this folder - without regard to user
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -758,7 +753,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
AddChildrenInternal(newItems);
|
AddChildrenInternal(newItems);
|
||||||
|
|
||||||
await ItemRepository.SaveChildren(Id, _children.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
|
await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
//force the indexes to rebuild next time
|
//force the indexes to rebuild next time
|
||||||
if (IndexCache != null)
|
if (IndexCache != null)
|
||||||
@ -1007,8 +1002,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
var initialCount = _children.Count;
|
var list = new List<BaseItem>();
|
||||||
var list = new List<BaseItem>(initialCount);
|
|
||||||
|
|
||||||
AddChildrenToList(user, includeLinkedChildren, list, false, null);
|
AddChildrenToList(user, includeLinkedChildren, list, false, null);
|
||||||
|
|
||||||
@ -1038,19 +1032,16 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recursive)
|
if (recursive && child.IsFolder)
|
||||||
{
|
{
|
||||||
var folder = child as Folder;
|
var folder = (Folder)child;
|
||||||
|
|
||||||
if (folder != null)
|
|
||||||
{
|
|
||||||
if (folder.AddChildrenToList(user, includeLinkedChildren, list, true, filter))
|
if (folder.AddChildrenToList(user, includeLinkedChildren, list, true, filter))
|
||||||
{
|
{
|
||||||
hasLinkedChildren = true;
|
hasLinkedChildren = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (includeLinkedChildren)
|
if (includeLinkedChildren)
|
||||||
{
|
{
|
||||||
@ -1073,7 +1064,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return hasLinkedChildren;
|
return hasLinkedChildren;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int _lastRecursiveCount;
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets allowed recursive children of an item
|
/// Gets allowed recursive children of an item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -1101,13 +1091,10 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
throw new ArgumentNullException("user");
|
throw new ArgumentNullException("user");
|
||||||
}
|
}
|
||||||
|
|
||||||
var initialCount = _lastRecursiveCount == 0 ? _children.Count : _lastRecursiveCount;
|
var list = new List<BaseItem>();
|
||||||
var list = new List<BaseItem>(initialCount);
|
|
||||||
|
|
||||||
var hasLinkedChildren = AddChildrenToList(user, includeLinkedChildren, list, true, filter);
|
var hasLinkedChildren = AddChildrenToList(user, includeLinkedChildren, list, true, filter);
|
||||||
|
|
||||||
_lastRecursiveCount = list.Count;
|
|
||||||
|
|
||||||
return hasLinkedChildren ? list.DistinctBy(i => i.Id).ToList() : list;
|
return hasLinkedChildren ? list.DistinctBy(i => i.Id).ToList() : list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1127,8 +1114,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
/// <returns>IEnumerable{BaseItem}.</returns>
|
||||||
public IList<BaseItem> GetRecursiveChildren(Func<BaseItem, bool> filter)
|
public IList<BaseItem> GetRecursiveChildren(Func<BaseItem, bool> filter)
|
||||||
{
|
{
|
||||||
var initialCount = _lastRecursiveCount == 0 ? _children.Count : _lastRecursiveCount;
|
var list = new List<BaseItem>();
|
||||||
var list = new List<BaseItem>(initialCount);
|
|
||||||
|
|
||||||
AddChildrenToList(list, true, filter);
|
AddChildrenToList(list, true, filter);
|
||||||
|
|
||||||
@ -1150,17 +1136,14 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
list.Add(child);
|
list.Add(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recursive)
|
if (recursive && child.IsFolder)
|
||||||
{
|
{
|
||||||
var folder = child as Folder;
|
var folder = (Folder)child;
|
||||||
|
|
||||||
if (folder != null)
|
|
||||||
{
|
|
||||||
folder.AddChildrenToList(list, true, filter);
|
folder.AddChildrenToList(list, true, filter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -4,7 +4,7 @@ using System.Collections.Generic;
|
|||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
public class Game : BaseItem, IHasSoundtracks
|
public class Game : BaseItem, IHasSoundtracks, IHasTrailers
|
||||||
{
|
{
|
||||||
public List<Guid> SoundtrackIds { get; set; }
|
public List<Guid> SoundtrackIds { get; set; }
|
||||||
|
|
||||||
@ -12,8 +12,18 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
MultiPartGameFiles = new List<string>();
|
MultiPartGameFiles = new List<string>();
|
||||||
SoundtrackIds = new List<Guid>();
|
SoundtrackIds = new List<Guid>();
|
||||||
|
RemoteTrailers = new List<MediaUrl>();
|
||||||
|
LocalTrailerIds = new List<Guid>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Guid> LocalTrailerIds { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the remote trailers.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The remote trailers.</value>
|
||||||
|
public List<MediaUrl> RemoteTrailers { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the type of the media.
|
/// Gets the type of the media.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -84,5 +94,15 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
return base.GetUserDataKey();
|
return base.GetUserDataKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override IEnumerable<string> GetDeletePaths()
|
||||||
|
{
|
||||||
|
if (!IsInMixedFolder)
|
||||||
|
{
|
||||||
|
return new[] { System.IO.Path.GetDirectoryName(Path) };
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.GetDeletePaths();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
public GameGenre()
|
public GameGenre()
|
||||||
{
|
{
|
||||||
UserItemCounts = new Dictionary<Guid, ItemByNameCounts>();
|
UserItemCountList = new List<ItemByNameCounts>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -22,6 +22,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; }
|
public List<ItemByNameCounts> UserItemCountList { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
using System.Runtime.Serialization;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Dto;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
@ -12,7 +12,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
public Genre()
|
public Genre()
|
||||||
{
|
{
|
||||||
UserItemCounts = new Dictionary<Guid, ItemByNameCounts>();
|
UserItemCountList = new List<ItemByNameCounts>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -25,6 +25,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; }
|
public List<ItemByNameCounts> UserItemCountList { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
14
MediaBrowser.Controller/Entities/IHasAspectRatio.cs
Normal file
14
MediaBrowser.Controller/Entities/IHasAspectRatio.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
namespace MediaBrowser.Controller.Entities
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interface IHasAspectRatio
|
||||||
|
/// </summary>
|
||||||
|
public interface IHasAspectRatio
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the aspect ratio.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The aspect ratio.</value>
|
||||||
|
string AspectRatio { get; set; }
|
||||||
|
}
|
||||||
|
}
|
18
MediaBrowser.Controller/Entities/IHasBudget.cs
Normal file
18
MediaBrowser.Controller/Entities/IHasBudget.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
namespace MediaBrowser.Controller.Entities
|
||||||
|
{
|
||||||
|
public interface IHasBudget
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the budget.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The budget.</value>
|
||||||
|
double? Budget { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the revenue.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The revenue.</value>
|
||||||
|
double? Revenue { get; set; }
|
||||||
|
}
|
||||||
|
}
|
21
MediaBrowser.Controller/Entities/IHasTrailers.cs
Normal file
21
MediaBrowser.Controller/Entities/IHasTrailers.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using MediaBrowser.Model.Entities;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.Entities
|
||||||
|
{
|
||||||
|
public interface IHasTrailers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the remote trailers.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The remote trailers.</value>
|
||||||
|
List<MediaUrl> RemoteTrailers { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the local trailer ids.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The local trailer ids.</value>
|
||||||
|
List<Guid> LocalTrailerIds { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
@ -9,26 +10,37 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IItemByName
|
public interface IItemByName
|
||||||
{
|
{
|
||||||
Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; }
|
List<ItemByNameCounts> UserItemCountList { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class IItemByNameExtensions
|
public interface IHasDualAccess : IItemByName
|
||||||
{
|
{
|
||||||
public static ItemByNameCounts GetItemByNameCounts(this IItemByName item, User user)
|
bool IsAccessedByName { get; }
|
||||||
{
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("user");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemByNameCounts counts;
|
public static class ItemByNameExtensions
|
||||||
|
|
||||||
if (item.UserItemCounts.TryGetValue(user.Id, out counts))
|
|
||||||
{
|
{
|
||||||
return counts;
|
public static ItemByNameCounts GetItemByNameCounts(this IItemByName item, Guid userId)
|
||||||
|
{
|
||||||
|
if (userId == Guid.Empty)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("userId");
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return item.UserItemCountList.FirstOrDefault(i => i.UserId == userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetItemByNameCounts(this IItemByName item, Guid userId, ItemByNameCounts counts)
|
||||||
|
{
|
||||||
|
var current = item.UserItemCountList.FirstOrDefault(i => i.UserId == userId);
|
||||||
|
|
||||||
|
if (current != null)
|
||||||
|
{
|
||||||
|
item.UserItemCountList.Remove(current);
|
||||||
|
}
|
||||||
|
|
||||||
|
counts.UserId = userId;
|
||||||
|
item.UserItemCountList.Add(counts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
IndexName = indexName;
|
IndexName = indexName;
|
||||||
Parent = parent;
|
Parent = parent;
|
||||||
LoadSavedChildren();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1,10 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
using MediaBrowser.Model.Entities;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities.Movies
|
namespace MediaBrowser.Controller.Entities.Movies
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class BoxSet
|
/// Class BoxSet
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class BoxSet : Folder
|
public class BoxSet : Folder, IHasTrailers
|
||||||
{
|
{
|
||||||
|
public BoxSet()
|
||||||
|
{
|
||||||
|
RemoteTrailers = new List<MediaUrl>();
|
||||||
|
LocalTrailerIds = new List<Guid>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Guid> LocalTrailerIds { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the remote trailers.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The remote trailers.</value>
|
||||||
|
public List<MediaUrl> RemoteTrailers { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ namespace MediaBrowser.Controller.Entities.Movies
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class Movie
|
/// Class Movie
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Movie : Video, IHasCriticRating, IHasSoundtracks
|
public class Movie : Video, IHasCriticRating, IHasSoundtracks, IHasBudget, IHasTrailers
|
||||||
{
|
{
|
||||||
public List<Guid> SpecialFeatureIds { get; set; }
|
public List<Guid> SpecialFeatureIds { get; set; }
|
||||||
|
|
||||||
@ -21,8 +21,26 @@ namespace MediaBrowser.Controller.Entities.Movies
|
|||||||
{
|
{
|
||||||
SpecialFeatureIds = new List<Guid>();
|
SpecialFeatureIds = new List<Guid>();
|
||||||
SoundtrackIds = new List<Guid>();
|
SoundtrackIds = new List<Guid>();
|
||||||
|
RemoteTrailers = new List<MediaUrl>();
|
||||||
|
LocalTrailerIds = new List<Guid>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Guid> LocalTrailerIds { get; set; }
|
||||||
|
|
||||||
|
public List<MediaUrl> RemoteTrailers { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the budget.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The budget.</value>
|
||||||
|
public double? Budget { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the revenue.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The revenue.</value>
|
||||||
|
public double? Revenue { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the critic rating.
|
/// Gets or sets the critic rating.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -4,7 +4,7 @@ using System;
|
|||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
public class MusicVideo : Video, IHasArtist, IHasMusicGenres
|
public class MusicVideo : Video, IHasArtist, IHasMusicGenres, IHasBudget
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the artist.
|
/// Gets or sets the artist.
|
||||||
@ -18,6 +18,18 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <value>The album.</value>
|
/// <value>The album.</value>
|
||||||
public string Album { get; set; }
|
public string Album { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the budget.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The budget.</value>
|
||||||
|
public double? Budget { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the revenue.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The revenue.</value>
|
||||||
|
public double? Revenue { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether the specified name has artist.
|
/// Determines whether the specified name has artist.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
using System.Runtime.Serialization;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Dto;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
@ -12,11 +12,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
public Person()
|
public Person()
|
||||||
{
|
{
|
||||||
UserItemCounts = new Dictionary<Guid, ItemByNameCounts>();
|
UserItemCountList = new List<ItemByNameCounts>();
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; }
|
public List<ItemByNameCounts> UserItemCountList { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the user data key.
|
/// Gets the user data key.
|
||||||
@ -49,6 +49,12 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <value>The type.</value>
|
/// <value>The type.</value>
|
||||||
public string Type { get; set; }
|
public string Type { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the sort order - ascending
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The sort order.</value>
|
||||||
|
public int? SortOrder { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a <see cref="System.String" /> that represents this instance.
|
/// Returns a <see cref="System.String" /> that represents this instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -12,7 +12,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
public Studio()
|
public Studio()
|
||||||
{
|
{
|
||||||
UserItemCounts = new Dictionary<Guid, ItemByNameCounts>();
|
UserItemCountList = new List<ItemByNameCounts>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -25,6 +25,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; }
|
public List<ItemByNameCounts> UserItemCountList { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,33 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
get { return true; }
|
get { return true; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public int? AiredSeasonNumber
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return AirsAfterSeasonNumber ?? AirsBeforeSeasonNumber ?? PhysicalSeasonNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public int? PhysicalSeasonNumber
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var value = ParentIndexNumber;
|
||||||
|
|
||||||
|
if (value.HasValue)
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
var season = Parent as Season;
|
||||||
|
|
||||||
|
return season != null ? season.IndexNumber : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// We roll up into series
|
/// We roll up into series
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -59,7 +86,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return Season;
|
return FindParent<Season>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,20 +178,6 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
get { return _series ?? (_series = FindParent<Series>()); }
|
get { return _series ?? (_series = FindParent<Series>()); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The _season
|
|
||||||
/// </summary>
|
|
||||||
private Season _season;
|
|
||||||
/// <summary>
|
|
||||||
/// This Episode's Season Instance
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The season.</value>
|
|
||||||
[IgnoreDataMember]
|
|
||||||
public Season Season
|
|
||||||
{
|
|
||||||
get { return _season ?? (_season = FindParent<Season>()); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is the ending episode number for double episodes.
|
/// This is the ending episode number for double episodes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -221,5 +234,46 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
{
|
{
|
||||||
get { return LocationType == Model.Entities.LocationType.Virtual && IsUnaired; }
|
get { return LocationType == Model.Entities.LocationType.Virtual && IsUnaired; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public Guid? SeasonId
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
// First see if the parent is a Season
|
||||||
|
var season = Parent as Season;
|
||||||
|
|
||||||
|
if (season != null)
|
||||||
|
{
|
||||||
|
return season.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
var seasonNumber = ParentIndexNumber;
|
||||||
|
|
||||||
|
// Parent is a Series
|
||||||
|
if (seasonNumber.HasValue)
|
||||||
|
{
|
||||||
|
var series = Parent as Series;
|
||||||
|
|
||||||
|
if (series != null)
|
||||||
|
{
|
||||||
|
season = series.Children.OfType<Season>()
|
||||||
|
.FirstOrDefault(i => i.IndexNumber.HasValue && i.IndexNumber.Value == seasonNumber.Value);
|
||||||
|
|
||||||
|
if (season != null)
|
||||||
|
{
|
||||||
|
return season.Id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IEnumerable<string> GetDeletePaths()
|
||||||
|
{
|
||||||
|
return new[] { Path };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
using System.Linq;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Library;
|
|
||||||
using MediaBrowser.Controller.Localization;
|
using MediaBrowser.Controller.Localization;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities.TV
|
namespace MediaBrowser.Controller.Entities.TV
|
||||||
@ -94,6 +94,22 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
get { return _series ?? (_series = FindParent<Series>()); }
|
get { return _series ?? (_series = FindParent<Series>()); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public string SeriesPath
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var series = Series;
|
||||||
|
|
||||||
|
if (series != null)
|
||||||
|
{
|
||||||
|
return series.Path;
|
||||||
|
}
|
||||||
|
|
||||||
|
return System.IO.Path.GetDirectoryName(Path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Our rating comes from our series
|
/// Our rating comes from our series
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -149,16 +165,34 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name;
|
return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IEnumerable<Episode> GetEpisodes()
|
||||||
|
{
|
||||||
|
var series = Series;
|
||||||
|
|
||||||
|
if (series != null && series.ContainsEpisodesWithoutSeasonFolders)
|
||||||
|
{
|
||||||
|
var seasonNumber = IndexNumber;
|
||||||
|
|
||||||
|
if (seasonNumber.HasValue)
|
||||||
|
{
|
||||||
|
return series.RecursiveChildren.OfType<Episode>()
|
||||||
|
.Where(i => i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == seasonNumber.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Children.OfType<Episode>();
|
||||||
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsMissingSeason
|
public bool IsMissingSeason
|
||||||
{
|
{
|
||||||
get { return LocationType == Model.Entities.LocationType.Virtual && Children.OfType<Episode>().All(i => i.IsMissingEpisode); }
|
get { return LocationType == Model.Entities.LocationType.Virtual && GetEpisodes().All(i => i.IsMissingEpisode); }
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsUnaired
|
public bool IsUnaired
|
||||||
{
|
{
|
||||||
get { return Children.OfType<Episode>().All(i => i.IsUnaired); }
|
get { return GetEpisodes().All(i => i.IsUnaired); }
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
@ -170,7 +204,13 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsMissingOrVirtualUnaired
|
public bool IsMissingOrVirtualUnaired
|
||||||
{
|
{
|
||||||
get { return LocationType == Model.Entities.LocationType.Virtual && Children.OfType<Episode>().All(i => i.IsVirtualUnaired || i.IsMissingEpisode); }
|
get { return LocationType == Model.Entities.LocationType.Virtual && GetEpisodes().All(i => i.IsVirtualUnaired || i.IsMissingEpisode); }
|
||||||
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public bool IsSpecialSeason
|
||||||
|
{
|
||||||
|
get { return (IndexNumber ?? -1) == 0; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ using MediaBrowser.Model.Entities;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities.TV
|
namespace MediaBrowser.Controller.Entities.TV
|
||||||
@ -11,7 +12,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class Series
|
/// Class Series
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Series : Folder, IHasSoundtracks
|
public class Series : Folder, IHasSoundtracks, IHasTrailers
|
||||||
{
|
{
|
||||||
public List<Guid> SpecialFeatureIds { get; set; }
|
public List<Guid> SpecialFeatureIds { get; set; }
|
||||||
public List<Guid> SoundtrackIds { get; set; }
|
public List<Guid> SoundtrackIds { get; set; }
|
||||||
@ -24,8 +25,14 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
|
|
||||||
SpecialFeatureIds = new List<Guid>();
|
SpecialFeatureIds = new List<Guid>();
|
||||||
SoundtrackIds = new List<Guid>();
|
SoundtrackIds = new List<Guid>();
|
||||||
|
RemoteTrailers = new List<MediaUrl>();
|
||||||
|
LocalTrailerIds = new List<Guid>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Guid> LocalTrailerIds { get; set; }
|
||||||
|
|
||||||
|
public List<MediaUrl> RemoteTrailers { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the status.
|
/// Gets or sets the status.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -94,5 +101,14 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
|
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public bool ContainsEpisodesWithoutSeasonFolders
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Children.OfType<Video>().Any();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class Trailer
|
/// Class Trailer
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Trailer : Video, IHasCriticRating, IHasSoundtracks
|
public class Trailer : Video, IHasCriticRating, IHasSoundtracks, IHasBudget, IHasTrailers
|
||||||
{
|
{
|
||||||
public List<Guid> SoundtrackIds { get; set; }
|
public List<Guid> SoundtrackIds { get; set; }
|
||||||
|
|
||||||
@ -17,8 +17,25 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
RemoteTrailers = new List<MediaUrl>();
|
RemoteTrailers = new List<MediaUrl>();
|
||||||
Taglines = new List<string>();
|
Taglines = new List<string>();
|
||||||
SoundtrackIds = new List<Guid>();
|
SoundtrackIds = new List<Guid>();
|
||||||
|
LocalTrailerIds = new List<Guid>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Guid> LocalTrailerIds { get; set; }
|
||||||
|
|
||||||
|
public List<MediaUrl> RemoteTrailers { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the budget.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The budget.</value>
|
||||||
|
public double? Budget { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the revenue.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The revenue.</value>
|
||||||
|
public double? Revenue { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the critic rating.
|
/// Gets or sets the critic rating.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -14,7 +14,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class Video
|
/// Class Video
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Video : BaseItem, IHasMediaStreams
|
public class Video : BaseItem, IHasMediaStreams, IHasAspectRatio
|
||||||
{
|
{
|
||||||
public bool IsMultiPart { get; set; }
|
public bool IsMultiPart { get; set; }
|
||||||
|
|
||||||
@ -65,6 +65,12 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return GetPlayableStreamFiles(Path);
|
return GetPlayableStreamFiles(Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the aspect ratio.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The aspect ratio.</value>
|
||||||
|
public string AspectRatio { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Should be overridden to return the proper folder where metadata lives
|
/// Should be overridden to return the proper folder where metadata lives
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -252,5 +258,17 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}).ToList();
|
}).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override IEnumerable<string> GetDeletePaths()
|
||||||
|
{
|
||||||
|
if (!IsInMixedFolder)
|
||||||
|
{
|
||||||
|
if (VideoType == VideoType.VideoFile || VideoType == VideoType.Iso)
|
||||||
|
{
|
||||||
|
return new[] { System.IO.Path.GetDirectoryName(Path) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.GetDeletePaths();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,11 +12,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
public Year()
|
public Year()
|
||||||
{
|
{
|
||||||
UserItemCounts = new Dictionary<Guid, ItemByNameCounts>();
|
UserItemCountList = new List<ItemByNameCounts>();
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; }
|
public List<ItemByNameCounts> UserItemCountList { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the user data key.
|
/// Gets the user data key.
|
||||||
|
@ -60,7 +60,7 @@ namespace MediaBrowser.Controller.Library
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="name">The name.</param>
|
/// <param name="name">The name.</param>
|
||||||
/// <returns>Task{Artist}.</returns>
|
/// <returns>Task{Artist}.</returns>
|
||||||
Artist GetArtist(string name);
|
MusicArtist GetArtist(string name);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a Studio
|
/// Gets a Studio
|
||||||
@ -302,5 +302,18 @@ namespace MediaBrowser.Controller.Library
|
|||||||
/// <param name="updateType">Type of the update.</param>
|
/// <param name="updateType">Type of the update.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task SaveMetadata(BaseItem item, ItemUpdateType updateType);
|
Task SaveMetadata(BaseItem item, ItemUpdateType updateType);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets all artists.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>IEnumerable{System.String}.</returns>
|
||||||
|
IEnumerable<string> GetAllArtists();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets all artists.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="items">The items.</param>
|
||||||
|
/// <returns>IEnumerable{System.String}.</returns>
|
||||||
|
IEnumerable<string> GetAllArtists(IEnumerable<BaseItem> items);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -257,7 +257,7 @@ namespace MediaBrowser.Controller.Library
|
|||||||
|
|
||||||
if (match != null)
|
if (match != null)
|
||||||
{
|
{
|
||||||
return ParseEpisodeNumber(match.Value);
|
return ParseEpisodeNumber(match.Groups["epnumber"].Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
73
MediaBrowser.Controller/LiveTv/Channel.cs
Normal file
73
MediaBrowser.Controller/LiveTv/Channel.cs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
using MediaBrowser.Controller.Entities;
|
||||||
|
using MediaBrowser.Model.Dto;
|
||||||
|
using MediaBrowser.Model.LiveTv;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
|
{
|
||||||
|
public class Channel : BaseItem, IItemByName
|
||||||
|
{
|
||||||
|
public Channel()
|
||||||
|
{
|
||||||
|
UserItemCountList = new List<ItemByNameCounts>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the user data key.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>System.String.</returns>
|
||||||
|
public override string GetUserDataKey()
|
||||||
|
{
|
||||||
|
return "Channel-" + Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public List<ItemByNameCounts> UserItemCountList { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the number.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The number.</value>
|
||||||
|
public string ChannelNumber { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get or sets the Id.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The id of the channel.</value>
|
||||||
|
public string ChannelId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the name of the service.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The name of the service.</value>
|
||||||
|
public string ServiceName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the type of the channel.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The type of the channel.</value>
|
||||||
|
public ChannelType ChannelType { get; set; }
|
||||||
|
|
||||||
|
protected override string CreateSortName()
|
||||||
|
{
|
||||||
|
double number = 0;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(ChannelNumber))
|
||||||
|
{
|
||||||
|
double.TryParse(ChannelNumber, out number);
|
||||||
|
}
|
||||||
|
|
||||||
|
return number.ToString("000-") + (Name ?? string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string MediaType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ChannelType == ChannelType.Radio ? Model.Entities.MediaType.Audio : Model.Entities.MediaType.Video;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -25,12 +25,6 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
/// <value>The id of the channel.</value>
|
/// <value>The id of the channel.</value>
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the name of the service.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The name of the service.</value>
|
|
||||||
public string ServiceName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the type of the channel.
|
/// Gets or sets the type of the channel.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
using System.Threading.Tasks;
|
using MediaBrowser.Model.LiveTv;
|
||||||
using MediaBrowser.Model.LiveTv;
|
using MediaBrowser.Model.Querying;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.LiveTv
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
{
|
{
|
||||||
@ -15,6 +17,27 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
/// <value>The services.</value>
|
/// <value>The services.</value>
|
||||||
IReadOnlyList<ILiveTvService> Services { get; }
|
IReadOnlyList<ILiveTvService> Services { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Schedules the recording.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="programId">The program identifier.</param>
|
||||||
|
/// <returns>Task.</returns>
|
||||||
|
Task ScheduleRecording(string programId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deletes the recording.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The identifier.</param>
|
||||||
|
/// <returns>Task.</returns>
|
||||||
|
Task DeleteRecording(string id);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cancels the timer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The identifier.</param>
|
||||||
|
/// <returns>Task.</returns>
|
||||||
|
Task CancelTimer(string id);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the parts.
|
/// Adds the parts.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -22,10 +45,65 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
void AddParts(IEnumerable<ILiveTvService> services);
|
void AddParts(IEnumerable<ILiveTvService> services);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the channel info dto.
|
/// Gets the channels.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="info">The info.</param>
|
/// <param name="query">The query.</param>
|
||||||
/// <returns>ChannelInfoDto.</returns>
|
/// <returns>IEnumerable{Channel}.</returns>
|
||||||
ChannelInfoDto GetChannelInfoDto(ChannelInfo info);
|
QueryResult<ChannelInfoDto> GetChannels(ChannelQuery query);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the recording.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The identifier.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>Task{RecordingInfoDto}.</returns>
|
||||||
|
Task<RecordingInfoDto> GetRecording(string id, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the timer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The identifier.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>Task{TimerInfoDto}.</returns>
|
||||||
|
Task<TimerInfoDto> GetTimer(string id, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the recordings.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="query">The query.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>QueryResult{RecordingInfoDto}.</returns>
|
||||||
|
Task<QueryResult<RecordingInfoDto>> GetRecordings(RecordingQuery query, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the timers.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="query">The query.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>Task{QueryResult{TimerInfoDto}}.</returns>
|
||||||
|
Task<QueryResult<TimerInfoDto>> GetTimers(TimerQuery query, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the channel.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The identifier.</param>
|
||||||
|
/// <returns>Channel.</returns>
|
||||||
|
Channel GetChannel(string id);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the channel.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The identifier.</param>
|
||||||
|
/// <param name="userId">The user identifier.</param>
|
||||||
|
/// <returns>Channel.</returns>
|
||||||
|
ChannelInfoDto GetChannelInfoDto(string id, string userId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the programs.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="query">The query.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>IEnumerable{ProgramInfo}.</returns>
|
||||||
|
Task<QueryResult<ProgramInfoDto>> GetPrograms(ProgramQuery query, CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using MediaBrowser.Model.LiveTv;
|
using MediaBrowser.Common.Net;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -24,19 +24,88 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
Task<IEnumerable<ChannelInfo>> GetChannelsAsync(CancellationToken cancellationToken);
|
Task<IEnumerable<ChannelInfo>> GetChannelsAsync(CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the recordings asynchronous.
|
/// Cancels the timer asynchronous.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="query">The query.</param>
|
/// <param name="timerId">The timer identifier.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task{IEnumerable{RecordingInfo}}.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task<IEnumerable<RecordingInfo>> GetRecordingsAsync(RecordingQuery query, CancellationToken cancellationToken);
|
Task CancelTimerAsync(string timerId, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the channel guides.
|
/// Deletes the recording asynchronous.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="channelIdList">The channel identifier list.</param>
|
/// <param name="recordingId">The recording identifier.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task{IEnumerable{ChannelGuide}}.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task<IEnumerable<ChannelGuide>> GetChannelGuidesAsync(IEnumerable<string> channelIdList, CancellationToken cancellationToken);
|
Task DeleteRecordingAsync(string recordingId, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates the timer asynchronous.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="info">The information.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>Task.</returns>
|
||||||
|
Task CreateTimerAsync(TimerInfo info, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates the series timer asynchronous.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="info">The information.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>Task.</returns>
|
||||||
|
Task CreateSeriesTimerAsync(SeriesTimerInfo info, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the series timer asynchronous.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="info">The information.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>Task.</returns>
|
||||||
|
Task UpdateSeriesTimerAsync(SeriesTimerInfo info, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the channel image asynchronous.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="channelId">The channel identifier.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>Task{Stream}.</returns>
|
||||||
|
Task<ImageResponseInfo> GetChannelImageAsync(string channelId, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the program image asynchronous.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="programId">The program identifier.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>Task{ImageResponseInfo}.</returns>
|
||||||
|
Task<ImageResponseInfo> GetProgramImageAsync(string programId, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the recordings asynchronous.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>Task{IEnumerable{RecordingInfo}}.</returns>
|
||||||
|
Task<IEnumerable<RecordingInfo>> GetRecordingsAsync(CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the recordings asynchronous.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>Task{IEnumerable{RecordingInfo}}.</returns>
|
||||||
|
Task<IEnumerable<TimerInfo>> GetTimersAsync(CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the series timers asynchronous.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>Task{IEnumerable{SeriesTimerInfo}}.</returns>
|
||||||
|
Task<IEnumerable<SeriesTimerInfo>> GetSeriesTimersAsync(CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the programs asynchronous.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="channelId">The channel identifier.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>Task{IEnumerable{ProgramInfo}}.</returns>
|
||||||
|
Task<IEnumerable<ProgramInfo>> GetProgramsAsync(string channelId, CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
19
MediaBrowser.Controller/LiveTv/ImageResponseInfo.cs
Normal file
19
MediaBrowser.Controller/LiveTv/ImageResponseInfo.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
|
{
|
||||||
|
public class ImageResponseInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the stream.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The stream.</value>
|
||||||
|
public Stream Stream { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the type of the MIME.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The type of the MIME.</value>
|
||||||
|
public string MimeType { get; set; }
|
||||||
|
}
|
||||||
|
}
|
98
MediaBrowser.Controller/LiveTv/ProgramInfo.cs
Normal file
98
MediaBrowser.Controller/LiveTv/ProgramInfo.cs
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
using MediaBrowser.Model.LiveTv;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
|
{
|
||||||
|
public class ProgramInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Id of the program.
|
||||||
|
/// </summary>
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the channel identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The channel identifier.</value>
|
||||||
|
public string ChannelId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Name of the program
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the official rating.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The official rating.</value>
|
||||||
|
public string OfficialRating { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Description of the progam.
|
||||||
|
/// </summary>
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The start date of the program, in UTC.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime StartDate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The end date of the program, in UTC.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime EndDate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the aspect ratio.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The aspect ratio.</value>
|
||||||
|
public string AspectRatio { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Genre of the program.
|
||||||
|
/// </summary>
|
||||||
|
public List<string> Genres { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the quality.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The quality.</value>
|
||||||
|
public ProgramVideoQuality Quality { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the original air date.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The original air date.</value>
|
||||||
|
public DateTime? OriginalAirDate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the audio.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The audio.</value>
|
||||||
|
public ProgramAudio Audio { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the community rating.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The community rating.</value>
|
||||||
|
public float? CommunityRating { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether this instance is repeat.
|
||||||
|
/// </summary>
|
||||||
|
/// <value><c>true</c> if this instance is repeat; otherwise, <c>false</c>.</value>
|
||||||
|
public bool IsRepeat { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the episode title.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The episode title.</value>
|
||||||
|
public string EpisodeTitle { get; set; }
|
||||||
|
|
||||||
|
public ProgramInfo()
|
||||||
|
{
|
||||||
|
Genres = new List<string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
102
MediaBrowser.Controller/LiveTv/RecordingInfo.cs
Normal file
102
MediaBrowser.Controller/LiveTv/RecordingInfo.cs
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
using MediaBrowser.Model.LiveTv;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
|
{
|
||||||
|
public class RecordingInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Id of the recording.
|
||||||
|
/// </summary>
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ChannelId of the recording.
|
||||||
|
/// </summary>
|
||||||
|
public string ChannelId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ChannelName of the recording.
|
||||||
|
/// </summary>
|
||||||
|
public string ChannelName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the type of the channel.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The type of the channel.</value>
|
||||||
|
public ChannelType ChannelType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Name of the recording.
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the path.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The path.</value>
|
||||||
|
public string Path { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Description of the recording.
|
||||||
|
/// </summary>
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The start date of the recording, in UTC.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime StartDate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The end date of the recording, in UTC.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime EndDate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the program identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The program identifier.</value>
|
||||||
|
public string ProgramId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the status.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The status.</value>
|
||||||
|
public RecordingStatus Status { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Genre of the program.
|
||||||
|
/// </summary>
|
||||||
|
public List<string> Genres { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether this instance is repeat.
|
||||||
|
/// </summary>
|
||||||
|
/// <value><c>true</c> if this instance is repeat; otherwise, <c>false</c>.</value>
|
||||||
|
public bool IsRepeat { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the episode title.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The episode title.</value>
|
||||||
|
public string EpisodeTitle { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the official rating.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The official rating.</value>
|
||||||
|
public string OfficialRating { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the community rating.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The community rating.</value>
|
||||||
|
public float? CommunityRating { get; set; }
|
||||||
|
|
||||||
|
public RecordingInfo()
|
||||||
|
{
|
||||||
|
Genres = new List<string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
85
MediaBrowser.Controller/LiveTv/SeriesTimerInfo.cs
Normal file
85
MediaBrowser.Controller/LiveTv/SeriesTimerInfo.cs
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
using MediaBrowser.Model.LiveTv;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
|
{
|
||||||
|
public class SeriesTimerInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Id of the recording.
|
||||||
|
/// </summary>
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ChannelId of the recording.
|
||||||
|
/// </summary>
|
||||||
|
public string ChannelId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ChannelName of the recording.
|
||||||
|
/// </summary>
|
||||||
|
public string ChannelName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the program identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The program identifier.</value>
|
||||||
|
public string ProgramId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Name of the recording.
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Description of the recording.
|
||||||
|
/// </summary>
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The start date of the recording, in UTC.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime StartDate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The end date of the recording, in UTC.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime EndDate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the pre padding seconds.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The pre padding seconds.</value>
|
||||||
|
public int PrePaddingSeconds { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the post padding seconds.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The post padding seconds.</value>
|
||||||
|
public int PostPaddingSeconds { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the type of the recurrence.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The type of the recurrence.</value>
|
||||||
|
public RecurrenceType RecurrenceType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the days.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The days.</value>
|
||||||
|
public List<DayOfWeek> Days { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the priority.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The priority.</value>
|
||||||
|
public int Priority { get; set; }
|
||||||
|
|
||||||
|
public SeriesTimerInfo()
|
||||||
|
{
|
||||||
|
Days = new List<DayOfWeek>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
73
MediaBrowser.Controller/LiveTv/TimerInfo.cs
Normal file
73
MediaBrowser.Controller/LiveTv/TimerInfo.cs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
using MediaBrowser.Model.LiveTv;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
|
{
|
||||||
|
public class TimerInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Id of the recording.
|
||||||
|
/// </summary>
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the series timer identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The series timer identifier.</value>
|
||||||
|
public string SeriesTimerId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ChannelId of the recording.
|
||||||
|
/// </summary>
|
||||||
|
public string ChannelId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ChannelName of the recording.
|
||||||
|
/// </summary>
|
||||||
|
public string ChannelName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the program identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The program identifier.</value>
|
||||||
|
public string ProgramId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Name of the recording.
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Description of the recording.
|
||||||
|
/// </summary>
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The start date of the recording, in UTC.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime StartDate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The end date of the recording, in UTC.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime EndDate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the status.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The status.</value>
|
||||||
|
public RecordingStatus Status { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the pre padding seconds.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The pre padding seconds.</value>
|
||||||
|
public int PrePaddingSeconds { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the post padding seconds.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The post padding seconds.</value>
|
||||||
|
public int PostPaddingSeconds { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -89,8 +89,11 @@
|
|||||||
<Compile Include="Entities\GameGenre.cs" />
|
<Compile Include="Entities\GameGenre.cs" />
|
||||||
<Compile Include="Entities\GameSystem.cs" />
|
<Compile Include="Entities\GameSystem.cs" />
|
||||||
<Compile Include="Entities\IByReferenceItem.cs" />
|
<Compile Include="Entities\IByReferenceItem.cs" />
|
||||||
|
<Compile Include="Entities\IHasAspectRatio.cs" />
|
||||||
|
<Compile Include="Entities\IHasBudget.cs" />
|
||||||
<Compile Include="Entities\IHasCriticRating.cs" />
|
<Compile Include="Entities\IHasCriticRating.cs" />
|
||||||
<Compile Include="Entities\IHasSoundtracks.cs" />
|
<Compile Include="Entities\IHasSoundtracks.cs" />
|
||||||
|
<Compile Include="Entities\IHasTrailers.cs" />
|
||||||
<Compile Include="Entities\IItemByName.cs" />
|
<Compile Include="Entities\IItemByName.cs" />
|
||||||
<Compile Include="Entities\ILibraryItem.cs" />
|
<Compile Include="Entities\ILibraryItem.cs" />
|
||||||
<Compile Include="Entities\ImageSourceInfo.cs" />
|
<Compile Include="Entities\ImageSourceInfo.cs" />
|
||||||
@ -103,18 +106,24 @@
|
|||||||
<Compile Include="Library\ItemUpdateType.cs" />
|
<Compile Include="Library\ItemUpdateType.cs" />
|
||||||
<Compile Include="Library\IUserDataManager.cs" />
|
<Compile Include="Library\IUserDataManager.cs" />
|
||||||
<Compile Include="Library\UserDataSaveEventArgs.cs" />
|
<Compile Include="Library\UserDataSaveEventArgs.cs" />
|
||||||
|
<Compile Include="LiveTv\Channel.cs" />
|
||||||
<Compile Include="LiveTv\ChannelInfo.cs" />
|
<Compile Include="LiveTv\ChannelInfo.cs" />
|
||||||
<Compile Include="LiveTv\ILiveTvManager.cs" />
|
<Compile Include="LiveTv\ILiveTvManager.cs" />
|
||||||
<Compile Include="LiveTv\ILiveTvService.cs" />
|
<Compile Include="LiveTv\ILiveTvService.cs" />
|
||||||
|
<Compile Include="LiveTv\ImageResponseInfo.cs" />
|
||||||
|
<Compile Include="LiveTv\ProgramInfo.cs" />
|
||||||
|
<Compile Include="LiveTv\RecordingInfo.cs" />
|
||||||
|
<Compile Include="LiveTv\SeriesTimerInfo.cs" />
|
||||||
|
<Compile Include="LiveTv\TimerInfo.cs" />
|
||||||
<Compile Include="Localization\ILocalizationManager.cs" />
|
<Compile Include="Localization\ILocalizationManager.cs" />
|
||||||
<Compile Include="Notifications\INotificationsRepository.cs" />
|
<Compile Include="Notifications\INotificationsRepository.cs" />
|
||||||
<Compile Include="Notifications\NotificationUpdateEventArgs.cs" />
|
<Compile Include="Notifications\NotificationUpdateEventArgs.cs" />
|
||||||
<Compile Include="Providers\IDynamicInfoProvider.cs" />
|
<Compile Include="Providers\IDynamicInfoProvider.cs" />
|
||||||
<Compile Include="Providers\IImageProvider.cs" />
|
<Compile Include="Providers\IImageProvider.cs" />
|
||||||
|
<Compile Include="Providers\NameParser.cs" />
|
||||||
<Compile Include="Session\ISessionManager.cs" />
|
<Compile Include="Session\ISessionManager.cs" />
|
||||||
<Compile Include="Drawing\ImageExtensions.cs" />
|
<Compile Include="Drawing\ImageExtensions.cs" />
|
||||||
<Compile Include="Entities\AggregateFolder.cs" />
|
<Compile Include="Entities\AggregateFolder.cs" />
|
||||||
<Compile Include="Entities\Audio\Artist.cs" />
|
|
||||||
<Compile Include="Entities\Audio\Audio.cs" />
|
<Compile Include="Entities\Audio\Audio.cs" />
|
||||||
<Compile Include="Entities\Audio\MusicAlbum.cs" />
|
<Compile Include="Entities\Audio\MusicAlbum.cs" />
|
||||||
<Compile Include="Entities\Audio\MusicArtist.cs" />
|
<Compile Include="Entities\Audio\MusicArtist.cs" />
|
||||||
|
@ -69,6 +69,12 @@ namespace MediaBrowser.Controller.Providers
|
|||||||
item.People.Clear();
|
item.People.Clear();
|
||||||
item.Tags.Clear();
|
item.Tags.Clear();
|
||||||
|
|
||||||
|
var hasTrailers = item as IHasTrailers;
|
||||||
|
if (hasTrailers != null)
|
||||||
|
{
|
||||||
|
hasTrailers.RemoteTrailers.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
//Fetch(item, metadataFile, settings, Encoding.GetEncoding("ISO-8859-1"), cancellationToken);
|
//Fetch(item, metadataFile, settings, Encoding.GetEncoding("ISO-8859-1"), cancellationToken);
|
||||||
Fetch(item, metadataFile, settings, Encoding.UTF8, cancellationToken);
|
Fetch(item, metadataFile, settings, Encoding.UTF8, cancellationToken);
|
||||||
}
|
}
|
||||||
@ -161,10 +167,14 @@ namespace MediaBrowser.Controller.Providers
|
|||||||
case "Budget":
|
case "Budget":
|
||||||
{
|
{
|
||||||
var text = reader.ReadElementContentAsString();
|
var text = reader.ReadElementContentAsString();
|
||||||
|
var hasBudget = item as IHasBudget;
|
||||||
|
if (hasBudget != null)
|
||||||
|
{
|
||||||
double value;
|
double value;
|
||||||
if (double.TryParse(text, NumberStyles.Any, _usCulture, out value))
|
if (double.TryParse(text, NumberStyles.Any, _usCulture, out value))
|
||||||
{
|
{
|
||||||
item.Budget = value;
|
hasBudget.Budget = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -173,10 +183,14 @@ namespace MediaBrowser.Controller.Providers
|
|||||||
case "Revenue":
|
case "Revenue":
|
||||||
{
|
{
|
||||||
var text = reader.ReadElementContentAsString();
|
var text = reader.ReadElementContentAsString();
|
||||||
|
var hasBudget = item as IHasBudget;
|
||||||
|
if (hasBudget != null)
|
||||||
|
{
|
||||||
double value;
|
double value;
|
||||||
if (double.TryParse(text, NumberStyles.Any, _usCulture, out value))
|
if (double.TryParse(text, NumberStyles.Any, _usCulture, out value))
|
||||||
{
|
{
|
||||||
item.Revenue = value;
|
hasBudget.Revenue = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -375,9 +389,10 @@ namespace MediaBrowser.Controller.Providers
|
|||||||
{
|
{
|
||||||
var val = reader.ReadElementContentAsString();
|
var val = reader.ReadElementContentAsString();
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(val))
|
var hasAspectRatio = item as IHasAspectRatio;
|
||||||
|
if (!string.IsNullOrWhiteSpace(val) && hasAspectRatio != null)
|
||||||
{
|
{
|
||||||
item.AspectRatio = val;
|
hasAspectRatio.AspectRatio = val;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -474,9 +489,26 @@ namespace MediaBrowser.Controller.Providers
|
|||||||
{
|
{
|
||||||
var val = reader.ReadElementContentAsString();
|
var val = reader.ReadElementContentAsString();
|
||||||
|
|
||||||
|
var hasTrailers = item as IHasTrailers;
|
||||||
|
if (hasTrailers != null)
|
||||||
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(val))
|
if (!string.IsNullOrWhiteSpace(val))
|
||||||
{
|
{
|
||||||
item.AddTrailerUrl(val, false);
|
hasTrailers.AddTrailerUrl(val, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case "Trailers":
|
||||||
|
{
|
||||||
|
using (var subtree = reader.ReadSubtree())
|
||||||
|
{
|
||||||
|
var hasTrailers = item as IHasTrailers;
|
||||||
|
if (hasTrailers != null)
|
||||||
|
{
|
||||||
|
FetchDataFromTrailersNode(subtree, hasTrailers);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -921,6 +953,35 @@ namespace MediaBrowser.Controller.Providers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void FetchDataFromTrailersNode(XmlReader reader, IHasTrailers item)
|
||||||
|
{
|
||||||
|
reader.MoveToContent();
|
||||||
|
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
if (reader.NodeType == XmlNodeType.Element)
|
||||||
|
{
|
||||||
|
switch (reader.Name)
|
||||||
|
{
|
||||||
|
case "Trailer":
|
||||||
|
{
|
||||||
|
var val = reader.ReadElementContentAsString();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(val))
|
||||||
|
{
|
||||||
|
item.AddTrailerUrl(val, false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
reader.Skip();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected async Task FetchChaptersFromXmlNode(BaseItem item, XmlReader reader, IItemRepository repository, CancellationToken cancellationToken)
|
protected async Task FetchChaptersFromXmlNode(BaseItem item, XmlReader reader, IItemRepository repository, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var runtime = item.RunTimeTicks ?? 0;
|
var runtime = item.RunTimeTicks ?? 0;
|
||||||
@ -1071,9 +1132,10 @@ namespace MediaBrowser.Controller.Providers
|
|||||||
/// <returns>IEnumerable{PersonInfo}.</returns>
|
/// <returns>IEnumerable{PersonInfo}.</returns>
|
||||||
private IEnumerable<PersonInfo> GetPersonsFromXmlNode(XmlReader reader)
|
private IEnumerable<PersonInfo> GetPersonsFromXmlNode(XmlReader reader)
|
||||||
{
|
{
|
||||||
var names = new List<string>();
|
var name = string.Empty;
|
||||||
var type = "Actor"; // If type is not specified assume actor
|
var type = "Actor"; // If type is not specified assume actor
|
||||||
var role = string.Empty;
|
var role = string.Empty;
|
||||||
|
int? sortOrder = null;
|
||||||
|
|
||||||
reader.MoveToContent();
|
reader.MoveToContent();
|
||||||
|
|
||||||
@ -1084,7 +1146,7 @@ namespace MediaBrowser.Controller.Providers
|
|||||||
switch (reader.Name)
|
switch (reader.Name)
|
||||||
{
|
{
|
||||||
case "Name":
|
case "Name":
|
||||||
names.AddRange(SplitNames(reader.ReadElementContentAsString()));
|
name = reader.ReadElementContentAsString() ?? string.Empty;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "Type":
|
case "Type":
|
||||||
@ -1108,6 +1170,20 @@ namespace MediaBrowser.Controller.Providers
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "SortOrder":
|
||||||
|
{
|
||||||
|
var val = reader.ReadElementContentAsString();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(val))
|
||||||
|
{
|
||||||
|
int intVal;
|
||||||
|
if (int.TryParse(val, NumberStyles.Integer, _usCulture, out intVal))
|
||||||
|
{
|
||||||
|
sortOrder = intVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
reader.Skip();
|
reader.Skip();
|
||||||
@ -1116,7 +1192,15 @@ namespace MediaBrowser.Controller.Providers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return names.Select(n => new PersonInfo { Name = n.Trim(), Role = role, Type = type });
|
var personInfo = new PersonInfo
|
||||||
|
{
|
||||||
|
Name = name.Trim(),
|
||||||
|
Role = role,
|
||||||
|
Type = type,
|
||||||
|
SortOrder = sortOrder
|
||||||
|
};
|
||||||
|
|
||||||
|
return new[] { personInfo };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
39
MediaBrowser.Controller/Providers/NameParser.cs
Normal file
39
MediaBrowser.Controller/Providers/NameParser.cs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.Providers
|
||||||
|
{
|
||||||
|
public static class NameParser
|
||||||
|
{
|
||||||
|
static readonly Regex[] NameMatches = new[] {
|
||||||
|
new Regex(@"(?<name>.*)\((?<year>\d{4})\)"), // matches "My Movie (2001)" and gives us the name and the year
|
||||||
|
new Regex(@"(?<name>.*)(\.(?<year>\d{4})(\.|$)).*$"),
|
||||||
|
new Regex(@"(?<name>.*)") // last resort matches the whole string as the name
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parses the name.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The name.</param>
|
||||||
|
/// <param name="justName">Name of the just.</param>
|
||||||
|
/// <param name="year">The year.</param>
|
||||||
|
public static void ParseName(string name, out string justName, out int? year)
|
||||||
|
{
|
||||||
|
justName = null;
|
||||||
|
year = null;
|
||||||
|
foreach (var re in NameMatches)
|
||||||
|
{
|
||||||
|
Match m = re.Match(name);
|
||||||
|
if (m.Success)
|
||||||
|
{
|
||||||
|
justName = m.Groups["name"].Value.Trim();
|
||||||
|
string y = m.Groups["year"] != null ? m.Groups["year"].Value : null;
|
||||||
|
int temp;
|
||||||
|
year = Int32.TryParse(y, out temp) ? temp : (int?)null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -224,27 +224,36 @@
|
|||||||
<Compile Include="..\MediaBrowser.Model\IO\IZipClient.cs">
|
<Compile Include="..\MediaBrowser.Model\IO\IZipClient.cs">
|
||||||
<Link>IO\IZipClient.cs</Link>
|
<Link>IO\IZipClient.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\MediaBrowser.Model\LiveTv\ChannelGuide.cs">
|
|
||||||
<Link>LiveTv\ChannelGuide.cs</Link>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="..\MediaBrowser.Model\LiveTv\ChannelInfoDto.cs">
|
<Compile Include="..\MediaBrowser.Model\LiveTv\ChannelInfoDto.cs">
|
||||||
<Link>LiveTv\ChannelInfoDto.cs</Link>
|
<Link>LiveTv\ChannelInfoDto.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\MediaBrowser.Model\LiveTv\ChannelQuery.cs">
|
||||||
|
<Link>LiveTv\ChannelQuery.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\MediaBrowser.Model\LiveTv\ChannelType.cs">
|
<Compile Include="..\MediaBrowser.Model\LiveTv\ChannelType.cs">
|
||||||
<Link>LiveTv\ChannelType.cs</Link>
|
<Link>LiveTv\ChannelType.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\MediaBrowser.Model\LiveTv\LiveTvServiceInfo.cs">
|
<Compile Include="..\MediaBrowser.Model\LiveTv\LiveTvServiceInfo.cs">
|
||||||
<Link>LiveTv\LiveTvServiceInfo.cs</Link>
|
<Link>LiveTv\LiveTvServiceInfo.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\MediaBrowser.Model\LiveTv\ProgramInfo.cs">
|
<Compile Include="..\MediaBrowser.Model\LiveTv\ProgramInfoDto.cs">
|
||||||
<Link>LiveTv\ProgramInfo.cs</Link>
|
<Link>LiveTv\ProgramInfoDto.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\MediaBrowser.Model\LiveTv\RecordingInfo.cs">
|
<Compile Include="..\MediaBrowser.Model\LiveTv\ProgramQuery.cs">
|
||||||
<Link>LiveTv\RecordingInfo.cs</Link>
|
<Link>LiveTv\ProgramQuery.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\MediaBrowser.Model\LiveTv\RecordingInfoDto.cs">
|
||||||
|
<Link>LiveTv\RecordingInfoDto.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\MediaBrowser.Model\LiveTv\RecordingQuery.cs">
|
<Compile Include="..\MediaBrowser.Model\LiveTv\RecordingQuery.cs">
|
||||||
<Link>LiveTv\RecordingQuery.cs</Link>
|
<Link>LiveTv\RecordingQuery.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\MediaBrowser.Model\LiveTv\RecordingStatus.cs">
|
||||||
|
<Link>LiveTv\RecordingStatus.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\MediaBrowser.Model\LiveTv\TimerInfoDto.cs">
|
||||||
|
<Link>LiveTv\TimerInfoDto.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\MediaBrowser.Model\Logging\ILogger.cs">
|
<Compile Include="..\MediaBrowser.Model\Logging\ILogger.cs">
|
||||||
<Link>Logging\ILogger.cs</Link>
|
<Link>Logging\ILogger.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
@ -311,6 +320,9 @@
|
|||||||
<Compile Include="..\MediaBrowser.Model\Querying\ArtistsQuery.cs">
|
<Compile Include="..\MediaBrowser.Model\Querying\ArtistsQuery.cs">
|
||||||
<Link>Querying\ArtistsQuery.cs</Link>
|
<Link>Querying\ArtistsQuery.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\MediaBrowser.Model\Querying\EpisodeQuery.cs">
|
||||||
|
<Link>Querying\EpisodeQuery.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\MediaBrowser.Model\Querying\ItemCountsQuery.cs">
|
<Compile Include="..\MediaBrowser.Model\Querying\ItemCountsQuery.cs">
|
||||||
<Link>Querying\ItemCountsQuery.cs</Link>
|
<Link>Querying\ItemCountsQuery.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
@ -323,9 +335,6 @@
|
|||||||
<Compile Include="..\MediaBrowser.Model\Querying\ItemQuery.cs">
|
<Compile Include="..\MediaBrowser.Model\Querying\ItemQuery.cs">
|
||||||
<Link>Querying\ItemQuery.cs</Link>
|
<Link>Querying\ItemQuery.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\MediaBrowser.Model\Querying\ItemReviewsResult.cs">
|
|
||||||
<Link>Querying\ItemReviewsResult.cs</Link>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="..\MediaBrowser.Model\Querying\ItemsByNameQuery.cs">
|
<Compile Include="..\MediaBrowser.Model\Querying\ItemsByNameQuery.cs">
|
||||||
<Link>Querying\ItemsByNameQuery.cs</Link>
|
<Link>Querying\ItemsByNameQuery.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
@ -341,6 +350,9 @@
|
|||||||
<Compile Include="..\MediaBrowser.Model\Querying\PersonsQuery.cs">
|
<Compile Include="..\MediaBrowser.Model\Querying\PersonsQuery.cs">
|
||||||
<Link>Querying\PersonsQuery.cs</Link>
|
<Link>Querying\PersonsQuery.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\MediaBrowser.Model\Querying\QueryResult.cs">
|
||||||
|
<Link>Querying\QueryResult.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\MediaBrowser.Model\Querying\SessionQuery.cs">
|
<Compile Include="..\MediaBrowser.Model\Querying\SessionQuery.cs">
|
||||||
<Link>Querying\SessionQuery.cs</Link>
|
<Link>Querying\SessionQuery.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
@ -211,27 +211,36 @@
|
|||||||
<Compile Include="..\MediaBrowser.Model\IO\IZipClient.cs">
|
<Compile Include="..\MediaBrowser.Model\IO\IZipClient.cs">
|
||||||
<Link>IO\IZipClient.cs</Link>
|
<Link>IO\IZipClient.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\MediaBrowser.Model\LiveTv\ChannelGuide.cs">
|
|
||||||
<Link>LiveTv\ChannelGuide.cs</Link>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="..\MediaBrowser.Model\LiveTv\ChannelInfoDto.cs">
|
<Compile Include="..\MediaBrowser.Model\LiveTv\ChannelInfoDto.cs">
|
||||||
<Link>LiveTv\ChannelInfoDto.cs</Link>
|
<Link>LiveTv\ChannelInfoDto.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\MediaBrowser.Model\LiveTv\ChannelQuery.cs">
|
||||||
|
<Link>LiveTv\ChannelQuery.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\MediaBrowser.Model\LiveTv\ChannelType.cs">
|
<Compile Include="..\MediaBrowser.Model\LiveTv\ChannelType.cs">
|
||||||
<Link>LiveTv\ChannelType.cs</Link>
|
<Link>LiveTv\ChannelType.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\MediaBrowser.Model\LiveTv\LiveTvServiceInfo.cs">
|
<Compile Include="..\MediaBrowser.Model\LiveTv\LiveTvServiceInfo.cs">
|
||||||
<Link>LiveTv\LiveTvServiceInfo.cs</Link>
|
<Link>LiveTv\LiveTvServiceInfo.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\MediaBrowser.Model\LiveTv\ProgramInfo.cs">
|
<Compile Include="..\MediaBrowser.Model\LiveTv\ProgramInfoDto.cs">
|
||||||
<Link>LiveTv\ProgramInfo.cs</Link>
|
<Link>LiveTv\ProgramInfoDto.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\MediaBrowser.Model\LiveTv\RecordingInfo.cs">
|
<Compile Include="..\MediaBrowser.Model\LiveTv\ProgramQuery.cs">
|
||||||
<Link>LiveTv\RecordingInfo.cs</Link>
|
<Link>LiveTv\ProgramQuery.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\MediaBrowser.Model\LiveTv\RecordingInfoDto.cs">
|
||||||
|
<Link>LiveTv\RecordingInfoDto.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\MediaBrowser.Model\LiveTv\RecordingQuery.cs">
|
<Compile Include="..\MediaBrowser.Model\LiveTv\RecordingQuery.cs">
|
||||||
<Link>LiveTv\RecordingQuery.cs</Link>
|
<Link>LiveTv\RecordingQuery.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\MediaBrowser.Model\LiveTv\RecordingStatus.cs">
|
||||||
|
<Link>LiveTv\RecordingStatus.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\MediaBrowser.Model\LiveTv\TimerInfoDto.cs">
|
||||||
|
<Link>LiveTv\TimerInfoDto.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\MediaBrowser.Model\Logging\ILogger.cs">
|
<Compile Include="..\MediaBrowser.Model\Logging\ILogger.cs">
|
||||||
<Link>Logging\ILogger.cs</Link>
|
<Link>Logging\ILogger.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
@ -298,6 +307,9 @@
|
|||||||
<Compile Include="..\MediaBrowser.Model\Querying\ArtistsQuery.cs">
|
<Compile Include="..\MediaBrowser.Model\Querying\ArtistsQuery.cs">
|
||||||
<Link>Querying\ArtistsQuery.cs</Link>
|
<Link>Querying\ArtistsQuery.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\MediaBrowser.Model\Querying\EpisodeQuery.cs">
|
||||||
|
<Link>Querying\EpisodeQuery.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\MediaBrowser.Model\Querying\ItemCountsQuery.cs">
|
<Compile Include="..\MediaBrowser.Model\Querying\ItemCountsQuery.cs">
|
||||||
<Link>Querying\ItemCountsQuery.cs</Link>
|
<Link>Querying\ItemCountsQuery.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
@ -310,9 +322,6 @@
|
|||||||
<Compile Include="..\MediaBrowser.Model\Querying\ItemQuery.cs">
|
<Compile Include="..\MediaBrowser.Model\Querying\ItemQuery.cs">
|
||||||
<Link>Querying\ItemQuery.cs</Link>
|
<Link>Querying\ItemQuery.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\MediaBrowser.Model\Querying\ItemReviewsResult.cs">
|
|
||||||
<Link>Querying\ItemReviewsResult.cs</Link>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="..\MediaBrowser.Model\Querying\ItemsByNameQuery.cs">
|
<Compile Include="..\MediaBrowser.Model\Querying\ItemsByNameQuery.cs">
|
||||||
<Link>Querying\ItemsByNameQuery.cs</Link>
|
<Link>Querying\ItemsByNameQuery.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
@ -328,6 +337,9 @@
|
|||||||
<Compile Include="..\MediaBrowser.Model\Querying\PersonsQuery.cs">
|
<Compile Include="..\MediaBrowser.Model\Querying\PersonsQuery.cs">
|
||||||
<Link>Querying\PersonsQuery.cs</Link>
|
<Link>Querying\PersonsQuery.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\MediaBrowser.Model\Querying\QueryResult.cs">
|
||||||
|
<Link>Querying\QueryResult.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\MediaBrowser.Model\Querying\SessionQuery.cs">
|
<Compile Include="..\MediaBrowser.Model\Querying\SessionQuery.cs">
|
||||||
<Link>Querying\SessionQuery.cs</Link>
|
<Link>Querying\SessionQuery.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
@ -83,7 +83,7 @@ namespace MediaBrowser.Model.ApiClient
|
|||||||
/// <param name="startIndex">The start index.</param>
|
/// <param name="startIndex">The start index.</param>
|
||||||
/// <param name="limit">The limit.</param>
|
/// <param name="limit">The limit.</param>
|
||||||
/// <returns>Task{ItemReviewsResult}.</returns>
|
/// <returns>Task{ItemReviewsResult}.</returns>
|
||||||
Task<ItemReviewsResult> GetCriticReviews(string itemId, CancellationToken cancellationToken, int? startIndex = null, int? limit = null);
|
Task<QueryResult<ItemReview>> GetCriticReviews(string itemId, CancellationToken cancellationToken, int? startIndex = null, int? limit = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the theme songs async.
|
/// Gets the theme songs async.
|
||||||
@ -225,6 +225,20 @@ namespace MediaBrowser.Model.ApiClient
|
|||||||
/// <returns>Task{ItemCounts}.</returns>
|
/// <returns>Task{ItemCounts}.</returns>
|
||||||
Task<ItemCounts> GetItemCountsAsync(ItemCountsQuery query);
|
Task<ItemCounts> GetItemCountsAsync(ItemCountsQuery query);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the episodes asynchronous.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="query">The query.</param>
|
||||||
|
/// <returns>Task{ItemsResult}.</returns>
|
||||||
|
Task<ItemsResult> GetEpisodesAsync(EpisodeQuery query);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the seasons asynchronous.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="query">The query.</param>
|
||||||
|
/// <returns>Task{ItemsResult}.</returns>
|
||||||
|
Task<ItemsResult> GetSeasonsAsync(SeasonQuery query);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Queries for items
|
/// Queries for items
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -312,6 +312,12 @@ namespace MediaBrowser.Model.Dto
|
|||||||
/// <value>The series id.</value>
|
/// <value>The series id.</value>
|
||||||
public string SeriesId { get; set; }
|
public string SeriesId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the season identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The season identifier.</value>
|
||||||
|
public string SeasonId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the special feature count.
|
/// Gets or sets the special feature count.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
namespace MediaBrowser.Model.Dto
|
namespace MediaBrowser.Model.Dto
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -6,6 +7,8 @@ namespace MediaBrowser.Model.Dto
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class ItemByNameCounts
|
public class ItemByNameCounts
|
||||||
{
|
{
|
||||||
|
public Guid UserId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the total count.
|
/// Gets or sets the total count.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Model.LiveTv
|
|
||||||
{
|
|
||||||
public class ChannelGuide
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the name of the service.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The name of the service.</value>
|
|
||||||
public string ServiceName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// ChannelId for the EPG.
|
|
||||||
/// </summary>
|
|
||||||
public string ChannelId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// List of all the programs for a specific channel
|
|
||||||
/// </summary>
|
|
||||||
public List<ProgramInfo> Programs { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,8 @@
|
|||||||
|
using MediaBrowser.Model.Dto;
|
||||||
|
using MediaBrowser.Model.Entities;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace MediaBrowser.Model.LiveTv
|
namespace MediaBrowser.Model.LiveTv
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -18,6 +22,12 @@ namespace MediaBrowser.Model.LiveTv
|
|||||||
/// <value>The identifier.</value>
|
/// <value>The identifier.</value>
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the image tags.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The image tags.</value>
|
||||||
|
public Dictionary<ImageType, Guid> ImageTags { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the number.
|
/// Gets or sets the number.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -35,5 +45,28 @@ namespace MediaBrowser.Model.LiveTv
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The type of the channel.</value>
|
/// <value>The type of the channel.</value>
|
||||||
public ChannelType ChannelType { get; set; }
|
public ChannelType ChannelType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the type.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The type.</value>
|
||||||
|
public string Type { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the type of the media.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The type of the media.</value>
|
||||||
|
public string MediaType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the user data.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The user data.</value>
|
||||||
|
public UserItemDataDto UserData { get; set; }
|
||||||
|
|
||||||
|
public ChannelInfoDto()
|
||||||
|
{
|
||||||
|
ImageTags = new Dictionary<ImageType, Guid>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
27
MediaBrowser.Model/LiveTv/ChannelQuery.cs
Normal file
27
MediaBrowser.Model/LiveTv/ChannelQuery.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
namespace MediaBrowser.Model.LiveTv
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Class ChannelQuery.
|
||||||
|
/// </summary>
|
||||||
|
public class ChannelQuery
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the name of the service.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The name of the service.</value>
|
||||||
|
public string ServiceName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the type of the channel.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The type of the channel.</value>
|
||||||
|
public ChannelType? ChannelType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the user identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The user identifier.</value>
|
||||||
|
public string UserId { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -1,37 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Model.LiveTv
|
|
||||||
{
|
|
||||||
public class ProgramInfo
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Id of the program.
|
|
||||||
/// </summary>
|
|
||||||
public string Id { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Name of the program
|
|
||||||
/// </summary>
|
|
||||||
public string Name { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Description of the progam.
|
|
||||||
/// </summary>
|
|
||||||
public string Description { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The start date of the program, in UTC.
|
|
||||||
/// </summary>
|
|
||||||
public DateTime StartDate { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The end date of the program, in UTC.
|
|
||||||
/// </summary>
|
|
||||||
public DateTime EndDate { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Genre of the program.
|
|
||||||
/// </summary>
|
|
||||||
public string Genre { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
120
MediaBrowser.Model/LiveTv/ProgramInfoDto.cs
Normal file
120
MediaBrowser.Model/LiveTv/ProgramInfoDto.cs
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Model.LiveTv
|
||||||
|
{
|
||||||
|
public class ProgramInfoDto
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Id of the program.
|
||||||
|
/// </summary>
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the external identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The external identifier.</value>
|
||||||
|
public string ExternalId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the channel identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The channel identifier.</value>
|
||||||
|
public string ChannelId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the community rating.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The community rating.</value>
|
||||||
|
public float? CommunityRating { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the aspect ratio.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The aspect ratio.</value>
|
||||||
|
public string AspectRatio { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the official rating.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The official rating.</value>
|
||||||
|
public string OfficialRating { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the name of the service.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The name of the service.</value>
|
||||||
|
public string ServiceName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Name of the program
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Description of the progam.
|
||||||
|
/// </summary>
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The start date of the program, in UTC.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime StartDate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The end date of the program, in UTC.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime EndDate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Genre of the program.
|
||||||
|
/// </summary>
|
||||||
|
public List<string> Genres { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the quality.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The quality.</value>
|
||||||
|
public ProgramVideoQuality Quality { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the audio.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The audio.</value>
|
||||||
|
public ProgramAudio Audio { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the original air date.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The original air date.</value>
|
||||||
|
public DateTime? OriginalAirDate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether this instance is repeat.
|
||||||
|
/// </summary>
|
||||||
|
/// <value><c>true</c> if this instance is repeat; otherwise, <c>false</c>.</value>
|
||||||
|
public bool IsRepeat { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the episode title.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The episode title.</value>
|
||||||
|
public string EpisodeTitle { get; set; }
|
||||||
|
|
||||||
|
public ProgramInfoDto()
|
||||||
|
{
|
||||||
|
Genres = new List<string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ProgramVideoQuality
|
||||||
|
{
|
||||||
|
StandardDefinition,
|
||||||
|
HighDefinition
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ProgramAudio
|
||||||
|
{
|
||||||
|
Stereo
|
||||||
|
}
|
||||||
|
}
|
31
MediaBrowser.Model/LiveTv/ProgramQuery.cs
Normal file
31
MediaBrowser.Model/LiveTv/ProgramQuery.cs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
namespace MediaBrowser.Model.LiveTv
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Class ProgramQuery.
|
||||||
|
/// </summary>
|
||||||
|
public class ProgramQuery
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the name of the service.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The name of the service.</value>
|
||||||
|
public string ServiceName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the channel identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The channel identifier.</value>
|
||||||
|
public string[] ChannelIdList { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the user identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The user identifier.</value>
|
||||||
|
public string UserId { get; set; }
|
||||||
|
|
||||||
|
public ProgramQuery()
|
||||||
|
{
|
||||||
|
ChannelIdList = new string[] { };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
119
MediaBrowser.Model/LiveTv/RecordingInfoDto.cs
Normal file
119
MediaBrowser.Model/LiveTv/RecordingInfoDto.cs
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Model.LiveTv
|
||||||
|
{
|
||||||
|
public class RecordingInfoDto
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Id of the recording.
|
||||||
|
/// </summary>
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the external identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The external identifier.</value>
|
||||||
|
public string ExternalId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the program identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The program identifier.</value>
|
||||||
|
public string ProgramId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ChannelId of the recording.
|
||||||
|
/// </summary>
|
||||||
|
public string ChannelId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ChannelName of the recording.
|
||||||
|
/// </summary>
|
||||||
|
public string ChannelName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Name of the recording.
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the path.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The path.</value>
|
||||||
|
public string Path { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Description of the recording.
|
||||||
|
/// </summary>
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The start date of the recording, in UTC.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime StartDate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The end date of the recording, in UTC.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime EndDate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the status.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The status.</value>
|
||||||
|
public RecordingStatus Status { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Genre of the program.
|
||||||
|
/// </summary>
|
||||||
|
public List<string> Genres { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether this instance is repeat.
|
||||||
|
/// </summary>
|
||||||
|
/// <value><c>true</c> if this instance is repeat; otherwise, <c>false</c>.</value>
|
||||||
|
public bool IsRepeat { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the episode title.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The episode title.</value>
|
||||||
|
public string EpisodeTitle { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the duration ms.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The duration ms.</value>
|
||||||
|
public int DurationMs { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the type of the media.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The type of the media.</value>
|
||||||
|
public string MediaType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the type of the channel.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The type of the channel.</value>
|
||||||
|
public ChannelType ChannelType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the official rating.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The official rating.</value>
|
||||||
|
public string OfficialRating { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the community rating.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The community rating.</value>
|
||||||
|
public float? CommunityRating { get; set; }
|
||||||
|
|
||||||
|
public RecordingInfoDto()
|
||||||
|
{
|
||||||
|
Genres = new List<string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,9 +6,30 @@
|
|||||||
public class RecordingQuery
|
public class RecordingQuery
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether this instance has recorded.
|
/// Gets or sets the channel identifier.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value><c>null</c> if [has recorded] contains no value, <c>true</c> if [has recorded]; otherwise, <c>false</c>.</value>
|
/// <value>The channel identifier.</value>
|
||||||
public bool? HasRecorded { get; set; }
|
public string ChannelId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the name of the service.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The name of the service.</value>
|
||||||
|
public string ServiceName { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TimerQuery
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the channel identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The channel identifier.</value>
|
||||||
|
public string ChannelId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the name of the service.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The name of the service.</value>
|
||||||
|
public string ServiceName { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
22
MediaBrowser.Model/LiveTv/RecordingStatus.cs
Normal file
22
MediaBrowser.Model/LiveTv/RecordingStatus.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
namespace MediaBrowser.Model.LiveTv
|
||||||
|
{
|
||||||
|
public enum RecordingStatus
|
||||||
|
{
|
||||||
|
Pending,
|
||||||
|
InProgress,
|
||||||
|
Completed,
|
||||||
|
CompletedWithError,
|
||||||
|
Conflicted,
|
||||||
|
Deleted
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum RecurrenceType
|
||||||
|
{
|
||||||
|
Manual,
|
||||||
|
NewProgramEventsOneChannel,
|
||||||
|
AllProgramEventsOneChannel,
|
||||||
|
NewProgramEventsAllChannels,
|
||||||
|
AllProgramEventsAllChannels
|
||||||
|
}
|
||||||
|
}
|
@ -1,15 +1,20 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Model.LiveTv
|
namespace MediaBrowser.Model.LiveTv
|
||||||
{
|
{
|
||||||
public class RecordingInfo
|
public class TimerInfoDto
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Id of the recording.
|
/// Id of the recording.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the external identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The external identifier.</value>
|
||||||
|
public string ExternalId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ChannelId of the recording.
|
/// ChannelId of the recording.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -20,6 +25,12 @@ namespace MediaBrowser.Model.LiveTv
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string ChannelName { get; set; }
|
public string ChannelName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the program identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The program identifier.</value>
|
||||||
|
public string ProgramId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Name of the recording.
|
/// Name of the recording.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -41,38 +52,33 @@ namespace MediaBrowser.Model.LiveTv
|
|||||||
public DateTime EndDate { get; set; }
|
public DateTime EndDate { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Status of the recording.
|
/// Gets or sets the status.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Status { get; set; } //TODO: Enum for status?? Difference NextPvr,Argus,...
|
/// <value>The status.</value>
|
||||||
|
public RecordingStatus Status { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Quality of the Recording.
|
/// Gets or sets the series timer identifier.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Quality { get; set; } // TODO: Enum for quality?? Difference NextPvr,Argus,...
|
/// <value>The series timer identifier.</value>
|
||||||
|
public string SeriesTimerId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Recurring recording?
|
/// Gets or sets the pre padding seconds.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool Recurring { get; set; }
|
/// <value>The pre padding seconds.</value>
|
||||||
|
public int PrePaddingSeconds { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Parent recurring.
|
/// Gets or sets the post padding seconds.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string RecurringParent { get; set; }
|
/// <value>The post padding seconds.</value>
|
||||||
|
public int PostPaddingSeconds { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Start date for the recurring, in UTC.
|
/// Gets or sets the duration ms.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime RecurrringStartDate { get; set; }
|
/// <value>The duration ms.</value>
|
||||||
|
public int DurationMs { get; set; }
|
||||||
/// <summary>
|
|
||||||
/// End date for the recurring, in UTC
|
|
||||||
/// </summary>
|
|
||||||
public DateTime RecurringEndDate { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// When do we need the recording?
|
|
||||||
/// </summary>
|
|
||||||
public List<string> DayMask { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -60,9 +60,13 @@
|
|||||||
<Compile Include="Dto\ItemCounts.cs" />
|
<Compile Include="Dto\ItemCounts.cs" />
|
||||||
<Compile Include="Dto\ItemIndex.cs" />
|
<Compile Include="Dto\ItemIndex.cs" />
|
||||||
<Compile Include="Entities\PackageReviewInfo.cs" />
|
<Compile Include="Entities\PackageReviewInfo.cs" />
|
||||||
<Compile Include="LiveTv\ChannelGuide.cs" />
|
<Compile Include="LiveTv\ChannelInfoDto.cs" />
|
||||||
<Compile Include="LiveTv\ProgramInfo.cs" />
|
<Compile Include="LiveTv\ChannelQuery.cs" />
|
||||||
|
<Compile Include="LiveTv\ProgramInfoDto.cs" />
|
||||||
|
<Compile Include="LiveTv\ProgramQuery.cs" />
|
||||||
<Compile Include="LiveTv\RecordingQuery.cs" />
|
<Compile Include="LiveTv\RecordingQuery.cs" />
|
||||||
|
<Compile Include="LiveTv\RecordingStatus.cs" />
|
||||||
|
<Compile Include="LiveTv\TimerInfoDto.cs" />
|
||||||
<Compile Include="Providers\ImageProviderInfo.cs" />
|
<Compile Include="Providers\ImageProviderInfo.cs" />
|
||||||
<Compile Include="Providers\RemoteImageInfo.cs" />
|
<Compile Include="Providers\RemoteImageInfo.cs" />
|
||||||
<Compile Include="Dto\StudioDto.cs" />
|
<Compile Include="Dto\StudioDto.cs" />
|
||||||
@ -76,10 +80,9 @@
|
|||||||
<Compile Include="IO\IIsoManager.cs" />
|
<Compile Include="IO\IIsoManager.cs" />
|
||||||
<Compile Include="IO\IIsoMount.cs" />
|
<Compile Include="IO\IIsoMount.cs" />
|
||||||
<Compile Include="IO\IIsoMounter.cs" />
|
<Compile Include="IO\IIsoMounter.cs" />
|
||||||
<Compile Include="LiveTv\ChannelInfoDto.cs" />
|
|
||||||
<Compile Include="LiveTv\ChannelType.cs" />
|
<Compile Include="LiveTv\ChannelType.cs" />
|
||||||
<Compile Include="LiveTv\LiveTvServiceInfo.cs" />
|
<Compile Include="LiveTv\LiveTvServiceInfo.cs" />
|
||||||
<Compile Include="LiveTv\RecordingInfo.cs" />
|
<Compile Include="LiveTv\RecordingInfoDto.cs" />
|
||||||
<Compile Include="Net\WebSocketMessage.cs" />
|
<Compile Include="Net\WebSocketMessage.cs" />
|
||||||
<Compile Include="Net\WebSocketMessageType.cs" />
|
<Compile Include="Net\WebSocketMessageType.cs" />
|
||||||
<Compile Include="Net\WebSocketState.cs" />
|
<Compile Include="Net\WebSocketState.cs" />
|
||||||
@ -90,11 +93,12 @@
|
|||||||
<Compile Include="Notifications\NotificationsSummary.cs" />
|
<Compile Include="Notifications\NotificationsSummary.cs" />
|
||||||
<Compile Include="Providers\RemoteImageResult.cs" />
|
<Compile Include="Providers\RemoteImageResult.cs" />
|
||||||
<Compile Include="Querying\ArtistsQuery.cs" />
|
<Compile Include="Querying\ArtistsQuery.cs" />
|
||||||
|
<Compile Include="Querying\EpisodeQuery.cs" />
|
||||||
<Compile Include="Querying\ItemCountsQuery.cs" />
|
<Compile Include="Querying\ItemCountsQuery.cs" />
|
||||||
<Compile Include="Querying\ItemReviewsResult.cs" />
|
|
||||||
<Compile Include="Querying\ItemsByNameQuery.cs" />
|
<Compile Include="Querying\ItemsByNameQuery.cs" />
|
||||||
<Compile Include="Entities\BaseItemInfo.cs" />
|
<Compile Include="Entities\BaseItemInfo.cs" />
|
||||||
<Compile Include="Querying\NextUpQuery.cs" />
|
<Compile Include="Querying\NextUpQuery.cs" />
|
||||||
|
<Compile Include="Querying\QueryResult.cs" />
|
||||||
<Compile Include="Querying\SessionQuery.cs" />
|
<Compile Include="Querying\SessionQuery.cs" />
|
||||||
<Compile Include="Querying\SimilarItemsQuery.cs" />
|
<Compile Include="Querying\SimilarItemsQuery.cs" />
|
||||||
<Compile Include="Querying\UserQuery.cs" />
|
<Compile Include="Querying\UserQuery.cs" />
|
||||||
|
45
MediaBrowser.Model/Querying/EpisodeQuery.cs
Normal file
45
MediaBrowser.Model/Querying/EpisodeQuery.cs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
|
||||||
|
namespace MediaBrowser.Model.Querying
|
||||||
|
{
|
||||||
|
public class EpisodeQuery
|
||||||
|
{
|
||||||
|
public string UserId { get; set; }
|
||||||
|
|
||||||
|
public string SeasonId { get; set; }
|
||||||
|
|
||||||
|
public string SeriesId { get; set; }
|
||||||
|
|
||||||
|
public bool? IsMissing { get; set; }
|
||||||
|
|
||||||
|
public bool? IsVirtualUnaired { get; set; }
|
||||||
|
|
||||||
|
public int? SeasonNumber { get; set; }
|
||||||
|
|
||||||
|
public ItemFields[] Fields { get; set; }
|
||||||
|
|
||||||
|
public EpisodeQuery()
|
||||||
|
{
|
||||||
|
Fields = new ItemFields[] { };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SeasonQuery
|
||||||
|
{
|
||||||
|
public string UserId { get; set; }
|
||||||
|
|
||||||
|
public string SeriesId { get; set; }
|
||||||
|
|
||||||
|
public bool? IsMissing { get; set; }
|
||||||
|
|
||||||
|
public bool? IsVirtualUnaired { get; set; }
|
||||||
|
|
||||||
|
public ItemFields[] Fields { get; set; }
|
||||||
|
|
||||||
|
public bool? IsSpecialSeason { get; set; }
|
||||||
|
|
||||||
|
public SeasonQuery()
|
||||||
|
{
|
||||||
|
Fields = new ItemFields[] { };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -267,6 +267,10 @@ namespace MediaBrowser.Model.Querying
|
|||||||
|
|
||||||
public int? AiredDuringSeason { get; set; }
|
public int? AiredDuringSeason { get; set; }
|
||||||
|
|
||||||
|
public DateTime? MinPremiereDate { get; set; }
|
||||||
|
|
||||||
|
public DateTime? MaxPremiereDate { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ItemQuery" /> class.
|
/// Initializes a new instance of the <see cref="ItemQuery" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -6,6 +6,7 @@ namespace MediaBrowser.Model.Querying
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class ItemSortBy
|
public static class ItemSortBy
|
||||||
{
|
{
|
||||||
|
public const string AiredEpisodeOrder = "AiredEpisodeOrder";
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The album
|
/// The album
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1,17 +1,13 @@
|
|||||||
using MediaBrowser.Model.Entities;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Model.Querying
|
namespace MediaBrowser.Model.Querying
|
||||||
{
|
{
|
||||||
/// <summary>
|
public class QueryResult<T>
|
||||||
/// Class ItemReviewsResult
|
|
||||||
/// </summary>
|
|
||||||
public class ItemReviewsResult
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the item reviews.
|
/// Gets or sets the items.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The item reviews.</value>
|
/// <value>The items.</value>
|
||||||
public ItemReview[] ItemReviews { get; set; }
|
public T[] Items { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The total number of records available
|
/// The total number of records available
|
||||||
@ -22,9 +18,9 @@ namespace MediaBrowser.Model.Querying
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ItemsResult" /> class.
|
/// Initializes a new instance of the <see cref="ItemsResult" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ItemReviewsResult()
|
public QueryResult()
|
||||||
{
|
{
|
||||||
ItemReviews = new ItemReview[] { };
|
Items = new T[] { };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -92,6 +92,18 @@ namespace MediaBrowser.Model.System
|
|||||||
/// <value>The program data path.</value>
|
/// <value>The program data path.</value>
|
||||||
public string ProgramDataPath { get; set; }
|
public string ProgramDataPath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the items by name path.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The items by name path.</value>
|
||||||
|
public string ItemsByNamePath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the log path.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The log path.</value>
|
||||||
|
public string LogPath { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the HTTP server port number.
|
/// Gets or sets the HTTP server port number.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
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