diff options
35 files changed, 374 insertions, 132 deletions
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 2bd02cfcf..37d8d2520 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; } /// <summary> /// 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="fileSystem">The file system.</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; 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. /// </summary> /// <param name="request">The request.</param> + /// <param name="cancellationToken">The cancellation token.</param> /// <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; 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<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; - state.VideoType = video.VideoType; - state.IsoType = video.IsoType; + item = DtoService.GetItemByDtoId(request.Id); - state.PlayableStreamFileNames = video.PlayableStreamFileNames == null - ? new List<string>() - : 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<string>() + : 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 fc36d6ea8..d5bf22362 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 /// </summary> 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 d30788452..68342e91d 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 /// </summary> 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 /// <returns>System.Object.</returns> 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 daefe9bc9..99772d2ec 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 /// </summary> 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 5889dc169..baf7f48fe 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 /// </summary> 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 fcbcc5623..e367801d2 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 /// <returns>Task.</returns> protected object ProcessRequest(StreamRequest request, bool isHeadRequest) { - var state = GetState(request); + var state = GetState(request, CancellationToken.None).Result; var responseHeaders = new Dictionary<string, string>(); diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index 2d09b5b6f..31dbcaafb 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 /// </summary> 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 1486c0de7..454cc411c 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 /// </summary> 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 diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs index 3b2cfbd2b..be1ad85eb 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<string> 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 3be555f49..aaf35d707 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs @@ -96,7 +96,7 @@ namespace MediaBrowser.Controller.Entities.Audio /// </summary> /// <param name="item">The item.</param> /// <returns>System.String.</returns> - 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 f8cbfc6ab..005c2d261 100644 --- a/MediaBrowser.Controller/Entities/IHasImages.cs +++ b/MediaBrowser.Controller/Entities/IHasImages.cs @@ -63,6 +63,18 @@ namespace MediaBrowser.Controller.Entities /// <param name="index2">The index2.</param> /// <returns>Task.</returns> 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 diff --git a/MediaBrowser.Controller/Providers/IImageProvider.cs b/MediaBrowser.Controller/Providers/IImageProvider.cs index d70532b59..ccf199844 100644 --- a/MediaBrowser.Controller/Providers/IImageProvider.cs +++ b/MediaBrowser.Controller/Providers/IImageProvider.cs @@ -23,7 +23,7 @@ namespace MediaBrowser.Controller.Providers /// </summary> /// <param name="item">The item.</param> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> - bool Supports(BaseItem item); + bool Supports(IHasImages item); /// <summary> /// Gets the images. @@ -32,7 +32,7 @@ namespace MediaBrowser.Controller.Providers /// <param name="imageType">Type of the image.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <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> /// Gets the images. @@ -40,7 +40,7 @@ namespace MediaBrowser.Controller.Providers /// <param name="item">The item.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task{IEnumerable{RemoteImageInfo}}.</returns> - Task<IEnumerable<RemoteImageInfo>> GetAllImages(BaseItem item, CancellationToken cancellationToken); + Task<IEnumerable<RemoteImageInfo>> GetAllImages(IHasImages item, CancellationToken cancellationToken); /// <summary> /// Gets the priority. diff --git a/MediaBrowser.Model/LiveTv/ProgramInfoDto.cs b/MediaBrowser.Model/LiveTv/ProgramInfoDto.cs index d48bb4087..8b8b0cd07 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 { @@ -13,6 +13,18 @@ namespace MediaBrowser.Model.LiveTv 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> /// Gets or sets the external identifier. /// </summary> /// <value>The external identifier.</value> diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 2f35cb003..db6c21ff1 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -146,6 +146,7 @@ <Compile Include="TV\TvdbPrescanTask.cs" /> <Compile Include="TV\TvdbSeriesImageProvider.cs" /> <Compile Include="UserRootFolderNameProvider.cs" /> + <Compile Include="VirtualItemImageValidator.cs" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj"> diff --git a/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs b/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs index 952d7e218..3ee273145 100644 --- a/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs +++ b/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs @@ -112,6 +112,11 @@ namespace MediaBrowser.Providers.Movies /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> public override bool Supports(BaseItem item) { + return SupportsItem(item); + } + + internal static bool SupportsItem(IHasImages item) + { var trailer = item as Trailer; if (trailer != null) diff --git a/MediaBrowser.Providers/Movies/ManualFanartMovieImageProvider.cs b/MediaBrowser.Providers/Movies/ManualFanartMovieImageProvider.cs index d714128ea..ec9f86919 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<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); 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 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 e5bd3bf47..d02ae5550 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<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); 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>(); @@ -114,14 +114,14 @@ namespace MediaBrowser.Providers.Movies .ThenByDescending(i => i.VoteCount ?? 0) .ToList(); } - + /// <summary> /// Gets the posters. /// </summary> /// <param name="images">The images.</param> /// <param name="item">The item.</param> /// <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; @@ -134,7 +134,7 @@ namespace MediaBrowser.Providers.Movies /// <param name="images">The images.</param> /// <param name="item">The item.</param> /// <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>() : images.backdrops @@ -150,9 +150,9 @@ namespace MediaBrowser.Providers.Movies /// <param name="item">The item.</param> /// <param name="jsonSerializer">The json serializer.</param> /// <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)) { diff --git a/MediaBrowser.Providers/Movies/ManualMovieDbPersonImageProvider.cs b/MediaBrowser.Providers/Movies/ManualMovieDbPersonImageProvider.cs index b381de332..a074b10c2 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<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); 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); } - 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)) { @@ -86,7 +87,7 @@ namespace MediaBrowser.Providers.Movies return new List<RemoteImageInfo>(); } - + private IEnumerable<RemoteImageInfo> GetImages(MovieDbPersonProvider.Images images, string baseImageUrl) { var list = new List<RemoteImageInfo>(); diff --git a/MediaBrowser.Providers/Movies/MovieDbImagesProvider.cs b/MediaBrowser.Providers/Movies/MovieDbImagesProvider.cs index d63fcec5c..f15d13222 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 d95365b02..99e7212fc 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<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); 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 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 cdb07d3d7..85209a0e1 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<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); 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 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 72e8c6f6b..6d6f1ec7b 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<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); 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>(); diff --git a/MediaBrowser.Providers/TV/ManualFanartSeasonProvider.cs b/MediaBrowser.Providers/TV/ManualFanartSeasonProvider.cs index f9b779011..6132f1097 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<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); 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 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 cb7a4efd1..12f9d2247 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<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); 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>(); diff --git a/MediaBrowser.Providers/TV/ManualTvdbEpisodeImageProvider.cs b/MediaBrowser.Providers/TV/ManualTvdbEpisodeImageProvider.cs index d63fb5091..6d38dee2e 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<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); 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; diff --git a/MediaBrowser.Providers/TV/ManualTvdbPersonImageProvider.cs b/MediaBrowser.Providers/TV/ManualTvdbPersonImageProvider.cs index adeca12f2..456db1048 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<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); 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 .RecursiveChildren diff --git a/MediaBrowser.Providers/TV/ManualTvdbSeasonImageProvider.cs b/MediaBrowser.Providers/TV/ManualTvdbSeasonImageProvider.cs index 3efd0a3e3..e0c8434ce 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<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); 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; diff --git a/MediaBrowser.Providers/TV/ManualTvdbSeriesImageProvider.cs b/MediaBrowser.Providers/TV/ManualTvdbSeriesImageProvider.cs index 5987215d1..0b48ddb2b 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<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); 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)) { diff --git a/MediaBrowser.Providers/VirtualItemImageValidator.cs b/MediaBrowser.Providers/VirtualItemImageValidator.cs new file mode 100644 index 000000000..d4bbaf713 --- /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<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; } + } + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs index f8f5d02e9..5465b70da 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 06e6fbe15..25b0bb222 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<ILiveTvService> _services = new List<ILiveTvService>(); 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) { @@ -138,7 +138,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv return await GetRecording(recording, service.Name, cancellationToken).ConfigureAwait(false); } - + 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)); @@ -189,6 +189,35 @@ namespace MediaBrowser.Server.Implementations.LiveTv 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) { var isNew = false; @@ -218,27 +247,50 @@ namespace MediaBrowser.Server.Implementations.LiveTv 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 - .OrderBy(i => i.StartDate) - .ThenBy(i => i.EndDate); + IEnumerable<LiveTvProgram> 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<ProgramInfoDto> { @@ -246,7 +298,31 @@ namespace MediaBrowser.Server.Implementations.LiveTv 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) @@ -266,7 +342,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv var allChannelsList = allChannels.ToList(); var list = new List<LiveTvChannel>(); - var programs = new List<ProgramInfoDto>(); + var programs = new List<LiveTvProgram>(); 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<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 - { - 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<SeriesTimerInfoDto> GetNewTimerDefaults(CancellationToken cancellationToken) diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 5d3d8c491..8962d088e 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -85,6 +85,9 @@ </ItemGroup>
<ItemGroup>
<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">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index e84fb011b..084a9da1f 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <metadata> <id>MediaBrowser.Common.Internal</id> - <version>3.0.284</version> + <version>3.0.285</version> <title>MediaBrowser.Common.Internal</title> <authors>Luke</authors> <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> <copyright>Copyright © Media Browser 2013</copyright> <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="SimpleInjector" version="2.4.0" /> <dependency id="sharpcompress" version="0.10.2" /> diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index 67eedbf58..e9eb11a92 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <metadata> <id>MediaBrowser.Common</id> - <version>3.0.284</version> + <version>3.0.285</version> <title>MediaBrowser.Common</title> <authors>Media Browser Team</authors> <owners>ebr,Luke,scottisafool</owners> diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index 050e3086c..423091830 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <metadata> <id>MediaBrowser.Server.Core</id> - <version>3.0.284</version> + <version>3.0.285</version> <title>Media Browser.Server.Core</title> <authors>Media Browser Team</authors> <owners>ebr,Luke,scottisafool</owners> @@ -12,7 +12,7 @@ <description>Contains core components required to build plugins for Media Browser Server.</description> <copyright>Copyright © Media Browser 2013</copyright> <dependencies> - <dependency id="MediaBrowser.Common" version="3.0.284" /> + <dependency id="MediaBrowser.Common" version="3.0.285" /> </dependencies> </metadata> <files> |
