Merge pull request #2790 from MediaBrowser/dev

Dev
This commit is contained in:
Luke 2017-08-01 12:46:37 -04:00 committed by GitHub
commit cd8642a4bc
19 changed files with 202 additions and 197 deletions

View File

@ -2622,6 +2622,11 @@ namespace Emby.Server.Implementations.Data
groups.Add("PresentationUniqueKey"); groups.Add("PresentationUniqueKey");
} }
if (query.GroupBySeriesPresentationUniqueKey)
{
groups.Add("SeriesPresentationUniqueKey");
}
if (groups.Count > 0) if (groups.Count > 0)
{ {
return " Group by " + string.Join(",", groups.ToArray()); return " Group by " + string.Join(",", groups.ToArray());
@ -2934,6 +2939,10 @@ namespace Emby.Server.Implementations.Data
{ {
commandText += " select count (distinct PresentationUniqueKey)" + GetFromText(); commandText += " select count (distinct PresentationUniqueKey)" + GetFromText();
} }
else if (query.GroupBySeriesPresentationUniqueKey)
{
commandText += " select count (distinct SeriesPresentationUniqueKey)" + GetFromText();
}
else else
{ {
commandText += " select count (guid)" + GetFromText(); commandText += " select count (guid)" + GetFromText();
@ -3079,6 +3088,11 @@ namespace Emby.Server.Implementations.Data
} }
if (string.Equals(name, ItemSortBy.DatePlayed, StringComparison.OrdinalIgnoreCase)) if (string.Equals(name, ItemSortBy.DatePlayed, StringComparison.OrdinalIgnoreCase))
{ {
if (query.GroupBySeriesPresentationUniqueKey)
{
return new Tuple<string, bool>("MAX(LastPlayedDate)", false);
}
return new Tuple<string, bool>("LastPlayedDate", false); return new Tuple<string, bool>("LastPlayedDate", false);
} }
if (string.Equals(name, ItemSortBy.PlayCount, StringComparison.OrdinalIgnoreCase)) if (string.Equals(name, ItemSortBy.PlayCount, StringComparison.OrdinalIgnoreCase))
@ -3353,6 +3367,10 @@ namespace Emby.Server.Implementations.Data
{ {
commandText += " select count (distinct PresentationUniqueKey)" + GetFromText(); commandText += " select count (distinct PresentationUniqueKey)" + GetFromText();
} }
else if (query.GroupBySeriesPresentationUniqueKey)
{
commandText += " select count (distinct SeriesPresentationUniqueKey)" + GetFromText();
}
else else
{ {
commandText += " select count (guid)" + GetFromText(); commandText += " select count (guid)" + GetFromText();
@ -4640,6 +4658,11 @@ namespace Emby.Server.Implementations.Data
return false; return false;
} }
if (query.GroupBySeriesPresentationUniqueKey)
{
return false;
}
if (!string.IsNullOrWhiteSpace(query.PresentationUniqueKey)) if (!string.IsNullOrWhiteSpace(query.PresentationUniqueKey))
{ {
return false; return false;

View File

@ -6,19 +6,16 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.IO.Compression;
using System.Net; using System.Net;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Xml; using System.Xml;
using Emby.Server.Implementations.HttpServer;
using Emby.Server.Implementations.Services; using Emby.Server.Implementations.Services;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using MediaBrowser.Model.Services; using MediaBrowser.Model.Services;
using IRequest = MediaBrowser.Model.Services.IRequest; using IRequest = MediaBrowser.Model.Services.IRequest;
using MimeTypes = MediaBrowser.Model.Net.MimeTypes; using MimeTypes = MediaBrowser.Model.Net.MimeTypes;
using StreamWriter = Emby.Server.Implementations.HttpServer.StreamWriter;
namespace Emby.Server.Implementations.HttpServer namespace Emby.Server.Implementations.HttpServer
{ {
@ -193,48 +190,35 @@ namespace Emby.Server.Implementations.HttpServer
/// <returns></returns> /// <returns></returns>
public object ToOptimizedResult<T>(IRequest request, T dto) public object ToOptimizedResult<T>(IRequest request, T dto)
{ {
var compressionType = GetCompressionType(request); var contentType = request.ResponseContentType;
if (compressionType == null)
switch (GetRealContentType(contentType))
{ {
var contentType = request.ResponseContentType; case "application/xml":
case "text/xml":
case "text/xml; charset=utf-8": //"text/xml; charset=utf-8" also matches xml
return SerializeToXmlString(dto);
switch (GetRealContentType(contentType)) case "application/json":
{ case "text/json":
case "application/xml": return _jsonSerializer.SerializeToString(dto);
case "text/xml": default:
case "text/xml; charset=utf-8": //"text/xml; charset=utf-8" also matches xml {
return SerializeToXmlString(dto); var ms = new MemoryStream();
var writerFn = RequestHelper.GetResponseWriter(HttpListenerHost.Instance, contentType);
case "application/json": writerFn(dto, ms);
case "text/json":
return _jsonSerializer.SerializeToString(dto); ms.Position = 0;
}
if (string.Equals(request.Verb, "head", StringComparison.OrdinalIgnoreCase))
{
return GetHttpResult(new byte[] { }, contentType, true);
}
return GetHttpResult(ms, contentType, true);
}
} }
// Do not use the memoryStreamFactory here, they don't place nice with compression
using (var ms = new MemoryStream())
{
var contentType = request.ResponseContentType;
var writerFn = RequestHelper.GetResponseWriter(HttpListenerHost.Instance, contentType);
writerFn(dto, ms);
ms.Position = 0;
var responseHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
return GetCompressedResult(ms, compressionType, responseHeaders, false, request.ResponseContentType).Result;
}
}
private static Stream GetCompressionStream(Stream outputStream, string compressionType)
{
if (compressionType == "deflate")
return new DeflateStream(outputStream, CompressionMode.Compress, true);
if (compressionType == "gzip")
return new GZipStream(outputStream, CompressionMode.Compress, true);
throw new NotSupportedException(compressionType);
} }
public static string GetRealContentType(string contentType) public static string GetRealContentType(string contentType)
@ -568,123 +552,47 @@ namespace Emby.Server.Implementations.HttpServer
var contentType = options.ContentType; var contentType = options.ContentType;
var responseHeaders = options.ResponseHeaders; var responseHeaders = options.ResponseHeaders;
var requestedCompressionType = GetCompressionType(requestContext); //var requestedCompressionType = GetCompressionType(requestContext);
if (!compress || string.IsNullOrEmpty(requestedCompressionType)) var rangeHeader = requestContext.Headers.Get("Range");
if (!isHeadRequest && !string.IsNullOrWhiteSpace(options.Path))
{ {
var rangeHeader = requestContext.Headers.Get("Range"); return new FileWriter(options.Path, contentType, rangeHeader, _logger, _fileSystem)
if (!isHeadRequest && !string.IsNullOrWhiteSpace(options.Path))
{ {
return new FileWriter(options.Path, contentType, rangeHeader, _logger, _fileSystem) OnComplete = options.OnComplete,
{ OnError = options.OnError,
OnComplete = options.OnComplete, FileShare = options.FileShare
OnError = options.OnError, };
FileShare = options.FileShare
};
}
if (!string.IsNullOrWhiteSpace(rangeHeader))
{
var stream = await factoryFn().ConfigureAwait(false);
return new RangeRequestWriter(rangeHeader, stream, contentType, isHeadRequest, _logger)
{
OnComplete = options.OnComplete
};
}
else
{
var stream = await factoryFn().ConfigureAwait(false);
responseHeaders["Content-Length"] = stream.Length.ToString(UsCulture);
if (isHeadRequest)
{
stream.Dispose();
return GetHttpResult(new byte[] { }, contentType, true);
}
return new StreamWriter(stream, contentType, _logger)
{
OnComplete = options.OnComplete,
OnError = options.OnError
};
}
} }
using (var stream = await factoryFn().ConfigureAwait(false)) if (!string.IsNullOrWhiteSpace(rangeHeader))
{ {
return await GetCompressedResult(stream, requestedCompressionType, responseHeaders, isHeadRequest, contentType).ConfigureAwait(false); var stream = await factoryFn().ConfigureAwait(false);
}
}
private async Task<IHasHeaders> GetCompressedResult(Stream stream, return new RangeRequestWriter(rangeHeader, stream, contentType, isHeadRequest, _logger)
string requestedCompressionType,
IDictionary<string, string> responseHeaders,
bool isHeadRequest,
string contentType)
{
using (var reader = new MemoryStream())
{
await stream.CopyToAsync(reader).ConfigureAwait(false);
reader.Position = 0;
var content = reader.ToArray();
if (content.Length >= 1024)
{ {
content = Compress(content, requestedCompressionType); OnComplete = options.OnComplete
responseHeaders["Content-Encoding"] = requestedCompressionType; };
} }
else
{
var stream = await factoryFn().ConfigureAwait(false);
responseHeaders["Vary"] = "Accept-Encoding"; responseHeaders["Content-Length"] = stream.Length.ToString(UsCulture);
responseHeaders["Content-Length"] = content.Length.ToString(UsCulture);
if (isHeadRequest) if (isHeadRequest)
{ {
stream.Dispose();
return GetHttpResult(new byte[] { }, contentType, true); return GetHttpResult(new byte[] { }, contentType, true);
} }
return GetHttpResult(content, contentType, true, responseHeaders); return new StreamWriter(stream, contentType, _logger)
} {
} OnComplete = options.OnComplete,
OnError = options.OnError
private byte[] Compress(byte[] bytes, string compressionType) };
{
if (compressionType == "deflate")
return Deflate(bytes);
if (compressionType == "gzip")
return GZip(bytes);
throw new NotSupportedException(compressionType);
}
private byte[] Deflate(byte[] bytes)
{
// In .NET FX incompat-ville, you can't access compressed bytes without closing DeflateStream
// Which means we must use MemoryStream since you have to use ToArray() on a closed Stream
using (var ms = new MemoryStream())
using (var zipStream = new DeflateStream(ms, CompressionMode.Compress))
{
zipStream.Write(bytes, 0, bytes.Length);
zipStream.Dispose();
return ms.ToArray();
}
}
private byte[] GZip(byte[] buffer)
{
using (var ms = new MemoryStream())
using (var zipStream = new GZipStream(ms, CompressionMode.Compress))
{
zipStream.Write(buffer, 0, buffer.Length);
zipStream.Dispose();
return ms.ToArray();
} }
} }

View File

@ -269,7 +269,41 @@ namespace Emby.Server.Implementations.Library
return new List<BaseItem>(); return new List<BaseItem>();
} }
var excludeItemTypes = includeItemTypes.Length == 0 ? new[] var mediaTypes = new List<string>();
if (includeItemTypes.Length == 0)
{
foreach (var parent in parents.OfType<ICollectionFolder>())
{
switch (parent.CollectionType)
{
case CollectionType.Books:
mediaTypes.Add(MediaType.Book);
break;
case CollectionType.Games:
mediaTypes.Add(MediaType.Game);
break;
case CollectionType.Music:
mediaTypes.Add(MediaType.Audio);
break;
case CollectionType.Photos:
mediaTypes.Add(MediaType.Photo);
mediaTypes.Add(MediaType.Video);
break;
case CollectionType.HomeVideos:
mediaTypes.Add(MediaType.Photo);
mediaTypes.Add(MediaType.Video);
break;
default:
mediaTypes.Add(MediaType.Video);
break;
}
}
mediaTypes = mediaTypes.Distinct().ToList();
}
var excludeItemTypes = includeItemTypes.Length == 0 && mediaTypes.Count == 0 ? new[]
{ {
typeof(Person).Name, typeof(Person).Name,
typeof(Studio).Name, typeof(Studio).Name,
@ -290,7 +324,8 @@ namespace Emby.Server.Implementations.Library
IsVirtualItem = false, IsVirtualItem = false,
Limit = limit * 5, Limit = limit * 5,
IsPlayed = isPlayed, IsPlayed = isPlayed,
DtoOptions = options DtoOptions = options,
MediaTypes = mediaTypes.ToArray()
}; };
if (parents.Count == 0) if (parents.Count == 0)

View File

@ -1632,7 +1632,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
return; return;
} }
var episodesToDelete = (librarySeries.GetItems(new InternalItemsQuery var episodesToDelete = (librarySeries.GetItemList(new InternalItemsQuery
{ {
SortBy = new[] { ItemSortBy.DateCreated }, SortBy = new[] { ItemSortBy.DateCreated },
SortOrder = SortOrder.Descending, SortOrder = SortOrder.Descending,
@ -1642,7 +1642,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
DtoOptions = new DtoOptions(true) DtoOptions = new DtoOptions(true)
})) }))
.Items
.Where(i => i.LocationType == LocationType.FileSystem && _fileSystem.FileExists(i.Path)) .Where(i => i.LocationType == LocationType.FileSystem && _fileSystem.FileExists(i.Path))
.Skip(seriesTimer.KeepUpTo - 1) .Skip(seriesTimer.KeepUpTo - 1)
.ToList(); .ToList();

View File

@ -1845,6 +1845,9 @@ namespace Emby.Server.Implementations.LiveTv
public async Task AddInfoToProgramDto(List<Tuple<BaseItem, BaseItemDto>> tuples, List<ItemFields> fields, User user = null) public async Task AddInfoToProgramDto(List<Tuple<BaseItem, BaseItemDto>> tuples, List<ItemFields> fields, User user = null)
{ {
var programTuples = new List<Tuple<BaseItemDto, string, string, string>>(); var programTuples = new List<Tuple<BaseItemDto, string, string, string>>();
var hasChannelImage = fields.Contains(ItemFields.ChannelImage);
var hasChannelInfo = fields.Contains(ItemFields.ChannelInfo);
var hasServiceName = fields.Contains(ItemFields.ServiceName);
foreach (var tuple in tuples) foreach (var tuple in tuples)
{ {
@ -1887,7 +1890,7 @@ namespace Emby.Server.Implementations.LiveTv
dto.IsPremiere = program.IsPremiere; dto.IsPremiere = program.IsPremiere;
} }
if (fields.Contains(ItemFields.ChannelInfo)) if (hasChannelInfo || hasChannelImage)
{ {
var channel = GetInternalChannel(program.ChannelId); var channel = GetInternalChannel(program.ChannelId);
@ -1897,7 +1900,7 @@ namespace Emby.Server.Implementations.LiveTv
dto.MediaType = channel.MediaType; dto.MediaType = channel.MediaType;
dto.ChannelNumber = channel.Number; dto.ChannelNumber = channel.Number;
if (channel.HasImage(ImageType.Primary)) if (hasChannelImage && channel.HasImage(ImageType.Primary))
{ {
dto.ChannelPrimaryImageTag = _tvDtoService.GetImageTag(channel); dto.ChannelPrimaryImageTag = _tvDtoService.GetImageTag(channel);
} }
@ -1906,7 +1909,7 @@ namespace Emby.Server.Implementations.LiveTv
var serviceName = program.ServiceName; var serviceName = program.ServiceName;
if (fields.Contains(ItemFields.ServiceName)) if (hasServiceName)
{ {
dto.ServiceName = serviceName; dto.ServiceName = serviceName;
} }

View File

@ -1089,7 +1089,7 @@ namespace Emby.Server.Implementations.Session
{ {
var folder = (Folder)item; var folder = (Folder)item;
var itemsResult = folder.GetItems(new InternalItemsQuery(user) var itemsResult = folder.GetItemList(new InternalItemsQuery(user)
{ {
Recursive = true, Recursive = true,
IsFolder = false, IsFolder = false,
@ -1104,7 +1104,7 @@ namespace Emby.Server.Implementations.Session
}); });
return FilterToSingleMediaType(itemsResult.Items) return FilterToSingleMediaType(itemsResult)
.OrderBy(i => i.SortName) .OrderBy(i => i.SortName)
.ToList(); .ToList();
} }

View File

@ -42,7 +42,7 @@ namespace Emby.Server.Implementations.TV
int? limit = null; int? limit = null;
if (!string.IsNullOrWhiteSpace(request.SeriesId)) if (!string.IsNullOrWhiteSpace(request.SeriesId))
{ {
var series = _libraryManager.GetItemById(request.SeriesId); var series = _libraryManager.GetItemById(request.SeriesId) as Series;
if (series != null) if (series != null)
{ {
@ -51,17 +51,22 @@ namespace Emby.Server.Implementations.TV
} }
} }
if (string.IsNullOrWhiteSpace(presentationUniqueKey) && limit.HasValue) if (!string.IsNullOrWhiteSpace(presentationUniqueKey))
{
return GetResult(GetNextUpEpisodes(request, user, new[] { presentationUniqueKey }, dtoOptions), request);
}
if (limit.HasValue)
{ {
limit = limit.Value + 10; limit = limit.Value + 10;
} }
var items = _libraryManager.GetItemList(new InternalItemsQuery(user) var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
{ {
IncludeItemTypes = new[] { typeof(Series).Name }, IncludeItemTypes = new[] { typeof(Episode).Name },
SortBy = new[] { ItemSortBy.SeriesDatePlayed }, SortBy = new[] { ItemSortBy.DatePlayed },
SortOrder = SortOrder.Descending, SortOrder = SortOrder.Descending,
PresentationUniqueKey = presentationUniqueKey, SeriesPresentationUniqueKey = presentationUniqueKey,
Limit = limit, Limit = limit,
ParentId = parentIdGuid, ParentId = parentIdGuid,
Recursive = true, Recursive = true,
@ -69,11 +74,12 @@ namespace Emby.Server.Implementations.TV
{ {
Fields = new List<ItemFields> Fields = new List<ItemFields>
{ {
ItemFields.PresentationUniqueKey ItemFields.SeriesPresentationUniqueKey
} }
} },
GroupBySeriesPresentationUniqueKey = true
}).Cast<Series>().Select(GetUniqueSeriesKey); }).Cast<Episode>().Select(GetUniqueSeriesKey);
// Avoid implicitly captured closure // Avoid implicitly captured closure
var episodes = GetNextUpEpisodes(request, user, items, dtoOptions); var episodes = GetNextUpEpisodes(request, user, items, dtoOptions);
@ -94,7 +100,7 @@ namespace Emby.Server.Implementations.TV
int? limit = null; int? limit = null;
if (!string.IsNullOrWhiteSpace(request.SeriesId)) if (!string.IsNullOrWhiteSpace(request.SeriesId))
{ {
var series = _libraryManager.GetItemById(request.SeriesId); var series = _libraryManager.GetItemById(request.SeriesId) as Series;
if (series != null) if (series != null)
{ {
@ -103,28 +109,34 @@ namespace Emby.Server.Implementations.TV
} }
} }
if (string.IsNullOrWhiteSpace(presentationUniqueKey) && limit.HasValue) if (!string.IsNullOrWhiteSpace(presentationUniqueKey))
{
return GetResult(GetNextUpEpisodes(request, user, new [] { presentationUniqueKey }, dtoOptions), request);
}
if (limit.HasValue)
{ {
limit = limit.Value + 10; limit = limit.Value + 10;
} }
var items = _libraryManager.GetItemList(new InternalItemsQuery(user) var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
{ {
IncludeItemTypes = new[] { typeof(Series).Name }, IncludeItemTypes = new[] { typeof(Episode).Name },
SortBy = new[] { ItemSortBy.SeriesDatePlayed }, SortBy = new[] { ItemSortBy.DatePlayed },
SortOrder = SortOrder.Descending, SortOrder = SortOrder.Descending,
PresentationUniqueKey = presentationUniqueKey, SeriesPresentationUniqueKey = presentationUniqueKey,
Limit = limit, Limit = limit,
DtoOptions = new MediaBrowser.Controller.Dto.DtoOptions DtoOptions = new MediaBrowser.Controller.Dto.DtoOptions
{ {
Fields = new List<ItemFields> Fields = new List<ItemFields>
{ {
ItemFields.PresentationUniqueKey ItemFields.SeriesPresentationUniqueKey
}, },
EnableImages = false EnableImages = false
} },
GroupBySeriesPresentationUniqueKey = true
}, parentsFolders.Cast<BaseItem>().ToList()).Cast<Series>().Select(GetUniqueSeriesKey); }, parentsFolders.Cast<BaseItem>().ToList()).Cast<Episode>().Select(GetUniqueSeriesKey);
// Avoid implicitly captured closure // Avoid implicitly captured closure
var episodes = GetNextUpEpisodes(request, user, items, dtoOptions); var episodes = GetNextUpEpisodes(request, user, items, dtoOptions);
@ -167,7 +179,12 @@ namespace Emby.Server.Implementations.TV
.Where(i => i != null); .Where(i => i != null);
} }
private string GetUniqueSeriesKey(BaseItem series) private string GetUniqueSeriesKey(Episode episode)
{
return episode.SeriesPresentationUniqueKey;
}
private string GetUniqueSeriesKey(Series series)
{ {
return series.GetPresentationUniqueKey(); return series.GetPresentationUniqueKey();
} }

View File

@ -42,7 +42,7 @@ namespace Emby.Server.Implementations.UserViews
var recursive = !new[] { CollectionType.Playlists, CollectionType.Channels }.Contains(view.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase); var recursive = !new[] { CollectionType.Playlists, CollectionType.Channels }.Contains(view.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
var result = view.GetItems(new InternalItemsQuery var result = view.GetItemList(new InternalItemsQuery
{ {
CollapseBoxSetItems = false, CollapseBoxSetItems = false,
Recursive = recursive, Recursive = recursive,
@ -51,7 +51,7 @@ namespace Emby.Server.Implementations.UserViews
}); });
var items = result.Items.Select(i => var items = result.Select(i =>
{ {
var episode = i as Episode; var episode = i as Episode;
if (episode != null) if (episode != null)

View File

@ -70,19 +70,19 @@ namespace Emby.Server.Implementations.UserViews
if (string.Equals(view.ViewType, SpecialFolder.MovieGenre, StringComparison.OrdinalIgnoreCase) || if (string.Equals(view.ViewType, SpecialFolder.MovieGenre, StringComparison.OrdinalIgnoreCase) ||
string.Equals(view.ViewType, SpecialFolder.TvGenre, StringComparison.OrdinalIgnoreCase)) string.Equals(view.ViewType, SpecialFolder.TvGenre, StringComparison.OrdinalIgnoreCase))
{ {
var userItemsResult = view.GetItems(new InternalItemsQuery var userItemsResult = view.GetItemList(new InternalItemsQuery
{ {
CollapseBoxSetItems = false, CollapseBoxSetItems = false,
DtoOptions = new DtoOptions(false) DtoOptions = new DtoOptions(false)
}); });
return userItemsResult.Items.ToList(); return userItemsResult.ToList();
} }
var isUsingCollectionStrip = IsUsingCollectionStrip(view); var isUsingCollectionStrip = IsUsingCollectionStrip(view);
var recursive = isUsingCollectionStrip && !new[] { CollectionType.Channels, CollectionType.BoxSets, CollectionType.Playlists }.Contains(view.ViewType ?? string.Empty, StringComparer.OrdinalIgnoreCase); var recursive = isUsingCollectionStrip && !new[] { CollectionType.Channels, CollectionType.BoxSets, CollectionType.Playlists }.Contains(view.ViewType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
var result = view.GetItems(new InternalItemsQuery var result = view.GetItemList(new InternalItemsQuery
{ {
User = view.UserId.HasValue ? _userManager.GetUserById(view.UserId.Value) : null, User = view.UserId.HasValue ? _userManager.GetUserById(view.UserId.Value) : null,
CollapseBoxSetItems = false, CollapseBoxSetItems = false,
@ -91,7 +91,7 @@ namespace Emby.Server.Implementations.UserViews
DtoOptions = new DtoOptions(false) DtoOptions = new DtoOptions(false)
}); });
var items = result.Items.Select(i => var items = result.Select(i =>
{ {
var episode = i as Episode; var episode = i as Episode;
if (episode != null) if (episode != null)

View File

@ -61,9 +61,9 @@ namespace MediaBrowser.Api
user == null ? _libraryManager.RootFolder : user.RootFolder : user == null ? _libraryManager.RootFolder : user.RootFolder :
parentItem; parentItem;
var result = ((Folder)item).GetItems(GetItemsQuery(request, user)); var result = ((Folder)item).GetItemList(GetItemsQuery(request, user));
return ToOptimizedResult(GetFilters(result.Items)); return ToOptimizedResult(GetFilters(result.ToArray()));
} }
private QueryFilters GetFilters(BaseItem[] items) private QueryFilters GetFilters(BaseItem[] items)

View File

@ -438,14 +438,14 @@ namespace MediaBrowser.Api
throw new ResourceNotFoundException("Series not found"); throw new ResourceNotFoundException("Series not found");
} }
var seasons = (series.GetItems(new InternalItemsQuery(user) var seasons = (series.GetItemList(new InternalItemsQuery(user)
{ {
IsMissing = request.IsMissing, IsMissing = request.IsMissing,
IsVirtualUnaired = request.IsVirtualUnaired, IsVirtualUnaired = request.IsVirtualUnaired,
IsSpecialSeason = request.IsSpecialSeason, IsSpecialSeason = request.IsSpecialSeason,
AdjacentTo = request.AdjacentTo AdjacentTo = request.AdjacentTo
})).Items.OfType<Season>(); })).OfType<Season>();
var dtoOptions = GetDtoOptions(_authContext, request); var dtoOptions = GetDtoOptions(_authContext, request);

View File

@ -970,6 +970,27 @@ namespace MediaBrowser.Controller.Entities
return GetItemsInternal(query); return GetItemsInternal(query);
} }
public IEnumerable<BaseItem> GetItemList(InternalItemsQuery query)
{
query.EnableTotalRecordCount = false;
if (query.ItemIds.Length > 0)
{
var result = LibraryManager.GetItemList(query);
if (query.SortBy.Length == 0)
{
var ids = query.ItemIds.ToList();
// Try to preserve order
result = result.OrderBy(i => ids.IndexOf(i.Id.ToString("N"))).ToArray();
}
return result;
}
return GetItemsInternal(query).Items;
}
protected virtual QueryResult<BaseItem> GetItemsInternal(InternalItemsQuery query) protected virtual QueryResult<BaseItem> GetItemsInternal(InternalItemsQuery query)
{ {
if (SourceType == SourceType.Channel) if (SourceType == SourceType.Channel)
@ -1375,10 +1396,10 @@ namespace MediaBrowser.Controller.Entities
query.IsVirtualItem = false; query.IsVirtualItem = false;
} }
var itemsResult = GetItems(query); var itemsResult = GetItemList(query);
// Sweep through recursively and update status // Sweep through recursively and update status
var tasks = itemsResult.Items.Select(c => c.MarkPlayed(user, datePlayed, resetPosition)); var tasks = itemsResult.Select(c => c.MarkPlayed(user, datePlayed, resetPosition));
await Task.WhenAll(tasks).ConfigureAwait(false); await Task.WhenAll(tasks).ConfigureAwait(false);
} }
@ -1390,7 +1411,7 @@ namespace MediaBrowser.Controller.Entities
/// <returns>Task.</returns> /// <returns>Task.</returns>
public override async Task MarkUnplayed(User user) public override async Task MarkUnplayed(User user)
{ {
var itemsResult = GetItems(new InternalItemsQuery var itemsResult = GetItemList(new InternalItemsQuery
{ {
User = user, User = user,
Recursive = true, Recursive = true,
@ -1400,14 +1421,14 @@ namespace MediaBrowser.Controller.Entities
}); });
// Sweep through recursively and update status // Sweep through recursively and update status
var tasks = itemsResult.Items.Select(c => c.MarkUnplayed(user)); var tasks = itemsResult.Select(c => c.MarkUnplayed(user));
await Task.WhenAll(tasks).ConfigureAwait(false); await Task.WhenAll(tasks).ConfigureAwait(false);
} }
public override bool IsPlayed(User user) public override bool IsPlayed(User user)
{ {
var itemsResult = GetItems(new InternalItemsQuery(user) var itemsResult = GetItemList(new InternalItemsQuery(user)
{ {
Recursive = true, Recursive = true,
IsFolder = false, IsFolder = false,
@ -1416,7 +1437,7 @@ namespace MediaBrowser.Controller.Entities
}); });
return itemsResult.Items return itemsResult
.All(i => i.IsPlayed(user)); .All(i => i.IsPlayed(user));
} }

View File

@ -161,6 +161,7 @@ namespace MediaBrowser.Controller.Entities
public string SeriesPresentationUniqueKey { get; set; } public string SeriesPresentationUniqueKey { get; set; }
public bool GroupByPresentationUniqueKey { get; set; } public bool GroupByPresentationUniqueKey { get; set; }
public bool GroupBySeriesPresentationUniqueKey { get; set; }
public bool EnableTotalRecordCount { get; set; } public bool EnableTotalRecordCount { get; set; }
public bool ForceDirect { get; set; } public bool ForceDirect { get; set; }
public Dictionary<string, string> ExcludeProviderIds { get; set; } public Dictionary<string, string> ExcludeProviderIds { get; set; }

View File

@ -193,7 +193,7 @@ namespace MediaBrowser.Controller.Entities.TV
if (query.IncludeItemTypes.Length == 0) if (query.IncludeItemTypes.Length == 0)
{ {
query.IncludeItemTypes = new[] { typeof(Episode).Name, typeof(Season).Name }; query.IncludeItemTypes = new[] { typeof(Episode).Name };
} }
query.IsVirtualItem = false; query.IsVirtualItem = false;
query.Limit = 0; query.Limit = 0;

View File

@ -82,7 +82,7 @@ namespace MediaBrowser.Controller.Entities
public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren) public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
{ {
var result = GetItems(new InternalItemsQuery var result = GetItemList(new InternalItemsQuery
{ {
User = user, User = user,
EnableTotalRecordCount = false, EnableTotalRecordCount = false,
@ -90,7 +90,7 @@ namespace MediaBrowser.Controller.Entities
}); });
return result.Items; return result;
} }
public override bool CanDelete() public override bool CanDelete()
@ -105,7 +105,7 @@ namespace MediaBrowser.Controller.Entities
public override IEnumerable<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query) public override IEnumerable<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query)
{ {
var result = GetItems(new InternalItemsQuery var result = GetItemList(new InternalItemsQuery
{ {
User = user, User = user,
Recursive = true, Recursive = true,
@ -117,7 +117,7 @@ namespace MediaBrowser.Controller.Entities
}); });
return result.Items.Where(i => UserViewBuilder.FilterItem(i, query)); return result.Where(i => UserViewBuilder.FilterItem(i, query));
} }
protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user) protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user)

View File

@ -182,10 +182,7 @@ namespace MediaBrowser.Controller.Playlists
DtoOptions = options DtoOptions = options
}; };
var itemsResult = folder.GetItems(query); return folder.GetItemList(query);
var items = itemsResult.Items;
return items;
} }
return new[] { item }; return new[] { item };

View File

@ -224,6 +224,7 @@
SeriesPresentationUniqueKey, SeriesPresentationUniqueKey,
DateLastRefreshed, DateLastRefreshed,
DateLastSaved, DateLastSaved,
RefreshState RefreshState,
ChannelImage
} }
} }

View File

@ -97,7 +97,7 @@ namespace MediaBrowser.Server.Mono
private static void RunApplication(ServerApplicationPaths appPaths, ILogManager logManager, StartupOptions options) private static void RunApplication(ServerApplicationPaths appPaths, ILogManager logManager, StartupOptions options)
{ {
// Allow all https requests // Allow all https requests
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; }); //ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; });
var environmentInfo = GetEnvironmentInfo(); var environmentInfo = GetEnvironmentInfo();

View File

@ -1,3 +1,3 @@
using System.Reflection; using System.Reflection;
[assembly: AssemblyVersion("3.2.26.10")] [assembly: AssemblyVersion("3.2.26.11")]