From 4b2b36d1a3a3e0324697b59230c4e4346011b7c0 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 21 Dec 2013 13:37:34 -0500 Subject: [PATCH] live tv updates --- .../Playback/BaseStreamingService.cs | 102 +++++++++++---- .../Playback/Hls/AudioHlsService.cs | 5 +- .../Playback/Hls/BaseHlsService.cs | 8 +- .../Playback/Hls/VideoHlsService.cs | 5 +- .../Playback/Progressive/AudioService.cs | 5 +- .../BaseProgressiveStreamingService.cs | 8 +- .../Playback/Progressive/VideoService.cs | 5 +- MediaBrowser.Api/Playback/StreamRequest.cs | 6 + MediaBrowser.Api/Playback/StreamState.cs | 2 + .../Entities/Audio/MusicArtist.cs | 2 +- .../Entities/IHasImages.cs | 12 ++ .../Providers/IImageProvider.cs | 6 +- MediaBrowser.Model/LiveTv/ProgramInfoDto.cs | 18 ++- .../MediaBrowser.Providers.csproj | 1 + .../Movies/FanArtMovieProvider.cs | 5 + .../Movies/ManualFanartMovieImageProvider.cs | 13 +- .../Movies/ManualMovieDbImageProvider.cs | 16 +-- .../ManualMovieDbPersonImageProvider.cs | 13 +- .../Movies/MovieDbImagesProvider.cs | 2 +- .../Music/ManualFanartAlbumProvider.cs | 14 +- .../Music/ManualFanartArtistProvider.cs | 10 +- .../Music/ManualLastFmImageProvider.cs | 6 +- .../TV/ManualFanartSeasonProvider.cs | 13 +- .../TV/ManualFanartSeriesProvider.cs | 6 +- .../TV/ManualTvdbEpisodeImageProvider.cs | 6 +- .../TV/ManualTvdbPersonImageProvider.cs | 6 +- .../TV/ManualTvdbSeasonImageProvider.cs | 6 +- .../TV/ManualTvdbSeriesImageProvider.cs | 9 +- .../VirtualItemImageValidator.cs | 48 +++++++ .../LiveTv/LiveTvDtoService.cs | 12 +- .../LiveTv/LiveTvManager.cs | 123 +++++++++++++++--- .../MediaBrowser.WebDashboard.csproj | 3 + Nuget/MediaBrowser.Common.Internal.nuspec | 4 +- Nuget/MediaBrowser.Common.nuspec | 2 +- Nuget/MediaBrowser.Server.Core.nuspec | 4 +- 35 files changed, 374 insertions(+), 132 deletions(-) create mode 100644 MediaBrowser.Providers/VirtualItemImageValidator.cs diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 2bd02cfcf4..37d8d2520a 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -5,6 +5,7 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.MediaInfo; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Configuration; @@ -62,6 +63,7 @@ namespace MediaBrowser.Api.Playback protected IFileSystem FileSystem { get; private set; } protected IItemRepository ItemRepository { get; private set; } + protected ILiveTvManager LiveTvManager { get; private set; } /// /// Initializes a new instance of the class. @@ -74,8 +76,9 @@ namespace MediaBrowser.Api.Playback /// The dto service. /// The file system. /// The item repository. - 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; FileSystem = fileSystem; DtoService = dtoService; @@ -194,6 +197,10 @@ namespace MediaBrowser.Api.Playback { args += string.Format("-map 0:{0}", state.VideoStream.Index); } + else if (!state.HasMediaStreams) + { + args += string.Format("-map 0:{0}", 0); + } else { args += "-map -0:v"; @@ -203,6 +210,10 @@ namespace MediaBrowser.Api.Playback { args += string.Format(" -map 0:{0}", state.AudioStream.Index); } + else if (!state.HasMediaStreams) + { + args += string.Format(" -map 0:{0}", 1); + } else { @@ -336,7 +347,10 @@ namespace MediaBrowser.Api.Playback // If fixed dimensions were supplied 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); @@ -344,33 +358,41 @@ namespace MediaBrowser.Api.Playback // If a fixed width was requested if (request.Width.HasValue) { + var widthParam = request.Width.Value.ToString(UsCulture); + return isH264Output ? - string.Format(" -vf \"scale={0}:trunc(ow/a/2)*2{1}\"", request.Width.Value, assSubtitleParam) : - string.Format(" -vf \"scale={0}:-1{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}\"", widthParam, assSubtitleParam); } // If a fixed height was requested if (request.Height.HasValue) { + var heightParam = request.Height.Value.ToString(UsCulture); + return isH264Output ? - string.Format(" -vf \"scale=trunc(oh*a*2)/2:{0}{1}\"", request.Height.Value, assSubtitleParam) : - string.Format(" -vf \"scale=-1:{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}\"", heightParam, assSubtitleParam); } // If a max width was requested if (request.MaxWidth.HasValue && (!request.MaxHeight.HasValue || state.VideoStream == null)) { + var maxWidthParam = request.MaxWidth.Value.ToString(UsCulture); + 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}):-1{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}\"", maxWidthParam, assSubtitleParam); } // If a max height was requested if (request.MaxHeight.HasValue && (!request.MaxWidth.HasValue || state.VideoStream == null)) { + var maxHeightParam = request.MaxHeight.Value.ToString(UsCulture); + return isH264Output ? - string.Format(" -vf \"scale=trunc(oh*a*2)/2:min(ih\\,{0}){1}\"", request.MaxHeight.Value, assSubtitleParam) : - string.Format(" -vf \"scale=-1: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}\"", maxHeightParam, assSubtitleParam); } 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 (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 @@ -823,11 +848,10 @@ namespace MediaBrowser.Api.Playback /// Gets the state. /// /// The request. + /// The cancellation token. /// StreamState. - protected StreamState GetState(StreamRequest request) + protected async Task GetState(StreamRequest request, CancellationToken cancellationToken) { - var item = DtoService.GetItemByDtoId(request.Id); - var url = Request.PathInfo; if (!request.AudioCodec.HasValue) @@ -838,22 +862,48 @@ namespace MediaBrowser.Api.Playback var state = new StreamState { Request = request, - RequestedUrl = url, - MediaPath = item.Path, - IsRemote = item.LocationType == LocationType.Remote + RequestedUrl = url }; - 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(); + + 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; - state.VideoType = video.VideoType; - state.IsoType = video.IsoType; + item = DtoService.GetItemByDtoId(request.Id); - state.PlayableStreamFileNames = video.PlayableStreamFileNames == null - ? new List() - : video.PlayableStreamFileNames.ToList(); + var video = item as Video; + + if (video != null) + { + state.IsInputVideo = true; + state.VideoType = video.VideoType; + state.IsoType = video.IsoType; + + state.PlayableStreamFileNames = video.PlayableStreamFileNames == null + ? new List() + : video.PlayableStreamFileNames.ToList(); + } } var videoRequest = request as VideoStreamRequest; @@ -880,6 +930,8 @@ namespace MediaBrowser.Api.Playback state.AudioStream = GetMediaStream(mediaStreams, null, MediaStreamType.Audio, true); } + state.HasMediaStreams = mediaStreams.Count > 0; + return state; } diff --git a/MediaBrowser.Api/Playback/Hls/AudioHlsService.cs b/MediaBrowser.Api/Playback/Hls/AudioHlsService.cs index fc36d6ea83..d5bf223624 100644 --- a/MediaBrowser.Api/Playback/Hls/AudioHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/AudioHlsService.cs @@ -3,6 +3,7 @@ using MediaBrowser.Common.MediaInfo; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Dto; using MediaBrowser.Model.IO; @@ -26,8 +27,8 @@ namespace MediaBrowser.Api.Playback.Hls /// public class AudioHlsService : BaseHlsService { - public AudioHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository) - : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, 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, liveTvManager) { } diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index d307884528..68342e91d6 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -5,6 +5,7 @@ using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Dto; using MediaBrowser.Model.IO; @@ -12,6 +13,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Text; +using System.Threading; using System.Threading.Tasks; namespace MediaBrowser.Api.Playback.Hls @@ -21,8 +23,8 @@ namespace MediaBrowser.Api.Playback.Hls /// public abstract class BaseHlsService : BaseStreamingService { - protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository) - : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, 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, liveTvManager) { } @@ -72,7 +74,7 @@ namespace MediaBrowser.Api.Playback.Hls /// System.Object. protected object ProcessRequest(StreamRequest request) { - var state = GetState(request); + var state = GetState(request, CancellationToken.None).Result; return ProcessRequestAsync(state).Result; } diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index daefe9bc9f..99772d2ece 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -3,6 +3,7 @@ using MediaBrowser.Common.MediaInfo; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.IO; using ServiceStack; @@ -32,8 +33,8 @@ namespace MediaBrowser.Api.Playback.Hls /// public class VideoHlsService : BaseHlsService { - public VideoHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository) - : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, 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, liveTvManager) { } diff --git a/MediaBrowser.Api/Playback/Progressive/AudioService.cs b/MediaBrowser.Api/Playback/Progressive/AudioService.cs index 5889dc169d..baf7f48fe1 100644 --- a/MediaBrowser.Api/Playback/Progressive/AudioService.cs +++ b/MediaBrowser.Api/Playback/Progressive/AudioService.cs @@ -4,6 +4,7 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.IO; using ServiceStack; @@ -41,8 +42,8 @@ namespace MediaBrowser.Api.Playback.Progressive /// public class AudioService : BaseProgressiveStreamingService { - public AudioService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, IImageProcessor imageProcessor) - : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, 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, liveTvManager, imageProcessor) { } diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs index fcbcc5623b..e367801d25 100644 --- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs +++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs @@ -5,12 +5,14 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Dto; using MediaBrowser.Model.IO; using System.Collections.Generic; using System.IO; using System.Net.Http; +using System.Threading; using System.Threading.Tasks; namespace MediaBrowser.Api.Playback.Progressive @@ -22,8 +24,8 @@ namespace MediaBrowser.Api.Playback.Progressive { protected readonly IImageProcessor ImageProcessor; - protected BaseProgressiveStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, IImageProcessor imageProcessor) - : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository) + 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, liveTvManager) { ImageProcessor = imageProcessor; } @@ -178,7 +180,7 @@ namespace MediaBrowser.Api.Playback.Progressive /// Task. protected object ProcessRequest(StreamRequest request, bool isHeadRequest) { - var state = GetState(request); + var state = GetState(request, CancellationToken.None).Result; var responseHeaders = new Dictionary(); diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index 2d09b5b6f0..31dbcaafbf 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -4,6 +4,7 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.IO; using ServiceStack; @@ -54,8 +55,8 @@ namespace MediaBrowser.Api.Playback.Progressive /// public class VideoService : BaseProgressiveStreamingService { - public VideoService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, IImageProcessor imageProcessor) - : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, 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, liveTvManager, imageProcessor) { } diff --git a/MediaBrowser.Api/Playback/StreamRequest.cs b/MediaBrowser.Api/Playback/StreamRequest.cs index 1486c0de7a..454cc411cb 100644 --- a/MediaBrowser.Api/Playback/StreamRequest.cs +++ b/MediaBrowser.Api/Playback/StreamRequest.cs @@ -65,6 +65,12 @@ namespace MediaBrowser.Api.Playback /// No need to put this in api docs since it's dlna only /// public bool AlbumArt { get; set; } + + /// + /// Gets or sets the type. + /// + /// The type. + public string Type { get; set; } } public class VideoStreamRequest : StreamRequest diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs index 3b2cfbd2b1..be1ad85eb0 100644 --- a/MediaBrowser.Api/Playback/StreamState.cs +++ b/MediaBrowser.Api/Playback/StreamState.cs @@ -45,5 +45,7 @@ namespace MediaBrowser.Api.Playback public IsoType? IsoType { get; set; } public List PlayableStreamFileNames { get; set; } + + public bool HasMediaStreams { get; set; } } } diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs index 3be555f491..aaf35d7075 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs @@ -96,7 +96,7 @@ namespace MediaBrowser.Controller.Entities.Audio /// /// The item. /// System.String. - public static string GetUserDataKey(BaseItem item) + private static string GetUserDataKey(MusicArtist item) { var id = item.GetProviderId(MetadataProviders.Musicbrainz); diff --git a/MediaBrowser.Controller/Entities/IHasImages.cs b/MediaBrowser.Controller/Entities/IHasImages.cs index f8cbfc6abc..005c2d2619 100644 --- a/MediaBrowser.Controller/Entities/IHasImages.cs +++ b/MediaBrowser.Controller/Entities/IHasImages.cs @@ -63,6 +63,18 @@ namespace MediaBrowser.Controller.Entities /// The index2. /// Task. Task SwapImages(ImageType type, int index1, int index2); + + /// + /// Gets the display type of the media. + /// + /// The display type of the media. + string DisplayMediaType { get; set; } + + /// + /// Gets or sets the primary image path. + /// + /// The primary image path. + string PrimaryImagePath { get; set; } } public static class HasImagesExtensions diff --git a/MediaBrowser.Controller/Providers/IImageProvider.cs b/MediaBrowser.Controller/Providers/IImageProvider.cs index d70532b592..ccf1998445 100644 --- a/MediaBrowser.Controller/Providers/IImageProvider.cs +++ b/MediaBrowser.Controller/Providers/IImageProvider.cs @@ -23,7 +23,7 @@ namespace MediaBrowser.Controller.Providers /// /// The item. /// true if XXXX, false otherwise - bool Supports(BaseItem item); + bool Supports(IHasImages item); /// /// Gets the images. @@ -32,7 +32,7 @@ namespace MediaBrowser.Controller.Providers /// Type of the image. /// The cancellation token. /// Task{IEnumerable{RemoteImageInfo}}. - Task> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken); + Task> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken); /// /// Gets the images. @@ -40,7 +40,7 @@ namespace MediaBrowser.Controller.Providers /// The item. /// The cancellation token. /// Task{IEnumerable{RemoteImageInfo}}. - Task> GetAllImages(BaseItem item, CancellationToken cancellationToken); + Task> GetAllImages(IHasImages item, CancellationToken cancellationToken); /// /// Gets the priority. diff --git a/MediaBrowser.Model/LiveTv/ProgramInfoDto.cs b/MediaBrowser.Model/LiveTv/ProgramInfoDto.cs index d48bb40874..8b8b0cd078 100644 --- a/MediaBrowser.Model/LiveTv/ProgramInfoDto.cs +++ b/MediaBrowser.Model/LiveTv/ProgramInfoDto.cs @@ -1,7 +1,7 @@ -using System; -using System.Collections.Generic; -using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; +using System; +using System.Collections.Generic; namespace MediaBrowser.Model.LiveTv { @@ -12,6 +12,18 @@ namespace MediaBrowser.Model.LiveTv /// public string Id { get; set; } + /// + /// Gets or sets the timer identifier. + /// + /// The timer identifier. + public string TimerId { get; set; } + + /// + /// Gets or sets the series timer identifier. + /// + /// The series timer identifier. + public string SeriesTimerId { get; set; } + /// /// Gets or sets the external identifier. /// diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 2f35cb0031..db6c21ff15 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -146,6 +146,7 @@ + diff --git a/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs b/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs index 952d7e218e..3ee273145a 100644 --- a/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs +++ b/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs @@ -111,6 +111,11 @@ namespace MediaBrowser.Providers.Movies /// The item. /// true if XXXX, false otherwise public override bool Supports(BaseItem item) + { + return SupportsItem(item); + } + + internal static bool SupportsItem(IHasImages item) { var trailer = item as Trailer; diff --git a/MediaBrowser.Providers/Movies/ManualFanartMovieImageProvider.cs b/MediaBrowser.Providers/Movies/ManualFanartMovieImageProvider.cs index d714128ea6..ec9f869195 100644 --- a/MediaBrowser.Providers/Movies/ManualFanartMovieImageProvider.cs +++ b/MediaBrowser.Providers/Movies/ManualFanartMovieImageProvider.cs @@ -36,23 +36,24 @@ namespace MediaBrowser.Providers.Movies 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> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) + public async Task> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken) { var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); return images.Where(i => i.Type == imageType); } - public Task> GetAllImages(BaseItem item, CancellationToken cancellationToken) + public Task> GetAllImages(IHasImages item, CancellationToken cancellationToken) { + var baseItem = (BaseItem)item; var list = new List(); - var movieId = item.GetProviderId(MetadataProviders.Tmdb); + var movieId = baseItem.GetProviderId(MetadataProviders.Tmdb); if (!string.IsNullOrEmpty(movieId)) { @@ -71,7 +72,7 @@ namespace MediaBrowser.Providers.Movies var language = _config.Configuration.PreferredMetadataLanguage; var isLanguageEn = string.Equals(language, "en", StringComparison.OrdinalIgnoreCase); - + // Sort first by width to prioritize HD versions list = list.OrderByDescending(i => i.Width ?? 0) .ThenByDescending(i => diff --git a/MediaBrowser.Providers/Movies/ManualMovieDbImageProvider.cs b/MediaBrowser.Providers/Movies/ManualMovieDbImageProvider.cs index e5bd3bf472..d02ae55509 100644 --- a/MediaBrowser.Providers/Movies/ManualMovieDbImageProvider.cs +++ b/MediaBrowser.Providers/Movies/ManualMovieDbImageProvider.cs @@ -35,19 +35,19 @@ namespace MediaBrowser.Providers.Movies get { return "TheMovieDb"; } } - public bool Supports(BaseItem item) + public bool Supports(IHasImages item) { return MovieDbImagesProvider.SupportsItem(item); } - public async Task> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) + public async Task> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken) { var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); return images.Where(i => i.Type == imageType); } - public async Task> GetAllImages(BaseItem item, CancellationToken cancellationToken) + public async Task> GetAllImages(IHasImages item, CancellationToken cancellationToken) { var list = new List(); @@ -114,14 +114,14 @@ namespace MediaBrowser.Providers.Movies .ThenByDescending(i => i.VoteCount ?? 0) .ToList(); } - + /// /// Gets the posters. /// /// The images. /// The item. /// IEnumerable{MovieDbProvider.Poster}. - private IEnumerable GetPosters(MovieDbProvider.Images images, BaseItem item) + private IEnumerable GetPosters(MovieDbProvider.Images images, IHasImages item) { var language = _config.Configuration.PreferredMetadataLanguage; @@ -134,7 +134,7 @@ namespace MediaBrowser.Providers.Movies /// The images. /// The item. /// IEnumerable{MovieDbProvider.Backdrop}. - private IEnumerable GetBackdrops(MovieDbProvider.Images images, BaseItem item) + private IEnumerable GetBackdrops(MovieDbProvider.Images images, IHasImages item) { var eligibleBackdrops = images.backdrops == null ? new List() : images.backdrops @@ -150,9 +150,9 @@ namespace MediaBrowser.Providers.Movies /// The item. /// The json serializer. /// Task{MovieImages}. - 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)) { diff --git a/MediaBrowser.Providers/Movies/ManualMovieDbPersonImageProvider.cs b/MediaBrowser.Providers/Movies/ManualMovieDbPersonImageProvider.cs index b381de3322..a074b10c20 100644 --- a/MediaBrowser.Providers/Movies/ManualMovieDbPersonImageProvider.cs +++ b/MediaBrowser.Providers/Movies/ManualMovieDbPersonImageProvider.cs @@ -34,26 +34,27 @@ namespace MediaBrowser.Providers.Movies get { return "TheMovieDb"; } } - public bool Supports(BaseItem item) + public bool Supports(IHasImages item) { return item is Person; } - public async Task> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) + public async Task> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken) { var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); return images.Where(i => i.Type == imageType); } - public Task> GetAllImages(BaseItem item, CancellationToken cancellationToken) + public Task> GetAllImages(IHasImages item, CancellationToken cancellationToken) { return GetAllImagesInternal(item, true, cancellationToken); } - public async Task> GetAllImagesInternal(BaseItem item, bool retryOnMissingData, CancellationToken cancellationToken) + public async Task> 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)) { @@ -86,7 +87,7 @@ namespace MediaBrowser.Providers.Movies return new List(); } - + private IEnumerable GetImages(MovieDbPersonProvider.Images images, string baseImageUrl) { var list = new List(); diff --git a/MediaBrowser.Providers/Movies/MovieDbImagesProvider.cs b/MediaBrowser.Providers/Movies/MovieDbImagesProvider.cs index d63fcec5c0..f15d13222d 100644 --- a/MediaBrowser.Providers/Movies/MovieDbImagesProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbImagesProvider.cs @@ -61,7 +61,7 @@ namespace MediaBrowser.Providers.Movies return SupportsItem(item); } - public static bool SupportsItem(BaseItem item) + internal static bool SupportsItem(IHasImages item) { var trailer = item as Trailer; diff --git a/MediaBrowser.Providers/Music/ManualFanartAlbumProvider.cs b/MediaBrowser.Providers/Music/ManualFanartAlbumProvider.cs index d95365b02d..99e7212fc9 100644 --- a/MediaBrowser.Providers/Music/ManualFanartAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/ManualFanartAlbumProvider.cs @@ -37,32 +37,34 @@ namespace MediaBrowser.Providers.Music get { return "FanArt"; } } - public bool Supports(BaseItem item) + public bool Supports(IHasImages item) { return item is MusicAlbum; } - public async Task> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) + public async Task> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken) { var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); return images.Where(i => i.Type == imageType); } - public Task> GetAllImages(BaseItem item, CancellationToken cancellationToken) + public Task> GetAllImages(IHasImages item, CancellationToken cancellationToken) { + var album = (MusicAlbum)item; + var list = new List(); - var artistMusicBrainzId = item.Parent.GetProviderId(MetadataProviders.Musicbrainz); + var artistMusicBrainzId = album.Parent.GetProviderId(MetadataProviders.Musicbrainz); if (!string.IsNullOrEmpty(artistMusicBrainzId)) { var artistXmlPath = FanArtArtistProvider.GetArtistDataPath(_config.CommonApplicationPaths, artistMusicBrainzId); 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 { diff --git a/MediaBrowser.Providers/Music/ManualFanartArtistProvider.cs b/MediaBrowser.Providers/Music/ManualFanartArtistProvider.cs index cdb07d3d7f..85209a0e12 100644 --- a/MediaBrowser.Providers/Music/ManualFanartArtistProvider.cs +++ b/MediaBrowser.Providers/Music/ManualFanartArtistProvider.cs @@ -37,23 +37,25 @@ namespace MediaBrowser.Providers.Music get { return "FanArt"; } } - public bool Supports(BaseItem item) + public bool Supports(IHasImages item) { return item is MusicArtist; } - public async Task> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) + public async Task> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken) { var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); return images.Where(i => i.Type == imageType); } - public Task> GetAllImages(BaseItem item, CancellationToken cancellationToken) + public Task> GetAllImages(IHasImages item, CancellationToken cancellationToken) { + var artist = (MusicArtist)item; + var list = new List(); - var artistMusicBrainzId = item.GetProviderId(MetadataProviders.Musicbrainz); + var artistMusicBrainzId = artist.GetProviderId(MetadataProviders.Musicbrainz); if (!string.IsNullOrEmpty(artistMusicBrainzId)) { diff --git a/MediaBrowser.Providers/Music/ManualLastFmImageProvider.cs b/MediaBrowser.Providers/Music/ManualLastFmImageProvider.cs index 72e8c6f6ba..6d6f1ec7b8 100644 --- a/MediaBrowser.Providers/Music/ManualLastFmImageProvider.cs +++ b/MediaBrowser.Providers/Music/ManualLastFmImageProvider.cs @@ -23,19 +23,19 @@ namespace MediaBrowser.Providers.Music get { return "last.fm"; } } - public bool Supports(BaseItem item) + public bool Supports(IHasImages item) { return item is MusicAlbum || item is MusicArtist; } - public async Task> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) + public async Task> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken) { var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); return images.Where(i => i.Type == imageType); } - public Task> GetAllImages(BaseItem item, CancellationToken cancellationToken) + public Task> GetAllImages(IHasImages item, CancellationToken cancellationToken) { var list = new List(); diff --git a/MediaBrowser.Providers/TV/ManualFanartSeasonProvider.cs b/MediaBrowser.Providers/TV/ManualFanartSeasonProvider.cs index f9b779011b..6132f10971 100644 --- a/MediaBrowser.Providers/TV/ManualFanartSeasonProvider.cs +++ b/MediaBrowser.Providers/TV/ManualFanartSeasonProvider.cs @@ -37,35 +37,36 @@ namespace MediaBrowser.Providers.TV get { return "FanArt"; } } - public bool Supports(BaseItem item) + public bool Supports(IHasImages item) { return item is Season; } - public async Task> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) + public async Task> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken) { var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); return images.Where(i => i.Type == imageType); } - public Task> GetAllImages(BaseItem item, CancellationToken cancellationToken) + public Task> GetAllImages(IHasImages item, CancellationToken cancellationToken) { var list = new List(); - var series = ((Season)item).Series; + var season = (Season)item; + var series = season.Series; if (series != null) { 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); try { - AddImages(list, item.IndexNumber.Value, xmlPath, cancellationToken); + AddImages(list, season.IndexNumber.Value, xmlPath, cancellationToken); } catch (FileNotFoundException) { diff --git a/MediaBrowser.Providers/TV/ManualFanartSeriesProvider.cs b/MediaBrowser.Providers/TV/ManualFanartSeriesProvider.cs index cb7a4efd11..12f9d2247b 100644 --- a/MediaBrowser.Providers/TV/ManualFanartSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/ManualFanartSeriesProvider.cs @@ -37,19 +37,19 @@ namespace MediaBrowser.Providers.TV get { return "FanArt"; } } - public bool Supports(BaseItem item) + public bool Supports(IHasImages item) { return item is Series; } - public async Task> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) + public async Task> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken) { var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); return images.Where(i => i.Type == imageType); } - public Task> GetAllImages(BaseItem item, CancellationToken cancellationToken) + public Task> GetAllImages(IHasImages item, CancellationToken cancellationToken) { var list = new List(); diff --git a/MediaBrowser.Providers/TV/ManualTvdbEpisodeImageProvider.cs b/MediaBrowser.Providers/TV/ManualTvdbEpisodeImageProvider.cs index d63fb5091f..6d38dee2ea 100644 --- a/MediaBrowser.Providers/TV/ManualTvdbEpisodeImageProvider.cs +++ b/MediaBrowser.Providers/TV/ManualTvdbEpisodeImageProvider.cs @@ -31,19 +31,19 @@ namespace MediaBrowser.Providers.TV get { return "TheTVDB"; } } - public bool Supports(BaseItem item) + public bool Supports(IHasImages item) { return item is Episode; } - public async Task> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) + public async Task> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken) { var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); return images.Where(i => i.Type == imageType); } - public Task> GetAllImages(BaseItem item, CancellationToken cancellationToken) + public Task> GetAllImages(IHasImages item, CancellationToken cancellationToken) { var episode = (Episode)item; diff --git a/MediaBrowser.Providers/TV/ManualTvdbPersonImageProvider.cs b/MediaBrowser.Providers/TV/ManualTvdbPersonImageProvider.cs index adeca12f26..456db10486 100644 --- a/MediaBrowser.Providers/TV/ManualTvdbPersonImageProvider.cs +++ b/MediaBrowser.Providers/TV/ManualTvdbPersonImageProvider.cs @@ -37,19 +37,19 @@ namespace MediaBrowser.Providers.TV get { return "TheTVDB"; } } - public bool Supports(BaseItem item) + public bool Supports(IHasImages item) { return item is Person; } - public async Task> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) + public async Task> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken) { var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); return images.Where(i => i.Type == imageType); } - public Task> GetAllImages(BaseItem item, CancellationToken cancellationToken) + public Task> GetAllImages(IHasImages item, CancellationToken cancellationToken) { var seriesWithPerson = _library.RootFolder .RecursiveChildren diff --git a/MediaBrowser.Providers/TV/ManualTvdbSeasonImageProvider.cs b/MediaBrowser.Providers/TV/ManualTvdbSeasonImageProvider.cs index 3efd0a3e36..e0c8434ce8 100644 --- a/MediaBrowser.Providers/TV/ManualTvdbSeasonImageProvider.cs +++ b/MediaBrowser.Providers/TV/ManualTvdbSeasonImageProvider.cs @@ -38,19 +38,19 @@ namespace MediaBrowser.Providers.TV get { return "TheTVDB"; } } - public bool Supports(BaseItem item) + public bool Supports(IHasImages item) { return item is Season; } - public async Task> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) + public async Task> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken) { var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); return images.Where(i => i.Type == imageType); } - public Task> GetAllImages(BaseItem item, CancellationToken cancellationToken) + public Task> GetAllImages(IHasImages item, CancellationToken cancellationToken) { var season = (Season)item; diff --git a/MediaBrowser.Providers/TV/ManualTvdbSeriesImageProvider.cs b/MediaBrowser.Providers/TV/ManualTvdbSeriesImageProvider.cs index 5987215d1b..0b48ddb2b7 100644 --- a/MediaBrowser.Providers/TV/ManualTvdbSeriesImageProvider.cs +++ b/MediaBrowser.Providers/TV/ManualTvdbSeriesImageProvider.cs @@ -38,21 +38,22 @@ namespace MediaBrowser.Providers.TV get { return "TheTVDB"; } } - public bool Supports(BaseItem item) + public bool Supports(IHasImages item) { return item is Series; } - public async Task> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) + public async Task> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken) { var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); return images.Where(i => i.Type == imageType); } - public Task> GetAllImages(BaseItem item, CancellationToken cancellationToken) + public Task> 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)) { diff --git a/MediaBrowser.Providers/VirtualItemImageValidator.cs b/MediaBrowser.Providers/VirtualItemImageValidator.cs new file mode 100644 index 0000000000..d4bbaf713c --- /dev/null +++ b/MediaBrowser.Providers/VirtualItemImageValidator.cs @@ -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 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; } + } + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs index f8f5d02e97..5465b70da4 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs @@ -243,18 +243,20 @@ namespace MediaBrowser.Server.Implementations.LiveTv 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 { - Id = GetInternalProgramId(channel.ServiceName, program.Id).ToString("N"), - ChannelId = channel.Id.ToString("N"), + Id = GetInternalProgramId(item.ServiceName, program.Id).ToString("N"), + ChannelId = GetInternalChannelId(item.ServiceName, program.ChannelId, program.ChannelName).ToString("N"), Overview = program.Overview, EndDate = program.EndDate, Genres = program.Genres, ExternalId = program.Id, Name = program.Name, - ServiceName = channel.ServiceName, + ServiceName = item.ServiceName, StartDate = program.StartDate, OfficialRating = program.OfficialRating, IsHD = program.IsHD, @@ -277,7 +279,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv 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; diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 06e6fbe159..25b0bb2220 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -37,7 +37,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv private readonly List _services = new List(); private List _channels = new List(); - private List _programs = new List(); + private List _programs = new List(); 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); } - + private async Task GetChannel(ChannelInfo channelInfo, string serviceName, CancellationToken cancellationToken) { 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; } + private async Task 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 GetRecording(RecordingInfo info, string serviceName, CancellationToken cancellationToken) { var isNew = false; @@ -218,27 +247,50 @@ namespace MediaBrowser.Server.Implementations.LiveTv return item; } - public Task GetProgram(string id, CancellationToken cancellationToken, User user = null) + public async Task 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> GetPrograms(ProgramQuery query, CancellationToken cancellationToken) + public async Task> GetPrograms(ProgramQuery query, CancellationToken cancellationToken) { - IEnumerable programs = _programs - .OrderBy(i => i.StartDate) - .ThenBy(i => i.EndDate); + IEnumerable programs = _programs; if (query.ChannelIdList.Length > 0) { 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 { @@ -246,7 +298,31 @@ namespace MediaBrowser.Server.Implementations.LiveTv TotalRecordCount = returnArray.Length }; - return Task.FromResult(result); + return result; + } + + private async Task AddRecordingInfo(IEnumerable 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 progress, CancellationToken cancellationToken) @@ -266,7 +342,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv var allChannelsList = allChannels.ToList(); var list = new List(); - var programs = new List(); + var programs = new List(); var numComplete = 0; @@ -278,7 +354,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv 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); } @@ -336,6 +415,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv 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 .Select(i => _tvDtoService.GetRecordingInfoDto(i, ActiveService, user)) .OrderByDescending(i => i.StartDate) @@ -504,15 +588,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv }; } - public async Task GetChannel(string id, CancellationToken cancellationToken, User user = null) + public Task GetChannel(string id, CancellationToken cancellationToken, User user = null) { - var results = await GetChannels(new ChannelQuery - { - UserId = user == null ? null : user.Id.ToString("N") + var guid = new Guid(id); + var channel = _channels.FirstOrDefault(i => guid == i.Id); - }, 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 GetNewTimerDefaults(CancellationToken cancellationToken) diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 5d3d8c491c..8962d088ee 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -85,6 +85,9 @@ + + PreserveNewest + PreserveNewest diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index e84fb011be..084a9da1f7 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common.Internal - 3.0.284 + 3.0.285 MediaBrowser.Common.Internal Luke ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption. Copyright © Media Browser 2013 - + diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index 67eedbf585..e9eb11a92d 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.284 + 3.0.285 MediaBrowser.Common Media Browser Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index 050e3086c9..4230918302 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.284 + 3.0.285 Media Browser.Server.Core Media Browser Team ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains core components required to build plugins for Media Browser Server. Copyright © Media Browser 2013 - +