live tv updates

pull/702/head
Luke Pulverenti 11 years ago
parent cb6350728d
commit 4b2b36d1a3

@ -5,6 +5,7 @@ using MediaBrowser.Controller.Configuration;
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.MediaInfo; using MediaBrowser.Controller.MediaInfo;
using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Configuration;
@ -62,6 +63,7 @@ namespace MediaBrowser.Api.Playback
protected IFileSystem FileSystem { get; private set; } protected IFileSystem FileSystem { get; private set; }
protected IItemRepository ItemRepository { get; private set; } protected IItemRepository ItemRepository { get; private set; }
protected ILiveTvManager LiveTvManager { get; private set; }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="BaseStreamingService" /> class. /// Initializes a new instance of the <see cref="BaseStreamingService" /> class.
@ -74,8 +76,9 @@ namespace MediaBrowser.Api.Playback
/// <param name="dtoService">The dto service.</param> /// <param name="dtoService">The dto service.</param>
/// <param name="fileSystem">The file system.</param> /// <param name="fileSystem">The file system.</param>
/// <param name="itemRepository">The item repository.</param> /// <param name="itemRepository">The item repository.</param>
protected BaseStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository) protected BaseStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager)
{ {
LiveTvManager = liveTvManager;
ItemRepository = itemRepository; ItemRepository = itemRepository;
FileSystem = fileSystem; FileSystem = fileSystem;
DtoService = dtoService; DtoService = dtoService;
@ -194,6 +197,10 @@ namespace MediaBrowser.Api.Playback
{ {
args += string.Format("-map 0:{0}", state.VideoStream.Index); args += string.Format("-map 0:{0}", state.VideoStream.Index);
} }
else if (!state.HasMediaStreams)
{
args += string.Format("-map 0:{0}", 0);
}
else else
{ {
args += "-map -0:v"; args += "-map -0:v";
@ -203,6 +210,10 @@ namespace MediaBrowser.Api.Playback
{ {
args += string.Format(" -map 0:{0}", state.AudioStream.Index); args += string.Format(" -map 0:{0}", state.AudioStream.Index);
} }
else if (!state.HasMediaStreams)
{
args += string.Format(" -map 0:{0}", 1);
}
else else
{ {
@ -336,7 +347,10 @@ namespace MediaBrowser.Api.Playback
// If fixed dimensions were supplied // If fixed dimensions were supplied
if (request.Width.HasValue && request.Height.HasValue) if (request.Width.HasValue && request.Height.HasValue)
{ {
return string.Format(" -vf \"scale=trunc({0}/2)*2:trunc({1}/2)*2{2}\"", request.Width.Value, request.Height.Value, assSubtitleParam); var widthParam = request.Width.Value.ToString(UsCulture);
var heightParam = request.Height.Value.ToString(UsCulture);
return string.Format(" -vf \"scale=trunc({0}/2)*2:trunc({1}/2)*2{2}\"", widthParam, heightParam, assSubtitleParam);
} }
var isH264Output = outputVideoCodec.Equals("libx264", StringComparison.OrdinalIgnoreCase); var isH264Output = outputVideoCodec.Equals("libx264", StringComparison.OrdinalIgnoreCase);
@ -344,33 +358,41 @@ namespace MediaBrowser.Api.Playback
// If a fixed width was requested // If a fixed width was requested
if (request.Width.HasValue) if (request.Width.HasValue)
{ {
var widthParam = request.Width.Value.ToString(UsCulture);
return isH264Output ? return isH264Output ?
string.Format(" -vf \"scale={0}:trunc(ow/a/2)*2{1}\"", request.Width.Value, assSubtitleParam) : string.Format(" -vf \"scale={0}:trunc(ow/a/2)*2{1}\"", widthParam, assSubtitleParam) :
string.Format(" -vf \"scale={0}:-1{1}\"", request.Width.Value, assSubtitleParam); string.Format(" -vf \"scale={0}:-1{1}\"", widthParam, assSubtitleParam);
} }
// If a fixed height was requested // If a fixed height was requested
if (request.Height.HasValue) if (request.Height.HasValue)
{ {
var heightParam = request.Height.Value.ToString(UsCulture);
return isH264Output ? return isH264Output ?
string.Format(" -vf \"scale=trunc(oh*a*2)/2:{0}{1}\"", request.Height.Value, assSubtitleParam) : string.Format(" -vf \"scale=trunc(oh*a*2)/2:{0}{1}\"", heightParam, assSubtitleParam) :
string.Format(" -vf \"scale=-1:{0}{1}\"", request.Height.Value, assSubtitleParam); string.Format(" -vf \"scale=-1:{0}{1}\"", heightParam, assSubtitleParam);
} }
// If a max width was requested // If a max width was requested
if (request.MaxWidth.HasValue && (!request.MaxHeight.HasValue || state.VideoStream == null)) if (request.MaxWidth.HasValue && (!request.MaxHeight.HasValue || state.VideoStream == null))
{ {
var maxWidthParam = request.MaxWidth.Value.ToString(UsCulture);
return isH264Output ? return isH264Output ?
string.Format(" -vf \"scale=min(iw\\,{0}):trunc(ow/a/2)*2{1}\"", request.MaxWidth.Value, assSubtitleParam) : string.Format(" -vf \"scale=min(iw\\,{0}):trunc(ow/a/2)*2{1}\"", maxWidthParam, assSubtitleParam) :
string.Format(" -vf \"scale=min(iw\\,{0}):-1{1}\"", request.MaxWidth.Value, assSubtitleParam); string.Format(" -vf \"scale=min(iw\\,{0}):-1{1}\"", maxWidthParam, assSubtitleParam);
} }
// If a max height was requested // If a max height was requested
if (request.MaxHeight.HasValue && (!request.MaxWidth.HasValue || state.VideoStream == null)) if (request.MaxHeight.HasValue && (!request.MaxWidth.HasValue || state.VideoStream == null))
{ {
var maxHeightParam = request.MaxHeight.Value.ToString(UsCulture);
return isH264Output ? return isH264Output ?
string.Format(" -vf \"scale=trunc(oh*a*2)/2:min(ih\\,{0}){1}\"", request.MaxHeight.Value, assSubtitleParam) : string.Format(" -vf \"scale=trunc(oh*a*2)/2:min(ih\\,{0}){1}\"", maxHeightParam, assSubtitleParam) :
string.Format(" -vf \"scale=-1:min(ih\\,{0}){1}\"", request.MaxHeight.Value, assSubtitleParam); string.Format(" -vf \"scale=-1:min(ih\\,{0}){1}\"", maxHeightParam, assSubtitleParam);
} }
if (state.VideoStream == null) if (state.VideoStream == null)
@ -390,7 +412,10 @@ namespace MediaBrowser.Api.Playback
// If we're encoding with libx264, it can't handle odd numbered widths or heights, so we'll have to fix that // If we're encoding with libx264, it can't handle odd numbered widths or heights, so we'll have to fix that
if (isH264Output) if (isH264Output)
{ {
return string.Format(" -vf \"scale=trunc({0}/2)*2:trunc({1}/2)*2{2}\"", outputSize.Width, outputSize.Height, assSubtitleParam); var widthParam = outputSize.Width.ToString(UsCulture);
var heightParam = outputSize.Height.ToString(UsCulture);
return string.Format(" -vf \"scale=trunc({0}/2)*2:trunc({1}/2)*2{2}\"", widthParam, heightParam, assSubtitleParam);
} }
// Otherwise use -vf scale since ffmpeg will ensure internally that the aspect ratio is preserved // Otherwise use -vf scale since ffmpeg will ensure internally that the aspect ratio is preserved
@ -823,11 +848,10 @@ namespace MediaBrowser.Api.Playback
/// Gets the state. /// Gets the state.
/// </summary> /// </summary>
/// <param name="request">The request.</param> /// <param name="request">The request.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>StreamState.</returns> /// <returns>StreamState.</returns>
protected StreamState GetState(StreamRequest request) protected async Task<StreamState> GetState(StreamRequest request, CancellationToken cancellationToken)
{ {
var item = DtoService.GetItemByDtoId(request.Id);
var url = Request.PathInfo; var url = Request.PathInfo;
if (!request.AudioCodec.HasValue) if (!request.AudioCodec.HasValue)
@ -838,22 +862,48 @@ namespace MediaBrowser.Api.Playback
var state = new StreamState var state = new StreamState
{ {
Request = request, Request = request,
RequestedUrl = url, RequestedUrl = url
MediaPath = item.Path,
IsRemote = item.LocationType == LocationType.Remote
}; };
var video = item as Video; BaseItem item;
if (string.Equals(request.Type, "Recording", StringComparison.OrdinalIgnoreCase))
{
var recording = await LiveTvManager.GetInternalRecording(request.Id, cancellationToken).ConfigureAwait(false);
state.VideoType = VideoType.VideoFile;
state.IsInputVideo = string.Equals(recording.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
state.PlayableStreamFileNames = new List<string>();
if (!string.IsNullOrEmpty(recording.RecordingInfo.Path) && File.Exists(recording.RecordingInfo.Path))
{
state.MediaPath = recording.RecordingInfo.Path;
state.IsRemote = false;
}
else if (!string.IsNullOrEmpty(recording.RecordingInfo.Url))
{
state.MediaPath = recording.RecordingInfo.Url;
state.IsRemote = true;
}
if (video != null) item = recording;
}
else
{ {
state.IsInputVideo = true; item = DtoService.GetItemByDtoId(request.Id);
state.VideoType = video.VideoType;
state.IsoType = video.IsoType;
state.PlayableStreamFileNames = video.PlayableStreamFileNames == null var video = item as Video;
? new List<string>()
: video.PlayableStreamFileNames.ToList(); if (video != null)
{
state.IsInputVideo = true;
state.VideoType = video.VideoType;
state.IsoType = video.IsoType;
state.PlayableStreamFileNames = video.PlayableStreamFileNames == null
? new List<string>()
: video.PlayableStreamFileNames.ToList();
}
} }
var videoRequest = request as VideoStreamRequest; var videoRequest = request as VideoStreamRequest;
@ -880,6 +930,8 @@ namespace MediaBrowser.Api.Playback
state.AudioStream = GetMediaStream(mediaStreams, null, MediaStreamType.Audio, true); state.AudioStream = GetMediaStream(mediaStreams, null, MediaStreamType.Audio, true);
} }
state.HasMediaStreams = mediaStreams.Count > 0;
return state; return state;
} }

@ -3,6 +3,7 @@ using MediaBrowser.Common.MediaInfo;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto; using MediaBrowser.Model.Dto;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
@ -26,8 +27,8 @@ namespace MediaBrowser.Api.Playback.Hls
/// </summary> /// </summary>
public class AudioHlsService : BaseHlsService public class AudioHlsService : BaseHlsService
{ {
public AudioHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository) public AudioHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager)
: base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager)
{ {
} }

@ -5,6 +5,7 @@ using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto; using MediaBrowser.Model.Dto;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
@ -12,6 +13,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace MediaBrowser.Api.Playback.Hls namespace MediaBrowser.Api.Playback.Hls
@ -21,8 +23,8 @@ namespace MediaBrowser.Api.Playback.Hls
/// </summary> /// </summary>
public abstract class BaseHlsService : BaseStreamingService public abstract class BaseHlsService : BaseStreamingService
{ {
protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository) protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager)
: base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager)
{ {
} }
@ -72,7 +74,7 @@ namespace MediaBrowser.Api.Playback.Hls
/// <returns>System.Object.</returns> /// <returns>System.Object.</returns>
protected object ProcessRequest(StreamRequest request) protected object ProcessRequest(StreamRequest request)
{ {
var state = GetState(request); var state = GetState(request, CancellationToken.None).Result;
return ProcessRequestAsync(state).Result; return ProcessRequestAsync(state).Result;
} }

@ -3,6 +3,7 @@ using MediaBrowser.Common.MediaInfo;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using ServiceStack; using ServiceStack;
@ -32,8 +33,8 @@ namespace MediaBrowser.Api.Playback.Hls
/// </summary> /// </summary>
public class VideoHlsService : BaseHlsService public class VideoHlsService : BaseHlsService
{ {
public VideoHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository) public VideoHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager)
: base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager)
{ {
} }

@ -4,6 +4,7 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using ServiceStack; using ServiceStack;
@ -41,8 +42,8 @@ namespace MediaBrowser.Api.Playback.Progressive
/// </summary> /// </summary>
public class AudioService : BaseProgressiveStreamingService public class AudioService : BaseProgressiveStreamingService
{ {
public AudioService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, IImageProcessor imageProcessor) public AudioService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IImageProcessor imageProcessor)
: base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, imageProcessor) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, imageProcessor)
{ {
} }

@ -5,12 +5,14 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto; using MediaBrowser.Model.Dto;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Net.Http; using System.Net.Http;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace MediaBrowser.Api.Playback.Progressive namespace MediaBrowser.Api.Playback.Progressive
@ -22,8 +24,8 @@ namespace MediaBrowser.Api.Playback.Progressive
{ {
protected readonly IImageProcessor ImageProcessor; protected readonly IImageProcessor ImageProcessor;
protected BaseProgressiveStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, IImageProcessor imageProcessor) protected BaseProgressiveStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IImageProcessor imageProcessor)
: base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager)
{ {
ImageProcessor = imageProcessor; ImageProcessor = imageProcessor;
} }
@ -178,7 +180,7 @@ namespace MediaBrowser.Api.Playback.Progressive
/// <returns>Task.</returns> /// <returns>Task.</returns>
protected object ProcessRequest(StreamRequest request, bool isHeadRequest) protected object ProcessRequest(StreamRequest request, bool isHeadRequest)
{ {
var state = GetState(request); var state = GetState(request, CancellationToken.None).Result;
var responseHeaders = new Dictionary<string, string>(); var responseHeaders = new Dictionary<string, string>();

@ -4,6 +4,7 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using ServiceStack; using ServiceStack;
@ -54,8 +55,8 @@ namespace MediaBrowser.Api.Playback.Progressive
/// </summary> /// </summary>
public class VideoService : BaseProgressiveStreamingService public class VideoService : BaseProgressiveStreamingService
{ {
public VideoService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, IImageProcessor imageProcessor) public VideoService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IImageProcessor imageProcessor)
: base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, imageProcessor) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, imageProcessor)
{ {
} }

@ -65,6 +65,12 @@ namespace MediaBrowser.Api.Playback
/// No need to put this in api docs since it's dlna only /// No need to put this in api docs since it's dlna only
/// </summary> /// </summary>
public bool AlbumArt { get; set; } public bool AlbumArt { get; set; }
/// <summary>
/// Gets or sets the type.
/// </summary>
/// <value>The type.</value>
public string Type { get; set; }
} }
public class VideoStreamRequest : StreamRequest public class VideoStreamRequest : StreamRequest

@ -45,5 +45,7 @@ namespace MediaBrowser.Api.Playback
public IsoType? IsoType { get; set; } public IsoType? IsoType { get; set; }
public List<string> PlayableStreamFileNames { get; set; } public List<string> PlayableStreamFileNames { get; set; }
public bool HasMediaStreams { get; set; }
} }
} }

@ -96,7 +96,7 @@ namespace MediaBrowser.Controller.Entities.Audio
/// </summary> /// </summary>
/// <param name="item">The item.</param> /// <param name="item">The item.</param>
/// <returns>System.String.</returns> /// <returns>System.String.</returns>
public static string GetUserDataKey(BaseItem item) private static string GetUserDataKey(MusicArtist item)
{ {
var id = item.GetProviderId(MetadataProviders.Musicbrainz); var id = item.GetProviderId(MetadataProviders.Musicbrainz);

@ -63,6 +63,18 @@ namespace MediaBrowser.Controller.Entities
/// <param name="index2">The index2.</param> /// <param name="index2">The index2.</param>
/// <returns>Task.</returns> /// <returns>Task.</returns>
Task SwapImages(ImageType type, int index1, int index2); Task SwapImages(ImageType type, int index1, int index2);
/// <summary>
/// Gets the display type of the media.
/// </summary>
/// <value>The display type of the media.</value>
string DisplayMediaType { get; set; }
/// <summary>
/// Gets or sets the primary image path.
/// </summary>
/// <value>The primary image path.</value>
string PrimaryImagePath { get; set; }
} }
public static class HasImagesExtensions public static class HasImagesExtensions

@ -23,7 +23,7 @@ namespace MediaBrowser.Controller.Providers
/// </summary> /// </summary>
/// <param name="item">The item.</param> /// <param name="item">The item.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
bool Supports(BaseItem item); bool Supports(IHasImages item);
/// <summary> /// <summary>
/// Gets the images. /// Gets the images.
@ -32,7 +32,7 @@ namespace MediaBrowser.Controller.Providers
/// <param name="imageType">Type of the image.</param> /// <param name="imageType">Type of the image.</param>
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{IEnumerable{RemoteImageInfo}}.</returns> /// <returns>Task{IEnumerable{RemoteImageInfo}}.</returns>
Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken); Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Gets the images. /// Gets the images.
@ -40,7 +40,7 @@ namespace MediaBrowser.Controller.Providers
/// <param name="item">The item.</param> /// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{IEnumerable{RemoteImageInfo}}.</returns> /// <returns>Task{IEnumerable{RemoteImageInfo}}.</returns>
Task<IEnumerable<RemoteImageInfo>> GetAllImages(BaseItem item, CancellationToken cancellationToken); Task<IEnumerable<RemoteImageInfo>> GetAllImages(IHasImages item, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Gets the priority. /// Gets the priority.

@ -1,7 +1,7 @@
using System; using MediaBrowser.Model.Dto;
using System.Collections.Generic;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
namespace MediaBrowser.Model.LiveTv namespace MediaBrowser.Model.LiveTv
{ {
@ -12,6 +12,18 @@ namespace MediaBrowser.Model.LiveTv
/// </summary> /// </summary>
public string Id { get; set; } public string Id { get; set; }
/// <summary>
/// Gets or sets the timer identifier.
/// </summary>
/// <value>The timer identifier.</value>
public string TimerId { get; set; }
/// <summary>
/// Gets or sets the series timer identifier.
/// </summary>
/// <value>The series timer identifier.</value>
public string SeriesTimerId { get; set; }
/// <summary> /// <summary>
/// Gets or sets the external identifier. /// Gets or sets the external identifier.
/// </summary> /// </summary>

@ -146,6 +146,7 @@
<Compile Include="TV\TvdbPrescanTask.cs" /> <Compile Include="TV\TvdbPrescanTask.cs" />
<Compile Include="TV\TvdbSeriesImageProvider.cs" /> <Compile Include="TV\TvdbSeriesImageProvider.cs" />
<Compile Include="UserRootFolderNameProvider.cs" /> <Compile Include="UserRootFolderNameProvider.cs" />
<Compile Include="VirtualItemImageValidator.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj"> <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj">

@ -111,6 +111,11 @@ namespace MediaBrowser.Providers.Movies
/// <param name="item">The item.</param> /// <param name="item">The item.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
public override bool Supports(BaseItem item) public override bool Supports(BaseItem item)
{
return SupportsItem(item);
}
internal static bool SupportsItem(IHasImages item)
{ {
var trailer = item as Trailer; var trailer = item as Trailer;

@ -36,23 +36,24 @@ namespace MediaBrowser.Providers.Movies
get { return "FanArt"; } get { return "FanArt"; }
} }
public bool Supports(BaseItem item) public bool Supports(IHasImages item)
{ {
return FanArtMovieProvider.Current.Supports(item); return FanArtMovieProvider.SupportsItem(item);
} }
public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) public async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken)
{ {
var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false);
return images.Where(i => i.Type == imageType); return images.Where(i => i.Type == imageType);
} }
public Task<IEnumerable<RemoteImageInfo>> GetAllImages(BaseItem item, CancellationToken cancellationToken) public Task<IEnumerable<RemoteImageInfo>> GetAllImages(IHasImages item, CancellationToken cancellationToken)
{ {
var baseItem = (BaseItem)item;
var list = new List<RemoteImageInfo>(); var list = new List<RemoteImageInfo>();
var movieId = item.GetProviderId(MetadataProviders.Tmdb); var movieId = baseItem.GetProviderId(MetadataProviders.Tmdb);
if (!string.IsNullOrEmpty(movieId)) if (!string.IsNullOrEmpty(movieId))
{ {
@ -71,7 +72,7 @@ namespace MediaBrowser.Providers.Movies
var language = _config.Configuration.PreferredMetadataLanguage; var language = _config.Configuration.PreferredMetadataLanguage;
var isLanguageEn = string.Equals(language, "en", StringComparison.OrdinalIgnoreCase); var isLanguageEn = string.Equals(language, "en", StringComparison.OrdinalIgnoreCase);
// Sort first by width to prioritize HD versions // Sort first by width to prioritize HD versions
list = list.OrderByDescending(i => i.Width ?? 0) list = list.OrderByDescending(i => i.Width ?? 0)
.ThenByDescending(i => .ThenByDescending(i =>

@ -35,19 +35,19 @@ namespace MediaBrowser.Providers.Movies
get { return "TheMovieDb"; } get { return "TheMovieDb"; }
} }
public bool Supports(BaseItem item) public bool Supports(IHasImages item)
{ {
return MovieDbImagesProvider.SupportsItem(item); return MovieDbImagesProvider.SupportsItem(item);
} }
public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) public async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken)
{ {
var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false);
return images.Where(i => i.Type == imageType); return images.Where(i => i.Type == imageType);
} }
public async Task<IEnumerable<RemoteImageInfo>> GetAllImages(BaseItem item, CancellationToken cancellationToken) public async Task<IEnumerable<RemoteImageInfo>> GetAllImages(IHasImages item, CancellationToken cancellationToken)
{ {
var list = new List<RemoteImageInfo>(); var list = new List<RemoteImageInfo>();
@ -114,14 +114,14 @@ namespace MediaBrowser.Providers.Movies
.ThenByDescending(i => i.VoteCount ?? 0) .ThenByDescending(i => i.VoteCount ?? 0)
.ToList(); .ToList();
} }
/// <summary> /// <summary>
/// Gets the posters. /// Gets the posters.
/// </summary> /// </summary>
/// <param name="images">The images.</param> /// <param name="images">The images.</param>
/// <param name="item">The item.</param> /// <param name="item">The item.</param>
/// <returns>IEnumerable{MovieDbProvider.Poster}.</returns> /// <returns>IEnumerable{MovieDbProvider.Poster}.</returns>
private IEnumerable<MovieDbProvider.Poster> GetPosters(MovieDbProvider.Images images, BaseItem item) private IEnumerable<MovieDbProvider.Poster> GetPosters(MovieDbProvider.Images images, IHasImages item)
{ {
var language = _config.Configuration.PreferredMetadataLanguage; var language = _config.Configuration.PreferredMetadataLanguage;
@ -134,7 +134,7 @@ namespace MediaBrowser.Providers.Movies
/// <param name="images">The images.</param> /// <param name="images">The images.</param>
/// <param name="item">The item.</param> /// <param name="item">The item.</param>
/// <returns>IEnumerable{MovieDbProvider.Backdrop}.</returns> /// <returns>IEnumerable{MovieDbProvider.Backdrop}.</returns>
private IEnumerable<MovieDbProvider.Backdrop> GetBackdrops(MovieDbProvider.Images images, BaseItem item) private IEnumerable<MovieDbProvider.Backdrop> GetBackdrops(MovieDbProvider.Images images, IHasImages item)
{ {
var eligibleBackdrops = images.backdrops == null ? new List<MovieDbProvider.Backdrop>() : var eligibleBackdrops = images.backdrops == null ? new List<MovieDbProvider.Backdrop>() :
images.backdrops images.backdrops
@ -150,9 +150,9 @@ namespace MediaBrowser.Providers.Movies
/// <param name="item">The item.</param> /// <param name="item">The item.</param>
/// <param name="jsonSerializer">The json serializer.</param> /// <param name="jsonSerializer">The json serializer.</param>
/// <returns>Task{MovieImages}.</returns> /// <returns>Task{MovieImages}.</returns>
private MovieDbProvider.Images FetchImages(BaseItem item, IJsonSerializer jsonSerializer) private MovieDbProvider.Images FetchImages(IHasImages item, IJsonSerializer jsonSerializer)
{ {
var path = MovieDbProvider.Current.GetImagesDataFilePath(item); var path = MovieDbProvider.Current.GetImagesDataFilePath((BaseItem)item);
if (!string.IsNullOrEmpty(path)) if (!string.IsNullOrEmpty(path))
{ {

@ -34,26 +34,27 @@ namespace MediaBrowser.Providers.Movies
get { return "TheMovieDb"; } get { return "TheMovieDb"; }
} }
public bool Supports(BaseItem item) public bool Supports(IHasImages item)
{ {
return item is Person; return item is Person;
} }
public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) public async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken)
{ {
var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false);
return images.Where(i => i.Type == imageType); return images.Where(i => i.Type == imageType);
} }
public Task<IEnumerable<RemoteImageInfo>> GetAllImages(BaseItem item, CancellationToken cancellationToken) public Task<IEnumerable<RemoteImageInfo>> GetAllImages(IHasImages item, CancellationToken cancellationToken)
{ {
return GetAllImagesInternal(item, true, cancellationToken); return GetAllImagesInternal(item, true, cancellationToken);
} }
public async Task<IEnumerable<RemoteImageInfo>> GetAllImagesInternal(BaseItem item, bool retryOnMissingData, CancellationToken cancellationToken) public async Task<IEnumerable<RemoteImageInfo>> GetAllImagesInternal(IHasImages item, bool retryOnMissingData, CancellationToken cancellationToken)
{ {
var id = item.GetProviderId(MetadataProviders.Tmdb); var person = (Person)item;
var id = person.GetProviderId(MetadataProviders.Tmdb);
if (!string.IsNullOrEmpty(id)) if (!string.IsNullOrEmpty(id))
{ {
@ -86,7 +87,7 @@ namespace MediaBrowser.Providers.Movies
return new List<RemoteImageInfo>(); return new List<RemoteImageInfo>();
} }
private IEnumerable<RemoteImageInfo> GetImages(MovieDbPersonProvider.Images images, string baseImageUrl) private IEnumerable<RemoteImageInfo> GetImages(MovieDbPersonProvider.Images images, string baseImageUrl)
{ {
var list = new List<RemoteImageInfo>(); var list = new List<RemoteImageInfo>();

@ -61,7 +61,7 @@ namespace MediaBrowser.Providers.Movies
return SupportsItem(item); return SupportsItem(item);
} }
public static bool SupportsItem(BaseItem item) internal static bool SupportsItem(IHasImages item)
{ {
var trailer = item as Trailer; var trailer = item as Trailer;

@ -37,32 +37,34 @@ namespace MediaBrowser.Providers.Music
get { return "FanArt"; } get { return "FanArt"; }
} }
public bool Supports(BaseItem item) public bool Supports(IHasImages item)
{ {
return item is MusicAlbum; return item is MusicAlbum;
} }
public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) public async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken)
{ {
var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false);
return images.Where(i => i.Type == imageType); return images.Where(i => i.Type == imageType);
} }
public Task<IEnumerable<RemoteImageInfo>> GetAllImages(BaseItem item, CancellationToken cancellationToken) public Task<IEnumerable<RemoteImageInfo>> GetAllImages(IHasImages item, CancellationToken cancellationToken)
{ {
var album = (MusicAlbum)item;
var list = new List<RemoteImageInfo>(); var list = new List<RemoteImageInfo>();
var artistMusicBrainzId = item.Parent.GetProviderId(MetadataProviders.Musicbrainz); var artistMusicBrainzId = album.Parent.GetProviderId(MetadataProviders.Musicbrainz);
if (!string.IsNullOrEmpty(artistMusicBrainzId)) if (!string.IsNullOrEmpty(artistMusicBrainzId))
{ {
var artistXmlPath = FanArtArtistProvider.GetArtistDataPath(_config.CommonApplicationPaths, artistMusicBrainzId); var artistXmlPath = FanArtArtistProvider.GetArtistDataPath(_config.CommonApplicationPaths, artistMusicBrainzId);
artistXmlPath = Path.Combine(artistXmlPath, "fanart.xml"); artistXmlPath = Path.Combine(artistXmlPath, "fanart.xml");
var musicBrainzReleaseGroupId = item.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup); var musicBrainzReleaseGroupId = album.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
var musicBrainzId = item.GetProviderId(MetadataProviders.Musicbrainz); var musicBrainzId = album.GetProviderId(MetadataProviders.Musicbrainz);
try try
{ {

@ -37,23 +37,25 @@ namespace MediaBrowser.Providers.Music
get { return "FanArt"; } get { return "FanArt"; }
} }
public bool Supports(BaseItem item) public bool Supports(IHasImages item)
{ {
return item is MusicArtist; return item is MusicArtist;
} }
public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) public async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken)
{ {
var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false);
return images.Where(i => i.Type == imageType); return images.Where(i => i.Type == imageType);
} }
public Task<IEnumerable<RemoteImageInfo>> GetAllImages(BaseItem item, CancellationToken cancellationToken) public Task<IEnumerable<RemoteImageInfo>> GetAllImages(IHasImages item, CancellationToken cancellationToken)
{ {
var artist = (MusicArtist)item;
var list = new List<RemoteImageInfo>(); var list = new List<RemoteImageInfo>();
var artistMusicBrainzId = item.GetProviderId(MetadataProviders.Musicbrainz); var artistMusicBrainzId = artist.GetProviderId(MetadataProviders.Musicbrainz);
if (!string.IsNullOrEmpty(artistMusicBrainzId)) if (!string.IsNullOrEmpty(artistMusicBrainzId))
{ {

@ -23,19 +23,19 @@ namespace MediaBrowser.Providers.Music
get { return "last.fm"; } get { return "last.fm"; }
} }
public bool Supports(BaseItem item) public bool Supports(IHasImages item)
{ {
return item is MusicAlbum || item is MusicArtist; return item is MusicAlbum || item is MusicArtist;
} }
public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) public async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken)
{ {
var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false);
return images.Where(i => i.Type == imageType); return images.Where(i => i.Type == imageType);
} }
public Task<IEnumerable<RemoteImageInfo>> GetAllImages(BaseItem item, CancellationToken cancellationToken) public Task<IEnumerable<RemoteImageInfo>> GetAllImages(IHasImages item, CancellationToken cancellationToken)
{ {
var list = new List<RemoteImageInfo>(); var list = new List<RemoteImageInfo>();

@ -37,35 +37,36 @@ namespace MediaBrowser.Providers.TV
get { return "FanArt"; } get { return "FanArt"; }
} }
public bool Supports(BaseItem item) public bool Supports(IHasImages item)
{ {
return item is Season; return item is Season;
} }
public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) public async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken)
{ {
var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false);
return images.Where(i => i.Type == imageType); return images.Where(i => i.Type == imageType);
} }
public Task<IEnumerable<RemoteImageInfo>> GetAllImages(BaseItem item, CancellationToken cancellationToken) public Task<IEnumerable<RemoteImageInfo>> GetAllImages(IHasImages item, CancellationToken cancellationToken)
{ {
var list = new List<RemoteImageInfo>(); var list = new List<RemoteImageInfo>();
var series = ((Season)item).Series; var season = (Season)item;
var series = season.Series;
if (series != null) if (series != null)
{ {
var id = series.GetProviderId(MetadataProviders.Tvdb); var id = series.GetProviderId(MetadataProviders.Tvdb);
if (!string.IsNullOrEmpty(id) && item.IndexNumber.HasValue) if (!string.IsNullOrEmpty(id) && season.IndexNumber.HasValue)
{ {
var xmlPath = FanArtTvProvider.Current.GetFanartXmlPath(id); var xmlPath = FanArtTvProvider.Current.GetFanartXmlPath(id);
try try
{ {
AddImages(list, item.IndexNumber.Value, xmlPath, cancellationToken); AddImages(list, season.IndexNumber.Value, xmlPath, cancellationToken);
} }
catch (FileNotFoundException) catch (FileNotFoundException)
{ {

@ -37,19 +37,19 @@ namespace MediaBrowser.Providers.TV
get { return "FanArt"; } get { return "FanArt"; }
} }
public bool Supports(BaseItem item) public bool Supports(IHasImages item)
{ {
return item is Series; return item is Series;
} }
public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) public async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken)
{ {
var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false);
return images.Where(i => i.Type == imageType); return images.Where(i => i.Type == imageType);
} }
public Task<IEnumerable<RemoteImageInfo>> GetAllImages(BaseItem item, CancellationToken cancellationToken) public Task<IEnumerable<RemoteImageInfo>> GetAllImages(IHasImages item, CancellationToken cancellationToken)
{ {
var list = new List<RemoteImageInfo>(); var list = new List<RemoteImageInfo>();

@ -31,19 +31,19 @@ namespace MediaBrowser.Providers.TV
get { return "TheTVDB"; } get { return "TheTVDB"; }
} }
public bool Supports(BaseItem item) public bool Supports(IHasImages item)
{ {
return item is Episode; return item is Episode;
} }
public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) public async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken)
{ {
var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false);
return images.Where(i => i.Type == imageType); return images.Where(i => i.Type == imageType);
} }
public Task<IEnumerable<RemoteImageInfo>> GetAllImages(BaseItem item, CancellationToken cancellationToken) public Task<IEnumerable<RemoteImageInfo>> GetAllImages(IHasImages item, CancellationToken cancellationToken)
{ {
var episode = (Episode)item; var episode = (Episode)item;

@ -37,19 +37,19 @@ namespace MediaBrowser.Providers.TV
get { return "TheTVDB"; } get { return "TheTVDB"; }
} }
public bool Supports(BaseItem item) public bool Supports(IHasImages item)
{ {
return item is Person; return item is Person;
} }
public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) public async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken)
{ {
var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false);
return images.Where(i => i.Type == imageType); return images.Where(i => i.Type == imageType);
} }
public Task<IEnumerable<RemoteImageInfo>> GetAllImages(BaseItem item, CancellationToken cancellationToken) public Task<IEnumerable<RemoteImageInfo>> GetAllImages(IHasImages item, CancellationToken cancellationToken)
{ {
var seriesWithPerson = _library.RootFolder var seriesWithPerson = _library.RootFolder
.RecursiveChildren .RecursiveChildren

@ -38,19 +38,19 @@ namespace MediaBrowser.Providers.TV
get { return "TheTVDB"; } get { return "TheTVDB"; }
} }
public bool Supports(BaseItem item) public bool Supports(IHasImages item)
{ {
return item is Season; return item is Season;
} }
public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) public async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken)
{ {
var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false);
return images.Where(i => i.Type == imageType); return images.Where(i => i.Type == imageType);
} }
public Task<IEnumerable<RemoteImageInfo>> GetAllImages(BaseItem item, CancellationToken cancellationToken) public Task<IEnumerable<RemoteImageInfo>> GetAllImages(IHasImages item, CancellationToken cancellationToken)
{ {
var season = (Season)item; var season = (Season)item;

@ -38,21 +38,22 @@ namespace MediaBrowser.Providers.TV
get { return "TheTVDB"; } get { return "TheTVDB"; }
} }
public bool Supports(BaseItem item) public bool Supports(IHasImages item)
{ {
return item is Series; return item is Series;
} }
public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) public async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken)
{ {
var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false);
return images.Where(i => i.Type == imageType); return images.Where(i => i.Type == imageType);
} }
public Task<IEnumerable<RemoteImageInfo>> GetAllImages(BaseItem item, CancellationToken cancellationToken) public Task<IEnumerable<RemoteImageInfo>> GetAllImages(IHasImages item, CancellationToken cancellationToken)
{ {
var seriesId = item.GetProviderId(MetadataProviders.Tvdb); var series = (Series)item;
var seriesId = series.GetProviderId(MetadataProviders.Tvdb);
if (!string.IsNullOrEmpty(seriesId)) if (!string.IsNullOrEmpty(seriesId))
{ {

@ -0,0 +1,48 @@
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Providers
{
public class VirtualItemImageValidator : BaseMetadataProvider
{
public VirtualItemImageValidator(ILogManager logManager, IServerConfigurationManager configurationManager)
: base(logManager, configurationManager)
{
}
public override bool Supports(BaseItem item)
{
var locationType = item.LocationType;
return locationType == LocationType.Virtual ||
locationType == LocationType.Remote;
}
public override Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken)
{
item.ValidateImages();
item.ValidateBackdrops();
var hasScreenshots = item as IHasScreenshots;
if (hasScreenshots != null)
{
hasScreenshots.ValidateScreenshots();
}
SetLastRefreshed(item, DateTime.UtcNow, providerInfo);
return TrueTaskResult;
}
public override MetadataProviderPriority Priority
{
get { return MetadataProviderPriority.First; }
}
}
}

@ -243,18 +243,20 @@ namespace MediaBrowser.Server.Implementations.LiveTv
return dto; return dto;
} }
public ProgramInfoDto GetProgramInfoDto(ProgramInfo program, LiveTvChannel channel, User user = null) public ProgramInfoDto GetProgramInfoDto(LiveTvProgram item, User user = null)
{ {
var program = item.ProgramInfo;
var dto = new ProgramInfoDto var dto = new ProgramInfoDto
{ {
Id = GetInternalProgramId(channel.ServiceName, program.Id).ToString("N"), Id = GetInternalProgramId(item.ServiceName, program.Id).ToString("N"),
ChannelId = channel.Id.ToString("N"), ChannelId = GetInternalChannelId(item.ServiceName, program.ChannelId, program.ChannelName).ToString("N"),
Overview = program.Overview, Overview = program.Overview,
EndDate = program.EndDate, EndDate = program.EndDate,
Genres = program.Genres, Genres = program.Genres,
ExternalId = program.Id, ExternalId = program.Id,
Name = program.Name, Name = program.Name,
ServiceName = channel.ServiceName, ServiceName = item.ServiceName,
StartDate = program.StartDate, StartDate = program.StartDate,
OfficialRating = program.OfficialRating, OfficialRating = program.OfficialRating,
IsHD = program.IsHD, IsHD = program.IsHD,
@ -277,7 +279,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
if (user != null) if (user != null)
{ {
//dto.UserData = _dtoService.GetUserItemDataDto(_userDataManager.GetUserData(user.Id, info.GetUserDataKey())); dto.UserData = _dtoService.GetUserItemDataDto(_userDataManager.GetUserData(user.Id, item.GetUserDataKey()));
} }
return dto; return dto;

@ -37,7 +37,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
private readonly List<ILiveTvService> _services = new List<ILiveTvService>(); private readonly List<ILiveTvService> _services = new List<ILiveTvService>();
private List<LiveTvChannel> _channels = new List<LiveTvChannel>(); private List<LiveTvChannel> _channels = new List<LiveTvChannel>();
private List<ProgramInfoDto> _programs = new List<ProgramInfoDto>(); private List<LiveTvProgram> _programs = new List<LiveTvProgram>();
public LiveTvManager(IServerApplicationPaths appPaths, IFileSystem fileSystem, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor, ILocalizationManager localization, IUserDataManager userDataManager, IDtoService dtoService, IUserManager userManager) public LiveTvManager(IServerApplicationPaths appPaths, IFileSystem fileSystem, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor, ILocalizationManager localization, IUserDataManager userDataManager, IDtoService dtoService, IUserManager userManager)
{ {
@ -138,7 +138,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
return await GetRecording(recording, service.Name, cancellationToken).ConfigureAwait(false); return await GetRecording(recording, service.Name, cancellationToken).ConfigureAwait(false);
} }
private async Task<LiveTvChannel> GetChannel(ChannelInfo channelInfo, string serviceName, CancellationToken cancellationToken) private async Task<LiveTvChannel> GetChannel(ChannelInfo channelInfo, string serviceName, CancellationToken cancellationToken)
{ {
var path = Path.Combine(_appPaths.ItemsByNamePath, "channels", _fileSystem.GetValidFilename(serviceName), _fileSystem.GetValidFilename(channelInfo.Name)); var path = Path.Combine(_appPaths.ItemsByNamePath, "channels", _fileSystem.GetValidFilename(serviceName), _fileSystem.GetValidFilename(channelInfo.Name));
@ -189,6 +189,35 @@ namespace MediaBrowser.Server.Implementations.LiveTv
return item; return item;
} }
private async Task<LiveTvProgram> GetProgram(ProgramInfo info, string serviceName, CancellationToken cancellationToken)
{
var isNew = false;
var id = _tvDtoService.GetInternalProgramId(serviceName, info.Id);
var item = _itemRepo.RetrieveItem(id) as LiveTvProgram;
if (item == null)
{
item = new LiveTvProgram
{
Name = info.Name,
Id = id,
DateCreated = DateTime.UtcNow,
DateModified = DateTime.UtcNow
};
isNew = true;
}
item.ProgramInfo = info;
item.ServiceName = serviceName;
await item.RefreshMetadata(cancellationToken, forceSave: isNew, resetResolveArgs: false);
return item;
}
private async Task<LiveTvRecording> GetRecording(RecordingInfo info, string serviceName, CancellationToken cancellationToken) private async Task<LiveTvRecording> GetRecording(RecordingInfo info, string serviceName, CancellationToken cancellationToken)
{ {
var isNew = false; var isNew = false;
@ -218,27 +247,50 @@ namespace MediaBrowser.Server.Implementations.LiveTv
return item; return item;
} }
public Task<ProgramInfoDto> GetProgram(string id, CancellationToken cancellationToken, User user = null) public async Task<ProgramInfoDto> GetProgram(string id, CancellationToken cancellationToken, User user = null)
{ {
var program = _programs.FirstOrDefault(i => string.Equals(i.Id, id, StringComparison.OrdinalIgnoreCase)); var guid = new Guid(id);
var program = _programs.FirstOrDefault(i => guid == i.Id);
var dto = _tvDtoService.GetProgramInfoDto(program, user);
await AddRecordingInfo(new[] { dto }, cancellationToken).ConfigureAwait(false);
return Task.FromResult(program); return dto;
} }
public Task<QueryResult<ProgramInfoDto>> GetPrograms(ProgramQuery query, CancellationToken cancellationToken) public async Task<QueryResult<ProgramInfoDto>> GetPrograms(ProgramQuery query, CancellationToken cancellationToken)
{ {
IEnumerable<ProgramInfoDto> programs = _programs IEnumerable<LiveTvProgram> programs = _programs;
.OrderBy(i => i.StartDate)
.ThenBy(i => i.EndDate);
if (query.ChannelIdList.Length > 0) if (query.ChannelIdList.Length > 0)
{ {
var guids = query.ChannelIdList.Select(i => new Guid(i)).ToList(); var guids = query.ChannelIdList.Select(i => new Guid(i)).ToList();
var serviceName = ActiveService.Name;
programs = programs.Where(i =>
{
var programChannelId = i.ProgramInfo.ChannelId;
var internalProgramChannelId = _tvDtoService.GetInternalChannelId(serviceName, programChannelId, i.ProgramInfo.ChannelName);
programs = programs.Where(i => guids.Contains(new Guid(i.ChannelId))); return guids.Contains(internalProgramChannelId);
});
} }
var returnArray = programs.ToArray(); var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(new Guid(query.UserId));
if (user != null)
{
programs = programs.Where(i => i.IsParentalAllowed(user, _localization));
}
var returnArray = programs
.OrderBy(i => i.ProgramInfo.StartDate)
.Select(i => _tvDtoService.GetProgramInfoDto(i, user))
.ToArray();
await AddRecordingInfo(returnArray, cancellationToken).ConfigureAwait(false);
var result = new QueryResult<ProgramInfoDto> var result = new QueryResult<ProgramInfoDto>
{ {
@ -246,7 +298,31 @@ namespace MediaBrowser.Server.Implementations.LiveTv
TotalRecordCount = returnArray.Length TotalRecordCount = returnArray.Length
}; };
return Task.FromResult(result); return result;
}
private async Task AddRecordingInfo(IEnumerable<ProgramInfoDto> programs, CancellationToken cancellationToken)
{
var timers = await ActiveService.GetTimersAsync(cancellationToken).ConfigureAwait(false);
var timerList = timers.ToList();
foreach (var program in programs)
{
var timer = timerList.FirstOrDefault(i => string.Equals(i.ProgramId, program.ExternalId, StringComparison.OrdinalIgnoreCase));
if (timer != null)
{
program.TimerId = _tvDtoService.GetInternalTimerId(program.ServiceName, timer.Id)
.ToString("N");
if (!string.IsNullOrEmpty(timer.SeriesTimerId))
{
program.SeriesTimerId = _tvDtoService.GetInternalSeriesTimerId(program.ServiceName, timer.SeriesTimerId)
.ToString("N");
}
}
}
} }
internal async Task RefreshChannels(IProgress<double> progress, CancellationToken cancellationToken) internal async Task RefreshChannels(IProgress<double> progress, CancellationToken cancellationToken)
@ -266,7 +342,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
var allChannelsList = allChannels.ToList(); var allChannelsList = allChannels.ToList();
var list = new List<LiveTvChannel>(); var list = new List<LiveTvChannel>();
var programs = new List<ProgramInfoDto>(); var programs = new List<LiveTvProgram>();
var numComplete = 0; var numComplete = 0;
@ -278,7 +354,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv
var channelPrograms = await service.GetProgramsAsync(channelInfo.Item2.Id, cancellationToken).ConfigureAwait(false); var channelPrograms = await service.GetProgramsAsync(channelInfo.Item2.Id, cancellationToken).ConfigureAwait(false);
programs.AddRange(channelPrograms.Select(program => _tvDtoService.GetProgramInfoDto(program, item))); var programTasks = channelPrograms.Select(program => GetProgram(program, service.Name, cancellationToken));
var programEntities = await Task.WhenAll(programTasks).ConfigureAwait(false);
programs.AddRange(programEntities);
list.Add(item); list.Add(item);
} }
@ -336,6 +415,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv
var entities = await GetEntities(list, service.Name, cancellationToken).ConfigureAwait(false); var entities = await GetEntities(list, service.Name, cancellationToken).ConfigureAwait(false);
if (user != null)
{
entities = entities.Where(i => i.IsParentalAllowed(user, _localization)).ToArray();
}
var returnArray = entities var returnArray = entities
.Select(i => _tvDtoService.GetRecordingInfoDto(i, ActiveService, user)) .Select(i => _tvDtoService.GetRecordingInfoDto(i, ActiveService, user))
.OrderByDescending(i => i.StartDate) .OrderByDescending(i => i.StartDate)
@ -504,15 +588,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv
}; };
} }
public async Task<ChannelInfoDto> GetChannel(string id, CancellationToken cancellationToken, User user = null) public Task<ChannelInfoDto> GetChannel(string id, CancellationToken cancellationToken, User user = null)
{ {
var results = await GetChannels(new ChannelQuery var guid = new Guid(id);
{ var channel = _channels.FirstOrDefault(i => guid == i.Id);
UserId = user == null ? null : user.Id.ToString("N")
}, cancellationToken).ConfigureAwait(false); var dto = _tvDtoService.GetChannelInfoDto(channel, user);
return results.Items.FirstOrDefault(i => string.Equals(i.Id, id, StringComparison.CurrentCulture)); return Task.FromResult(dto);
} }
public async Task<SeriesTimerInfoDto> GetNewTimerDefaults(CancellationToken cancellationToken) public async Task<SeriesTimerInfoDto> GetNewTimerDefaults(CancellationToken cancellationToken)

@ -85,6 +85,9 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="ApiClient.js" /> <EmbeddedResource Include="ApiClient.js" />
<Content Include="dashboard-ui\css\images\clients\xbmc.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\css\images\editor.png"> <Content Include="dashboard-ui\css\images\editor.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata> <metadata>
<id>MediaBrowser.Common.Internal</id> <id>MediaBrowser.Common.Internal</id>
<version>3.0.284</version> <version>3.0.285</version>
<title>MediaBrowser.Common.Internal</title> <title>MediaBrowser.Common.Internal</title>
<authors>Luke</authors> <authors>Luke</authors>
<owners>ebr,Luke,scottisafool</owners> <owners>ebr,Luke,scottisafool</owners>
@ -12,7 +12,7 @@
<description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description> <description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description>
<copyright>Copyright © Media Browser 2013</copyright> <copyright>Copyright © Media Browser 2013</copyright>
<dependencies> <dependencies>
<dependency id="MediaBrowser.Common" version="3.0.284" /> <dependency id="MediaBrowser.Common" version="3.0.285" />
<dependency id="NLog" version="2.1.0" /> <dependency id="NLog" version="2.1.0" />
<dependency id="SimpleInjector" version="2.4.0" /> <dependency id="SimpleInjector" version="2.4.0" />
<dependency id="sharpcompress" version="0.10.2" /> <dependency id="sharpcompress" version="0.10.2" />

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata> <metadata>
<id>MediaBrowser.Common</id> <id>MediaBrowser.Common</id>
<version>3.0.284</version> <version>3.0.285</version>
<title>MediaBrowser.Common</title> <title>MediaBrowser.Common</title>
<authors>Media Browser Team</authors> <authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners> <owners>ebr,Luke,scottisafool</owners>

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata> <metadata>
<id>MediaBrowser.Server.Core</id> <id>MediaBrowser.Server.Core</id>
<version>3.0.284</version> <version>3.0.285</version>
<title>Media Browser.Server.Core</title> <title>Media Browser.Server.Core</title>
<authors>Media Browser Team</authors> <authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners> <owners>ebr,Luke,scottisafool</owners>
@ -12,7 +12,7 @@
<description>Contains core components required to build plugins for Media Browser Server.</description> <description>Contains core components required to build plugins for Media Browser Server.</description>
<copyright>Copyright © Media Browser 2013</copyright> <copyright>Copyright © Media Browser 2013</copyright>
<dependencies> <dependencies>
<dependency id="MediaBrowser.Common" version="3.0.284" /> <dependency id="MediaBrowser.Common" version="3.0.285" />
</dependencies> </dependencies>
</metadata> </metadata>
<files> <files>

Loading…
Cancel
Save