From ed8159117519209418d04e293e116ad4b6711492 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 27 Aug 2017 20:33:05 -0400 Subject: update dto methods --- MediaBrowser.Api/UserLibrary/ItemsService.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'MediaBrowser.Api/UserLibrary/ItemsService.cs') diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index 9dd5aa565..2f946e35a 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -84,14 +84,14 @@ namespace MediaBrowser.Api.UserLibrary /// /// The request. /// System.Object. - public async Task Get(GetItems request) + public object Get(GetItems request) { if (request == null) { throw new ArgumentNullException("request"); } - var result = await GetItems(request).ConfigureAwait(false); + var result = GetItems(request); return ToOptimizedSerializedResultUsingCache(result); } @@ -100,8 +100,7 @@ namespace MediaBrowser.Api.UserLibrary /// Gets the items. /// /// The request. - /// Task{ItemsResult}. - private async Task> GetItems(GetItems request) + private QueryResult GetItems(GetItems request) { var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null; @@ -119,7 +118,7 @@ namespace MediaBrowser.Api.UserLibrary throw new InvalidOperationException("GetItemsToSerialize result.Items returned null"); } - var dtoList = await _dtoService.GetBaseItemDtos(result.Items, dtoOptions, user).ConfigureAwait(false); + var dtoList = _dtoService.GetBaseItemDtos(result.Items, dtoOptions, user); if (dtoList == null) { -- cgit v1.2.3 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 --- Emby.Dlna/ContentDirectory/ControlHandler.cs | 18 ++++--- .../Channels/ChannelManager.cs | 13 ++--- .../Data/SqliteItemRepository.cs | 18 ++----- .../HttpServer/FileWriter.cs | 3 ++ .../Library/LibraryManager.cs | 34 ++++++++++++- .../Library/MusicManager.cs | 3 +- .../Library/SearchEngine.cs | 3 +- .../Library/UserViewManager.cs | 3 +- .../LiveTv/EmbyTV/EmbyTV.cs | 3 +- .../LiveTv/LiveTvManager.cs | 34 ++++++------- .../Playlists/PlaylistImageProvider.cs | 7 +-- Emby.Server.Implementations/TV/TVSeriesManager.cs | 12 ++--- .../UserViews/CollectionFolderImageProvider.cs | 2 +- MediaBrowser.Api/ChannelService.cs | 15 ++++-- MediaBrowser.Api/LiveTv/LiveTvService.cs | 6 +-- MediaBrowser.Api/Movies/MoviesService.cs | 6 +-- MediaBrowser.Api/Reports/ReportsService.cs | 3 +- MediaBrowser.Api/SuggestionsService.cs | 4 +- MediaBrowser.Api/TvShowsService.cs | 3 +- .../UserLibrary/BaseItemsByNameService.cs | 2 +- MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs | 35 ++++++++++++-- MediaBrowser.Api/UserLibrary/ItemsService.cs | 3 +- MediaBrowser.Controller/Channels/Channel.cs | 3 +- MediaBrowser.Controller/Entities/Folder.cs | 7 ++- .../Entities/InternalItemsQuery.cs | 9 +--- MediaBrowser.Controller/Entities/TV/Series.cs | 12 ++--- .../Entities/UserViewBuilder.cs | 18 +++---- MediaBrowser.Controller/Library/ILibraryManager.cs | 4 +- MediaBrowser.Controller/Playlists/Playlist.cs | 8 ++-- MediaBrowser.Model/Channels/ChannelItemQuery.cs | 9 ++-- MediaBrowser.Model/LiveTv/ProgramQuery.cs | 14 +----- Nuget/MediaBrowser.Common.nuspec | 2 +- Nuget/MediaBrowser.Server.Core.nuspec | 4 +- .../Net/HttpResponseStream.Managed.cs | 56 ++++++++++++++++++++++ 34 files changed, 229 insertions(+), 147 deletions(-) (limited to 'MediaBrowser.Api/UserLibrary/ItemsService.cs') diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs index 205f4e890..47d199e6e 100644 --- a/Emby.Dlna/ContentDirectory/ControlHandler.cs +++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs @@ -458,8 +458,7 @@ namespace Emby.Dlna.ContentDirectory { Limit = limit, StartIndex = startIndex, - SortBy = sortOrders.ToArray(sortOrders.Count), - SortOrder = sort.SortOrder, + OrderBy = sortOrders.Select(i => new Tuple(i, sort.SortOrder)).ToArray(), User = user, Recursive = true, IsMissing = false, @@ -828,7 +827,7 @@ namespace Emby.Dlna.ContentDirectory query.Parent = parent; query.SetUser(user); - query.OrderBy = new List> + query.OrderBy = new Tuple[] { new Tuple (ItemSortBy.DatePlayed, SortOrder.Descending), new Tuple (ItemSortBy.SortName, SortOrder.Ascending) @@ -1077,7 +1076,7 @@ namespace Emby.Dlna.ContentDirectory private QueryResult GetMusicLatest(BaseItem parent, User user, InternalItemsQuery query) { - query.SortBy = new string[] { }; + query.OrderBy = new Tuple[] { }; var items = _userViewManager.GetLatestItems(new LatestItemsQuery { @@ -1094,7 +1093,7 @@ namespace Emby.Dlna.ContentDirectory private QueryResult GetNextUp(BaseItem parent, User user, InternalItemsQuery query) { - query.SortBy = new string[] { }; + query.OrderBy = new Tuple[] { }; var result = _tvSeriesManager.GetNextUp(new NextUpQuery { @@ -1109,7 +1108,7 @@ namespace Emby.Dlna.ContentDirectory private QueryResult GetTvLatest(BaseItem parent, User user, InternalItemsQuery query) { - query.SortBy = new string[] { }; + query.OrderBy = new Tuple[] { }; var items = _userViewManager.GetLatestItems(new LatestItemsQuery { @@ -1126,7 +1125,7 @@ namespace Emby.Dlna.ContentDirectory private QueryResult GetMovieLatest(BaseItem parent, User user, InternalItemsQuery query) { - query.SortBy = new string[] { }; + query.OrderBy = new Tuple[] { }; var items = _userViewManager.GetLatestItems(new LatestItemsQuery { @@ -1236,8 +1235,7 @@ namespace Emby.Dlna.ContentDirectory sortOrders.Add(ItemSortBy.SortName); } - query.SortBy = sortOrders.ToArray(sortOrders.Count); - query.SortOrder = sort.SortOrder; + query.OrderBy = sortOrders.Select(i => new Tuple(i, sort.SortOrder)).ToArray(); } private QueryResult GetItemsFromPerson(Person person, User user, int? startIndex, int? limit) @@ -1246,7 +1244,7 @@ namespace Emby.Dlna.ContentDirectory { PersonIds = new[] { person.Id.ToString("N") }, IncludeItemTypes = new[] { typeof(Movie).Name, typeof(Series).Name, typeof(Trailer).Name }, - SortBy = new[] { ItemSortBy.SortName }, + OrderBy = new[] { ItemSortBy.SortName }.Select(i => new Tuple(i, SortOrder.Ascending)).ToArray(), Limit = limit, StartIndex = startIndex, DtoOptions = GetDtoOptions() diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index 1a90c85ee..e842005a5 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -466,7 +466,7 @@ namespace Emby.Server.Implementations.Channels return _libraryManager.GetItemIds(new InternalItemsQuery { IncludeItemTypes = new[] { typeof(Channel).Name }, - SortBy = new[] { ItemSortBy.SortName } + OrderBy = new Tuple[] { new Tuple(ItemSortBy.SortName, SortOrder.Ascending) } }).Select(i => GetChannelFeatures(i.ToString("N"))).ToArray(); } @@ -932,14 +932,15 @@ namespace Emby.Server.Implementations.Channels ChannelItemSortField? sortField = null; ChannelItemSortField parsedField; - if (query.SortBy.Length == 1 && - Enum.TryParse(query.SortBy[0], true, out parsedField)) + var sortDescending = false; + + if (query.OrderBy.Length == 1 && + Enum.TryParse(query.OrderBy[0].Item1, true, out parsedField)) { sortField = parsedField; + sortDescending = query.OrderBy[0].Item2 == SortOrder.Descending; } - var sortDescending = query.SortOrder.HasValue && query.SortOrder.Value == SortOrder.Descending; - var itemsResult = await GetChannelItems(channelProvider, user, query.FolderId, @@ -1166,7 +1167,7 @@ namespace Emby.Server.Implementations.Channels { items = ApplyFilters(items, query.Filters, user); - items = _libraryManager.Sort(items, user, query.SortBy, query.SortOrder ?? SortOrder.Ascending); + items = _libraryManager.Sort(items, user, query.OrderBy); var all = items.ToList(); var totalCount = totalCountFromProvider ?? all.Count; 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) { diff --git a/Emby.Server.Implementations/HttpServer/FileWriter.cs b/Emby.Server.Implementations/HttpServer/FileWriter.cs index 8cb7b5dbf..aa679e1b9 100644 --- a/Emby.Server.Implementations/HttpServer/FileWriter.cs +++ b/Emby.Server.Implementations/HttpServer/FileWriter.cs @@ -160,6 +160,9 @@ namespace Emby.Server.Implementations.HttpServer if (string.IsNullOrWhiteSpace(RangeHeader) || (RangeStart <= 0 && RangeEnd >= TotalContentLength - 1)) { Logger.Info("Transmit file {0}", Path); + + //var count = FileShare == FileShareMode.ReadWrite ? TotalContentLength : 0; + await response.TransmitFile(Path, 0, 0, FileShare, cancellationToken).ConfigureAwait(false); return; } diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 57e42985d..8c5ecf782 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -846,8 +846,7 @@ namespace Emby.Server.Implementations.Library { Path = path, IsFolder = isFolder, - SortBy = new[] { ItemSortBy.DateCreated }, - SortOrder = SortOrder.Descending, + OrderBy = new[] { ItemSortBy.DateCreated }.Select(i => new Tuple(i, SortOrder.Descending)).ToArray(), Limit = 1, DtoOptions = new DtoOptions(true) }; @@ -1777,6 +1776,37 @@ namespace Emby.Server.Implementations.Library return orderedItems ?? items; } + public IEnumerable Sort(IEnumerable items, User user, IEnumerable> orderByList) + { + var isFirst = true; + + IOrderedEnumerable orderedItems = null; + + foreach (var orderBy in orderByList) + { + var comparer = GetComparer(orderBy.Item1, user); + if (comparer == null) + { + continue; + } + + var sortOrder = orderBy.Item2; + + if (isFirst) + { + orderedItems = sortOrder == SortOrder.Descending ? items.OrderByDescending(i => i, comparer) : items.OrderBy(i => i, comparer); + } + else + { + orderedItems = sortOrder == SortOrder.Descending ? orderedItems.ThenByDescending(i => i, comparer) : orderedItems.ThenBy(i => i, comparer); + } + + isFirst = false; + } + + return orderedItems ?? items; + } + /// /// Gets the comparer. /// diff --git a/Emby.Server.Implementations/Library/MusicManager.cs b/Emby.Server.Implementations/Library/MusicManager.cs index 7f77170ad..1cbf4235a 100644 --- a/Emby.Server.Implementations/Library/MusicManager.cs +++ b/Emby.Server.Implementations/Library/MusicManager.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Linq; using MediaBrowser.Controller.Dto; +using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; namespace Emby.Server.Implementations.Library @@ -88,7 +89,7 @@ namespace Emby.Server.Implementations.Library Limit = 200, - SortBy = new[] { ItemSortBy.Random }, + OrderBy = new [] { new Tuple(ItemSortBy.Random, SortOrder.Ascending) }, DtoOptions = dtoOptions diff --git a/Emby.Server.Implementations/Library/SearchEngine.cs b/Emby.Server.Implementations/Library/SearchEngine.cs index d4c4f2794..b1ed034ca 100644 --- a/Emby.Server.Implementations/Library/SearchEngine.cs +++ b/Emby.Server.Implementations/Library/SearchEngine.cs @@ -10,6 +10,7 @@ using System.Linq; using System.Threading.Tasks; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Extensions; +using MediaBrowser.Model.Entities; using MediaBrowser.Model.Extensions; namespace Emby.Server.Implementations.Library @@ -169,7 +170,7 @@ namespace Emby.Server.Implementations.Library Limit = query.Limit, IncludeItemsByName = string.IsNullOrWhiteSpace(query.ParentId), ParentId = string.IsNullOrWhiteSpace(query.ParentId) ? (Guid?)null : new Guid(query.ParentId), - SortBy = new[] { ItemSortBy.SortName }, + OrderBy = new[] { new Tuple(ItemSortBy.SortName, SortOrder.Ascending) }, Recursive = true, IsKids = query.IsKids, diff --git a/Emby.Server.Implementations/Library/UserViewManager.cs b/Emby.Server.Implementations/Library/UserViewManager.cs index b02c114bb..8c9377291 100644 --- a/Emby.Server.Implementations/Library/UserViewManager.cs +++ b/Emby.Server.Implementations/Library/UserViewManager.cs @@ -319,8 +319,7 @@ namespace Emby.Server.Implementations.Library var query = new InternalItemsQuery(user) { IncludeItemTypes = includeItemTypes, - SortOrder = SortOrder.Descending, - SortBy = new[] { ItemSortBy.DateCreated }, + OrderBy = new[] { new Tuple(ItemSortBy.DateCreated, SortOrder.Descending) }, IsFolder = includeItemTypes.Length == 0 ? false : (bool?)null, ExcludeItemTypes = excludeItemTypes, IsVirtualItem = false, diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index f1694efb4..885e3b0ee 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1687,8 +1687,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV var episodesToDelete = (librarySeries.GetItemList(new InternalItemsQuery { - SortBy = new[] { ItemSortBy.DateCreated }, - SortOrder = SortOrder.Descending, + OrderBy = new[] { new Tuple(ItemSortBy.DateCreated, SortOrder.Descending) }, IsVirtualItem = false, IsFolder = false, Recursive = true, diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 185935e88..089af2a01 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -187,7 +187,6 @@ namespace Emby.Server.Implementations.LiveTv IsSports = query.IsSports, IsSeries = query.IsSeries, IncludeItemTypes = new[] { typeof(LiveTvChannel).Name }, - SortOrder = query.SortOrder ?? SortOrder.Ascending, TopParentIds = new[] { topFolder.Id.ToString("N") }, IsFavorite = query.IsFavorite, IsLiked = query.IsLiked, @@ -196,18 +195,22 @@ namespace Emby.Server.Implementations.LiveTv DtoOptions = dtoOptions }; - internalQuery.OrderBy.AddRange(query.SortBy.Select(i => new Tuple(i, query.SortOrder ?? SortOrder.Ascending))); + var orderBy = internalQuery.OrderBy.ToList(); + + orderBy.AddRange(query.SortBy.Select(i => new Tuple(i, query.SortOrder ?? SortOrder.Ascending))); if (query.EnableFavoriteSorting) { - internalQuery.OrderBy.Insert(0, new Tuple(ItemSortBy.IsFavoriteOrLiked, SortOrder.Descending)); + orderBy.Insert(0, new Tuple(ItemSortBy.IsFavoriteOrLiked, SortOrder.Descending)); } if (!internalQuery.OrderBy.Any(i => string.Equals(i.Item1, ItemSortBy.SortName, StringComparison.OrdinalIgnoreCase))) { - internalQuery.OrderBy.Add(new Tuple(ItemSortBy.SortName, SortOrder.Ascending)); + orderBy.Add(new Tuple(ItemSortBy.SortName, SortOrder.Ascending)); } + internalQuery.OrderBy = orderBy.ToArray(); + return _libraryManager.GetItemsResult(internalQuery); } @@ -918,10 +921,10 @@ namespace Emby.Server.Implementations.LiveTv var topFolder = await GetInternalLiveTvFolder(cancellationToken).ConfigureAwait(false); - if (query.SortBy.Length == 0) + if (query.OrderBy.Length == 0) { // Unless something else was specified, order by start date to take advantage of a specialized index - query.SortBy = new[] { ItemSortBy.StartDate }; + query.OrderBy = new Tuple[] { new Tuple(ItemSortBy.StartDate, SortOrder.Ascending) }; } RemoveFields(options); @@ -942,8 +945,7 @@ namespace Emby.Server.Implementations.LiveTv Genres = query.Genres, StartIndex = query.StartIndex, Limit = query.Limit, - SortBy = query.SortBy, - SortOrder = query.SortOrder ?? SortOrder.Ascending, + OrderBy = query.OrderBy, EnableTotalRecordCount = query.EnableTotalRecordCount, TopParentIds = new[] { topFolder.Id.ToString("N") }, Name = query.Name, @@ -1012,7 +1014,7 @@ namespace Emby.Server.Implementations.LiveTv IsSports = query.IsSports, IsKids = query.IsKids, EnableTotalRecordCount = query.EnableTotalRecordCount, - SortBy = new[] { ItemSortBy.StartDate }, + OrderBy = new[] { new Tuple(ItemSortBy.StartDate, SortOrder.Ascending) }, TopParentIds = new[] { topFolder.Id.ToString("N") }, DtoOptions = options }; @@ -1644,8 +1646,7 @@ namespace Emby.Server.Implementations.LiveTv IsVirtualItem = false, Limit = query.Limit, StartIndex = query.StartIndex, - SortBy = new[] { ItemSortBy.DateCreated }, - SortOrder = SortOrder.Descending, + OrderBy = new[] { new Tuple(ItemSortBy.DateCreated, SortOrder.Descending) }, EnableTotalRecordCount = query.EnableTotalRecordCount, IncludeItemTypes = includeItemTypes.ToArray(includeItemTypes.Count), ExcludeItemTypes = excludeItemTypes.ToArray(excludeItemTypes.Count), @@ -1692,8 +1693,7 @@ namespace Emby.Server.Implementations.LiveTv Recursive = true, AncestorIds = folders.Select(i => i.Id.ToString("N")).ToArray(folders.Count), Limit = query.Limit, - SortBy = new[] { ItemSortBy.DateCreated }, - SortOrder = SortOrder.Descending, + OrderBy = new[] { new Tuple(ItemSortBy.DateCreated, SortOrder.Descending) }, EnableTotalRecordCount = query.EnableTotalRecordCount, IncludeItemTypes = includeItemTypes.ToArray(includeItemTypes.Count), ExcludeItemTypes = excludeItemTypes.ToArray(excludeItemTypes.Count), @@ -1927,11 +1927,11 @@ namespace Emby.Server.Implementations.LiveTv var info = recording; - dto.SeriesTimerId = string.IsNullOrEmpty(info.SeriesTimerId) + dto.SeriesTimerId = string.IsNullOrEmpty(info.SeriesTimerId) || service == null ? null : _tvDtoService.GetInternalSeriesTimerId(service.Name, info.SeriesTimerId).ToString("N"); - dto.TimerId = string.IsNullOrEmpty(info.TimerId) + dto.TimerId = string.IsNullOrEmpty(info.TimerId) || service == null ? null : _tvDtoService.GetInternalTimerId(service.Name, info.TimerId).ToString("N"); @@ -2037,7 +2037,7 @@ namespace Emby.Server.Implementations.LiveTv var internalResult = await GetInternalRecordings(query, options, cancellationToken).ConfigureAwait(false); - var returnArray = _dtoService.GetBaseItemDtos(internalResult.Items, options, user); + var returnArray = _dtoService.GetBaseItemDtos(internalResult.Items, options, user); return new QueryResult { @@ -2377,7 +2377,7 @@ namespace Emby.Server.Implementations.LiveTv MaxStartDate = now, MinEndDate = now, Limit = channelIds.Length, - SortBy = new[] { "StartDate" }, + OrderBy = new[] { new Tuple(ItemSortBy.StartDate, SortOrder.Ascending) }, TopParentIds = new[] { GetInternalLiveTvFolder(CancellationToken.None).Result.Id.ToString("N") }, DtoOptions = options diff --git a/Emby.Server.Implementations/Playlists/PlaylistImageProvider.cs b/Emby.Server.Implementations/Playlists/PlaylistImageProvider.cs index c2e860339..525df0350 100644 --- a/Emby.Server.Implementations/Playlists/PlaylistImageProvider.cs +++ b/Emby.Server.Implementations/Playlists/PlaylistImageProvider.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.Configuration; +using System; +using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; @@ -86,7 +87,7 @@ namespace Emby.Server.Implementations.Playlists { Genres = new[] { item.Name }, IncludeItemTypes = new[] { typeof(MusicAlbum).Name, typeof(MusicVideo).Name, typeof(Audio).Name }, - SortBy = new[] { ItemSortBy.Random }, + OrderBy = new[] { new Tuple(ItemSortBy.Random, SortOrder.Ascending) }, Limit = 4, Recursive = true, ImageTypes = new[] { ImageType.Primary }, @@ -118,7 +119,7 @@ namespace Emby.Server.Implementations.Playlists { Genres = new[] { item.Name }, IncludeItemTypes = new[] { typeof(Series).Name, typeof(Movie).Name }, - SortBy = new[] { ItemSortBy.Random }, + OrderBy = new[] { new Tuple(ItemSortBy.Random, SortOrder.Ascending) }, Limit = 4, Recursive = true, ImageTypes = new[] { ImageType.Primary }, diff --git a/Emby.Server.Implementations/TV/TVSeriesManager.cs b/Emby.Server.Implementations/TV/TVSeriesManager.cs index 018e452be..0b81f7e93 100644 --- a/Emby.Server.Implementations/TV/TVSeriesManager.cs +++ b/Emby.Server.Implementations/TV/TVSeriesManager.cs @@ -64,8 +64,7 @@ namespace Emby.Server.Implementations.TV var items = _libraryManager.GetItemList(new InternalItemsQuery(user) { IncludeItemTypes = new[] { typeof(Episode).Name }, - SortBy = new[] { ItemSortBy.DatePlayed }, - SortOrder = SortOrder.Descending, + OrderBy = new[] { new Tuple(ItemSortBy.DatePlayed, SortOrder.Descending) }, SeriesPresentationUniqueKey = presentationUniqueKey, Limit = limit, ParentId = parentIdGuid, @@ -122,8 +121,7 @@ namespace Emby.Server.Implementations.TV var items = _libraryManager.GetItemList(new InternalItemsQuery(user) { IncludeItemTypes = new[] { typeof(Episode).Name }, - SortBy = new[] { ItemSortBy.DatePlayed }, - SortOrder = SortOrder.Descending, + OrderBy = new[] { new Tuple(ItemSortBy.DatePlayed, SortOrder.Descending) }, SeriesPresentationUniqueKey = presentationUniqueKey, Limit = limit, DtoOptions = new MediaBrowser.Controller.Dto.DtoOptions @@ -200,8 +198,7 @@ namespace Emby.Server.Implementations.TV AncestorWithPresentationUniqueKey = null, SeriesPresentationUniqueKey = seriesKey, IncludeItemTypes = new[] { typeof(Episode).Name }, - SortBy = new[] { ItemSortBy.SortName }, - SortOrder = SortOrder.Descending, + OrderBy = new[] { new Tuple(ItemSortBy.SortName, SortOrder.Descending) }, IsPlayed = true, Limit = 1, ParentIndexNumberNotEquals = 0, @@ -223,8 +220,7 @@ namespace Emby.Server.Implementations.TV AncestorWithPresentationUniqueKey = null, SeriesPresentationUniqueKey = seriesKey, IncludeItemTypes = new[] { typeof(Episode).Name }, - SortBy = new[] { ItemSortBy.SortName }, - SortOrder = SortOrder.Ascending, + OrderBy = new[] { new Tuple(ItemSortBy.SortName, SortOrder.Ascending) }, Limit = 1, IsPlayed = false, IsVirtualItem = false, diff --git a/Emby.Server.Implementations/UserViews/CollectionFolderImageProvider.cs b/Emby.Server.Implementations/UserViews/CollectionFolderImageProvider.cs index 98e0c4080..fa1d5b74e 100644 --- a/Emby.Server.Implementations/UserViews/CollectionFolderImageProvider.cs +++ b/Emby.Server.Implementations/UserViews/CollectionFolderImageProvider.cs @@ -145,7 +145,7 @@ namespace Emby.Server.Implementations.UserViews Recursive = recursive, IncludeItemTypes = new[] { typeof(BoxSet).Name }, Limit = 20, - SortBy = new[] { ItemSortBy.Random }, + OrderBy = new [] { new Tuple(ItemSortBy.Random, SortOrder.Ascending) }, DtoOptions = new DtoOptions(false) }); diff --git a/MediaBrowser.Api/ChannelService.cs b/MediaBrowser.Api/ChannelService.cs index 35ac2b482..d64bf7ec7 100644 --- a/MediaBrowser.Api/ChannelService.cs +++ b/MediaBrowser.Api/ChannelService.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Api.UserLibrary; using MediaBrowser.Model.Services; namespace MediaBrowser.Api @@ -90,7 +91,7 @@ namespace MediaBrowser.Api public int? Limit { get; set; } [ApiMember(Name = "SortOrder", Description = "Sort Order - Ascending,Descending", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] - public SortOrder? SortOrder { get; set; } + public string SortOrder { get; set; } [ApiMember(Name = "Filters", Description = "Optional. Specify additional filters to apply. This allows multiple, comma delimeted. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] public string Filters { get; set; } @@ -116,6 +117,15 @@ namespace MediaBrowser.Api return val.Split(',').Select(v => (ItemFilter)Enum.Parse(typeof(ItemFilter), v, true)); } + + /// + /// Gets the order by. + /// + /// IEnumerable{ItemSortBy}. + public Tuple[] GetOrderBy() + { + return BaseItemsRequest.GetOrderBy(SortBy, SortOrder); + } } [Route("/Channels/Items/Latest", "GET", Summary = "Gets channel items")] @@ -228,8 +238,7 @@ namespace MediaBrowser.Api UserId = request.UserId, ChannelId = request.Id, FolderId = request.FolderId, - SortOrder = request.SortOrder, - SortBy = (request.SortBy ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToArray(), + OrderBy = request.GetOrderBy(), Filters = request.GetFilters().ToArray(), Fields = request.GetItemFields() diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index 81b0894ac..36bcee913 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -15,6 +15,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Api.UserLibrary; using MediaBrowser.Model.IO; using MediaBrowser.Controller.Configuration; @@ -373,7 +374,7 @@ namespace MediaBrowser.Api.LiveTv public string SortBy { get; set; } [ApiMember(Name = "SortOrder", Description = "Sort Order - Ascending,Descending", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] - public SortOrder? SortOrder { get; set; } + public string SortOrder { get; set; } [ApiMember(Name = "Genres", Description = "The genres to return guide information for.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")] public string Genres { get; set; } @@ -994,8 +995,7 @@ namespace MediaBrowser.Api.LiveTv query.StartIndex = request.StartIndex; query.Limit = request.Limit; - query.SortBy = (request.SortBy ?? String.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - query.SortOrder = request.SortOrder; + query.OrderBy = BaseItemsRequest.GetOrderBy(request.SortBy, request.SortOrder); query.IsNews = request.IsNews; query.IsMovie = request.IsMovie; query.IsSeries = request.IsSeries; diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs index 9157e6d89..254c93b33 100644 --- a/MediaBrowser.Api/Movies/MoviesService.cs +++ b/MediaBrowser.Api/Movies/MoviesService.cs @@ -193,8 +193,7 @@ namespace MediaBrowser.Api.Movies //typeof(LiveTvProgram).Name }, // IsMovie = true - SortBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.Random }, - SortOrder = SortOrder.Descending, + OrderBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.Random }.Select(i => new Tuple(i, SortOrder.Descending)).ToArray(), Limit = 7, ParentId = parentIdGuid, Recursive = true, @@ -215,8 +214,7 @@ namespace MediaBrowser.Api.Movies { IncludeItemTypes = itemTypes.ToArray(itemTypes.Count), IsMovie = true, - SortBy = new[] { ItemSortBy.Random }, - SortOrder = SortOrder.Descending, + OrderBy = new[] { ItemSortBy.Random }.Select(i => new Tuple(i, SortOrder.Descending)).ToArray(), Limit = 10, IsFavoriteOrLiked = true, ExcludeItemIds = recentlyPlayedMovies.Select(i => i.Id.ToString("N")).ToArray(recentlyPlayedMovies.Count), diff --git a/MediaBrowser.Api/Reports/ReportsService.cs b/MediaBrowser.Api/Reports/ReportsService.cs index 76d282990..a100b91e6 100644 --- a/MediaBrowser.Api/Reports/ReportsService.cs +++ b/MediaBrowser.Api/Reports/ReportsService.cs @@ -176,8 +176,7 @@ namespace MediaBrowser.Api.Reports IncludeItemTypes = request.GetIncludeItemTypes(), ExcludeItemTypes = request.GetExcludeItemTypes(), Recursive = request.Recursive, - SortBy = request.GetOrderBy(), - SortOrder = request.SortOrder ?? SortOrder.Ascending, + OrderBy = request.GetOrderBy(), IsFavorite = request.IsFavorite, Limit = request.Limit, diff --git a/MediaBrowser.Api/SuggestionsService.cs b/MediaBrowser.Api/SuggestionsService.cs index 616e22519..3b918d8a2 100644 --- a/MediaBrowser.Api/SuggestionsService.cs +++ b/MediaBrowser.Api/SuggestionsService.cs @@ -5,8 +5,10 @@ using MediaBrowser.Model.Dto; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Services; using System; +using System.Linq; using System.Threading.Tasks; using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Entities; using MediaBrowser.Model.Extensions; namespace MediaBrowser.Api @@ -79,7 +81,7 @@ namespace MediaBrowser.Api { return _libraryManager.GetItemsResult(new InternalItemsQuery(user) { - SortBy = new string[] { ItemSortBy.Random }, + OrderBy = new[] { ItemSortBy.Random }.Select(i => new Tuple(i, SortOrder.Descending)).ToArray(), MediaTypes = request.GetMediaTypes(), IncludeItemTypes = request.GetIncludeItemTypes(), IsVirtualItem = false, diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index 3d0116665..fd81a9a3e 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -347,8 +347,7 @@ namespace MediaBrowser.Api var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user) { IncludeItemTypes = new[] { typeof(Episode).Name }, - SortBy = new[] { "PremiereDate", "AirTime", "SortName" }, - SortOrder = SortOrder.Ascending, + OrderBy = new[] { ItemSortBy.PremiereDate, ItemSortBy.SortName }.Select(i => new Tuple(i, SortOrder.Ascending)).ToArray(), MinPremiereDate = minPremiereDate, StartIndex = request.StartIndex, Limit = request.Limit, diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs index fca842289..ed0c4069b 100644 --- a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs +++ b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs @@ -299,7 +299,7 @@ namespace MediaBrowser.Api.UserLibrary var filteredItems = FilterItems(request, extractedItems, user); - filteredItems = LibraryManager.Sort(filteredItems, user, request.GetOrderBy(), request.SortOrder ?? SortOrder.Ascending); + filteredItems = LibraryManager.Sort(filteredItems, user, request.GetOrderBy()); var ibnItemsArray = filteredItems.ToList(); diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs index 66aa35de9..88d080db5 100644 --- a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs +++ b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs @@ -136,7 +136,7 @@ namespace MediaBrowser.Api.UserLibrary /// /// The sort order. [ApiMember(Name = "SortOrder", Description = "Sort Order - Ascending,Descending", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] - public SortOrder? SortOrder { get; set; } + public string SortOrder { get; set; } /// /// Specify this to localize the search to a specific item or folder. Omit to use the root. @@ -467,16 +467,41 @@ namespace MediaBrowser.Api.UserLibrary /// Gets the order by. /// /// IEnumerable{ItemSortBy}. - public string[] GetOrderBy() + public Tuple[] GetOrderBy() { - var val = SortBy; + return GetOrderBy(SortBy, SortOrder); + } + + public static Tuple[] GetOrderBy(string sortBy, string requestedSortOrder) + { + var val = sortBy; if (string.IsNullOrEmpty(val)) { - return new string[] { }; + return new Tuple[] { }; + } + + var vals = val.Split(','); + if (string.IsNullOrWhiteSpace(requestedSortOrder)) + { + requestedSortOrder = "Ascending"; + } + + var sortOrders = requestedSortOrder.Split(','); + + var result = new Tuple[vals.Length]; + + for (var i = 0; i < vals.Length; i++) + { + var sortOrderIndex = sortOrders.Length > i ? i : 0; + + var sortOrderValue = sortOrders.Length > sortOrderIndex ? sortOrders[sortOrderIndex] : null; + var sortOrder = string.Equals(sortOrderValue, "Descending", StringComparison.OrdinalIgnoreCase) ? MediaBrowser.Model.Entities.SortOrder.Descending : MediaBrowser.Model.Entities.SortOrder.Ascending; + + result[i] = new Tuple(vals[i], sortOrder); } - return val.Split(','); + return result; } } } diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index 2f946e35a..fb48f65e4 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -198,8 +198,7 @@ namespace MediaBrowser.Api.UserLibrary IncludeItemTypes = request.GetIncludeItemTypes(), ExcludeItemTypes = request.GetExcludeItemTypes(), Recursive = request.Recursive, - SortBy = request.GetOrderBy(), - SortOrder = request.SortOrder ?? SortOrder.Ascending, + OrderBy = request.GetOrderBy(), IsFavorite = request.IsFavorite, Limit = request.Limit, diff --git a/MediaBrowser.Controller/Channels/Channel.cs b/MediaBrowser.Controller/Channels/Channel.cs index c6e750a0c..54faa1443 100644 --- a/MediaBrowser.Controller/Channels/Channel.cs +++ b/MediaBrowser.Controller/Channels/Channel.cs @@ -58,8 +58,7 @@ namespace MediaBrowser.Controller.Channels Limit = query.Limit, StartIndex = query.StartIndex, UserId = query.User.Id.ToString("N"), - SortBy = query.SortBy, - SortOrder = query.SortOrder + OrderBy = query.OrderBy }, new SimpleProgress(), CancellationToken.None).Result; } diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 8a87f3c6a..2e741a8c4 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -952,7 +952,7 @@ namespace MediaBrowser.Controller.Entities { var result = LibraryManager.GetItemsResult(query); - if (query.SortBy.Length == 0) + if (query.OrderBy.Length == 0) { var ids = query.ItemIds.ToList(); @@ -973,7 +973,7 @@ namespace MediaBrowser.Controller.Entities { var result = LibraryManager.GetItemList(query); - if (query.SortBy.Length == 0) + if (query.OrderBy.Length == 0) { var ids = query.ItemIds.ToList(); @@ -1000,8 +1000,7 @@ namespace MediaBrowser.Controller.Entities Limit = query.Limit, StartIndex = query.StartIndex, UserId = query.User.Id.ToString("N"), - SortBy = query.SortBy, - SortOrder = query.SortOrder + OrderBy = query.OrderBy }, new SimpleProgress(), CancellationToken.None).Result; } diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index 04833d049..03dc18b7a 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -16,10 +16,6 @@ namespace MediaBrowser.Controller.Entities public int? Limit { get; set; } - public string[] SortBy { get; set; } - - public SortOrder SortOrder { get; set; } - public User User { get; set; } public BaseItem SimilarTo { get; set; } @@ -165,7 +161,7 @@ namespace MediaBrowser.Controller.Entities public Dictionary ExcludeProviderIds { get; set; } public bool EnableGroupByMetadataKey { get; set; } - public List> OrderBy { get; set; } + public Tuple[] OrderBy { get; set; } public DateTime? MinDateCreated { get; set; } public DateTime? MinDateLastSaved { get; set; } @@ -190,7 +186,6 @@ namespace MediaBrowser.Controller.Entities BlockUnratedItems = new UnratedItem[] { }; Tags = new string[] { }; OfficialRatings = new string[] { }; - SortBy = new string[] { }; MediaTypes = new string[] { }; IncludeItemTypes = new string[] { }; ExcludeItemTypes = new string[] { }; @@ -213,7 +208,7 @@ namespace MediaBrowser.Controller.Entities TrailerTypes = new TrailerType[] { }; SourceTypes = new SourceType[] { }; SeriesStatuses = new SeriesStatus[] { }; - OrderBy = new List>(); + OrderBy = new Tuple[] { }; } public InternalItemsQuery(User user) diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 6514d31d2..60d2624fa 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -252,7 +252,7 @@ namespace MediaBrowser.Controller.Entities.TV query.AncestorWithPresentationUniqueKey = null; query.SeriesPresentationUniqueKey = seriesKey; query.IncludeItemTypes = new[] { typeof(Season).Name }; - query.SortBy = new[] {ItemSortBy.SortName}; + query.OrderBy = new[] { ItemSortBy.SortName }.Select(i => new Tuple(i, SortOrder.Ascending)).ToArray(); if (!config.DisplayMissingEpisodes) { @@ -275,9 +275,9 @@ namespace MediaBrowser.Controller.Entities.TV query.AncestorWithPresentationUniqueKey = null; query.SeriesPresentationUniqueKey = seriesKey; - if (query.SortBy.Length == 0) + if (query.OrderBy.Length == 0) { - query.SortBy = new[] { ItemSortBy.SortName }; + query.OrderBy = new[] { ItemSortBy.SortName }.Select(i => new Tuple(i, SortOrder.Ascending)).ToArray(); } if (query.IncludeItemTypes.Length == 0) { @@ -301,7 +301,7 @@ namespace MediaBrowser.Controller.Entities.TV AncestorWithPresentationUniqueKey = null, SeriesPresentationUniqueKey = seriesKey, IncludeItemTypes = new[] { typeof(Episode).Name, typeof(Season).Name }, - SortBy = new[] { ItemSortBy.SortName }, + OrderBy = new[] { ItemSortBy.SortName }.Select(i => new Tuple(i, SortOrder.Ascending)).ToArray(), DtoOptions = options }; var config = user.Configuration; @@ -410,7 +410,7 @@ namespace MediaBrowser.Controller.Entities.TV AncestorWithPresentationUniqueKey = queryFromSeries ? null : seriesKey, SeriesPresentationUniqueKey = queryFromSeries ? seriesKey : null, IncludeItemTypes = new[] { typeof(Episode).Name }, - SortBy = new[] { ItemSortBy.SortName }, + OrderBy = new[] { ItemSortBy.SortName }.Select(i => new Tuple(i, SortOrder.Ascending)).ToArray(), DtoOptions = options }; if (user != null) @@ -453,7 +453,7 @@ namespace MediaBrowser.Controller.Entities.TV return episodes.Where(episode => { - var episodeItem = (Episode) episode; + var episodeItem = (Episode)episode; var currentSeasonNumber = supportSpecialsInSeason ? episodeItem.AiredSeasonNumber : episode.ParentIndexNumber; if (currentSeasonNumber.HasValue && seasonNumber.HasValue && currentSeasonNumber.Value == seasonNumber.Value) diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index acfa239d3..3ab82a103 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -397,7 +397,7 @@ namespace MediaBrowser.Controller.Entities }, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null); - query.SortBy = new string[] { }; + query.OrderBy = new Tuple[] { }; return PostFilterAndSort(items, parent, null, query, false, true); } @@ -507,8 +507,7 @@ namespace MediaBrowser.Controller.Entities private QueryResult GetMovieLatest(Folder parent, User user, InternalItemsQuery query) { - query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName }; - query.SortOrder = SortOrder.Descending; + query.OrderBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName }.Select(i => new Tuple(i, SortOrder.Descending)).ToArray(); query.Recursive = true; query.Parent = parent; @@ -521,8 +520,7 @@ namespace MediaBrowser.Controller.Entities private QueryResult GetMovieResume(Folder parent, User user, InternalItemsQuery query) { - query.SortBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName }; - query.SortOrder = SortOrder.Descending; + query.OrderBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName }.Select(i => new Tuple(i, SortOrder.Descending)).ToArray(); query.IsResumable = true; query.Recursive = true; query.Parent = parent; @@ -633,8 +631,7 @@ namespace MediaBrowser.Controller.Entities private QueryResult GetTvLatest(Folder parent, User user, InternalItemsQuery query) { - query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName }; - query.SortOrder = SortOrder.Descending; + query.OrderBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName }.Select(i => new Tuple(i, SortOrder.Descending)).ToArray(); query.Recursive = true; query.Parent = parent; @@ -663,8 +660,7 @@ namespace MediaBrowser.Controller.Entities private QueryResult GetTvResume(Folder parent, User user, InternalItemsQuery query) { - query.SortBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName }; - query.SortOrder = SortOrder.Descending; + query.OrderBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName }.Select(i => new Tuple(i, SortOrder.Descending)).ToArray(); query.IsResumable = true; query.Recursive = true; query.Parent = parent; @@ -1104,9 +1100,9 @@ namespace MediaBrowser.Controller.Entities { items = items.DistinctBy(i => i.GetPresentationUniqueKey(), StringComparer.OrdinalIgnoreCase); - if (query.SortBy.Length > 0) + if (query.OrderBy.Length > 0) { - items = libraryManager.Sort(items, query.User, query.SortBy, query.SortOrder); + items = libraryManager.Sort(items, query.User, query.OrderBy); } var itemsArray = totalRecordLimit.HasValue ? items.Take(totalRecordLimit.Value).ToArray() : items.ToArray(); diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 265d4d786..05845102b 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -181,8 +181,8 @@ namespace MediaBrowser.Controller.Library /// The sort by. /// The sort order. /// IEnumerable{BaseItem}. - IEnumerable Sort(IEnumerable items, User user, IEnumerable sortBy, - SortOrder sortOrder); + IEnumerable Sort(IEnumerable items, User user, IEnumerable sortBy, SortOrder sortOrder); + IEnumerable Sort(IEnumerable items, User user, IEnumerable> orderBy); /// /// Gets the user root folder. diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs index e36e6ad5d..ee96a8c3b 100644 --- a/MediaBrowser.Controller/Playlists/Playlist.cs +++ b/MediaBrowser.Controller/Playlists/Playlist.cs @@ -149,8 +149,7 @@ namespace MediaBrowser.Controller.Playlists Recursive = true, IncludeItemTypes = new[] { typeof(Audio).Name }, GenreIds = new[] { musicGenre.Id.ToString("N") }, - SortBy = new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }, - SortOrder = SortOrder.Ascending, + OrderBy = new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }.Select(i => new Tuple(i, SortOrder.Ascending)).ToArray(), DtoOptions = options }); } @@ -163,8 +162,7 @@ namespace MediaBrowser.Controller.Playlists Recursive = true, IncludeItemTypes = new[] { typeof(Audio).Name }, ArtistIds = new[] { musicArtist.Id.ToString("N") }, - SortBy = new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }, - SortOrder = SortOrder.Ascending, + OrderBy = new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }.Select(i => new Tuple(i, SortOrder.Ascending)).ToArray(), DtoOptions = options }); } @@ -176,7 +174,7 @@ namespace MediaBrowser.Controller.Playlists { Recursive = true, IsFolder = false, - SortBy = new[] { ItemSortBy.SortName }, + OrderBy = new[] { ItemSortBy.SortName }.Select(i => new Tuple(i, SortOrder.Ascending)).ToArray(), MediaTypes = new[] { mediaType }, EnableTotalRecordCount = false, DtoOptions = options diff --git a/MediaBrowser.Model/Channels/ChannelItemQuery.cs b/MediaBrowser.Model/Channels/ChannelItemQuery.cs index 4aacc1619..909d35b38 100644 --- a/MediaBrowser.Model/Channels/ChannelItemQuery.cs +++ b/MediaBrowser.Model/Channels/ChannelItemQuery.cs @@ -1,4 +1,6 @@ -using MediaBrowser.Model.Entities; +using System; +using System.Collections.Generic; +using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; namespace MediaBrowser.Model.Channels @@ -35,16 +37,15 @@ namespace MediaBrowser.Model.Channels /// The limit. public int? Limit { get; set; } - public SortOrder? SortOrder { get; set; } - public string[] SortBy { get; set; } public ItemFilter[] Filters { get; set; } public ItemFields[] Fields { get; set; } + public Tuple[] OrderBy { get; set; } public ChannelItemQuery() { Filters = new ItemFilter[] { }; - SortBy = new string[] { }; Fields = new ItemFields[] { }; + OrderBy = new Tuple[] { }; } } diff --git a/MediaBrowser.Model/LiveTv/ProgramQuery.cs b/MediaBrowser.Model/LiveTv/ProgramQuery.cs index 1fd995760..c0959635f 100644 --- a/MediaBrowser.Model/LiveTv/ProgramQuery.cs +++ b/MediaBrowser.Model/LiveTv/ProgramQuery.cs @@ -12,7 +12,7 @@ namespace MediaBrowser.Model.LiveTv public ProgramQuery() { ChannelIds = new string[] { }; - SortBy = new string[] { }; + OrderBy = new Tuple[] { }; Genres = new string[] { }; EnableTotalRecordCount = true; EnableUserData = true; @@ -104,17 +104,7 @@ namespace MediaBrowser.Model.LiveTv /// public int? Limit { get; set; } - /// - /// What to sort the results by - /// - /// The sort by. - public string[] SortBy { get; set; } - - /// - /// The sort order to return results with - /// - /// The sort order. - public SortOrder? SortOrder { get; set; } + public Tuple[] OrderBy { get; set; } /// /// Limit results to items containing specific genres diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index 87c8a70ae..a3cb05bf7 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.747 + 3.0.748 Emby.Common Emby Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index 20c043007..6c2f2d399 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.747 + 3.0.748 Emby.Server.Core Emby Team ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains core components required to build plugins for Emby Server. Copyright © Emby 2013 - + diff --git a/SocketHttpListener/Net/HttpResponseStream.Managed.cs b/SocketHttpListener/Net/HttpResponseStream.Managed.cs index d5ef0b320..7e175f8d6 100644 --- a/SocketHttpListener/Net/HttpResponseStream.Managed.cs +++ b/SocketHttpListener/Net/HttpResponseStream.Managed.cs @@ -289,9 +289,65 @@ namespace SocketHttpListener.Net public Task TransmitFile(string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken) { + //if (_supportsDirectSocketAccess && offset == 0 && count == 0 && !_response.SendChunked && _response.ContentLength64 > 8192) + //{ + // if (EnableSendFileWithSocket) + // { + // return TransmitFileOverSocket(path, offset, count, fileShareMode, cancellationToken); + // } + //} + return TransmitFileManaged(path, offset, count, fileShareMode, cancellationToken); } + private readonly byte[] _emptyBuffer = new byte[] { }; + private Task TransmitFileOverSocket(string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken) + { + var ms = GetHeaders(false); + + byte[] preBuffer; + if (ms != null) + { + using (var msCopy = new MemoryStream()) + { + ms.CopyTo(msCopy); + preBuffer = msCopy.ToArray(); + } + } + else + { + return TransmitFileManaged(path, offset, count, fileShareMode, cancellationToken); + } + + //_logger.Info("Socket sending file {0} {1}", path, response.ContentLength64); + + var taskCompletion = new TaskCompletionSource(); + + Action callback = callbackResult => + { + try + { + _socket.EndSendFile(callbackResult); + taskCompletion.TrySetResult(true); + } + catch (Exception ex) + { + taskCompletion.TrySetException(ex); + } + }; + + var result = _socket.BeginSendFile(path, preBuffer, _emptyBuffer, TransmitFileOptions.UseDefaultWorkerThread, new AsyncCallback(callback), null); + + if (result.CompletedSynchronously) + { + callback(result); + } + + cancellationToken.Register(() => taskCompletion.TrySetCanceled()); + + return taskCompletion.Task; + } + const int StreamCopyToBufferSize = 81920; private async Task TransmitFileManaged(string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken) { -- 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 'MediaBrowser.Api/UserLibrary/ItemsService.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