From 39c4542cf691134cfa7f9d5cafbd7dd1083d5ec9 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 4 Sep 2017 15:28:22 -0400 Subject: update query objects --- .../Data/SqliteItemRepository.cs | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) (limited to 'Emby.Server.Implementations/Data/SqliteItemRepository.cs') diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 74e009bd9..165d17a57 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -2135,8 +2135,7 @@ namespace Emby.Server.Implementations.Data //return true; } - var sortingFields = query.SortBy.ToList(); - sortingFields.AddRange(query.OrderBy.Select(i => i.Item1)); + var sortingFields = query.OrderBy.Select(i => i.Item1).ToList(); if (sortingFields.Contains(ItemSortBy.IsFavoriteOrLiked, StringComparer.OrdinalIgnoreCase)) { @@ -2975,16 +2974,7 @@ namespace Emby.Server.Implementations.Data private string GetOrderByText(InternalItemsQuery query) { var orderBy = query.OrderBy.ToList(); - var enableOrderInversion = true; - - if (orderBy.Count == 0) - { - orderBy.AddRange(query.SortBy.Select(i => new Tuple(i, query.SortOrder))); - } - else - { - enableOrderInversion = false; - } + var enableOrderInversion = false; if (query.SimilarTo != null) { @@ -2993,12 +2983,10 @@ namespace Emby.Server.Implementations.Data orderBy.Add(new Tuple(ItemSortBy.Random, SortOrder.Ascending)); orderBy.Add(new Tuple("SimilarityScore", SortOrder.Descending)); //orderBy.Add(new Tuple(ItemSortBy.Random, SortOrder.Ascending)); - query.SortOrder = SortOrder.Descending; - enableOrderInversion = false; } } - query.OrderBy = orderBy; + query.OrderBy = orderBy.ToArray(); if (orderBy.Count == 0) { -- cgit v1.2.3 From eb63e0d264d563b100a353c12859f226e9303910 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 7 Sep 2017 14:17:18 -0400 Subject: update image processor --- Emby.Drawing/ImageProcessor.cs | 94 +++++++---- Emby.Server.Implementations/ApplicationHost.cs | 4 +- .../Data/SqliteItemRepository.cs | 2 +- .../Data/SqliteUserDataRepository.cs | 2 +- Emby.Server.Implementations/Dto/DtoService.cs | 3 +- .../Emby.Server.Implementations.csproj | 1 + .../Services/SwaggerService.cs | 183 +++++++++++++++++++++ MediaBrowser.Api/Images/ImageService.cs | 47 +----- MediaBrowser.Api/UserLibrary/ItemsService.cs | 14 ++ MediaBrowser.Controller/Drawing/IImageProcessor.cs | 2 + .../Drawing/ImageProcessingOptions.cs | 8 +- MediaBrowser.Controller/Entities/Movies/BoxSet.cs | 28 ++++ .../Providers/IImageEnhancer.cs | 7 + MediaBrowser.Model/Dlna/StreamBuilder.cs | 122 ++++++++++++-- 14 files changed, 428 insertions(+), 89 deletions(-) create mode 100644 Emby.Server.Implementations/Services/SwaggerService.cs (limited to 'Emby.Server.Implementations/Data/SqliteItemRepository.cs') diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index 1d3f4a8e3..9e941b38c 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -203,10 +203,9 @@ namespace Emby.Drawing } private static readonly string[] TransparentImageTypes = new string[] { ".png", ".webp" }; - private bool SupportsTransparency(string path) + public bool SupportsTransparency(string path) { return TransparentImageTypes.Contains(Path.GetExtension(path) ?? string.Empty); - ; } public async Task> ProcessImage(ImageProcessingOptions options) @@ -239,6 +238,7 @@ namespace Emby.Drawing var supportedImageInfo = await GetSupportedImage(originalImagePath, dateModified).ConfigureAwait(false); originalImagePath = supportedImageInfo.Item1; dateModified = supportedImageInfo.Item2; + var requiresTransparency = TransparentImageTypes.Contains(Path.GetExtension(originalImagePath) ?? string.Empty); if (options.Enhancers.Count > 0) { @@ -253,10 +253,11 @@ namespace Emby.Drawing Type = originalImage.Type, Path = originalImagePath - }, item, options.ImageIndex, options.Enhancers).ConfigureAwait(false); + }, requiresTransparency, item, options.ImageIndex, options.Enhancers).ConfigureAwait(false); originalImagePath = tuple.Item1; dateModified = tuple.Item2; + requiresTransparency = tuple.Item3; } var photo = item as Photo; @@ -268,7 +269,7 @@ namespace Emby.Drawing orientation = photo.Orientation; } - if (options.HasDefaultOptions(originalImagePath) && !autoOrient) + if (options.HasDefaultOptions(originalImagePath) && (!autoOrient || !options.RequiresAutoOrientation)) { // Just spit out the original file if all the options are default return new Tuple(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified); @@ -285,7 +286,7 @@ namespace Emby.Drawing var newSize = ImageHelper.GetNewImageSize(options, originalImageSize); var quality = options.Quality; - var outputFormat = GetOutputFormat(options.SupportedOutputFormats[0]); + var outputFormat = GetOutputFormat(options.SupportedOutputFormats, requiresTransparency); var cacheFilePath = GetCacheFilePath(originalImagePath, newSize, quality, dateModified, outputFormat, options.AddPlayedIndicator, options.PercentPlayed, options.UnplayedCount, options.Blur, options.BackgroundColor, options.ForegroundLayer); try @@ -336,6 +337,34 @@ namespace Emby.Drawing } } + private ImageFormat GetOutputFormat(ImageFormat[] clientSupportedFormats, bool requiresTransparency) + { + var serverFormats = GetSupportedImageOutputFormats(); + + // Client doesn't care about format, so start with webp if supported + if (serverFormats.Contains(ImageFormat.Webp) && clientSupportedFormats.Contains(ImageFormat.Webp)) + { + return ImageFormat.Webp; + } + + // If transparency is needed and webp isn't supported, than png is the only option + if (requiresTransparency) + { + return ImageFormat.Png; + } + + foreach (var format in clientSupportedFormats) + { + if (serverFormats.Contains(format)) + { + return format; + } + } + + // We should never actually get here + return ImageFormat.Jpg; + } + private void CopyFile(string src, string destination) { try @@ -389,21 +418,6 @@ namespace Emby.Drawing return MimeTypes.GetMimeType(path); } - private ImageFormat GetOutputFormat(ImageFormat requestedFormat) - { - if (requestedFormat == ImageFormat.Webp && !_imageEncoder.SupportedOutputFormats.Contains(ImageFormat.Webp)) - { - return ImageFormat.Png; - } - - return requestedFormat; - } - - private Tuple GetResult(string path) - { - return new Tuple(path, _fileSystem.GetLastWriteTimeUtc(path)); - } - /// /// Increment this when there's a change requiring caches to be invalidated /// @@ -753,12 +767,15 @@ namespace Emby.Drawing var imageInfo = item.GetImageInfo(imageType, imageIndex); - var result = await GetEnhancedImage(imageInfo, item, imageIndex, enhancers); + var inputImageSupportsTransparency = SupportsTransparency(imageInfo.Path); + + var result = await GetEnhancedImage(imageInfo, inputImageSupportsTransparency, item, imageIndex, enhancers); return result.Item1; } - private async Task> GetEnhancedImage(ItemImageInfo image, + private async Task> GetEnhancedImage(ItemImageInfo image, + bool inputImageSupportsTransparency, IHasMetadata item, int imageIndex, List enhancers) @@ -772,12 +789,16 @@ namespace Emby.Drawing var cacheGuid = GetImageCacheTag(item, image, enhancers); // Enhance if we have enhancers - var ehnancedImagePath = await GetEnhancedImageInternal(originalImagePath, item, imageType, imageIndex, enhancers, cacheGuid).ConfigureAwait(false); + var ehnancedImageInfo = await GetEnhancedImageInternal(originalImagePath, item, imageType, imageIndex, enhancers, cacheGuid).ConfigureAwait(false); + + var ehnancedImagePath = ehnancedImageInfo.Item1; // If the path changed update dateModified if (!string.Equals(ehnancedImagePath, originalImagePath, StringComparison.OrdinalIgnoreCase)) { - return GetResult(ehnancedImagePath); + var treatmentRequiresTransparency = ehnancedImageInfo.Item2; + + return new Tuple(ehnancedImagePath, _fileSystem.GetLastWriteTimeUtc(ehnancedImagePath), treatmentRequiresTransparency); } } catch (Exception ex) @@ -785,7 +806,7 @@ namespace Emby.Drawing _logger.Error("Error enhancing image", ex); } - return new Tuple(originalImagePath, dateModified); + return new Tuple(originalImagePath, dateModified, inputImageSupportsTransparency); } /// @@ -803,11 +824,11 @@ namespace Emby.Drawing /// or /// item /// - private async Task GetEnhancedImageInternal(string originalImagePath, + private async Task> GetEnhancedImageInternal(string originalImagePath, IHasMetadata item, ImageType imageType, int imageIndex, - IEnumerable supportedEnhancers, + List supportedEnhancers, string cacheGuid) { if (string.IsNullOrEmpty(originalImagePath)) @@ -820,13 +841,26 @@ namespace Emby.Drawing throw new ArgumentNullException("item"); } + var treatmentRequiresTransparency = false; + foreach (var enhancer in supportedEnhancers) + { + if (!treatmentRequiresTransparency) + { + treatmentRequiresTransparency = enhancer.GetEnhancedImageInfo(item, originalImagePath, imageType, imageIndex).RequiresTransparency; + } + } + // All enhanced images are saved as png to allow transparency - var enhancedImagePath = GetCachePath(EnhancedImageCachePath, cacheGuid + ".png"); + var cacheExtension = _imageEncoder.SupportedOutputFormats.Contains(ImageFormat.Webp) ? + ".webp" : + (treatmentRequiresTransparency ? ".png" : ".jpg"); + + var enhancedImagePath = GetCachePath(EnhancedImageCachePath, cacheGuid + cacheExtension); // Check again in case of contention if (_fileSystem.FileExists(enhancedImagePath)) { - return enhancedImagePath; + return new Tuple(enhancedImagePath, treatmentRequiresTransparency); } _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(enhancedImagePath)); @@ -845,7 +879,7 @@ namespace Emby.Drawing } - return tmpPath; + return new Tuple(tmpPath, treatmentRequiresTransparency); } /// diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index b3268b156..673798294 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1861,7 +1861,9 @@ namespace Emby.Server.Implementations { "mbplus.dll", "mbintros.dll", - "embytv.dll" + "embytv.dll", + "Messenger.dll", + "MediaBrowser.Plugins.TvMazeProvider.dll" }; return !exclude.Contains(filename ?? string.Empty, StringComparer.OrdinalIgnoreCase); diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 165d17a57..a07b79e10 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -114,7 +114,7 @@ namespace Emby.Server.Implementations.Data { get { - return true; + return false; } } diff --git a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs index ef1d7ba44..d078a31c9 100644 --- a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs @@ -94,7 +94,7 @@ namespace Emby.Server.Implementations.Data { get { - return true; + return false; } } diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index a0bbd171f..b57662e31 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -275,8 +275,7 @@ namespace Emby.Server.Implementations.Dto { var hasFullSyncInfo = options.Fields.Contains(ItemFields.SyncInfo); - if (!options.Fields.Contains(ItemFields.BasicSyncInfo) && - !hasFullSyncInfo) + if (!hasFullSyncInfo && !options.Fields.Contains(ItemFields.BasicSyncInfo)) { return; } diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 75a9d8588..719510fc3 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -496,6 +496,7 @@ + diff --git a/Emby.Server.Implementations/Services/SwaggerService.cs b/Emby.Server.Implementations/Services/SwaggerService.cs new file mode 100644 index 000000000..4590369fa --- /dev/null +++ b/Emby.Server.Implementations/Services/SwaggerService.cs @@ -0,0 +1,183 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using MediaBrowser.Model.Services; + +namespace Emby.Server.Implementations.Services +{ + [Route("/swagger", "GET", Summary = "Gets the swagger specifications")] + [Route("/swagger.json", "GET", Summary = "Gets the swagger specifications")] + public class GetSwaggerSpec : IReturn + { + } + + public class SwaggerSpec + { + public string swagger { get; set; } + public string[] schemes { get; set; } + public SwaggerInfo info { get; set; } + public string host { get; set; } + public string basePath { get; set; } + public SwaggerTag[] tags { get; set; } + public Dictionary> paths { get; set; } + public Dictionary definitions { get; set; } + } + + public class SwaggerInfo + { + public string description { get; set; } + public string version { get; set; } + public string title { get; set; } + + public SwaggerConcactInfo contact { get; set; } + } + + public class SwaggerConcactInfo + { + public string email { get; set; } + } + + public class SwaggerTag + { + public string description { get; set; } + public string name { get; set; } + } + + public class SwaggerMethod + { + public string summary { get; set; } + public string description { get; set; } + public string[] tags { get; set; } + public string operationId { get; set; } + public string[] consumes { get; set; } + public string[] produces { get; set; } + public SwaggerParam[] parameters { get; set; } + public Dictionary responses { get; set; } + } + + public class SwaggerParam + { + public string @in { get; set; } + public string name { get; set; } + public string description { get; set; } + public bool required { get; set; } + public string type { get; set; } + public string collectionFormat { get; set; } + } + + public class SwaggerResponse + { + public string description { get; set; } + + // ex. "$ref":"#/definitions/Pet" + public Dictionary schema { get; set; } + } + + public class SwaggerDefinition + { + public string type { get; set; } + public Dictionary properties { get; set; } + } + + public class SwaggerProperty + { + public string type { get; set; } + public string format { get; set; } + public string description { get; set; } + public string[] @enum { get; set; } + public string @default { get; set; } + } + + public class SwaggerService : IService + { + private SwaggerSpec _spec; + + public object Get(GetSwaggerSpec request) + { + return _spec ?? (_spec = GetSpec()); + } + + private SwaggerSpec GetSpec() + { + var spec = new SwaggerSpec + { + schemes = new[] { "http" }, + tags = GetTags(), + swagger = "2.0", + info = new SwaggerInfo + { + title = "Emby Server API", + version = "1", + description = "Explore the Emby Server API", + contact = new SwaggerConcactInfo + { + email = "api@emby.media" + } + }, + paths = GetPaths(), + definitions = GetDefinitions() + }; + + return spec; + } + + + private SwaggerTag[] GetTags() + { + return new SwaggerTag[] { }; + } + + private Dictionary GetDefinitions() + { + return new Dictionary(); + } + + private Dictionary> GetPaths() + { + var paths = new Dictionary>(); + + var all = ServiceController.Instance.RestPathMap.ToList(); + + foreach (var current in all) + { + foreach (var info in current.Value) + { + paths[info.Path] = GetPathInfo(info); + } + } + + return paths; + } + + private Dictionary GetPathInfo(RestPath info) + { + var result = new Dictionary(); + + foreach (var verb in info.Verbs) + { + result[verb] = new SwaggerMethod + { + summary = info.Summary, + produces = new[] + { + "application/json", + "application/xml" + }, + consumes = new[] + { + "application/json", + "application/xml" + }, + operationId = info.RequestType.Name, + tags = new string[] { }, + + parameters = new SwaggerParam[] { } + }; + } + + return result; + } + } +} diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs index 69d4a4ab4..f8481517d 100644 --- a/MediaBrowser.Api/Images/ImageService.cs +++ b/MediaBrowser.Api/Images/ImageService.cs @@ -567,7 +567,7 @@ namespace MediaBrowser.Api.Images cropwhitespace = request.CropWhitespace.Value; } - var outputFormats = GetOutputFormats(request, imageInfo, cropwhitespace, supportedImageEnhancers); + var outputFormats = GetOutputFormats(request); TimeSpan? cacheDuration = null; @@ -597,7 +597,7 @@ namespace MediaBrowser.Api.Images ImageRequest request, ItemImageInfo image, bool cropwhitespace, - List supportedFormats, + ImageFormat[] supportedFormats, List enhancers, TimeSpan? cacheDuration, IDictionary headers, @@ -644,55 +644,18 @@ namespace MediaBrowser.Api.Images }).ConfigureAwait(false); } - private List GetOutputFormats(ImageRequest request, ItemImageInfo image, bool cropwhitespace, List enhancers) + private ImageFormat[] GetOutputFormats(ImageRequest request) { if (!string.IsNullOrWhiteSpace(request.Format)) { ImageFormat format; if (Enum.TryParse(request.Format, true, out format)) { - return new List { format }; + return new ImageFormat[] { format }; } } - var extension = Path.GetExtension(image.Path); - ImageFormat? inputFormat = null; - - if (string.Equals(extension, ".jpg", StringComparison.OrdinalIgnoreCase) || - string.Equals(extension, ".jpeg", StringComparison.OrdinalIgnoreCase)) - { - inputFormat = ImageFormat.Jpg; - } - else if (string.Equals(extension, ".png", StringComparison.OrdinalIgnoreCase)) - { - inputFormat = ImageFormat.Png; - } - - var clientSupportedFormats = GetClientSupportedFormats(); - - var serverFormats = _imageProcessor.GetSupportedImageOutputFormats(); - var outputFormats = new List(); - - // Client doesn't care about format, so start with webp if supported - if (serverFormats.Contains(ImageFormat.Webp) && clientSupportedFormats.Contains(ImageFormat.Webp)) - { - outputFormats.Add(ImageFormat.Webp); - } - - if (enhancers.Count > 0) - { - outputFormats.Add(ImageFormat.Png); - } - - if (inputFormat.HasValue && inputFormat.Value == ImageFormat.Jpg) - { - outputFormats.Add(ImageFormat.Jpg); - } - - // We can't predict if there will be transparency or not, so play it safe - outputFormats.Add(ImageFormat.Png); - - return outputFormats; + return GetClientSupportedFormats(); } private ImageFormat[] GetClientSupportedFormats() diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index fb48f65e4..5919c50d4 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -408,6 +408,20 @@ namespace MediaBrowser.Api.UserLibrary }).Where(i => i != null).Select(i => i.Id.ToString("N")).ToArray(); } + // Apply default sorting if none requested + if (query.OrderBy.Length == 0) + { + // Albums by artist + if (query.ArtistIds.Length > 0 && query.IncludeItemTypes.Length == 1 && string.Equals(query.IncludeItemTypes[0], "MusicAlbum", StringComparison.OrdinalIgnoreCase)) + { + query.OrderBy = new Tuple[] + { + new Tuple(ItemSortBy.ProductionYear, SortOrder.Descending), + new Tuple(ItemSortBy.SortName, SortOrder.Ascending) + }; + } + } + return query; } } diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs index 113f823f5..d7b68d1e7 100644 --- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs +++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs @@ -118,5 +118,7 @@ namespace MediaBrowser.Controller.Drawing IImageEncoder ImageEncoder { get; set; } void SaveImageSize(string path, DateTime imageDateModified, ImageSize size); + + bool SupportsTransparency(string path); } } diff --git a/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs b/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs index fac21c744..26283b5ea 100644 --- a/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs +++ b/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs @@ -10,6 +10,11 @@ namespace MediaBrowser.Controller.Drawing { public class ImageProcessingOptions { + public ImageProcessingOptions() + { + RequiresAutoOrientation = true; + } + public string ItemId { get; set; } public string ItemType { get; set; } public IHasMetadata Item { get; set; } @@ -32,7 +37,7 @@ namespace MediaBrowser.Controller.Drawing public List Enhancers { get; set; } - public List SupportedOutputFormats { get; set; } + public ImageFormat[] SupportedOutputFormats { get; set; } public bool AddPlayedIndicator { get; set; } @@ -43,6 +48,7 @@ namespace MediaBrowser.Controller.Drawing public string BackgroundColor { get; set; } public string ForegroundLayer { get; set; } + public bool RequiresAutoOrientation { get; set; } public bool HasDefaultOptions(string originalImagePath) { diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs index 900e8a664..bd8d9024d 100644 --- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs +++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs @@ -80,15 +80,43 @@ namespace MediaBrowser.Controller.Entities.Movies protected override IEnumerable GetNonCachedChildren(IDirectoryService directoryService) { + if (IsLegacyBoxSet) + { + return base.GetNonCachedChildren(directoryService); + } return new List(); } protected override List LoadChildren() { + if (IsLegacyBoxSet) + { + return base.LoadChildren(); + } + // Save a trip to the database return new List(); } + [IgnoreDataMember] + private bool IsLegacyBoxSet + { + get + { + if (string.IsNullOrWhiteSpace(Path)) + { + return false; + } + + if (LinkedChildren.Length > 0) + { + return false; + } + + return !FileSystem.ContainsSubPath(ConfigurationManager.ApplicationPaths.DataPath, Path); + } + } + [IgnoreDataMember] public override bool IsPreSorted { diff --git a/MediaBrowser.Controller/Providers/IImageEnhancer.cs b/MediaBrowser.Controller/Providers/IImageEnhancer.cs index a993f536d..90f7296c6 100644 --- a/MediaBrowser.Controller/Providers/IImageEnhancer.cs +++ b/MediaBrowser.Controller/Providers/IImageEnhancer.cs @@ -39,6 +39,8 @@ namespace MediaBrowser.Controller.Providers /// ImageSize. ImageSize GetEnhancedImageSize(IHasMetadata item, ImageType imageType, int imageIndex, ImageSize originalImageSize); + EnhancedImageInfo GetEnhancedImageInfo(IHasMetadata item, string inputFile, ImageType imageType, int imageIndex); + /// /// Enhances the image async. /// @@ -51,4 +53,9 @@ namespace MediaBrowser.Controller.Providers /// Task EnhanceImageAsync(IHasMetadata item, string inputFile, string outputFile, ImageType imageType, int imageIndex); } + + public class EnhancedImageInfo + { + public bool RequiresTransparency { get; set; } + } } \ No newline at end of file diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 10c6a05c0..a5ec0f26c 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -849,8 +849,6 @@ namespace MediaBrowser.Model.Dlna } } } - ApplyTranscodingConditions(playlistItem, audioTranscodingConditions); - // Honor requested max channels if (options.MaxAudioChannels.HasValue) { @@ -878,6 +876,9 @@ namespace MediaBrowser.Model.Dlna var longBitrate = Math.Max(Math.Min(videoBitrate, currentValue), 64000); playlistItem.VideoBitrate = longBitrate > int.MaxValue ? int.MaxValue : Convert.ToInt32(longBitrate); } + + // Do this after initial values are set to account for greater than/less than conditions + ApplyTranscodingConditions(playlistItem, audioTranscodingConditions); } playlistItem.TranscodeReasons = transcodeReasons; @@ -1430,7 +1431,18 @@ namespace MediaBrowser.Model.Dlna int num; if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num)) { - item.AudioBitrate = num; + if (condition.Condition == ProfileConditionType.Equals) + { + item.AudioBitrate = num; + } + else if (condition.Condition == ProfileConditionType.LessThanEqual) + { + item.AudioBitrate = Math.Min(num, item.AudioBitrate ?? num); + } + else if (condition.Condition == ProfileConditionType.GreaterThanEqual) + { + item.AudioBitrate = Math.Max(num, item.AudioBitrate ?? num); + } } break; } @@ -1439,7 +1451,18 @@ namespace MediaBrowser.Model.Dlna int num; if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num)) { - item.MaxAudioChannels = num; + if (condition.Condition == ProfileConditionType.Equals) + { + item.MaxAudioChannels = num; + } + else if (condition.Condition == ProfileConditionType.LessThanEqual) + { + item.MaxAudioChannels = Math.Min(num, item.MaxAudioChannels ?? num); + } + else if (condition.Condition == ProfileConditionType.GreaterThanEqual) + { + item.MaxAudioChannels = Math.Max(num, item.MaxAudioChannels ?? num); + } } break; } @@ -1507,7 +1530,18 @@ namespace MediaBrowser.Model.Dlna int num; if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num)) { - item.MaxRefFrames = num; + if (condition.Condition == ProfileConditionType.Equals) + { + item.MaxRefFrames = num; + } + else if (condition.Condition == ProfileConditionType.LessThanEqual) + { + item.MaxRefFrames = Math.Min(num, item.MaxRefFrames ?? num); + } + else if (condition.Condition == ProfileConditionType.GreaterThanEqual) + { + item.MaxRefFrames = Math.Max(num, item.MaxRefFrames ?? num); + } } break; } @@ -1516,7 +1550,18 @@ namespace MediaBrowser.Model.Dlna int num; if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num)) { - item.MaxVideoBitDepth = num; + if (condition.Condition == ProfileConditionType.Equals) + { + item.MaxVideoBitDepth = num; + } + else if (condition.Condition == ProfileConditionType.LessThanEqual) + { + item.MaxVideoBitDepth = Math.Min(num, item.MaxVideoBitDepth ?? num); + } + else if (condition.Condition == ProfileConditionType.GreaterThanEqual) + { + item.MaxVideoBitDepth = Math.Max(num, item.MaxVideoBitDepth ?? num); + } } break; } @@ -1530,7 +1575,18 @@ namespace MediaBrowser.Model.Dlna int num; if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num)) { - item.MaxHeight = num; + if (condition.Condition == ProfileConditionType.Equals) + { + item.MaxHeight = num; + } + else if (condition.Condition == ProfileConditionType.LessThanEqual) + { + item.MaxHeight = Math.Min(num, item.MaxHeight ?? num); + } + else if (condition.Condition == ProfileConditionType.GreaterThanEqual) + { + item.MaxHeight = Math.Max(num, item.MaxHeight ?? num); + } } break; } @@ -1539,7 +1595,18 @@ namespace MediaBrowser.Model.Dlna int num; if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num)) { - item.VideoBitrate = num; + if (condition.Condition == ProfileConditionType.Equals) + { + item.VideoBitrate = num; + } + else if (condition.Condition == ProfileConditionType.LessThanEqual) + { + item.VideoBitrate = Math.Min(num, item.VideoBitrate ?? num); + } + else if (condition.Condition == ProfileConditionType.GreaterThanEqual) + { + item.VideoBitrate = Math.Max(num, item.VideoBitrate ?? num); + } } break; } @@ -1548,7 +1615,18 @@ namespace MediaBrowser.Model.Dlna float num; if (float.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num)) { - item.MaxFramerate = num; + if (condition.Condition == ProfileConditionType.Equals) + { + item.MaxFramerate = num; + } + else if (condition.Condition == ProfileConditionType.LessThanEqual) + { + item.MaxFramerate = Math.Min(num, item.MaxFramerate ?? num); + } + else if (condition.Condition == ProfileConditionType.GreaterThanEqual) + { + item.MaxFramerate = Math.Max(num, item.MaxFramerate ?? num); + } } break; } @@ -1557,7 +1635,18 @@ namespace MediaBrowser.Model.Dlna int num; if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num)) { - item.VideoLevel = num; + if (condition.Condition == ProfileConditionType.Equals) + { + item.VideoLevel = num; + } + else if (condition.Condition == ProfileConditionType.LessThanEqual) + { + item.VideoLevel = Math.Min(num, item.VideoLevel ?? num); + } + else if (condition.Condition == ProfileConditionType.GreaterThanEqual) + { + item.VideoLevel = Math.Max(num, item.VideoLevel ?? num); + } } break; } @@ -1566,7 +1655,18 @@ namespace MediaBrowser.Model.Dlna int num; if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num)) { - item.MaxWidth = num; + if (condition.Condition == ProfileConditionType.Equals) + { + item.MaxWidth = num; + } + else if (condition.Condition == ProfileConditionType.LessThanEqual) + { + item.MaxWidth = Math.Min(num, item.MaxWidth ?? num); + } + else if (condition.Condition == ProfileConditionType.GreaterThanEqual) + { + item.MaxWidth = Math.Max(num, item.MaxWidth ?? num); + } } break; } -- cgit v1.2.3 From adc22b5e811ff1d570946a65b94930c1c338c7d3 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 8 Sep 2017 12:13:58 -0400 Subject: rework epg storage --- .../Data/SqliteItemRepository.cs | 37 ++- .../Data/SqliteUserDataRepository.cs | 2 +- .../LiveTv/EmbyTV/EmbyTV.cs | 338 +++++++++++++-------- .../LiveTv/EmbyTV/RecordingHelper.cs | 61 +--- .../LiveTv/LiveTvDtoService.cs | 6 +- .../LiveTv/LiveTvManager.cs | 18 +- MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs | 1 - MediaBrowser.Controller/LiveTv/LiveTvProgram.cs | 3 + MediaBrowser.Model/Net/ISocket.cs | 3 - RSSDP/RSSDP.csproj | 17 +- RSSDP/RSSDP.nuget.targets | 6 - SharedVersion.cs | 2 +- 12 files changed, 274 insertions(+), 220 deletions(-) delete mode 100644 RSSDP/RSSDP.nuget.targets (limited to 'Emby.Server.Implementations/Data/SqliteItemRepository.cs') diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index a07b79e10..b5bc7692e 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -114,7 +114,7 @@ namespace Emby.Server.Implementations.Data { get { - return false; + return true; } } @@ -252,6 +252,7 @@ namespace Emby.Server.Implementations.Data AddColumn(db, "TypedBaseItems", "AlbumArtists", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "ExternalId", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "SeriesPresentationUniqueKey", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "ShowId", "Text", existingColumnNames); existingColumnNames = GetColumnNames(db, "ItemValues"); AddColumn(db, "ItemValues", "CleanValue", "Text", existingColumnNames); @@ -457,7 +458,8 @@ namespace Emby.Server.Implementations.Data "Artists", "AlbumArtists", "ExternalId", - "SeriesPresentationUniqueKey" + "SeriesPresentationUniqueKey", + "ShowId" }; private readonly string[] _mediaStreamSaveColumns = @@ -577,7 +579,8 @@ namespace Emby.Server.Implementations.Data "Artists", "AlbumArtists", "ExternalId", - "SeriesPresentationUniqueKey" + "SeriesPresentationUniqueKey", + "ShowId" }; var saveItemCommandCommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values ("; @@ -1044,6 +1047,16 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBind("@AlbumArtists", albumArtists); saveItemStatement.TryBind("@ExternalId", item.ExternalId); + var program = item as LiveTvProgram; + if (program != null) + { + saveItemStatement.TryBind("@ShowId", program.ShowId); + } + else + { + saveItemStatement.TryBindNull("@ShowId"); + } + saveItemStatement.MoveNext(); } @@ -1935,6 +1948,23 @@ namespace Emby.Server.Implementations.Data index++; } + if (enableProgramAttributes) + { + var program = item as LiveTvProgram; + if (program != null) + { + if (!reader.IsDBNull(index)) + { + program.ShowId = reader.GetString(index); + } + index++; + } + else + { + index ++; + } + } + return item; } @@ -2441,6 +2471,7 @@ namespace Emby.Server.Implementations.Data list.Remove("IsPremiere"); list.Remove("EpisodeTitle"); list.Remove("IsRepeat"); + list.Remove("ShowId"); } if (!HasEpisodeAttributes(query)) diff --git a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs index d078a31c9..ef1d7ba44 100644 --- a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs @@ -94,7 +94,7 @@ namespace Emby.Server.Implementations.Data { get { - return false; + return true; } } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index b1d4b096f..bd9754f26 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -305,26 +305,9 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { var seriesTimers = await GetSeriesTimersAsync(cancellationToken).ConfigureAwait(false); - List channels = null; - foreach (var timer in seriesTimers) { - List epgData; - - if (timer.RecordAnyChannel) - { - if (channels == null) - { - channels = (await GetChannelsAsync(true, CancellationToken.None).ConfigureAwait(false)).ToList(); - } - var channelIds = channels.Select(i => i.Id).ToList(); - epgData = channelIds.SelectMany(GetEpgDataForChannel).ToList(); - } - else - { - epgData = GetEpgDataForChannel(timer.ChannelId); - } - await UpdateTimersForSeriesTimer(epgData, timer, false, true).ConfigureAwait(false); + await UpdateTimersForSeriesTimer(timer, false, true).ConfigureAwait(false); } } @@ -332,6 +315,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { var timers = await GetTimersAsync(cancellationToken).ConfigureAwait(false); + var tempChannelCache = new Dictionary(); + foreach (var timer in timers) { if (DateTime.UtcNow > timer.EndDate && !_activeRecordings.ContainsKey(timer.Id)) @@ -345,15 +330,14 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV continue; } - var epg = GetEpgDataForChannel(timer.ChannelId); - var program = epg.FirstOrDefault(i => string.Equals(i.Id, timer.ProgramId, StringComparison.OrdinalIgnoreCase)); + var program = GetProgramInfoFromCache(timer); if (program == null) { OnTimerOutOfDate(timer); continue; } - RecordingHelper.CopyProgramInfoToTimerInfo(program, timer); + CopyProgramInfoToTimerInfo(program, timer, tempChannelCache); _timerProvider.Update(timer); } } @@ -621,7 +605,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV ActiveRecordingInfo activeRecordingInfo; if (_activeRecordings.TryGetValue(timerId, out activeRecordingInfo)) - { + { activeRecordingInfo.Timer = timer; activeRecordingInfo.CancellationTokenSource.Cancel(); } @@ -672,11 +656,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV timer.Id = Guid.NewGuid().ToString("N"); - ProgramInfo programInfo = null; + LiveTvProgram programInfo = null; if (!string.IsNullOrWhiteSpace(timer.ProgramId)) { - programInfo = GetProgramInfoFromCache(timer.ChannelId, timer.ProgramId); + programInfo = GetProgramInfoFromCache(timer); } if (programInfo == null) { @@ -686,7 +670,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV if (programInfo != null) { - RecordingHelper.CopyProgramInfoToTimerInfo(programInfo, timer); + CopyProgramInfoToTimerInfo(programInfo, timer); } timer.IsManual = true; @@ -698,24 +682,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { info.Id = Guid.NewGuid().ToString("N"); - List epgData; - if (info.RecordAnyChannel) - { - var channels = await GetChannelsAsync(true, CancellationToken.None).ConfigureAwait(false); - var channelIds = channels.Select(i => i.Id).ToList(); - epgData = channelIds.SelectMany(GetEpgDataForChannel).ToList(); - } - else - { - epgData = GetEpgDataForChannel(info.ChannelId); - } - // populate info.seriesID - var program = epgData.FirstOrDefault(i => string.Equals(i.Id, info.ProgramId, StringComparison.OrdinalIgnoreCase)); + var program = GetProgramInfoFromCache(info.ProgramId); if (program != null) { - info.SeriesId = program.SeriesId; + info.SeriesId = program.ExternalSeriesId; } else { @@ -750,7 +722,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV _timerProvider.AddOrUpdate(timer, false); } - await UpdateTimersForSeriesTimer(epgData, info, true, false).ConfigureAwait(false); + await UpdateTimersForSeriesTimer(info, true, false).ConfigureAwait(false); return info.Id; } @@ -779,19 +751,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV _seriesTimerProvider.Update(instance); - List epgData; - if (instance.RecordAnyChannel) - { - var channels = await GetChannelsAsync(true, CancellationToken.None).ConfigureAwait(false); - var channelIds = channels.Select(i => i.Id).ToList(); - epgData = channelIds.SelectMany(GetEpgDataForChannel).ToList(); - } - else - { - epgData = GetEpgDataForChannel(instance.ChannelId); - } - - await UpdateTimersForSeriesTimer(epgData, instance, true, true).ConfigureAwait(false); + await UpdateTimersForSeriesTimer(instance, true, true).ConfigureAwait(false); } } @@ -962,23 +922,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return Task.FromResult((IEnumerable)_seriesTimerProvider.GetAll()); } - public async Task> GetProgramsAsync(string channelId, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken) - { - try - { - return await GetProgramsAsyncInternal(channelId, startDateUtc, endDateUtc, cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - throw; - } - catch (Exception ex) - { - _logger.ErrorException("Error getting programs", ex); - return GetEpgDataForChannel(channelId).Where(i => i.StartDate <= endDateUtc && i.EndDate >= startDateUtc); - } - } - private bool IsListingProviderEnabledForTuner(ListingsProviderInfo info, string tunerHostId) { if (info.EnableAllTuners) @@ -994,7 +937,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return info.EnabledTuners.Contains(tunerHostId, StringComparer.OrdinalIgnoreCase); } - private async Task> GetProgramsAsyncInternal(string channelId, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken) + public async Task> GetProgramsAsync(string channelId, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken) { var channels = await GetChannelsAsync(true, cancellationToken).ConfigureAwait(false); var channel = channels.First(i => string.Equals(i.Id, channelId, StringComparison.OrdinalIgnoreCase)); @@ -1037,8 +980,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV if (programs.Count > 0) { - SaveEpgDataForChannel(channelId, programs); - return programs; } } @@ -1464,11 +1405,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV throw new ArgumentNullException("timer"); } - ProgramInfo programInfo = null; + LiveTvProgram programInfo = null; if (!string.IsNullOrWhiteSpace(timer.ProgramId)) { - programInfo = GetProgramInfoFromCache(timer.ChannelId, timer.ProgramId); + programInfo = GetProgramInfoFromCache(timer); } if (programInfo == null) { @@ -1478,8 +1419,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV if (programInfo != null) { - RecordingHelper.CopyProgramInfoToTimerInfo(programInfo, timer); - activeRecordingInfo.Program = programInfo; + CopyProgramInfoToTimerInfo(programInfo, timer); + //activeRecordingInfo.Program = programInfo; } string seriesPath = null; @@ -2336,18 +2277,49 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } } - private ProgramInfo GetProgramInfoFromCache(string channelId, string programId) + private LiveTvProgram GetProgramInfoFromCache(string programId) { - var epgData = GetEpgDataForChannel(channelId); - return epgData.FirstOrDefault(p => string.Equals(p.Id, programId, StringComparison.OrdinalIgnoreCase)); + var query = new InternalItemsQuery + { + ItemIds = new[] { _liveTvManager.GetInternalProgramId(Name, programId).ToString("N") }, + Limit = 1, + DtoOptions = new DtoOptions() + }; + + return _libraryManager.GetItemList(query).Cast().FirstOrDefault(); } - private ProgramInfo GetProgramInfoFromCache(string channelId, DateTime startDateUtc) + private LiveTvProgram GetProgramInfoFromCache(TimerInfo timer) { - var epgData = GetEpgDataForChannel(channelId); - var startDateTicks = startDateUtc.Ticks; - // Find the first program that starts within 3 minutes - return epgData.FirstOrDefault(p => Math.Abs(startDateTicks - p.StartDate.Ticks) <= TimeSpan.FromMinutes(3).Ticks); + return GetProgramInfoFromCache(timer.ProgramId, timer.ChannelId); + } + + private LiveTvProgram GetProgramInfoFromCache(string programId, string channelId) + { + return GetProgramInfoFromCache(programId); + } + + private LiveTvProgram GetProgramInfoFromCache(string channelId, DateTime startDateUtc) + { + var query = new InternalItemsQuery + { + IncludeItemTypes = new string[] { typeof(LiveTvProgram).Name }, + Limit = 1, + DtoOptions = new DtoOptions(true) + { + EnableImages = false + }, + MinStartDate = startDateUtc.AddMinutes(-3), + MaxStartDate = startDateUtc.AddMinutes(3), + OrderBy = new[] { new Tuple(ItemSortBy.StartDate, SortOrder.Ascending) } + }; + + if (!string.IsNullOrWhiteSpace(channelId)) + { + query.ChannelIds = new[] { _liveTvManager.GetInternalChannelId(Name, channelId).ToString("N") }; + } + + return _libraryManager.GetItemList(query).Cast().FirstOrDefault(); } private LiveTvOptions GetConfiguration() @@ -2421,9 +2393,9 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } } - private async Task UpdateTimersForSeriesTimer(List epgData, SeriesTimerInfo seriesTimer, bool updateTimerSettings, bool deleteInvalidTimers) + private async Task UpdateTimersForSeriesTimer(SeriesTimerInfo seriesTimer, bool updateTimerSettings, bool deleteInvalidTimers) { - var allTimers = GetTimersForSeries(seriesTimer, epgData) + var allTimers = GetTimersForSeries(seriesTimer) .ToList(); var registration = await _liveTvManager.GetRegistrationInfo("seriesrecordings").ConfigureAwait(false); @@ -2520,23 +2492,160 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } } - private IEnumerable GetTimersForSeries(SeriesTimerInfo seriesTimer, IEnumerable allPrograms) + private IEnumerable GetTimersForSeries(SeriesTimerInfo seriesTimer) { if (seriesTimer == null) { throw new ArgumentNullException("seriesTimer"); } - if (allPrograms == null) + + if (string.IsNullOrWhiteSpace(seriesTimer.SeriesId)) + { + return new List(); + } + + var query = new InternalItemsQuery + { + IncludeItemTypes = new string[] { typeof(LiveTvProgram).Name }, + ExternalSeriesId = seriesTimer.SeriesId, + DtoOptions = new DtoOptions(true) + { + EnableImages = false + }, + MinEndDate = DateTime.UtcNow + }; + + if (!seriesTimer.RecordAnyChannel) + { + query.ChannelIds = new[] { _liveTvManager.GetInternalChannelId(Name, seriesTimer.ChannelId).ToString("N") }; + } + + var tempChannelCache = new Dictionary(); + + return _libraryManager.GetItemList(query).Cast().Select(i => CreateTimer(i, seriesTimer, tempChannelCache)); + } + + private TimerInfo CreateTimer(LiveTvProgram parent, SeriesTimerInfo seriesTimer, Dictionary tempChannelCache) + { + string channelId = seriesTimer.RecordAnyChannel ? null : seriesTimer.ChannelId; + + if (string.IsNullOrWhiteSpace(channelId) && !string.IsNullOrWhiteSpace(parent.ChannelId)) + { + LiveTvChannel channel; + + if (!tempChannelCache.TryGetValue(parent.ChannelId, out channel)) + { + channel = _libraryManager.GetItemList(new InternalItemsQuery + { + IncludeItemTypes = new string[] { typeof(LiveTvChannel).Name }, + ItemIds = new[] { parent.ChannelId }, + DtoOptions = new DtoOptions() + + }).Cast().FirstOrDefault(); + + if (channel != null && !string.IsNullOrWhiteSpace(channel.ExternalId)) + { + tempChannelCache[parent.ChannelId] = channel; + } + } + + if (channel != null || tempChannelCache.TryGetValue(parent.ChannelId, out channel)) + { + channelId = channel.ExternalId; + } + } + + var timer = new TimerInfo + { + ChannelId = channelId, + Id = (seriesTimer.Id + parent.ExternalId).GetMD5().ToString("N"), + StartDate = parent.StartDate, + EndDate = parent.EndDate.Value, + ProgramId = parent.ExternalId, + PrePaddingSeconds = seriesTimer.PrePaddingSeconds, + PostPaddingSeconds = seriesTimer.PostPaddingSeconds, + IsPostPaddingRequired = seriesTimer.IsPostPaddingRequired, + IsPrePaddingRequired = seriesTimer.IsPrePaddingRequired, + KeepUntil = seriesTimer.KeepUntil, + Priority = seriesTimer.Priority, + Name = parent.Name, + Overview = parent.Overview, + SeriesId = parent.ExternalSeriesId, + SeriesTimerId = seriesTimer.Id, + ShowId = parent.ShowId + }; + + CopyProgramInfoToTimerInfo(parent, timer, tempChannelCache); + + return timer; + } + + private void CopyProgramInfoToTimerInfo(LiveTvProgram programInfo, TimerInfo timerInfo) + { + var tempChannelCache = new Dictionary(); + CopyProgramInfoToTimerInfo(programInfo, timerInfo, tempChannelCache); + } + + private void CopyProgramInfoToTimerInfo(LiveTvProgram programInfo, TimerInfo timerInfo, Dictionary tempChannelCache) + { + string channelId = null; + + if (!string.IsNullOrWhiteSpace(programInfo.ChannelId)) + { + LiveTvChannel channel; + + if (!tempChannelCache.TryGetValue(programInfo.ChannelId, out channel)) + { + channel = _libraryManager.GetItemList(new InternalItemsQuery + { + IncludeItemTypes = new string[] { typeof(LiveTvChannel).Name }, + ItemIds = new[] { programInfo.ChannelId }, + DtoOptions = new DtoOptions() + + }).Cast().FirstOrDefault(); + + if (channel != null && !string.IsNullOrWhiteSpace(channel.ExternalId)) + { + tempChannelCache[programInfo.ChannelId] = channel; + } + } + + if (channel != null || tempChannelCache.TryGetValue(programInfo.ChannelId, out channel)) + { + channelId = channel.ExternalId; + } + } + + timerInfo.Name = programInfo.Name; + timerInfo.StartDate = programInfo.StartDate; + timerInfo.EndDate = programInfo.EndDate.Value; + + if (!string.IsNullOrWhiteSpace(channelId)) { - throw new ArgumentNullException("allPrograms"); + timerInfo.ChannelId = channelId; } - // Exclude programs that have already ended - allPrograms = allPrograms.Where(i => i.EndDate > DateTime.UtcNow); + timerInfo.SeasonNumber = programInfo.ParentIndexNumber; + timerInfo.EpisodeNumber = programInfo.IndexNumber; + timerInfo.IsMovie = programInfo.IsMovie; + timerInfo.IsKids = programInfo.IsKids; + timerInfo.IsNews = programInfo.IsNews; + timerInfo.IsSports = programInfo.IsSports; + timerInfo.ProductionYear = programInfo.ProductionYear; + timerInfo.EpisodeTitle = programInfo.EpisodeTitle; + timerInfo.OriginalAirDate = programInfo.PremiereDate; + timerInfo.IsProgramSeries = programInfo.IsSeries; - allPrograms = GetProgramsForSeries(seriesTimer, allPrograms); + timerInfo.IsSeries = programInfo.IsSeries; + timerInfo.IsLive = programInfo.IsLive; + timerInfo.IsPremiere = programInfo.IsPremiere; - return allPrograms.Select(i => RecordingHelper.CreateTimer(i, seriesTimer)); + timerInfo.HomePageUrl = programInfo.HomePageUrl; + timerInfo.CommunityRating = programInfo.CommunityRating; + timerInfo.Overview = programInfo.Overview; + timerInfo.OfficialRating = programInfo.OfficialRating; + timerInfo.IsRepeat = programInfo.IsRepeat; + timerInfo.SeriesId = programInfo.ExternalSeriesId; } private bool IsProgramAlreadyInLibrary(TimerInfo program) @@ -2577,47 +2686,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return false; } - private IEnumerable GetProgramsForSeries(SeriesTimerInfo seriesTimer, IEnumerable allPrograms) - { - if (string.IsNullOrWhiteSpace(seriesTimer.SeriesId)) - { - _logger.Error("seriesTimer.SeriesId is null. Cannot find programs for series"); - return new List(); - } - - return allPrograms.Where(i => string.Equals(i.SeriesId, seriesTimer.SeriesId, StringComparison.OrdinalIgnoreCase)); - } - - private string GetChannelEpgCachePath(string channelId) - { - return Path.Combine(_config.CommonApplicationPaths.CachePath, "embytvepg", channelId + ".json"); - } - - private readonly object _epgLock = new object(); - private void SaveEpgDataForChannel(string channelId, List epgData) - { - var path = GetChannelEpgCachePath(channelId); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); - lock (_epgLock) - { - _jsonSerializer.SerializeToFile(epgData, path); - } - } - private List GetEpgDataForChannel(string channelId) - { - try - { - lock (_epgLock) - { - return _jsonSerializer.DeserializeFromFile>(GetChannelEpgCachePath(channelId)); - } - } - catch - { - return new List(); - } - } - private bool _disposed; public void Dispose() { diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs index b5de6ef01..a5712b480 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs @@ -1,8 +1,6 @@ -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Controller.LiveTv; using System; using System.Globalization; -using MediaBrowser.Model.LiveTv; namespace Emby.Server.Implementations.LiveTv.EmbyTV { @@ -13,63 +11,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return timer.StartDate.AddSeconds(-timer.PrePaddingSeconds); } - public static TimerInfo CreateTimer(ProgramInfo parent, SeriesTimerInfo seriesTimer) - { - var timer = new TimerInfo - { - ChannelId = parent.ChannelId, - Id = (seriesTimer.Id + parent.Id).GetMD5().ToString("N"), - StartDate = parent.StartDate, - EndDate = parent.EndDate, - ProgramId = parent.Id, - PrePaddingSeconds = seriesTimer.PrePaddingSeconds, - PostPaddingSeconds = seriesTimer.PostPaddingSeconds, - IsPostPaddingRequired = seriesTimer.IsPostPaddingRequired, - IsPrePaddingRequired = seriesTimer.IsPrePaddingRequired, - KeepUntil = seriesTimer.KeepUntil, - Priority = seriesTimer.Priority, - Name = parent.Name, - Overview = parent.Overview, - SeriesId = parent.SeriesId, - SeriesTimerId = seriesTimer.Id, - ShowId = parent.ShowId - }; - - CopyProgramInfoToTimerInfo(parent, timer); - - return timer; - } - - public static void CopyProgramInfoToTimerInfo(ProgramInfo programInfo, TimerInfo timerInfo) - { - timerInfo.Name = programInfo.Name; - timerInfo.StartDate = programInfo.StartDate; - timerInfo.EndDate = programInfo.EndDate; - timerInfo.ChannelId = programInfo.ChannelId; - - timerInfo.SeasonNumber = programInfo.SeasonNumber; - timerInfo.EpisodeNumber = programInfo.EpisodeNumber; - timerInfo.IsMovie = programInfo.IsMovie; - timerInfo.IsKids = programInfo.IsKids; - timerInfo.IsNews = programInfo.IsNews; - timerInfo.IsSports = programInfo.IsSports; - timerInfo.ProductionYear = programInfo.ProductionYear; - timerInfo.EpisodeTitle = programInfo.EpisodeTitle; - timerInfo.OriginalAirDate = programInfo.OriginalAirDate; - timerInfo.IsProgramSeries = programInfo.IsSeries; - - timerInfo.IsSeries = programInfo.IsSeries; - timerInfo.IsLive = programInfo.IsLive; - timerInfo.IsPremiere = programInfo.IsPremiere; - - timerInfo.HomePageUrl = programInfo.HomePageUrl; - timerInfo.CommunityRating = programInfo.CommunityRating; - timerInfo.Overview = programInfo.Overview; - timerInfo.OfficialRating = programInfo.OfficialRating; - timerInfo.IsRepeat = programInfo.IsRepeat; - timerInfo.SeriesId = programInfo.SeriesId; - } - public static string GetRecordingName(TimerInfo info) { var name = info.Name; diff --git a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs index eff2909fd..e6479feaa 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs @@ -9,14 +9,12 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Logging; using System; -using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Extensions; -using MediaBrowser.Model.Querying; namespace Emby.Server.Implementations.LiveTv { @@ -25,15 +23,13 @@ namespace Emby.Server.Implementations.LiveTv private readonly ILogger _logger; private readonly IImageProcessor _imageProcessor; - private readonly IUserDataManager _userDataManager; private readonly IDtoService _dtoService; private readonly IApplicationHost _appHost; private readonly ILibraryManager _libraryManager; - public LiveTvDtoService(IDtoService dtoService, IUserDataManager userDataManager, IImageProcessor imageProcessor, ILogger logger, IApplicationHost appHost, ILibraryManager libraryManager) + public LiveTvDtoService(IDtoService dtoService, IImageProcessor imageProcessor, ILogger logger, IApplicationHost appHost, ILibraryManager libraryManager) { _dtoService = dtoService; - _userDataManager = userDataManager; _imageProcessor = imageProcessor; _logger = logger; _appHost = appHost; diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index b243c6599..dc212492e 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -99,7 +99,7 @@ namespace Emby.Server.Implementations.LiveTv _dtoService = dtoService; _userDataManager = userDataManager; - _tvDtoService = new LiveTvDtoService(dtoService, userDataManager, imageProcessor, logger, appHost, _libraryManager); + _tvDtoService = new LiveTvDtoService(dtoService, imageProcessor, logger, appHost, _libraryManager); } /// @@ -600,6 +600,12 @@ namespace Emby.Server.Implementations.LiveTv }; } + if (!string.Equals(info.ShowId, item.ShowId, StringComparison.OrdinalIgnoreCase)) + { + item.ShowId = info.ShowId; + forceUpdate = true; + } + var seriesId = info.SeriesId; if (!item.ParentId.Equals(channel.Id)) @@ -3143,5 +3149,15 @@ namespace Emby.Server.Implementations.LiveTv var provider = _listingProviders.First(i => string.Equals(i.Type, info.Type, StringComparison.OrdinalIgnoreCase)); return provider.GetChannels(info, cancellationToken); } + + public Guid GetInternalChannelId(string serviceName, string externalId) + { + return _tvDtoService.GetInternalChannelId(serviceName, externalId); + } + + public Guid GetInternalProgramId(string serviceName, string externalId) + { + return _tvDtoService.GetInternalProgramId(serviceName, externalId); + } } } \ No newline at end of file diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs b/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs index 4b757f0b9..ed3b74bf9 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs @@ -42,7 +42,6 @@ namespace MediaBrowser.Controller.LiveTv public string Id { get; set; } public string Path { get; set; } public TimerInfo Timer { get; set; } - public ProgramInfo Program { get; set; } public CancellationTokenSource CancellationTokenSource { get; set; } } } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs index 1607dbcba..896615ad9 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs @@ -88,6 +88,9 @@ namespace MediaBrowser.Controller.LiveTv [IgnoreDataMember] public string EpisodeTitle { get; set; } + [IgnoreDataMember] + public string ShowId { get; set; } + /// /// Gets or sets a value indicating whether this instance is movie. /// diff --git a/MediaBrowser.Model/Net/ISocket.cs b/MediaBrowser.Model/Net/ISocket.cs index 42550340b..6a6781026 100644 --- a/MediaBrowser.Model/Net/ISocket.cs +++ b/MediaBrowser.Model/Net/ISocket.cs @@ -24,8 +24,5 @@ namespace MediaBrowser.Model.Net /// Sends a UDP message to a particular end point (uni or multicast). /// Task SendToAsync(byte[] buffer, int offset, int bytes, IpEndPointInfo endPoint, CancellationToken cancellationToken); - - IAsyncResult BeginSendTo(byte[] buffer, int offset, int size, IpEndPointInfo endPoint, AsyncCallback callback, object state); - int EndSendTo(IAsyncResult result); } } \ No newline at end of file diff --git a/RSSDP/RSSDP.csproj b/RSSDP/RSSDP.csproj index ef1f32207..aea144a5a 100644 --- a/RSSDP/RSSDP.csproj +++ b/RSSDP/RSSDP.csproj @@ -12,9 +12,8 @@ RSSDP en-US 512 - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Profile7 - v4.5 + + v4.6 true @@ -77,8 +76,18 @@ {7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b} MediaBrowser.Model + + + + + + + + + + - +