From 2fc0686c308e74654f4f7ef9ea6cf56fb61b5ff5 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 3 Mar 2015 02:03:17 -0500 Subject: [PATCH] add date content added comparer --- MediaBrowser.Api/Playback/MediaInfoService.cs | 1 + .../Entities/Audio/Audio.cs | 2 +- MediaBrowser.Controller/Entities/Video.cs | 15 ++-- .../Library/IMediaSourceManager.cs | 18 +++++ MediaBrowser.Model/Dlna/PlaybackErrorCode.cs | 3 +- .../Drawing/ImageHeader.cs | 3 +- .../Library/MediaSourceManager.cs | 55 +++++++++++++++ ...MediaBrowser.Server.Implementations.csproj | 1 + .../Photos/BaseDynamicImageProvider.cs | 14 +++- .../Photos/DynamicImageHelpers.cs | 15 +++- .../Session/SessionManager.cs | 6 +- .../Sorting/DateLastMediaAddedComparer.cs | 70 +++++++++++++++++++ .../Sorting/DatePlayedComparer.cs | 1 - 13 files changed, 186 insertions(+), 18 deletions(-) create mode 100644 MediaBrowser.Server.Implementations/Sorting/DateLastMediaAddedComparer.cs diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs index 77178c8cc1..330a8777c7 100644 --- a/MediaBrowser.Api/Playback/MediaInfoService.cs +++ b/MediaBrowser.Api/Playback/MediaInfoService.cs @@ -13,6 +13,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Api.Playback { [Route("/Items/{Id}/MediaInfo", "GET", Summary = "Gets live playback media info for an item")] + [Route("/Items/{Id}/PlaybackInfo", "GET", Summary = "Gets live playback media info for an item")] public class GetLiveMediaInfo : IReturn { [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index 9024479999..d868227d95 100644 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs @@ -239,7 +239,7 @@ namespace MediaBrowser.Controller.Entities.Audio { Id = i.Id.ToString("N"), Protocol = locationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File, - MediaStreams = MediaSourceManager.GetMediaStreams(new MediaStreamQuery { ItemId = i.Id }).ToList(), + MediaStreams = MediaSourceManager.GetMediaStreams(i.Id).ToList(), Name = i.Name, Path = enablePathSubstituion ? GetMappedPath(i.Path, locationType) : i.Path, RunTimeTicks = i.RunTimeTicks, diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index d4507bc337..a0c3a6cf98 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -420,12 +420,17 @@ namespace MediaBrowser.Controller.Entities return base.GetDeletePaths(); } - public virtual IEnumerable GetMediaStreams() + public IEnumerable GetMediaStreams() { - return MediaSourceManager.GetMediaStreams(new MediaStreamQuery + var mediaSource = GetMediaSources(false) + .FirstOrDefault(); + + if (mediaSource == null) { - ItemId = Id - }); + return new List(); + } + + return mediaSource.MediaStreams; } public virtual MediaStream GetDefaultVideoStream() @@ -474,7 +479,7 @@ namespace MediaBrowser.Controller.Entities private static MediaSourceInfo GetVersionInfo(bool enablePathSubstitution, Video i, MediaSourceType type) { - var mediaStreams = MediaSourceManager.GetMediaStreams(new MediaStreamQuery { ItemId = i.Id }) + var mediaStreams = MediaSourceManager.GetMediaStreams(i.Id) .ToList(); var locationType = i.LocationType; diff --git a/MediaBrowser.Controller/Library/IMediaSourceManager.cs b/MediaBrowser.Controller/Library/IMediaSourceManager.cs index 4378bc85d9..5d79f613db 100644 --- a/MediaBrowser.Controller/Library/IMediaSourceManager.cs +++ b/MediaBrowser.Controller/Library/IMediaSourceManager.cs @@ -1,11 +1,29 @@ using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Entities; +using System; using System.Collections.Generic; namespace MediaBrowser.Controller.Library { public interface IMediaSourceManager { + /// + /// Gets the media streams. + /// + /// The item identifier. + /// IEnumerable<MediaStream>. + IEnumerable GetMediaStreams(Guid itemId); + /// + /// Gets the media streams. + /// + /// The media source identifier. + /// IEnumerable<MediaStream>. + IEnumerable GetMediaStreams(string mediaSourceId); + /// + /// Gets the media streams. + /// + /// The query. + /// IEnumerable<MediaStream>. IEnumerable GetMediaStreams(MediaStreamQuery query); } } diff --git a/MediaBrowser.Model/Dlna/PlaybackErrorCode.cs b/MediaBrowser.Model/Dlna/PlaybackErrorCode.cs index d8d65e91aa..4ed4129854 100644 --- a/MediaBrowser.Model/Dlna/PlaybackErrorCode.cs +++ b/MediaBrowser.Model/Dlna/PlaybackErrorCode.cs @@ -4,6 +4,7 @@ namespace MediaBrowser.Model.Dlna public enum PlaybackErrorCode { NotAllowed = 0, - NoCompatibleStream = 1 + NoCompatibleStream = 1, + RateLimitExceeded = 2 } } diff --git a/MediaBrowser.Server.Implementations/Drawing/ImageHeader.cs b/MediaBrowser.Server.Implementations/Drawing/ImageHeader.cs index 81d4a786aa..6287d0bb86 100644 --- a/MediaBrowser.Server.Implementations/Drawing/ImageHeader.cs +++ b/MediaBrowser.Server.Implementations/Drawing/ImageHeader.cs @@ -62,8 +62,9 @@ namespace MediaBrowser.Server.Implementations.Drawing logger.Info("Failed to read image header for {0}. Doing it the slow way.", path); } - using (var wand = new MagickWand(path)) + using (var wand = new MagickWand()) { + wand.PingImage(path); var img = wand.CurrentImage; return new ImageSize diff --git a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs index a45757d135..6ce989b029 100644 --- a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs +++ b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs @@ -1,6 +1,7 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Entities; +using System; using System.Collections.Generic; using System.Linq; @@ -47,5 +48,59 @@ namespace MediaBrowser.Server.Implementations.Library { return true; } + + public IEnumerable GetMediaStreams(string mediaSourceId) + { + var list = GetMediaStreams(new MediaStreamQuery + { + ItemId = new Guid(mediaSourceId) + }); + + return GetMediaStreamsForItem(list); + } + + public IEnumerable GetMediaStreams(Guid itemId) + { + var list = GetMediaStreams(new MediaStreamQuery + { + ItemId = itemId + }); + + return GetMediaStreamsForItem(list); + } + + private IEnumerable GetMediaStreamsForItem(IEnumerable streams) + { + var list = streams.ToList(); + + var subtitleStreams = list + .Where(i => i.Type == MediaStreamType.Subtitle) + .ToList(); + + if (subtitleStreams.Count > 0) + { + var videoStream = list.FirstOrDefault(i => i.Type == MediaStreamType.Video); + + // This is abitrary but at some point it becomes too slow to extract subtitles on the fly + // We need to learn more about when this is the case vs. when it isn't + const int maxAllowedBitrateForExternalSubtitleStream = 10000000; + + var videoBitrate = videoStream == null ? maxAllowedBitrateForExternalSubtitleStream : videoStream.BitRate ?? maxAllowedBitrateForExternalSubtitleStream; + + foreach (var subStream in subtitleStreams) + { + var supportsExternalStream = StreamSupportsExternalStream(subStream); + + if (supportsExternalStream && videoBitrate >= maxAllowedBitrateForExternalSubtitleStream) + { + supportsExternalStream = false; + } + + subStream.SupportsExternalStream = supportsExternalStream; + } + } + + return list; + } } } diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index a265ffdf1d..54df9a86d5 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -278,6 +278,7 @@ + diff --git a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs index e1f98c6592..40b85dad10 100644 --- a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs @@ -108,7 +108,12 @@ namespace MediaBrowser.Server.Implementations.Photos protected Task GetThumbCollage(List items) { - return DynamicImageHelpers.GetThumbCollage(items.Select(i => i.GetImagePath(ImageType.Primary) ?? i.GetImagePath(ImageType.Thumb)).ToList(), + var files = items + .Select(i => i.GetImagePath(ImageType.Primary) ?? i.GetImagePath(ImageType.Thumb)) + .Where(i => !string.IsNullOrWhiteSpace(i)) + .ToList(); + + return DynamicImageHelpers.GetThumbCollage(files, FileSystem, 1600, 900, @@ -117,7 +122,12 @@ namespace MediaBrowser.Server.Implementations.Photos protected Task GetSquareCollage(List items) { - return DynamicImageHelpers.GetSquareCollage(items.Select(i => i.GetImagePath(ImageType.Primary) ?? i.GetImagePath(ImageType.Thumb)).ToList(), + var files = items + .Select(i => i.GetImagePath(ImageType.Primary) ?? i.GetImagePath(ImageType.Thumb)) + .Where(i => !string.IsNullOrWhiteSpace(i)) + .ToList(); + + return DynamicImageHelpers.GetSquareCollage(files, FileSystem, 800, ApplicationPaths); } diff --git a/MediaBrowser.Server.Implementations/Photos/DynamicImageHelpers.cs b/MediaBrowser.Server.Implementations/Photos/DynamicImageHelpers.cs index c2af9cdafc..e7cd2f4d26 100644 --- a/MediaBrowser.Server.Implementations/Photos/DynamicImageHelpers.cs +++ b/MediaBrowser.Server.Implementations/Photos/DynamicImageHelpers.cs @@ -4,6 +4,7 @@ using MediaBrowser.Common.IO; using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.Photos @@ -15,6 +16,11 @@ namespace MediaBrowser.Server.Implementations.Photos int width, int height, IApplicationPaths appPaths) { + if (files.Any(string.IsNullOrWhiteSpace)) + { + throw new ArgumentException("Empty file found in files list"); + } + if (files.Count < 3) { return await GetSingleImage(files, fileSystem).ConfigureAwait(false); @@ -27,7 +33,7 @@ namespace MediaBrowser.Server.Implementations.Photos int cellHeight = height; var index = 0; - using (var wand = new MagickWand(width, height, "transparent")) + using (var wand = new MagickWand(width, height, new PixelWand(ColorName.None, 1))) { for (var row = 0; row < rows; row++) { @@ -57,6 +63,11 @@ namespace MediaBrowser.Server.Implementations.Photos IFileSystem fileSystem, int size, IApplicationPaths appPaths) { + if (files.Any(string.IsNullOrWhiteSpace)) + { + throw new ArgumentException("Empty file found in files list"); + } + if (files.Count < 4) { return await GetSingleImage(files, fileSystem).ConfigureAwait(false); @@ -68,7 +79,7 @@ namespace MediaBrowser.Server.Implementations.Photos int singleSize = size / 2; var index = 0; - using (var wand = new MagickWand(size, size, "transparent")) + using (var wand = new MagickWand(size, size, new PixelWand(ColorName.None, 1))) { for (var row = 0; row < rows; row++) { diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index 3ffbf5cb90..8eef8536ab 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -1579,11 +1579,7 @@ namespace MediaBrowser.Server.Implementations.Session if (!string.IsNullOrWhiteSpace(mediaSourceId)) { - info.MediaStreams = _mediaSourceManager.GetMediaStreams(new MediaStreamQuery - { - ItemId = new Guid(mediaSourceId) - - }).ToList(); + info.MediaStreams = _mediaSourceManager.GetMediaStreams(mediaSourceId).ToList(); } return info; diff --git a/MediaBrowser.Server.Implementations/Sorting/DateLastMediaAddedComparer.cs b/MediaBrowser.Server.Implementations/Sorting/DateLastMediaAddedComparer.cs new file mode 100644 index 0000000000..68cd44ec94 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Sorting/DateLastMediaAddedComparer.cs @@ -0,0 +1,70 @@ +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Sorting; +using MediaBrowser.Model.Querying; +using System; +using System.Linq; + +namespace MediaBrowser.Server.Implementations.Sorting +{ + public class DateLastMediaAddedComparer : IUserBaseItemComparer + { + /// + /// Gets or sets the user. + /// + /// The user. + public User User { get; set; } + + /// + /// Gets or sets the user manager. + /// + /// The user manager. + public IUserManager UserManager { get; set; } + + /// + /// Gets or sets the user data repository. + /// + /// The user data repository. + public IUserDataManager UserDataRepository { get; set; } + + /// + /// Compares the specified x. + /// + /// The x. + /// The y. + /// System.Int32. + public int Compare(BaseItem x, BaseItem y) + { + return GetDate(x).CompareTo(GetDate(y)); + } + + /// + /// Gets the date. + /// + /// The x. + /// DateTime. + private DateTime GetDate(BaseItem x) + { + var folder = x as Folder; + + if (folder != null) + { + return folder.GetRecursiveChildren(User, i => !i.IsFolder) + .Select(i => i.DateCreated) + .OrderByDescending(i => i) + .FirstOrDefault(); + } + + return x.DateCreated; + } + + /// + /// Gets the name. + /// + /// The name. + public string Name + { + get { return ItemSortBy.DateLastContentAdded; } + } + } +} diff --git a/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs b/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs index 7605a7a50d..c881591beb 100644 --- a/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs +++ b/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs @@ -1,6 +1,5 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Querying; using System;