Ver código fonte

update live tv data transfer

Luke Pulverenti 7 anos atrás
pai
commit
1ad990ad72
100 arquivos alterados com 629 adições e 852 exclusões
  1. 25 0
      Emby.Dlna/ContentDirectory/ControlHandler.cs
  2. 2 2
      Emby.Dlna/Didl/DidlBuilder.cs
  3. 3 2
      Emby.Dlna/PlayTo/PlayToController.cs
  4. 1 1
      Emby.Dlna/PlayTo/PlayToManager.cs
  5. 3 3
      Emby.Server.Implementations/ApplicationHost.cs
  6. 12 20
      Emby.Server.Implementations/Channels/ChannelManager.cs
  7. 12 10
      Emby.Server.Implementations/Collections/CollectionManager.cs
  8. 2 1
      Emby.Server.Implementations/Data/SqliteItemRepository.cs
  9. 5 1
      Emby.Server.Implementations/Devices/DeviceRepository.cs
  10. 22 10
      Emby.Server.Implementations/Dto/DtoService.cs
  11. 5 5
      Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs
  12. 1 1
      Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs
  13. 1 1
      Emby.Server.Implementations/HttpServer/HttpListenerHost.cs
  14. 3 3
      Emby.Server.Implementations/IO/LibraryMonitor.cs
  15. 3 3
      Emby.Server.Implementations/Library/LibraryManager.cs
  16. 1 1
      Emby.Server.Implementations/Library/SearchEngine.cs
  17. 2 2
      Emby.Server.Implementations/Library/UserDataManager.cs
  18. 3 2
      Emby.Server.Implementations/Library/UserViewManager.cs
  19. 7 7
      Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
  20. 19 32
      Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs
  21. 49 46
      Emby.Server.Implementations/LiveTv/LiveTvManager.cs
  22. 1 1
      Emby.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs
  23. 5 5
      Emby.Server.Implementations/LiveTv/TunerHosts/MulticastStream.cs
  24. 4 20
      Emby.Server.Implementations/LiveTv/TunerHosts/QueueStream.cs
  25. 9 9
      Emby.Server.Implementations/Localization/LocalizationManager.cs
  26. 1 1
      Emby.Server.Implementations/MediaEncoder/EncodingManager.cs
  27. 16 16
      Emby.Server.Implementations/Notifications/CoreNotificationTypes.cs
  28. 1 1
      Emby.Server.Implementations/Notifications/NotificationManager.cs
  29. 1 1
      Emby.Server.Implementations/Playlists/PlaylistManager.cs
  30. 7 33
      Emby.Server.Implementations/Services/ServiceController.cs
  31. 46 35
      Emby.Server.Implementations/Session/SessionManager.cs
  32. 3 3
      Emby.Server.Implementations/TV/TVSeriesManager.cs
  33. 21 31
      Emby.Server.Implementations/Updates/InstallationManager.cs
  34. 20 4
      MediaBrowser.Api/BaseApiService.cs
  35. 3 3
      MediaBrowser.Api/ChannelService.cs
  36. 2 2
      MediaBrowser.Api/ConfigurationService.cs
  37. 2 3
      MediaBrowser.Api/Dlna/DlnaService.cs
  38. 3 6
      MediaBrowser.Api/EnvironmentService.cs
  39. 1 1
      MediaBrowser.Api/FilterService.cs
  40. 8 52
      MediaBrowser.Api/GamesService.cs
  41. 2 2
      MediaBrowser.Api/IHasItemFields.cs
  42. 5 5
      MediaBrowser.Api/Images/RemoteImageService.cs
  43. 4 4
      MediaBrowser.Api/ItemUpdateService.cs
  44. 4 4
      MediaBrowser.Api/Library/LibraryService.cs
  45. 11 9
      MediaBrowser.Api/LiveTv/LiveTvService.cs
  46. 6 6
      MediaBrowser.Api/LocalizationService.cs
  47. 0 1
      MediaBrowser.Api/MediaBrowser.Api.csproj
  48. 4 4
      MediaBrowser.Api/Movies/CollectionService.cs
  49. 4 4
      MediaBrowser.Api/Movies/MoviesService.cs
  50. 2 1
      MediaBrowser.Api/Movies/TrailersService.cs
  51. 9 3
      MediaBrowser.Api/Music/InstantMixService.cs
  52. 1 1
      MediaBrowser.Api/NotificationsService.cs
  53. 0 162
      MediaBrowser.Api/PackageReviewService.cs
  54. 14 13
      MediaBrowser.Api/PackageService.cs
  55. 3 5
      MediaBrowser.Api/PlaylistService.cs
  56. 5 6
      MediaBrowser.Api/PluginService.cs
  57. 2 2
      MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs
  58. 4 4
      MediaBrowser.Api/Session/SessionsService.cs
  59. 4 4
      MediaBrowser.Api/SimilarItemsHelper.cs
  60. 2 4
      MediaBrowser.Api/Subtitles/SubtitleService.cs
  61. 1 1
      MediaBrowser.Api/SuggestionsService.cs
  62. 3 3
      MediaBrowser.Api/System/SystemService.cs
  63. 28 31
      MediaBrowser.Api/TvShowsService.cs
  64. 8 8
      MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs
  65. 2 2
      MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs
  66. 9 12
      MediaBrowser.Api/UserLibrary/ItemsService.cs
  67. 17 12
      MediaBrowser.Api/UserLibrary/UserLibraryService.cs
  68. 11 10
      MediaBrowser.Api/UserLibrary/UserViewsService.cs
  69. 3 3
      MediaBrowser.Api/UserService.cs
  70. 2 2
      MediaBrowser.Api/VideosService.cs
  71. 2 2
      MediaBrowser.Common/Updates/IInstallationManager.cs
  72. 1 1
      MediaBrowser.Controller/Channels/IChannelManager.cs
  73. 0 9
      MediaBrowser.Controller/Channels/InternalChannelFeatures.cs
  74. 4 4
      MediaBrowser.Controller/Collections/CollectionCreationOptions.cs
  75. 2 2
      MediaBrowser.Controller/Collections/ICollectionManager.cs
  76. 14 10
      MediaBrowser.Controller/Dto/DtoOptions.cs
  77. 5 4
      MediaBrowser.Controller/Dto/IDtoService.cs
  78. 1 1
      MediaBrowser.Controller/Entities/BaseItem.cs
  79. 10 10
      MediaBrowser.Controller/Entities/Folder.cs
  80. 1 1
      MediaBrowser.Controller/Entities/IHasUserData.cs
  81. 4 4
      MediaBrowser.Controller/Entities/Movies/BoxSet.cs
  82. 5 5
      MediaBrowser.Controller/Entities/TV/Season.cs
  83. 16 23
      MediaBrowser.Controller/Entities/TV/Series.cs
  84. 1 1
      MediaBrowser.Controller/Entities/UserRootFolder.cs
  85. 2 2
      MediaBrowser.Controller/Entities/UserView.cs
  86. 3 5
      MediaBrowser.Controller/Entities/UserViewBuilder.cs
  87. 10 10
      MediaBrowser.Controller/Entities/Video.cs
  88. 1 1
      MediaBrowser.Controller/Library/IUserDataManager.cs
  89. 1 1
      MediaBrowser.Controller/Library/IUserViewManager.cs
  90. 3 3
      MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
  91. 3 3
      MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
  92. 5 5
      MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs
  93. 9 12
      MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs
  94. 2 2
      MediaBrowser.Controller/MediaEncoding/MediaInfoRequest.cs
  95. 1 1
      MediaBrowser.Controller/Notifications/INotificationManager.cs
  96. 1 1
      MediaBrowser.Controller/Playlists/Playlist.cs
  97. 1 1
      MediaBrowser.Controller/Providers/IProviderManager.cs
  98. 6 6
      MediaBrowser.Controller/Session/SessionInfo.cs
  99. 3 3
      MediaBrowser.Controller/Subtitles/ISubtitleManager.cs
  100. 7 11
      MediaBrowser.Controller/Sync/ISyncManager.cs

+ 25 - 0
Emby.Dlna/ContentDirectory/ControlHandler.cs

@@ -487,6 +487,11 @@ namespace Emby.Dlna.ContentDirectory
                 return GetMusicArtistItems(item, null, user, sort, startIndex, limit);
             }
 
+            if (item is Genre)
+            {
+                return GetGenreItems(item, null, user, sort, startIndex, limit);
+            }
+
             var collectionFolder = item as ICollectionFolder;
             if (collectionFolder != null && string.Equals(CollectionType.Music, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase))
             {
@@ -1173,6 +1178,26 @@ namespace Emby.Dlna.ContentDirectory
             return ToResult(result);
         }
 
+        private QueryResult<ServerItem> GetGenreItems(BaseItem item, Guid? parentId, User user, SortCriteria sort, int? startIndex, int? limit)
+        {
+            var query = new InternalItemsQuery(user)
+            {
+                Recursive = true,
+                ParentId = parentId,
+                GenreIds = new[] { item.Id.ToString("N") },
+                IncludeItemTypes = new[] { typeof(Movie).Name, typeof(Series).Name },
+                Limit = limit,
+                StartIndex = startIndex,
+                DtoOptions = GetDtoOptions()
+            };
+
+            SetSorting(query, sort, false);
+
+            var result = _libraryManager.GetItemsResult(query);
+
+            return ToResult(result);
+        }
+
         private QueryResult<ServerItem> GetMusicGenreItems(BaseItem item, Guid? parentId, User user, SortCriteria sort, int? startIndex, int? limit)
         {
             var query = new InternalItemsQuery(user)

+ 2 - 2
Emby.Dlna/Didl/DidlBuilder.cs

@@ -198,7 +198,7 @@ namespace Emby.Dlna.Didl
                 streamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger(options)).BuildVideoItem(new VideoOptions
                 {
                     ItemId = GetClientId(video),
-                    MediaSources = sources,
+                    MediaSources = sources.ToArray(sources.Count),
                     Profile = _profile,
                     DeviceId = deviceId,
                     MaxBitrate = _profile.MaxStreamingBitrate
@@ -513,7 +513,7 @@ namespace Emby.Dlna.Didl
                 streamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger(options)).BuildAudioItem(new AudioOptions
                 {
                     ItemId = GetClientId(audio),
-                    MediaSources = sources,
+                    MediaSources = sources.ToArray(sources.Count),
                     Profile = _profile,
                     DeviceId = deviceId
                 });

+ 3 - 2
Emby.Dlna/PlayTo/PlayToController.cs

@@ -20,6 +20,7 @@ using MediaBrowser.Common.Configuration;
 using MediaBrowser.Controller.MediaEncoding;
 using MediaBrowser.Model.Events;
 using MediaBrowser.Model.Globalization;
+using MediaBrowser.Model.Extensions;
 
 namespace Emby.Dlna.PlayTo
 {
@@ -589,7 +590,7 @@ namespace Emby.Dlna.PlayTo
                     StreamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger()).BuildVideoItem(new VideoOptions
                     {
                         ItemId = item.Id.ToString("N"),
-                        MediaSources = mediaSources,
+                        MediaSources = mediaSources.ToArray(mediaSources.Count),
                         Profile = profile,
                         DeviceId = deviceId,
                         MaxBitrate = profile.MaxStreamingBitrate,
@@ -609,7 +610,7 @@ namespace Emby.Dlna.PlayTo
                     StreamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger()).BuildAudioItem(new AudioOptions
                     {
                         ItemId = item.Id.ToString("N"),
-                        MediaSources = mediaSources,
+                        MediaSources = mediaSources.ToArray(mediaSources.Count),
                         Profile = profile,
                         DeviceId = deviceId,
                         MaxBitrate = profile.MaxStreamingBitrate,

+ 1 - 1
Emby.Dlna/PlayTo/PlayToManager.cs

@@ -182,7 +182,7 @@ namespace Emby.Dlna.PlayTo
                     {
                         PlayableMediaTypes = profile.GetSupportedMediaTypes(),
 
-                        SupportedCommands = new List<string>
+                        SupportedCommands = new string[]
                         {
                             GeneralCommandType.VolumeDown.ToString(),
                             GeneralCommandType.VolumeUp.ToString(),

+ 3 - 3
Emby.Server.Implementations/ApplicationHost.cs

@@ -1853,9 +1853,9 @@ namespace Emby.Server.Implementations
                 HasPendingRestart = HasPendingRestart,
                 Version = ApplicationVersion.ToString(),
                 WebSocketPortNumber = HttpPort,
-                FailedPluginAssemblies = FailedAssemblies.ToList(),
-                InProgressInstallations = InstallationManager.CurrentInstallations.Select(i => i.Item1).ToList(),
-                CompletedInstallations = InstallationManager.CompletedInstallations.ToList(),
+                FailedPluginAssemblies = FailedAssemblies.ToArray(),
+                InProgressInstallations = InstallationManager.CurrentInstallations.Select(i => i.Item1).ToArray(),
+                CompletedInstallations = InstallationManager.CompletedInstallations.ToArray(),
                 Id = SystemId,
                 ProgramDataPath = ApplicationPaths.ProgramDataPath,
                 LogPath = ApplicationPaths.LogDirectoryPath,

+ 12 - 20
Emby.Server.Implementations/Channels/ChannelManager.cs

@@ -182,10 +182,8 @@ namespace Emby.Server.Implementations.Channels
             {
             };
 
-            var returnList = (await _dtoService.GetBaseItemDtos(internalResult.Items, dtoOptions, user)
+            var returnItems = (await _dtoService.GetBaseItemDtos(internalResult.Items, dtoOptions, user)
                 .ConfigureAwait(false));
-            var returnItems = returnList
-                .ToArray(returnList.Count);
 
             var result = new QueryResult<BaseItemDto>
             {
@@ -464,14 +462,14 @@ namespace Emby.Server.Implementations.Channels
             return _libraryManager.GetItemById(id) as Channel;
         }
 
-        public IEnumerable<ChannelFeatures> GetAllChannelFeatures()
+        public ChannelFeatures[] GetAllChannelFeatures()
         {
             return _libraryManager.GetItemIds(new InternalItemsQuery
             {
                 IncludeItemTypes = new[] { typeof(Channel).Name },
                 SortBy = new[] { ItemSortBy.SortName }
 
-            }).Select(i => GetChannelFeatures(i.ToString("N")));
+            }).Select(i => GetChannelFeatures(i.ToString("N"))).ToArray();
         }
 
         public ChannelFeatures GetChannelFeatures(string id)
@@ -511,10 +509,10 @@ namespace Emby.Server.Implementations.Channels
             {
                 CanFilter = !features.MaxPageSize.HasValue,
                 CanSearch = provider is ISearchableChannel,
-                ContentTypes = features.ContentTypes,
-                DefaultSortFields = features.DefaultSortFields,
+                ContentTypes = features.ContentTypes.ToArray(),
+                DefaultSortFields = features.DefaultSortFields.ToArray(),
                 MaxPageSize = features.MaxPageSize,
-                MediaTypes = features.MediaTypes,
+                MediaTypes = features.MediaTypes.ToArray(),
                 SupportsSortOrderToggle = features.SupportsSortOrderToggle,
                 SupportsLatestMedia = supportsLatest,
                 Name = channel.Name,
@@ -566,12 +564,10 @@ namespace Emby.Server.Implementations.Channels
 
             var dtoOptions = new DtoOptions()
             {
-                Fields = query.Fields.ToList()
+                Fields = query.Fields
             };
 
-            var returnList = (await _dtoService.GetBaseItemDtos(items, dtoOptions, user).ConfigureAwait(false));
-            var returnItems = returnList
-                .ToArray(returnList.Count);
+            var returnItems = (await _dtoService.GetBaseItemDtos(items, dtoOptions, user).ConfigureAwait(false));
 
             var result = new QueryResult<BaseItemDto>
             {
@@ -833,13 +829,11 @@ namespace Emby.Server.Implementations.Channels
 
             var dtoOptions = new DtoOptions()
             {
-                Fields = query.Fields.ToList()
+                Fields = query.Fields
             };
 
-            var returnList = (await _dtoService.GetBaseItemDtos(internalResult.Items, dtoOptions, user)
+            var returnItems = (await _dtoService.GetBaseItemDtos(internalResult.Items, dtoOptions, user)
                 .ConfigureAwait(false));
-            var returnItems = returnList
-                .ToArray(returnList.Count);
 
             var result = new QueryResult<BaseItemDto>
             {
@@ -987,13 +981,11 @@ namespace Emby.Server.Implementations.Channels
 
             var dtoOptions = new DtoOptions()
             {
-                Fields = query.Fields.ToList()
+                Fields = query.Fields
             };
 
-            var returnList = (await _dtoService.GetBaseItemDtos(internalResult.Items, dtoOptions, user)
+            var returnItems = (await _dtoService.GetBaseItemDtos(internalResult.Items, dtoOptions, user)
                 .ConfigureAwait(false));
-            var returnItems = returnList
-                .ToArray(returnList.Count);
 
             var result = new QueryResult<BaseItemDto>
             {

+ 12 - 10
Emby.Server.Implementations/Collections/CollectionManager.cs

@@ -84,7 +84,7 @@ namespace Emby.Server.Implementations.Collections
                     ProviderIds = options.ProviderIds,
                     Shares = options.UserIds.Select(i => new Share
                     {
-                        UserId = i.ToString("N"),
+                        UserId = i,
                         CanEdit = true
 
                     }).ToList()
@@ -92,7 +92,7 @@ namespace Emby.Server.Implementations.Collections
 
                 await parentFolder.AddChild(collection, CancellationToken.None).ConfigureAwait(false);
 
-                if (options.ItemIdList.Count > 0)
+                if (options.ItemIdList.Length > 0)
                 {
                     await AddToCollection(collection.Id, options.ItemIdList, false, new MetadataRefreshOptions(_fileSystem)
                     {
@@ -149,12 +149,12 @@ namespace Emby.Server.Implementations.Collections
             return GetCollectionsFolder(string.Empty);
         }
 
-        public Task AddToCollection(Guid collectionId, IEnumerable<Guid> ids)
+        public Task AddToCollection(Guid collectionId, string[] ids)
         {
             return AddToCollection(collectionId, ids, true, new MetadataRefreshOptions(_fileSystem));
         }
 
-        private async Task AddToCollection(Guid collectionId, IEnumerable<Guid> ids, bool fireEvent, MetadataRefreshOptions refreshOptions)
+        private async Task AddToCollection(Guid collectionId, string[] ids, bool fireEvent, MetadataRefreshOptions refreshOptions)
         {
             var collection = _libraryManager.GetItemById(collectionId) as BoxSet;
 
@@ -165,11 +165,12 @@ namespace Emby.Server.Implementations.Collections
 
             var list = new List<LinkedChild>();
             var itemList = new List<BaseItem>();
-            var currentLinkedChildren = collection.GetLinkedChildren().ToList();
+            var currentLinkedChildrenIds = collection.GetLinkedChildren().Select(i => i.Id).ToList();
 
             foreach (var itemId in ids)
             {
-                var item = _libraryManager.GetItemById(itemId);
+                var guidId = new Guid(itemId);
+                var item = _libraryManager.GetItemById(guidId);
 
                 if (string.IsNullOrWhiteSpace(item.Path))
                 {
@@ -183,7 +184,7 @@ namespace Emby.Server.Implementations.Collections
 
                 itemList.Add(item);
 
-                if (currentLinkedChildren.All(i => i.Id != itemId))
+                if (!currentLinkedChildrenIds.Contains(guidId))
                 {
                     list.Add(LinkedChild.Create(item));
                 }
@@ -213,7 +214,7 @@ namespace Emby.Server.Implementations.Collections
             }
         }
 
-        public async Task RemoveFromCollection(Guid collectionId, IEnumerable<Guid> itemIds)
+        public async Task RemoveFromCollection(Guid collectionId, string[] itemIds)
         {
             var collection = _libraryManager.GetItemById(collectionId) as BoxSet;
 
@@ -227,9 +228,10 @@ namespace Emby.Server.Implementations.Collections
 
             foreach (var itemId in itemIds)
             {
-                var childItem = _libraryManager.GetItemById(itemId);
+                var guidId = new Guid(itemId);
+                var childItem = _libraryManager.GetItemById(guidId);
 
-                var child = collection.LinkedChildren.FirstOrDefault(i => (i.ItemId.HasValue && i.ItemId.Value == itemId) || (childItem != null && string.Equals(childItem.Path, i.Path, StringComparison.OrdinalIgnoreCase)));
+                var child = collection.LinkedChildren.FirstOrDefault(i => (i.ItemId.HasValue && i.ItemId.Value == guidId) || (childItem != null && string.Equals(childItem.Path, i.Path, StringComparison.OrdinalIgnoreCase)));
 
                 if (child == null)
                 {

+ 2 - 1
Emby.Server.Implementations/Data/SqliteItemRepository.cs

@@ -149,7 +149,7 @@ namespace Emby.Server.Implementations.Data
 
                                 "create table if not exists AncestorIds (ItemId GUID, AncestorId GUID, AncestorIdText TEXT, PRIMARY KEY (ItemId, AncestorId))",
                                 "create index if not exists idx_AncestorIds1 on AncestorIds(AncestorId)",
-                                "create index if not exists idx_AncestorIds2 on AncestorIds(AncestorIdText)",
+                                "create index if not exists idx_AncestorIds5 on AncestorIds(AncestorIdText,ItemId)",
 
                                 "create table if not exists ItemValues (ItemId GUID, Type INT, Value TEXT, CleanValue TEXT)",
 
@@ -308,6 +308,7 @@ namespace Emby.Server.Implementations.Data
                 "drop index if exists idx_TypeSeriesPresentationUniqueKey2",
                 "drop index if exists idx_AncestorIds3",
                 "drop index if exists idx_AncestorIds4",
+                "drop index if exists idx_AncestorIds2",
 
                 "create index if not exists idx_PathTypedBaseItems on TypedBaseItems(Path)",
                 "create index if not exists idx_ParentIdTypedBaseItems on TypedBaseItems(ParentId)",

+ 5 - 1
Emby.Server.Implementations/Devices/DeviceRepository.cs

@@ -11,6 +11,7 @@ using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Serialization;
 using MediaBrowser.Model.Session;
+using MediaBrowser.Model.Extensions;
 
 namespace Emby.Server.Implementations.Devices
 {
@@ -199,7 +200,10 @@ namespace Emby.Server.Implementations.Devices
                 }
 
                 history.DeviceId = deviceId;
-                history.FilesUploaded.Add(file);
+
+                var list = history.FilesUploaded.ToList();
+                list.Add(file);
+                history.FilesUploaded = list.ToArray(list.Count);
 
                 _json.SerializeToFile(history, path);
             }

+ 22 - 10
Emby.Server.Implementations/Dto/DtoService.cs

@@ -77,7 +77,7 @@ namespace Emby.Server.Implementations.Dto
         /// <param name="owner">The owner.</param>
         /// <returns>Task{DtoBaseItem}.</returns>
         /// <exception cref="System.ArgumentNullException">item</exception>
-        public BaseItemDto GetBaseItemDto(BaseItem item, List<ItemFields> fields, User user = null, BaseItem owner = null)
+        public BaseItemDto GetBaseItemDto(BaseItem item, ItemFields[] fields, User user = null, BaseItem owner = null)
         {
             var options = new DtoOptions
             {
@@ -87,7 +87,17 @@ namespace Emby.Server.Implementations.Dto
             return GetBaseItemDto(item, options, user, owner);
         }
 
-        public async Task<List<BaseItemDto>> GetBaseItemDtos(IEnumerable<BaseItem> items, DtoOptions options, User user = null, BaseItem owner = null)
+        public Task<BaseItemDto[]> GetBaseItemDtos(List<BaseItem> items, DtoOptions options, User user = null, BaseItem owner = null)
+        {
+            return GetBaseItemDtos(items, items.Count, options, user, owner);
+        }
+
+        public Task<BaseItemDto[]> GetBaseItemDtos(BaseItem[] items, DtoOptions options, User user = null, BaseItem owner = null)
+        {
+            return GetBaseItemDtos(items, items.Length, options, user, owner);
+        }
+
+        public async Task<BaseItemDto[]> GetBaseItemDtos(IEnumerable<BaseItem> items, int itemCount, DtoOptions options, User user = null, BaseItem owner = null)
         {
             if (items == null)
             {
@@ -101,7 +111,7 @@ namespace Emby.Server.Implementations.Dto
 
             var syncDictionary = GetSyncedItemProgress(options);
 
-            var list = new List<BaseItemDto>();
+            var returnItems = new BaseItemDto[itemCount];
             var programTuples = new List<Tuple<BaseItem, BaseItemDto>>();
             var channelTuples = new List<Tuple<BaseItemDto, LiveTvChannel>>();
 
@@ -109,6 +119,7 @@ namespace Emby.Server.Implementations.Dto
                 ? _providerManager.GetRefreshQueue()
                 : null;
 
+            var index = 0;
             foreach (var item in items)
             {
                 var dto = GetBaseItemDtoInternal(item, options, refreshQueue, user, owner);
@@ -144,7 +155,8 @@ namespace Emby.Server.Implementations.Dto
 
                 FillSyncInfo(dto, item, options, user, syncDictionary);
 
-                list.Add(dto);
+                returnItems[index] = dto;
+                index++;
             }
 
             if (programTuples.Count > 0)
@@ -157,7 +169,7 @@ namespace Emby.Server.Implementations.Dto
                 await _livetvManager().AddChannelInfo(channelTuples, options, user).ConfigureAwait(false);
             }
 
-            return list;
+            return returnItems;
         }
 
         public BaseItemDto GetBaseItemDto(BaseItem item, DtoOptions options, User user = null, BaseItem owner = null)
@@ -992,7 +1004,7 @@ namespace Emby.Server.Implementations.Dto
             {
                 dto.RemoteTrailers = hasTrailers != null ?
                     hasTrailers.RemoteTrailers :
-                    new MediaUrl[] {};
+                    new MediaUrl[] { };
             }
 
             dto.Name = item.Name;
@@ -1053,7 +1065,7 @@ namespace Emby.Server.Implementations.Dto
 
                 if (dto.Taglines == null)
                 {
-                    dto.Taglines = new string[]{};
+                    dto.Taglines = new string[] { };
                 }
             }
 
@@ -1243,17 +1255,17 @@ namespace Emby.Server.Implementations.Dto
 
                 if (iHasMediaSources != null)
                 {
-                    List<MediaStream> mediaStreams;
+                    MediaStream[] mediaStreams;
 
                     if (dto.MediaSources != null && dto.MediaSources.Count > 0)
                     {
                         mediaStreams = dto.MediaSources.Where(i => new Guid(i.Id) == item.Id)
                             .SelectMany(i => i.MediaStreams)
-                            .ToList();
+                            .ToArray();
                     }
                     else
                     {
-                        mediaStreams = _mediaSourceManager().GetStaticMediaSources(iHasMediaSources, true).First().MediaStreams;
+                        mediaStreams = _mediaSourceManager().GetStaticMediaSources(iHasMediaSources, true).First().MediaStreams.ToArray();
                     }
 
                     dto.MediaStreams = mediaStreams;

+ 5 - 5
Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs

@@ -367,15 +367,15 @@ namespace Emby.Server.Implementations.EntryPoints
 
             return new LibraryUpdateInfo
             {
-                ItemsAdded = itemsAdded.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToList(),
+                ItemsAdded = itemsAdded.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToArray(),
 
-                ItemsUpdated = itemsUpdated.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToList(),
+                ItemsUpdated = itemsUpdated.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToArray(),
 
-                ItemsRemoved = itemsRemoved.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, true)).Select(i => i.Id.ToString("N")).Distinct().ToList(),
+                ItemsRemoved = itemsRemoved.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, true)).Select(i => i.Id.ToString("N")).Distinct().ToArray(),
 
-                FoldersAddedTo = foldersAddedTo.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToList(),
+                FoldersAddedTo = foldersAddedTo.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToArray(),
 
-                FoldersRemovedFrom = foldersRemovedFrom.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToList()
+                FoldersRemovedFrom = foldersRemovedFrom.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToArray()
             };
         }
 

+ 1 - 1
Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs

@@ -126,7 +126,7 @@ namespace Emby.Server.Implementations.EntryPoints
                             dto.ItemId = i.Id.ToString("N");
                             return dto;
                         })
-                        .ToList();
+                        .ToArray();
 
                     var info = new UserDataChangeInfo
                     {

+ 1 - 1
Emby.Server.Implementations/HttpServer/HttpListenerHost.cs

@@ -162,7 +162,7 @@ namespace Emby.Server.Implementations.HttpServer
             return serviceType;
         }
 
-        public void AddServiceInfo(Type serviceType, Type requestType, Type responseType)
+        public void AddServiceInfo(Type serviceType, Type requestType)
         {
             ServiceOperationsMap[requestType] = serviceType;
         }

+ 3 - 3
Emby.Server.Implementations/IO/LibraryMonitor.cs

@@ -35,7 +35,7 @@ namespace Emby.Server.Implementations.IO
         /// <summary>
         /// Any file name ending in any of these will be ignored by the watchers
         /// </summary>
-        private readonly IReadOnlyList<string> _alwaysIgnoreFiles = new List<string>
+        private readonly string[] _alwaysIgnoreFiles = new string[]
         {
             "small.jpg",
             "albumart.jpg",
@@ -45,7 +45,7 @@ namespace Emby.Server.Implementations.IO
             "TempSBE"
         };
 
-        private readonly IReadOnlyList<string> _alwaysIgnoreSubstrings = new List<string>
+        private readonly string[] _alwaysIgnoreSubstrings = new string[]
         {
             // Synology
             "eaDir",
@@ -54,7 +54,7 @@ namespace Emby.Server.Implementations.IO
             ".actors"
         };
 
-        private readonly IReadOnlyList<string> _alwaysIgnoreExtensions = new List<string>
+        private readonly string[] _alwaysIgnoreExtensions = new string[]
         {
             // thumbs.db
             ".db",

+ 3 - 3
Emby.Server.Implementations/Library/LibraryManager.cs

@@ -1208,7 +1208,7 @@ namespace Emby.Server.Implementations.Library
                 .Where(i => string.Equals(ShortcutFileExtension, Path.GetExtension(i), StringComparison.OrdinalIgnoreCase))
                     .Select(_fileSystem.ResolveShortcut)
                     .OrderBy(i => i)
-                    .ToList(),
+                    .ToArray(),
 
                 CollectionType = GetCollectionType(dir)
             };
@@ -1554,7 +1554,7 @@ namespace Emby.Server.Implementations.Library
                     IncludeHidden = true,
                     IncludeExternalContent = allowExternalContent
 
-                }, CancellationToken.None).Result.ToList();
+                }, CancellationToken.None).Result;
 
                 query.TopParentIds = userViews.SelectMany(i => GetTopParentIdsForQuery(i, user)).Select(i => i.ToString("N")).ToArray();
             }
@@ -3061,7 +3061,7 @@ namespace Emby.Server.Implementations.Library
             var topLibraryFolders = GetUserRootFolder().Children.ToList();
             var info = GetVirtualFolderInfo(virtualFolderPath, topLibraryFolders, null);
 
-            if (info.Locations.Count > 0 && info.Locations.Count != options.PathInfos.Length)
+            if (info.Locations.Length > 0 && info.Locations.Length != options.PathInfos.Length)
             {
                 var list = options.PathInfos.ToList();
 

+ 1 - 1
Emby.Server.Implementations/Library/SearchEngine.cs

@@ -181,7 +181,7 @@ namespace Emby.Server.Implementations.Library
 
                 DtoOptions = new DtoOptions
                 {
-                    Fields = new List<ItemFields>
+                    Fields = new ItemFields[]
                     {
                          ItemFields.AirTime,
                          ItemFields.DateCreated,

+ 2 - 2
Emby.Server.Implementations/Library/UserDataManager.cs

@@ -187,11 +187,11 @@ namespace Emby.Server.Implementations.Library
             var userData = GetUserData(user.Id, item);
             var dto = GetUserItemDataDto(userData);
 
-            item.FillUserDataDtoValues(dto, userData, null, user, new List<ItemFields>());
+            item.FillUserDataDtoValues(dto, userData, null, user, new ItemFields[]{});
             return dto;
         }
 
-        public UserItemDataDto GetUserDataDto(IHasUserData item, BaseItemDto itemDto, User user, List<ItemFields> fields)
+        public UserItemDataDto GetUserDataDto(IHasUserData item, BaseItemDto itemDto, User user, ItemFields[] fields)
         {
             var userData = GetUserData(user.Id, item);
             var dto = GetUserItemDataDto(userData);

+ 3 - 2
Emby.Server.Implementations/Library/UserViewManager.cs

@@ -39,7 +39,7 @@ namespace Emby.Server.Implementations.Library
             _config = config;
         }
 
-        public async Task<IEnumerable<Folder>> GetUserViews(UserViewQuery query, CancellationToken cancellationToken)
+        public async Task<Folder[]> GetUserViews(UserViewQuery query, CancellationToken cancellationToken)
         {
             var user = _userManager.GetUserById(query.UserId);
 
@@ -154,7 +154,8 @@ namespace Emby.Server.Implementations.Library
                     return index == -1 ? int.MaxValue : index;
                 })
                 .ThenBy(sorted.IndexOf)
-                .ThenBy(i => i.SortName);
+                .ThenBy(i => i.SortName)
+                .ToArray();
         }
 
         public Task<UserView> GetUserSubView(string name, string parentId, string type, string sortName, CancellationToken cancellationToken)

+ 7 - 7
Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs

@@ -208,7 +208,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
                     continue;
                 }
 
-                if (virtualFolder.Locations.Count == 1)
+                if (virtualFolder.Locations.Length == 1)
                 {
                     // remove entire virtual folder
                     try
@@ -458,7 +458,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
             return GetEpgChannelFromTunerChannel(info, tunerChannel, epgChannels);
         }
 
-        private string GetMappedChannel(string channelId, List<NameValuePair> mappings)
+        private string GetMappedChannel(string channelId, NameValuePair[] mappings)
         {
             foreach (NameValuePair mapping in mappings)
             {
@@ -472,10 +472,10 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
 
         private ChannelInfo GetEpgChannelFromTunerChannel(ListingsProviderInfo info, ChannelInfo tunerChannel, List<ChannelInfo> epgChannels)
         {
-            return GetEpgChannelFromTunerChannel(info.ChannelMappings.ToList(), tunerChannel, epgChannels);
+            return GetEpgChannelFromTunerChannel(info.ChannelMappings, tunerChannel, epgChannels);
         }
 
-        public ChannelInfo GetEpgChannelFromTunerChannel(List<NameValuePair> mappings, ChannelInfo tunerChannel, List<ChannelInfo> epgChannels)
+        public ChannelInfo GetEpgChannelFromTunerChannel(NameValuePair[] mappings, ChannelInfo tunerChannel, List<ChannelInfo> epgChannels)
         {
             if (!string.IsNullOrWhiteSpace(tunerChannel.Id))
             {
@@ -2591,7 +2591,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
             {
                 list.Add(new VirtualFolderInfo
                 {
-                    Locations = new List<string> { defaultFolder },
+                    Locations = new string[] { defaultFolder },
                     Name = defaultName
                 });
             }
@@ -2601,7 +2601,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
             {
                 list.Add(new VirtualFolderInfo
                 {
-                    Locations = new List<string> { customPath },
+                    Locations = new string[] { customPath },
                     Name = "Recorded Movies",
                     CollectionType = CollectionType.Movies
                 });
@@ -2612,7 +2612,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
             {
                 list.Add(new VirtualFolderInfo
                 {
-                    Locations = new List<string> { customPath },
+                    Locations = new string[] { customPath },
                     Name = "Recorded Shows",
                     CollectionType = CollectionType.TvShows
                 });

+ 19 - 32
Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs

@@ -15,6 +15,8 @@ using System.Threading;
 using System.Threading.Tasks;
 using MediaBrowser.Controller.Entities.TV;
 using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Extensions;
+using MediaBrowser.Model.Querying;
 
 namespace Emby.Server.Implementations.LiveTv
 {
@@ -110,7 +112,7 @@ namespace Emby.Server.Implementations.LiveTv
                 PostPaddingSeconds = info.PostPaddingSeconds,
                 IsPostPaddingRequired = info.IsPostPaddingRequired,
                 IsPrePaddingRequired = info.IsPrePaddingRequired,
-                Days = info.Days,
+                Days = info.Days.ToArray(),
                 Priority = info.Priority,
                 RecordAnyChannel = info.RecordAnyChannel,
                 RecordAnyTime = info.RecordAnyTime,
@@ -135,7 +137,7 @@ namespace Emby.Server.Implementations.LiveTv
                 dto.ProgramId = GetInternalProgramId(service.Name, info.ProgramId).ToString("N");
             }
 
-            dto.DayPattern = info.Days == null ? null : GetDayPattern(info.Days);
+            dto.DayPattern = info.Days == null ? null : GetDayPattern(info.Days.ToArray(info.Days.Count));
 
             FillImages(dto, info.Name, info.SeriesId);
 
@@ -150,10 +152,7 @@ namespace Emby.Server.Implementations.LiveTv
                 Name = seriesName,
                 Limit = 1,
                 ImageTypes = new ImageType[] { ImageType.Thumb },
-                DtoOptions = new DtoOptions
-                {
-                    Fields = new List<MediaBrowser.Model.Querying.ItemFields>()
-                }
+                DtoOptions = new DtoOptions(false)
 
             }).FirstOrDefault();
 
@@ -196,10 +195,7 @@ namespace Emby.Server.Implementations.LiveTv
                     ExternalSeriesId = programSeriesId,
                     Limit = 1,
                     ImageTypes = new ImageType[] { ImageType.Primary },
-                    DtoOptions = new DtoOptions
-                    {
-                        Fields = new List<MediaBrowser.Model.Querying.ItemFields>()
-                    }
+                    DtoOptions = new DtoOptions(false)
 
                 }).FirstOrDefault();
 
@@ -248,10 +244,7 @@ namespace Emby.Server.Implementations.LiveTv
                 Name = seriesName,
                 Limit = 1,
                 ImageTypes = new ImageType[] { ImageType.Thumb },
-                DtoOptions = new DtoOptions
-                {
-                    Fields = new List<MediaBrowser.Model.Querying.ItemFields>()
-                }
+                DtoOptions = new DtoOptions(false)
 
             }).FirstOrDefault();
 
@@ -274,7 +267,7 @@ namespace Emby.Server.Implementations.LiveTv
                 {
                     try
                     {
-                        dto.ParentBackdropImageTags = new List<string>
+                        dto.ParentBackdropImageTags = new string[]
                             {
                                 _imageProcessor.GetImageCacheTag(librarySeries, image)
                             };
@@ -294,10 +287,7 @@ namespace Emby.Server.Implementations.LiveTv
                     Name = seriesName,
                     Limit = 1,
                     ImageTypes = new ImageType[] { ImageType.Primary },
-                    DtoOptions = new DtoOptions
-                    {
-                        Fields = new List<MediaBrowser.Model.Querying.ItemFields>()
-                    }
+                    DtoOptions = new DtoOptions(false)
 
                 }).FirstOrDefault() ?? _libraryManager.GetItemList(new InternalItemsQuery
                 {
@@ -305,10 +295,7 @@ namespace Emby.Server.Implementations.LiveTv
                     ExternalSeriesId = programSeriesId,
                     Limit = 1,
                     ImageTypes = new ImageType[] { ImageType.Primary },
-                    DtoOptions = new DtoOptions
-                    {
-                        Fields = new List<MediaBrowser.Model.Querying.ItemFields>()
-                    }
+                    DtoOptions = new DtoOptions(false)
 
                 }).FirstOrDefault();
 
@@ -327,14 +314,14 @@ namespace Emby.Server.Implementations.LiveTv
                         }
                     }
 
-                    if (dto.ParentBackdropImageTags == null || dto.ParentBackdropImageTags.Count == 0)
+                    if (dto.ParentBackdropImageTags == null || dto.ParentBackdropImageTags.Length == 0)
                     {
                         image = program.GetImageInfo(ImageType.Backdrop, 0);
                         if (image != null)
                         {
                             try
                             {
-                                dto.ParentBackdropImageTags = new List<string>
+                                dto.ParentBackdropImageTags = new string[]
                             {
                                 _imageProcessor.GetImageCacheTag(program, image)
                             };
@@ -349,24 +336,24 @@ namespace Emby.Server.Implementations.LiveTv
             }
         }
 
-        public DayPattern? GetDayPattern(List<DayOfWeek> days)
+        public DayPattern? GetDayPattern(DayOfWeek[] days)
         {
             DayPattern? pattern = null;
 
-            if (days.Count > 0)
+            if (days.Length > 0)
             {
-                if (days.Count == 7)
+                if (days.Length == 7)
                 {
                     pattern = DayPattern.Daily;
                 }
-                else if (days.Count == 2)
+                else if (days.Length == 2)
                 {
                     if (days.Contains(DayOfWeek.Saturday) && days.Contains(DayOfWeek.Sunday))
                     {
                         pattern = DayPattern.Weekends;
                     }
                 }
-                else if (days.Count == 5)
+                else if (days.Length == 5)
                 {
                     if (days.Contains(DayOfWeek.Monday) && days.Contains(DayOfWeek.Tuesday) && days.Contains(DayOfWeek.Wednesday) && days.Contains(DayOfWeek.Thursday) && days.Contains(DayOfWeek.Friday))
                     {
@@ -384,7 +371,7 @@ namespace Emby.Server.Implementations.LiveTv
             {
                 Name = info.Name,
                 Id = info.Id,
-                Clients = info.Clients,
+                Clients = info.Clients.ToArray(),
                 ProgramName = info.ProgramName,
                 SourceType = info.SourceType,
                 Status = info.Status,
@@ -543,7 +530,7 @@ namespace Emby.Server.Implementations.LiveTv
                 PostPaddingSeconds = dto.PostPaddingSeconds,
                 IsPostPaddingRequired = dto.IsPostPaddingRequired,
                 IsPrePaddingRequired = dto.IsPrePaddingRequired,
-                Days = dto.Days,
+                Days = dto.Days.ToList(),
                 Priority = dto.Priority,
                 RecordAnyChannel = dto.RecordAnyChannel,
                 RecordAnyTime = dto.RecordAnyTime,

+ 49 - 46
Emby.Server.Implementations/LiveTv/LiveTvManager.cs

@@ -985,9 +985,8 @@ namespace Emby.Server.Implementations.LiveTv
 
             var queryResult = _libraryManager.QueryItems(internalQuery);
 
-            var returnList = (await _dtoService.GetBaseItemDtos(queryResult.Items, options, user)
+            var returnArray = (await _dtoService.GetBaseItemDtos(queryResult.Items, options, user)
                 .ConfigureAwait(false));
-            var returnArray = returnList.ToArray(returnList.Count);
 
             var result = new QueryResult<BaseItemDto>
             {
@@ -998,7 +997,7 @@ namespace Emby.Server.Implementations.LiveTv
             return result;
         }
 
-        public async Task<QueryResult<LiveTvProgram>> GetRecommendedProgramsInternal(RecommendedProgramQuery query, DtoOptions options, CancellationToken cancellationToken)
+        public async Task<QueryResult<BaseItem>> GetRecommendedProgramsInternal(RecommendedProgramQuery query, DtoOptions options, CancellationToken cancellationToken)
         {
             var user = _userManager.GetUserById(query.UserId);
 
@@ -1036,10 +1035,10 @@ namespace Emby.Server.Implementations.LiveTv
                 }
             }
 
-            var programList = _libraryManager.QueryItems(internalQuery).Items.Cast<LiveTvProgram>().ToList();
-            var totalCount = programList.Count;
+            var programList = _libraryManager.QueryItems(internalQuery).Items;
+            var totalCount = programList.Length;
 
-            IOrderedEnumerable<LiveTvProgram> orderedPrograms = programList.OrderBy(i => i.StartDate.Date);
+            IOrderedEnumerable<LiveTvProgram> orderedPrograms = programList.Cast<LiveTvProgram>().OrderBy(i => i.StartDate.Date);
 
             if (query.IsAiring ?? false)
             {
@@ -1047,14 +1046,14 @@ namespace Emby.Server.Implementations.LiveTv
                     .ThenByDescending(i => GetRecommendationScore(i, user.Id, true));
             }
 
-            IEnumerable<LiveTvProgram> programs = orderedPrograms;
+            IEnumerable<BaseItem> programs = orderedPrograms;
 
             if (query.Limit.HasValue)
             {
                 programs = programs.Take(query.Limit.Value);
             }
 
-            var result = new QueryResult<LiveTvProgram>
+            var result = new QueryResult<BaseItem>
             {
                 Items = programs.ToArray(),
                 TotalRecordCount = totalCount
@@ -1071,9 +1070,8 @@ namespace Emby.Server.Implementations.LiveTv
 
             var user = _userManager.GetUserById(query.UserId);
 
-            var returnList = (await _dtoService.GetBaseItemDtos(internalResult.Items, options, user)
+            var returnArray = (await _dtoService.GetBaseItemDtos(internalResult.Items, options, user)
                 .ConfigureAwait(false));
-            var returnArray = returnList.ToArray(returnList.Count);
 
             var result = new QueryResult<BaseItemDto>
             {
@@ -1262,8 +1260,8 @@ namespace Emby.Server.Implementations.LiveTv
                 progress.Report(100 * percent);
             }
 
-            await CleanDatabaseInternal(newChannelIdList, new[] { typeof(LiveTvChannel).Name }, progress, cancellationToken).ConfigureAwait(false);
-            await CleanDatabaseInternal(newProgramIdList, new[] { typeof(LiveTvProgram).Name }, progress, cancellationToken).ConfigureAwait(false);
+            await CleanDatabaseInternal(newChannelIdList.ToArray(), new[] { typeof(LiveTvChannel).Name }, progress, cancellationToken).ConfigureAwait(false);
+            await CleanDatabaseInternal(newProgramIdList.ToArray(), new[] { typeof(LiveTvProgram).Name }, progress, cancellationToken).ConfigureAwait(false);
 
             var coreService = _services.OfType<EmbyTV.EmbyTV>().FirstOrDefault();
 
@@ -1275,8 +1273,11 @@ namespace Emby.Server.Implementations.LiveTv
 
             // Load these now which will prefetch metadata
             var dtoOptions = new DtoOptions();
-            dtoOptions.Fields.Remove(ItemFields.SyncInfo);
-            dtoOptions.Fields.Remove(ItemFields.BasicSyncInfo);
+            var fields = dtoOptions.Fields.ToList();
+            fields.Remove(ItemFields.SyncInfo);
+            fields.Remove(ItemFields.BasicSyncInfo);
+            dtoOptions.Fields = fields.ToArray(fields.Count);
+
             await GetRecordings(new RecordingQuery(), dtoOptions, cancellationToken).ConfigureAwait(false);
 
             progress.Report(100);
@@ -1446,14 +1447,14 @@ namespace Emby.Server.Implementations.LiveTv
             return new Tuple<List<Guid>, List<Guid>>(channels, programs);
         }
 
-        private async Task CleanDatabaseInternal(List<Guid> currentIdList, string[] validTypes, IProgress<double> progress, CancellationToken cancellationToken)
+        private async Task CleanDatabaseInternal(Guid[] currentIdList, string[] validTypes, IProgress<double> progress, CancellationToken cancellationToken)
         {
             var list = _itemRepo.GetItemIdsList(new InternalItemsQuery
             {
                 IncludeItemTypes = validTypes,
                 DtoOptions = new DtoOptions(false)
 
-            }).ToList();
+            });
 
             var numComplete = 0;
 
@@ -1543,7 +1544,7 @@ namespace Emby.Server.Implementations.LiveTv
 
                 var idList = await Task.WhenAll(recordingTasks).ConfigureAwait(false);
 
-                await CleanDatabaseInternal(idList.ToList(), new[] { typeof(LiveTvVideoRecording).Name, typeof(LiveTvAudioRecording).Name }, new SimpleProgress<double>(), cancellationToken).ConfigureAwait(false);
+                await CleanDatabaseInternal(idList, new[] { typeof(LiveTvVideoRecording).Name, typeof(LiveTvAudioRecording).Name }, new SimpleProgress<double>(), cancellationToken).ConfigureAwait(false);
 
                 _lastRecordingRefreshTime = DateTime.UtcNow;
             }
@@ -1701,11 +1702,9 @@ namespace Emby.Server.Implementations.LiveTv
                 DtoOptions = options
             });
 
-            var returnList = (await _dtoService.GetBaseItemDtos(internalResult.Items, options, user)
+            var returnArray = (await _dtoService.GetBaseItemDtos(internalResult.Items, options, user)
                 .ConfigureAwait(false));
 
-            var returnArray = returnList.ToArray(returnList.Count);
-
             return new QueryResult<BaseItemDto>
             {
                 Items = returnArray,
@@ -1841,7 +1840,7 @@ 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, ItemFields[] fields, User user = null)
         {
             var programTuples = new List<Tuple<BaseItemDto, string, string, string>>();
             var hasChannelImage = fields.Contains(ItemFields.ChannelImage);
@@ -1961,7 +1960,7 @@ namespace Emby.Server.Implementations.LiveTv
 
             if (dto.MediaStreams == null)
             {
-                dto.MediaStreams = dto.MediaSources.SelectMany(i => i.MediaStreams).ToList();
+                dto.MediaStreams = dto.MediaSources.SelectMany(i => i.MediaStreams).ToArray();
             }
 
             if (info.Status == RecordingStatus.InProgress && info.EndDate.HasValue)
@@ -1995,9 +1994,8 @@ namespace Emby.Server.Implementations.LiveTv
 
             var internalResult = await GetInternalRecordings(query, options, cancellationToken).ConfigureAwait(false);
 
-            var returnList = (await _dtoService.GetBaseItemDtos(internalResult.Items, options, user)
+            var returnArray = (await _dtoService.GetBaseItemDtos(internalResult.Items, options, user)
                 .ConfigureAwait(false));
-            var returnArray = returnList.ToArray(returnList.Count);
 
             return new QueryResult<BaseItemDto>
             {
@@ -2479,7 +2477,7 @@ namespace Emby.Server.Implementations.LiveTv
             var defaults = await GetNewTimerDefaultsInternal(cancellationToken, program).ConfigureAwait(false);
             var info = _tvDtoService.GetSeriesTimerInfoDto(defaults.Item1, defaults.Item2, null);
 
-            info.Days = defaults.Item1.Days;
+            info.Days = defaults.Item1.Days.ToArray();
 
             info.DayPattern = _tvDtoService.GetDayPattern(info.Days);
 
@@ -2656,8 +2654,7 @@ namespace Emby.Server.Implementations.LiveTv
 
             var series = recordings
                 .Where(i => i.IsSeries)
-                .ToLookup(i => i.Name, StringComparer.OrdinalIgnoreCase)
-                .ToList();
+                .ToLookup(i => i.Name, StringComparer.OrdinalIgnoreCase);
 
             groups.AddRange(series.OrderByString(i => i.Key).Select(i => new BaseItemDto
             {
@@ -2762,7 +2759,7 @@ namespace Emby.Server.Implementations.LiveTv
             }
         }
 
-        private async Task<IEnumerable<LiveTvServiceInfo>> GetServiceInfos(CancellationToken cancellationToken)
+        private async Task<LiveTvServiceInfo[]> GetServiceInfos(CancellationToken cancellationToken)
         {
             var tasks = Services.Select(i => GetServiceInfo(i, cancellationToken));
 
@@ -2806,7 +2803,7 @@ namespace Emby.Server.Implementations.LiveTv
 
                     return dto;
 
-                }).ToList();
+                }).ToArray();
             }
             catch (Exception ex)
             {
@@ -2822,25 +2819,24 @@ namespace Emby.Server.Implementations.LiveTv
         public async Task<LiveTvInfo> GetLiveTvInfo(CancellationToken cancellationToken)
         {
             var services = await GetServiceInfos(CancellationToken.None).ConfigureAwait(false);
-            var servicesList = services.ToList();
 
             var info = new LiveTvInfo
             {
-                Services = servicesList.ToList(),
-                IsEnabled = servicesList.Count > 0
+                Services = services,
+                IsEnabled = services.Length > 0
             };
 
             info.EnabledUsers = _userManager.Users
                 .Where(IsLiveTvEnabled)
                 .Select(i => i.Id.ToString("N"))
-                .ToList();
+                .ToArray();
 
             return info;
         }
 
         private bool IsLiveTvEnabled(User user)
         {
-            return user.Policy.EnableLiveTvAccess && (Services.Count > 1 || GetConfiguration().TunerHosts.Count > 0);
+            return user.Policy.EnableLiveTvAccess && (Services.Count > 1 || GetConfiguration().TunerHosts.Length > 0);
         }
 
         public IEnumerable<User> GetEnabledUsers()
@@ -2880,10 +2876,13 @@ namespace Emby.Server.Implementations.LiveTv
 
         private void RemoveFields(DtoOptions options)
         {
-            options.Fields.Remove(ItemFields.CanDelete);
-            options.Fields.Remove(ItemFields.CanDownload);
-            options.Fields.Remove(ItemFields.DisplayPreferencesId);
-            options.Fields.Remove(ItemFields.Etag);
+            var fields = options.Fields.ToList();
+
+            fields.Remove(ItemFields.CanDelete);
+            fields.Remove(ItemFields.CanDownload);
+            fields.Remove(ItemFields.DisplayPreferencesId);
+            fields.Remove(ItemFields.Etag);
+            options.Fields = fields.ToArray(fields.Count);
         }
 
         public async Task<Folder> GetInternalLiveTvFolder(CancellationToken cancellationToken)
@@ -2911,12 +2910,14 @@ namespace Emby.Server.Implementations.LiveTv
 
             var config = GetConfiguration();
 
-            var index = config.TunerHosts.FindIndex(i => string.Equals(i.Id, info.Id, StringComparison.OrdinalIgnoreCase));
+            var list = config.TunerHosts.ToList();
+            var index = list.FindIndex(i => string.Equals(i.Id, info.Id, StringComparison.OrdinalIgnoreCase));
 
             if (index == -1 || string.IsNullOrWhiteSpace(info.Id))
             {
                 info.Id = Guid.NewGuid().ToString("N");
-                config.TunerHosts.Add(info);
+                list.Add(info);
+                config.TunerHosts = list.ToArray(list.Count);
             }
             else
             {
@@ -2948,12 +2949,14 @@ namespace Emby.Server.Implementations.LiveTv
 
             var config = GetConfiguration();
 
-            var index = config.ListingProviders.FindIndex(i => string.Equals(i.Id, info.Id, StringComparison.OrdinalIgnoreCase));
+            var list = config.ListingProviders.ToList();
+            var index = list.FindIndex(i => string.Equals(i.Id, info.Id, StringComparison.OrdinalIgnoreCase));
 
             if (index == -1 || string.IsNullOrWhiteSpace(info.Id))
             {
                 info.Id = Guid.NewGuid().ToString("N");
-                config.ListingProviders.Add(info);
+                list.Add(info);
+                config.ListingProviders = list.ToArray(list.Count);
                 info.EnableNewProgramIds = true;
             }
             else
@@ -2972,7 +2975,7 @@ namespace Emby.Server.Implementations.LiveTv
         {
             var config = GetConfiguration();
 
-            config.ListingProviders = config.ListingProviders.Where(i => !string.Equals(id, i.Id, StringComparison.OrdinalIgnoreCase)).ToList();
+            config.ListingProviders = config.ListingProviders.Where(i => !string.Equals(id, i.Id, StringComparison.OrdinalIgnoreCase)).ToArray();
 
             _config.SaveConfiguration("livetv", config);
             _taskManager.CancelIfRunningAndQueue<RefreshChannelsScheduledTask>();
@@ -3004,7 +3007,7 @@ namespace Emby.Server.Implementations.LiveTv
             var providerChannels = await GetChannelsFromListingsProviderData(providerId, CancellationToken.None)
                      .ConfigureAwait(false);
 
-            var mappings = listingsProviderInfo.ChannelMappings.ToList();
+            var mappings = listingsProviderInfo.ChannelMappings;
 
             var tunerChannelMappings =
                 tunerChannels.Select(i => GetTunerChannelMapping(i, mappings, providerChannels)).ToList();
@@ -3014,7 +3017,7 @@ namespace Emby.Server.Implementations.LiveTv
             return tunerChannelMappings.First(i => string.Equals(i.Id, tunerChannelId, StringComparison.OrdinalIgnoreCase));
         }
 
-        public TunerChannelMapping GetTunerChannelMapping(ChannelInfo tunerChannel, List<NameValuePair> mappings, List<ChannelInfo> epgChannels)
+        public TunerChannelMapping GetTunerChannelMapping(ChannelInfo tunerChannel, NameValuePair[] mappings, List<ChannelInfo> epgChannels)
         {
             var result = new TunerChannelMapping
             {
@@ -3078,7 +3081,7 @@ namespace Emby.Server.Implementations.LiveTv
             if (string.Equals(feature, "dvr-l", StringComparison.OrdinalIgnoreCase))
             {
                 var config = GetConfiguration();
-                if (config.TunerHosts.Count > 0 &&
+                if (config.TunerHosts.Length > 0 &&
                     config.ListingProviders.Count(i => (i.EnableAllTuners || i.EnabledTuners.Length > 0) && string.Equals(i.Type, SchedulesDirect.TypeName, StringComparison.OrdinalIgnoreCase)) > 0)
                 {
                     return Task.FromResult(new MBRegistrationRecord

+ 1 - 1
Emby.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs

@@ -62,7 +62,7 @@ namespace Emby.Server.Implementations.LiveTv
 
         public bool IsHidden
         {
-            get { return _liveTvManager.Services.Count == 1 && GetConfiguration().TunerHosts.Count == 0; }
+            get { return _liveTvManager.Services.Count == 1 && GetConfiguration().TunerHosts.Length == 0; }
         }
 
         public bool IsEnabled

+ 5 - 5
Emby.Server.Implementations/LiveTv/TunerHosts/MulticastStream.cs

@@ -24,8 +24,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
 
         public async Task CopyUntilCancelled(Stream source, Action onStarted, CancellationToken cancellationToken)
         {
-            byte[] buffer = new byte[BufferSize];
-
             if (source == null)
             {
                 throw new ArgumentNullException("source");
@@ -35,6 +33,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
             {
                 cancellationToken.ThrowIfCancellationRequested();
 
+                byte[] buffer = new byte[BufferSize];
+
                 var bytesRead = source.Read(buffer, 0, buffer.Length);
 
                 if (bytesRead > 0)
@@ -47,12 +47,12 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
                     //}
                     //else
                     {
-                        byte[] copy = new byte[bytesRead];
-                        Buffer.BlockCopy(buffer, 0, copy, 0, bytesRead);
+                        //byte[] copy = new byte[bytesRead];
+                        //Buffer.BlockCopy(buffer, 0, copy, 0, bytesRead);
 
                         foreach (var stream in allStreams)
                         {
-                            stream.Value.Queue(copy, 0, copy.Length);
+                            stream.Value.Queue(buffer, 0, bytesRead);
                         }
                     }
 

+ 4 - 20
Emby.Server.Implementations/LiveTv/TunerHosts/QueueStream.cs

@@ -13,7 +13,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
     public class QueueStream
     {
         private readonly Stream _outputStream;
-        private readonly ConcurrentQueue<Tuple<byte[], int, int>> _queue = new ConcurrentQueue<Tuple<byte[], int, int>>();
+        private readonly BlockingCollection<Tuple<byte[], int, int>> _queue = new BlockingCollection<Tuple<byte[], int, int>>();
         public TaskCompletionSource<bool> TaskCompletion { get; private set; }
 
         public Action<QueueStream> OnFinished { get; set; }
@@ -29,7 +29,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
 
         public void Queue(byte[] bytes, int offset, int count)
         {
-            _queue.Enqueue(new Tuple<byte[], int, int>(bytes, offset, count));
+            _queue.Add(new Tuple<byte[], int, int>(bytes, offset, count));
         }
 
         public void Start(CancellationToken cancellationToken)
@@ -37,17 +37,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
             Task.Run(() => StartInternal(cancellationToken));
         }
 
-        private Tuple<byte[], int, int> Dequeue()
-        {
-            Tuple<byte[], int, int> result;
-            if (_queue.TryDequeue(out result))
-            {
-                return result;
-            }
-
-            return null;
-        }
-
         private void OnClosed()
         {
             GC.Collect();
@@ -79,7 +68,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
             }
         }
 
-        private async Task StartInternal(CancellationToken cancellationToken)
+        private void StartInternal(CancellationToken cancellationToken)
         {
             try
             {
@@ -87,15 +76,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
                 {
                     cancellationToken.ThrowIfCancellationRequested();
 
-                    var result = Dequeue();
-                    if (result != null)
+                    foreach (var result in _queue.GetConsumingEnumerable())
                     {
                         _outputStream.Write(result.Item1, result.Item2, result.Item3);
                     }
-                    else
-                    {
-                        await Task.Delay(50, cancellationToken).ConfigureAwait(false);
-                    }
                 }
             }
             catch (OperationCanceledException)

+ 9 - 9
Emby.Server.Implementations/Localization/LocalizationManager.cs

@@ -132,7 +132,7 @@ namespace Emby.Server.Implementations.Localization
         /// Gets the cultures.
         /// </summary>
         /// <returns>IEnumerable{CultureDto}.</returns>
-        public List<CultureDto> GetCultures()
+        public CultureDto[] GetCultures()
         {
             var type = GetType();
             var path = type.Namespace + ".iso6392.txt";
@@ -169,21 +169,21 @@ namespace Emby.Server.Implementations.Localization
             return list.Where(i => !string.IsNullOrWhiteSpace(i.Name) &&
                 !string.IsNullOrWhiteSpace(i.DisplayName) &&
                 !string.IsNullOrWhiteSpace(i.ThreeLetterISOLanguageName) &&
-                !string.IsNullOrWhiteSpace(i.TwoLetterISOLanguageName)).ToList();
+                !string.IsNullOrWhiteSpace(i.TwoLetterISOLanguageName)).ToArray();
         }
 
         /// <summary>
         /// Gets the countries.
         /// </summary>
         /// <returns>IEnumerable{CountryInfo}.</returns>
-        public List<CountryInfo> GetCountries()
+        public CountryInfo[] GetCountries()
         {
             var type = GetType();
             var path = type.Namespace + ".countries.json";
 
             using (var stream = _assemblyInfo.GetManifestResourceStream(type, path))
             {
-                return _jsonSerializer.DeserializeFromStream<List<CountryInfo>>(stream);
+                return _jsonSerializer.DeserializeFromStream<CountryInfo[]>(stream);
             }
         }
 
@@ -191,9 +191,9 @@ namespace Emby.Server.Implementations.Localization
         /// Gets the parental ratings.
         /// </summary>
         /// <returns>IEnumerable{ParentalRating}.</returns>
-        public IEnumerable<ParentalRating> GetParentalRatings()
+        public ParentalRating[] GetParentalRatings()
         {
-            return GetParentalRatingsDictionary().Values.ToList();
+            return GetParentalRatingsDictionary().Values.ToArray();
         }
 
         /// <summary>
@@ -382,9 +382,9 @@ namespace Emby.Server.Implementations.Localization
             return culture + ".json";
         }
 
-        public IEnumerable<LocalizatonOption> GetLocalizationOptions()
+        public LocalizatonOption[] GetLocalizationOptions()
         {
-            return new List<LocalizatonOption>
+            return new LocalizatonOption[]
             {
                 new LocalizatonOption{ Name="Arabic", Value="ar"},
                 new LocalizatonOption{ Name="Bulgarian (Bulgaria)", Value="bg-BG"},
@@ -421,7 +421,7 @@ namespace Emby.Server.Implementations.Localization
                 new LocalizatonOption{ Name="Ukrainian", Value="uk"},
                 new LocalizatonOption{ Name="Vietnamese", Value="vi"}
 
-            }.OrderBy(i => i.Name);
+            };
         }
     }
 

+ 1 - 1
Emby.Server.Implementations/MediaEncoder/EncodingManager.cs

@@ -129,7 +129,7 @@ namespace Emby.Server.Implementations.MediaEncoder
 
                             var protocol = MediaProtocol.File;
 
-                            var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, video.Path, protocol, null, new List<string>());
+                            var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, video.Path, protocol, null, new string[] { });
 
                             _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
 

+ 16 - 16
Emby.Server.Implementations/Notifications/CoreNotificationTypes.cs

@@ -28,21 +28,21 @@ namespace Emby.Server.Implementations.Notifications
                      Type = NotificationType.ApplicationUpdateInstalled.ToString(),
                      DefaultDescription = "{ReleaseNotes}",
                      DefaultTitle = "A new version of Emby Server has been installed.",
-                     Variables = new List<string>{"Version"}
+                     Variables = new string[]{"Version"}
                 },
 
                 new NotificationTypeInfo
                 {
                      Type = NotificationType.InstallationFailed.ToString(),
                      DefaultTitle = "{Name} installation failed.",
-                     Variables = new List<string>{"Name", "Version"}
+                     Variables = new string[]{"Name", "Version"}
                 },
 
                 new NotificationTypeInfo
                 {
                      Type = NotificationType.PluginInstalled.ToString(),
                      DefaultTitle = "{Name} was installed.",
-                     Variables = new List<string>{"Name", "Version"}
+                     Variables = new string[]{"Name", "Version"}
                 },
 
                 new NotificationTypeInfo
@@ -50,14 +50,14 @@ namespace Emby.Server.Implementations.Notifications
                      Type = NotificationType.PluginError.ToString(),
                      DefaultTitle = "{Name} has encountered an error.",
                      DefaultDescription = "{ErrorMessage}",
-                     Variables = new List<string>{"Name", "ErrorMessage"}
+                     Variables = new string[]{"Name", "ErrorMessage"}
                 },
 
                 new NotificationTypeInfo
                 {
                      Type = NotificationType.PluginUninstalled.ToString(),
                      DefaultTitle = "{Name} was uninstalled.",
-                     Variables = new List<string>{"Name", "Version"}
+                     Variables = new string[]{"Name", "Version"}
                 },
 
                 new NotificationTypeInfo
@@ -65,7 +65,7 @@ namespace Emby.Server.Implementations.Notifications
                      Type = NotificationType.PluginUpdateInstalled.ToString(),
                      DefaultTitle = "{Name} was updated.",
                      DefaultDescription = "{ReleaseNotes}",
-                     Variables = new List<string>{"Name", "ReleaseNotes", "Version"}
+                     Variables = new string[]{"Name", "ReleaseNotes", "Version"}
                 },
 
                 new NotificationTypeInfo
@@ -79,70 +79,70 @@ namespace Emby.Server.Implementations.Notifications
                      Type = NotificationType.TaskFailed.ToString(),
                      DefaultTitle = "{Name} failed.",
                      DefaultDescription = "{ErrorMessage}",
-                     Variables = new List<string>{"Name", "ErrorMessage"}
+                     Variables = new string[]{"Name", "ErrorMessage"}
                 },
 
                 new NotificationTypeInfo
                 {
                      Type = NotificationType.NewLibraryContent.ToString(),
                      DefaultTitle = "{Name} has been added to your media library.",
-                     Variables = new List<string>{"Name"}
+                     Variables = new string[]{"Name"}
                 },
 
                 new NotificationTypeInfo
                 {
                      Type = NotificationType.AudioPlayback.ToString(),
                      DefaultTitle = "{UserName} is playing {ItemName} on {DeviceName}.",
-                     Variables = new List<string>{"UserName", "ItemName", "DeviceName", "AppName"}
+                     Variables = new string[]{"UserName", "ItemName", "DeviceName", "AppName"}
                 },
 
                 new NotificationTypeInfo
                 {
                      Type = NotificationType.GamePlayback.ToString(),
                      DefaultTitle = "{UserName} is playing {ItemName} on {DeviceName}.",
-                     Variables = new List<string>{"UserName", "ItemName", "DeviceName", "AppName"}
+                     Variables = new string[]{"UserName", "ItemName", "DeviceName", "AppName"}
                 },
 
                 new NotificationTypeInfo
                 {
                      Type = NotificationType.VideoPlayback.ToString(),
                      DefaultTitle = "{UserName} is playing {ItemName} on {DeviceName}.",
-                     Variables = new List<string>{"UserName", "ItemName", "DeviceName", "AppName"}
+                     Variables = new string[]{"UserName", "ItemName", "DeviceName", "AppName"}
                 },
 
                 new NotificationTypeInfo
                 {
                      Type = NotificationType.AudioPlaybackStopped.ToString(),
                      DefaultTitle = "{UserName} has finished playing {ItemName} on {DeviceName}.",
-                     Variables = new List<string>{"UserName", "ItemName", "DeviceName", "AppName"}
+                     Variables = new string[]{"UserName", "ItemName", "DeviceName", "AppName"}
                 },
 
                 new NotificationTypeInfo
                 {
                      Type = NotificationType.GamePlaybackStopped.ToString(),
                      DefaultTitle = "{UserName} has finished playing {ItemName} on {DeviceName}.",
-                     Variables = new List<string>{"UserName", "ItemName", "DeviceName", "AppName"}
+                     Variables = new string[]{"UserName", "ItemName", "DeviceName", "AppName"}
                 },
 
                 new NotificationTypeInfo
                 {
                      Type = NotificationType.VideoPlaybackStopped.ToString(),
                      DefaultTitle = "{UserName} has finished playing {ItemName} on {DeviceName}.",
-                     Variables = new List<string>{"UserName", "ItemName", "DeviceName", "AppName"}
+                     Variables = new string[]{"UserName", "ItemName", "DeviceName", "AppName"}
                 },
 
                 new NotificationTypeInfo
                 {
                      Type = NotificationType.CameraImageUploaded.ToString(),
                      DefaultTitle = "A new camera image has been uploaded from {DeviceName}.",
-                     Variables = new List<string>{"DeviceName"}
+                     Variables = new string[]{"DeviceName"}
                 },
 
                 new NotificationTypeInfo
                 {
                      Type = NotificationType.UserLockedOut.ToString(),
                      DefaultTitle = "{UserName} has been locked out.",
-                     Variables = new List<string>{"UserName"}
+                     Variables = new string[]{"UserName"}
                 }
             };
 

+ 1 - 1
Emby.Server.Implementations/Notifications/NotificationManager.cs

@@ -251,7 +251,7 @@ namespace Emby.Server.Implementations.Notifications
             _typeFactories = notificationTypeFactories.ToArray();
         }
 
-        public IEnumerable<NotificationTypeInfo> GetNotificationTypes()
+        public List<NotificationTypeInfo> GetNotificationTypes()
         {
             var list = _typeFactories.Select(i =>
             {

+ 1 - 1
Emby.Server.Implementations/Playlists/PlaylistManager.cs

@@ -133,7 +133,7 @@ namespace Emby.Server.Implementations.Playlists
                 await playlist.RefreshMetadata(new MetadataRefreshOptions(_fileSystem) { ForceSave = true }, CancellationToken.None)
                     .ConfigureAwait(false);
 
-                if (options.ItemIdList.Count > 0)
+                if (options.ItemIdList.Length > 0)
                 {
                     await AddToPlaylistInternal(playlist.Id.ToString("N"), options.ItemIdList, user, new DtoOptions(false)
                     {

+ 7 - 33
Emby.Server.Implementations/Services/ServiceController.cs

@@ -29,13 +29,6 @@ namespace Emby.Server.Implementations.Services
             }
         }
 
-        private Type[] GetGenericArguments(Type type)
-        {
-            return type.GetTypeInfo().IsGenericTypeDefinition
-                ? type.GetTypeInfo().GenericTypeParameters
-                : type.GetTypeInfo().GenericTypeArguments;
-        }
-
         public void RegisterService(HttpListenerHost appHost, Type serviceType)
         {
             var processedReqs = new HashSet<Type>();
@@ -50,38 +43,19 @@ namespace Emby.Server.Implementations.Services
 
                 ServiceExecGeneral.CreateServiceRunnersFor(requestType, actions);
 
-                var returnMarker = GetTypeWithGenericTypeDefinitionOf(requestType, typeof(IReturn<>));
-                var responseType = returnMarker != null ?
-                      GetGenericArguments(returnMarker)[0]
-                    : mi.ReturnType != typeof(object) && mi.ReturnType != typeof(void) ?
-                      mi.ReturnType
-                    : Type.GetType(requestType.FullName + "Response");
+                //var returnMarker = GetTypeWithGenericTypeDefinitionOf(requestType, typeof(IReturn<>));
+                //var responseType = returnMarker != null ?
+                //      GetGenericArguments(returnMarker)[0]
+                //    : mi.ReturnType != typeof(object) && mi.ReturnType != typeof(void) ?
+                //      mi.ReturnType
+                //    : Type.GetType(requestType.FullName + "Response");
 
                 RegisterRestPaths(appHost, requestType);
 
-                appHost.AddServiceInfo(serviceType, requestType, responseType);
+                appHost.AddServiceInfo(serviceType, requestType);
             }
         }
 
-        private static Type GetTypeWithGenericTypeDefinitionOf(Type type, Type genericTypeDefinition)
-        {
-            foreach (var t in type.GetTypeInfo().ImplementedInterfaces)
-            {
-                if (t.GetTypeInfo().IsGenericType && t.GetGenericTypeDefinition() == genericTypeDefinition)
-                {
-                    return t;
-                }
-            }
-
-            var genericType = FirstGenericType(type);
-            if (genericType != null && genericType.GetGenericTypeDefinition() == genericTypeDefinition)
-            {
-                return genericType;
-            }
-
-            return null;
-        }
-
         public static Type FirstGenericType(Type type)
         {
             while (type != null)

+ 46 - 35
Emby.Server.Implementations/Session/SessionManager.cs

@@ -468,7 +468,7 @@ namespace Emby.Server.Implementations.Session
 
                 if (!userId.HasValue)
                 {
-                    sessionInfo.AdditionalUsers.Clear();
+                    sessionInfo.AdditionalUsers = new SessionUserInfo[] { };
                 }
 
                 if (sessionInfo.SessionController == null)
@@ -1074,7 +1074,7 @@ namespace Emby.Server.Implementations.Session
                     DtoOptions = new DtoOptions(false)
                     {
                         EnableImages = false,
-                        Fields = new List<ItemFields>
+                        Fields = new ItemFields[]
                         {
                             ItemFields.SortName
                         }
@@ -1097,7 +1097,7 @@ namespace Emby.Server.Implementations.Session
                     DtoOptions = new DtoOptions(false)
                     {
                         EnableImages = false,
-                        Fields = new List<ItemFields>
+                        Fields = new ItemFields[]
                         {
                             ItemFields.SortName
                         }
@@ -1340,11 +1340,15 @@ namespace Emby.Server.Implementations.Session
             {
                 var user = _userManager.GetUserById(userId);
 
-                session.AdditionalUsers.Add(new SessionUserInfo
+                var list = session.AdditionalUsers.ToList();
+
+                list.Add(new SessionUserInfo
                 {
                     UserId = userId,
                     UserName = user.Name
                 });
+
+                session.AdditionalUsers = list.ToArray(list.Count);
             }
         }
 
@@ -1368,7 +1372,10 @@ namespace Emby.Server.Implementations.Session
 
             if (user != null)
             {
-                session.AdditionalUsers.Remove(user);
+                var list = session.AdditionalUsers.ToList();
+                list.Remove(user);
+
+                session.AdditionalUsers = list.ToArray(list.Count);
             }
         }
 
@@ -1661,35 +1668,39 @@ namespace Emby.Server.Implementations.Session
                     AddProgramRecordingInfo = false
                 };
 
-                dtoOptions.Fields.Remove(ItemFields.BasicSyncInfo);
-                dtoOptions.Fields.Remove(ItemFields.SyncInfo);
-                dtoOptions.Fields.Remove(ItemFields.CanDelete);
-                dtoOptions.Fields.Remove(ItemFields.CanDownload);
-                dtoOptions.Fields.Remove(ItemFields.ChildCount);
-                dtoOptions.Fields.Remove(ItemFields.CustomRating);
-                dtoOptions.Fields.Remove(ItemFields.DateLastMediaAdded);
-                dtoOptions.Fields.Remove(ItemFields.DateLastRefreshed);
-                dtoOptions.Fields.Remove(ItemFields.DateLastSaved);
-                dtoOptions.Fields.Remove(ItemFields.DisplayPreferencesId);
-                dtoOptions.Fields.Remove(ItemFields.Etag);
-                dtoOptions.Fields.Remove(ItemFields.ExternalEtag);
-                dtoOptions.Fields.Remove(ItemFields.InheritedParentalRatingValue);
-                dtoOptions.Fields.Remove(ItemFields.ItemCounts);
-                dtoOptions.Fields.Remove(ItemFields.MediaSourceCount);
-                dtoOptions.Fields.Remove(ItemFields.MediaStreams);
-                dtoOptions.Fields.Remove(ItemFields.MediaSources);
-                dtoOptions.Fields.Remove(ItemFields.People);
-                dtoOptions.Fields.Remove(ItemFields.PlayAccess);
-                dtoOptions.Fields.Remove(ItemFields.People);
-                dtoOptions.Fields.Remove(ItemFields.ProductionLocations);
-                dtoOptions.Fields.Remove(ItemFields.RecursiveItemCount);
-                dtoOptions.Fields.Remove(ItemFields.RemoteTrailers);
-                dtoOptions.Fields.Remove(ItemFields.SeasonUserData);
-                dtoOptions.Fields.Remove(ItemFields.Settings);
-                dtoOptions.Fields.Remove(ItemFields.SortName);
-                dtoOptions.Fields.Remove(ItemFields.Tags);
-                dtoOptions.Fields.Remove(ItemFields.ThemeSongIds);
-                dtoOptions.Fields.Remove(ItemFields.ThemeVideoIds);
+                var fields = dtoOptions.Fields.ToList();
+
+                fields.Remove(ItemFields.BasicSyncInfo);
+                fields.Remove(ItemFields.SyncInfo);
+                fields.Remove(ItemFields.CanDelete);
+                fields.Remove(ItemFields.CanDownload);
+                fields.Remove(ItemFields.ChildCount);
+                fields.Remove(ItemFields.CustomRating);
+                fields.Remove(ItemFields.DateLastMediaAdded);
+                fields.Remove(ItemFields.DateLastRefreshed);
+                fields.Remove(ItemFields.DateLastSaved);
+                fields.Remove(ItemFields.DisplayPreferencesId);
+                fields.Remove(ItemFields.Etag);
+                fields.Remove(ItemFields.ExternalEtag);
+                fields.Remove(ItemFields.InheritedParentalRatingValue);
+                fields.Remove(ItemFields.ItemCounts);
+                fields.Remove(ItemFields.MediaSourceCount);
+                fields.Remove(ItemFields.MediaStreams);
+                fields.Remove(ItemFields.MediaSources);
+                fields.Remove(ItemFields.People);
+                fields.Remove(ItemFields.PlayAccess);
+                fields.Remove(ItemFields.People);
+                fields.Remove(ItemFields.ProductionLocations);
+                fields.Remove(ItemFields.RecursiveItemCount);
+                fields.Remove(ItemFields.RemoteTrailers);
+                fields.Remove(ItemFields.SeasonUserData);
+                fields.Remove(ItemFields.Settings);
+                fields.Remove(ItemFields.SortName);
+                fields.Remove(ItemFields.Tags);
+                fields.Remove(ItemFields.ThemeSongIds);
+                fields.Remove(ItemFields.ThemeVideoIds);
+
+                dtoOptions.Fields = fields.ToArray(fields.Count);
 
                 _itemInfoDtoOptions = dtoOptions;
             }
@@ -1698,7 +1709,7 @@ namespace Emby.Server.Implementations.Session
 
             if (mediaSource != null)
             {
-                info.MediaStreams = mediaSource.MediaStreams;
+                info.MediaStreams = mediaSource.MediaStreams.ToArray();
             }
 
             return info;

+ 3 - 3
Emby.Server.Implementations/TV/TVSeriesManager.cs

@@ -72,7 +72,7 @@ namespace Emby.Server.Implementations.TV
                 Recursive = true,
                 DtoOptions = new MediaBrowser.Controller.Dto.DtoOptions
                 {
-                    Fields = new List<ItemFields>
+                    Fields = new ItemFields[]
                     {
                         ItemFields.SeriesPresentationUniqueKey
                     }
@@ -128,7 +128,7 @@ namespace Emby.Server.Implementations.TV
                 Limit = limit,
                 DtoOptions = new MediaBrowser.Controller.Dto.DtoOptions
                 {
-                    Fields = new List<ItemFields>
+                    Fields = new ItemFields[]
                     {
                         ItemFields.SeriesPresentationUniqueKey
                     },
@@ -207,7 +207,7 @@ namespace Emby.Server.Implementations.TV
                 ParentIndexNumberNotEquals = 0,
                 DtoOptions = new MediaBrowser.Controller.Dto.DtoOptions
                 {
-                    Fields = new List<ItemFields>
+                    Fields = new ItemFields[]
                     {
                         ItemFields.SortName
                     },

+ 21 - 31
Emby.Server.Implementations/Updates/InstallationManager.cs

@@ -157,7 +157,7 @@ namespace Emby.Server.Implementations.Updates
         /// Gets all available packages.
         /// </summary>
         /// <returns>Task{List{PackageInfo}}.</returns>
-        public async Task<IEnumerable<PackageInfo>> GetAvailablePackages(CancellationToken cancellationToken,
+        public async Task<PackageInfo[]> GetAvailablePackages(CancellationToken cancellationToken,
             bool withRegistration = true,
             string packageType = null,
             Version applicationVersion = null)
@@ -175,7 +175,7 @@ namespace Emby.Server.Implementations.Updates
                 {
                     cancellationToken.ThrowIfCancellationRequested();
 
-                    var packages = _jsonSerializer.DeserializeFromStream<List<PackageInfo>>(json).ToList();
+                    var packages = _jsonSerializer.DeserializeFromStream<PackageInfo[]>(json);
 
                     return FilterPackages(packages, packageType, applicationVersion);
                 }
@@ -184,7 +184,7 @@ namespace Emby.Server.Implementations.Updates
             {
                 var packages = await GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false);
 
-                return FilterPackages(packages.ToList(), packageType, applicationVersion);
+                return FilterPackages(packages, packageType, applicationVersion);
             }
         }
 
@@ -195,14 +195,14 @@ namespace Emby.Server.Implementations.Updates
         /// </summary>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task{List{PackageInfo}}.</returns>
-        public async Task<IEnumerable<PackageInfo>> GetAvailablePackagesWithoutRegistrationInfo(CancellationToken cancellationToken)
+        public async Task<PackageInfo[]> GetAvailablePackagesWithoutRegistrationInfo(CancellationToken cancellationToken)
         {
             _logger.Info("Opening {0}", PackageCachePath);
             try
             {
                 using (var stream = _fileSystem.OpenRead(PackageCachePath))
                 {
-                    var packages = _jsonSerializer.DeserializeFromStream<List<PackageInfo>>(stream).ToList();
+                    var packages = _jsonSerializer.DeserializeFromStream<PackageInfo[]>(stream);
 
                     if (DateTime.UtcNow - _lastPackageUpdateTime > GetCacheLength())
                     {
@@ -221,7 +221,7 @@ namespace Emby.Server.Implementations.Updates
             await UpdateCachedPackages(cancellationToken, true).ConfigureAwait(false);
             using (var stream = _fileSystem.OpenRead(PackageCachePath))
             {
-                return _jsonSerializer.DeserializeFromStream<List<PackageInfo>>(stream).ToList();
+                return _jsonSerializer.DeserializeFromStream<PackageInfo[]>(stream);
             }
         }
 
@@ -288,31 +288,29 @@ namespace Emby.Server.Implementations.Updates
             }
         }
 
-        protected IEnumerable<PackageInfo> FilterPackages(List<PackageInfo> packages)
+        protected PackageInfo[] FilterPackages(List<PackageInfo> packages)
         {
             foreach (var package in packages)
             {
                 package.versions = package.versions.Where(v => !string.IsNullOrWhiteSpace(v.sourceUrl))
-                    .OrderByDescending(GetPackageVersion).ToList();
+                    .OrderByDescending(GetPackageVersion).ToArray();
             }
 
             // Remove packages with no versions
-            packages = packages.Where(p => p.versions.Any()).ToList();
-
-            return packages;
+            return packages.Where(p => p.versions.Any()).ToArray();
         }
 
-        protected IEnumerable<PackageInfo> FilterPackages(List<PackageInfo> packages, string packageType, Version applicationVersion)
+        protected PackageInfo[] FilterPackages(PackageInfo[] packages, string packageType, Version applicationVersion)
         {
             foreach (var package in packages)
             {
                 package.versions = package.versions.Where(v => !string.IsNullOrWhiteSpace(v.sourceUrl))
-                    .OrderByDescending(GetPackageVersion).ToList();
+                    .OrderByDescending(GetPackageVersion).ToArray();
             }
 
             if (!string.IsNullOrWhiteSpace(packageType))
             {
-                packages = packages.Where(p => string.Equals(p.type, packageType, StringComparison.OrdinalIgnoreCase)).ToList();
+                packages = packages.Where(p => string.Equals(p.type, packageType, StringComparison.OrdinalIgnoreCase)).ToArray();
             }
 
             // If an app version was supplied, filter the versions for each package to only include supported versions
@@ -320,14 +318,12 @@ namespace Emby.Server.Implementations.Updates
             {
                 foreach (var package in packages)
                 {
-                    package.versions = package.versions.Where(v => IsPackageVersionUpToDate(v, applicationVersion)).ToList();
+                    package.versions = package.versions.Where(v => IsPackageVersionUpToDate(v, applicationVersion)).ToArray();
                 }
             }
 
             // Remove packages with no versions
-            packages = packages.Where(p => p.versions.Any()).ToList();
-
-            return packages;
+            return packages.Where(p => p.versions.Any()).ToArray();
         }
 
         /// <summary>
@@ -418,30 +414,24 @@ namespace Emby.Server.Implementations.Updates
         /// <returns>Task{IEnumerable{PackageVersionInfo}}.</returns>
         public async Task<IEnumerable<PackageVersionInfo>> GetAvailablePluginUpdates(Version applicationVersion, bool withAutoUpdateEnabled, CancellationToken cancellationToken)
         {
-            var catalog = await GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false);
-
-            var plugins = _applicationHost.Plugins.ToList();
-
-            if (withAutoUpdateEnabled)
+            if (!_config.CommonConfiguration.EnableAutoUpdate)
             {
-                plugins = plugins
-                    .Where(p => _config.CommonConfiguration.EnableAutoUpdate)
-                    .ToList();
+                return new PackageVersionInfo[] { };
             }
 
+            var catalog = await GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false);
+
             var systemUpdateLevel = GetSystemUpdateLevel();
 
             // Figure out what needs to be installed
-            var packages = plugins.Select(p =>
+            return _applicationHost.Plugins.Select(p =>
             {
                 var latestPluginInfo = GetLatestCompatibleVersion(catalog, p.Name, p.Id.ToString(), applicationVersion, systemUpdateLevel);
 
                 return latestPluginInfo != null && GetPackageVersion(latestPluginInfo) > p.Version ? latestPluginInfo : null;
 
-            }).Where(i => i != null).ToList();
-
-            return packages
-                .Where(p => !string.IsNullOrWhiteSpace(p.sourceUrl) && !CompletedInstallations.Any(i => string.Equals(i.AssemblyGuid, p.guid, StringComparison.OrdinalIgnoreCase)));
+            }).Where(i => i != null)
+            .Where(p => !string.IsNullOrWhiteSpace(p.sourceUrl) && !CompletedInstallations.Any(i => string.Equals(i.AssemblyGuid, p.guid, StringComparison.OrdinalIgnoreCase)));
         }
 
         /// <summary>

+ 20 - 4
MediaBrowser.Api/BaseApiService.cs

@@ -11,6 +11,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
 using MediaBrowser.Model.Services;
+using MediaBrowser.Model.Extensions;
 
 namespace MediaBrowser.Api
 {
@@ -54,6 +55,17 @@ namespace MediaBrowser.Api
             return Request.Headers[name];
         }
 
+        private static readonly string[] EmptyStringArray = new string[] { };
+        public static string[] SplitValue(string value, char delim)
+        {
+            if (string.IsNullOrWhiteSpace(value))
+            {
+                return EmptyStringArray;
+            }
+
+            return value.Split(new[] { delim }, StringSplitOptions.RemoveEmptyEntries);
+        }
+        
         /// <summary>
         /// To the optimized result.
         /// </summary>
@@ -128,7 +140,7 @@ namespace MediaBrowser.Api
             var hasFields = request as IHasItemFields;
             if (hasFields != null)
             {
-                options.Fields = hasFields.GetItemFields().ToList();
+                options.Fields = hasFields.GetItemFields();
             }
 
             var client = authInfo.Client ?? string.Empty;
@@ -137,7 +149,9 @@ namespace MediaBrowser.Api
                 client.IndexOf("media center", StringComparison.OrdinalIgnoreCase) != -1 ||
                 client.IndexOf("classic", StringComparison.OrdinalIgnoreCase) != -1)
             {
-                options.Fields.Add(Model.Querying.ItemFields.RecursiveItemCount);
+                var list = options.Fields.ToList();
+                list.Add(Model.Querying.ItemFields.RecursiveItemCount);
+                options.Fields = list.ToArray(list.Count);
             }
 
             if (client.IndexOf("kodi", StringComparison.OrdinalIgnoreCase) != -1 ||
@@ -148,7 +162,9 @@ namespace MediaBrowser.Api
                client.IndexOf("samsung", StringComparison.OrdinalIgnoreCase) != -1 ||
                client.IndexOf("androidtv", StringComparison.OrdinalIgnoreCase) != -1)
             {
-                options.Fields.Add(Model.Querying.ItemFields.ChildCount);
+                var list = options.Fields.ToList();
+                list.Add(Model.Querying.ItemFields.ChildCount);
+                options.Fields = list.ToArray(list.Count);
             }
 
             var hasDtoOptions = request as IHasDtoOptions;
@@ -167,7 +183,7 @@ namespace MediaBrowser.Api
 
                 if (!string.IsNullOrWhiteSpace(hasDtoOptions.EnableImageTypes))
                 {
-                    options.ImageTypes = (hasDtoOptions.EnableImageTypes ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).Select(v => (ImageType)Enum.Parse(typeof(ImageType), v, true)).ToList();
+                    options.ImageTypes = (hasDtoOptions.EnableImageTypes ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).Select(v => (ImageType)Enum.Parse(typeof(ImageType), v, true)).ToArray();
                 }
             }
 

+ 3 - 3
MediaBrowser.Api/ChannelService.cs

@@ -55,7 +55,7 @@ namespace MediaBrowser.Api
     }
 
     [Route("/Channels/Features", "GET", Summary = "Gets features for a channel")]
-    public class GetAllChannelFeatures : IReturn<List<ChannelFeatures>>
+    public class GetAllChannelFeatures : IReturn<ChannelFeatures[]>
     {
     }
 
@@ -187,7 +187,7 @@ namespace MediaBrowser.Api
 
         public object Get(GetAllChannelFeatures request)
         {
-            var result = _channelManager.GetAllChannelFeatures().ToList();
+            var result = _channelManager.GetAllChannelFeatures();
 
             return ToOptimizedResult(result);
         }
@@ -247,7 +247,7 @@ namespace MediaBrowser.Api
                 ChannelIds = (request.ChannelIds ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToArray(),
                 UserId = request.UserId,
                 Filters = request.GetFilters().ToArray(),
-                Fields = request.GetItemFields().ToList()
+                Fields = request.GetItemFields()
 
             }, CancellationToken.None).ConfigureAwait(false);
 

+ 2 - 2
MediaBrowser.Api/ConfigurationService.cs

@@ -62,7 +62,7 @@ namespace MediaBrowser.Api
 
     [Route("/System/Configuration/MetadataPlugins", "GET", Summary = "Gets all available metadata plugins")]
     [Authenticated(Roles = "Admin")]
-    public class GetMetadataPlugins : IReturn<List<MetadataPluginSummary>>
+    public class GetMetadataPlugins : IReturn<MetadataPluginSummary[]>
     {
 
     }
@@ -170,7 +170,7 @@ namespace MediaBrowser.Api
 
         public object Get(GetMetadataPlugins request)
         {
-            return ToOptimizedSerializedResultUsingCache(_providerManager.GetAllMetadataPlugins().ToList());
+            return ToOptimizedSerializedResultUsingCache(_providerManager.GetAllMetadataPlugins());
         }
     }
 }

+ 2 - 3
MediaBrowser.Api/Dlna/DlnaService.cs

@@ -1,14 +1,13 @@
 using MediaBrowser.Controller.Dlna;
 using MediaBrowser.Controller.Net;
 using MediaBrowser.Model.Dlna;
-using System.Collections.Generic;
 using System.Linq;
 using MediaBrowser.Model.Services;
 
 namespace MediaBrowser.Api.Dlna
 {
     [Route("/Dlna/ProfileInfos", "GET", Summary = "Gets a list of profiles")]
-    public class GetProfileInfos : IReturn<List<DeviceProfileInfo>>
+    public class GetProfileInfos : IReturn<DeviceProfileInfo[]>
     {
     }
 
@@ -53,7 +52,7 @@ namespace MediaBrowser.Api.Dlna
 
         public object Get(GetProfileInfos request)
         {
-            var result = _dlnaManager.GetProfileInfos().ToList();
+            var result = _dlnaManager.GetProfileInfos().ToArray();
 
             return ToOptimizedResult(result);
         }

+ 3 - 6
MediaBrowser.Api/EnvironmentService.cs

@@ -226,7 +226,7 @@ namespace MediaBrowser.Api
                 return ToOptimizedSerializedResultUsingCache(GetNetworkShares(path).OrderBy(i => i.Path).ToList());
             }
 
-            return ToOptimizedSerializedResultUsingCache(GetFileSystemEntries(request).OrderBy(i => i.Path).ToList());
+            return ToOptimizedSerializedResultUsingCache(GetFileSystemEntries(request).ToList());
         }
 
         public object Get(GetNetworkShares request)
@@ -271,9 +271,7 @@ namespace MediaBrowser.Api
         /// <returns>System.Object.</returns>
         public object Get(GetNetworkDevices request)
         {
-            var result = _networkManager.GetNetworkDevices()
-                .OrderBy(i => i.Path)
-                .ToList();
+            var result = _networkManager.GetNetworkDevices().ToList();
 
             return ToOptimizedSerializedResultUsingCache(result);
         }
@@ -300,7 +298,6 @@ namespace MediaBrowser.Api
         /// <returns>IEnumerable{FileSystemEntryInfo}.</returns>
         private IEnumerable<FileSystemEntryInfo> GetFileSystemEntries(GetDirectoryContents request)
         {
-            // using EnumerateFileSystemInfos doesn't handle reparse points (symlinks)
             var entries = _fileSystem.GetFileSystemEntries(request.Path).Where(i =>
             {
                 if (!request.IncludeHidden && i.IsHidden)
@@ -329,7 +326,7 @@ namespace MediaBrowser.Api
                 Path = f.FullName,
                 Type = f.IsDirectory ? FileSystemEntryType.Directory : FileSystemEntryType.File
 
-            }).ToList();
+            });
         }
 
         public object Get(GetParentPath request)

+ 1 - 1
MediaBrowser.Api/FilterService.cs

@@ -108,7 +108,7 @@ namespace MediaBrowser.Api
                 EnableTotalRecordCount = false,
                 DtoOptions = new Controller.Dto.DtoOptions
                 {
-                    Fields = new List<ItemFields> { ItemFields.Genres, ItemFields.Tags },
+                    Fields = new ItemFields[] { ItemFields.Genres, ItemFields.Tags },
                     EnableImages = false,
                     EnableUserData = false
                 }

+ 8 - 52
MediaBrowser.Api/GamesService.cs

@@ -28,21 +28,7 @@ namespace MediaBrowser.Api
     /// Class GetGameSystemSummaries
     /// </summary>
     [Route("/Games/SystemSummaries", "GET", Summary = "Finds games similar to a given game.")]
-    public class GetGameSystemSummaries : IReturn<List<GameSystemSummary>>
-    {
-        /// <summary>
-        /// Gets or sets the user id.
-        /// </summary>
-        /// <value>The user id.</value>
-        [ApiMember(Name = "UserId", Description = "Optional. Filter by user id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
-    }
-
-    /// <summary>
-    /// Class GetGameSystemSummaries
-    /// </summary>
-    [Route("/Games/PlayerIndex", "GET", Summary = "Gets an index of players (1-x) and the number of games listed under each")]
-    public class GetPlayerIndex : IReturn<List<ItemIndex>>
+    public class GetGameSystemSummaries : IReturn<GameSystemSummary[]>
     {
         /// <summary>
         /// Gets or sets the user id.
@@ -117,47 +103,17 @@ namespace MediaBrowser.Api
                     EnableImages = false
                 }
             };
-            var gameSystems = _libraryManager.GetItemList(query)
-                .Cast<GameSystem>()
-                .ToList();
 
-            var result = gameSystems
+            var result = _libraryManager.GetItemList(query)
+                .Cast<GameSystem>()
                 .Select(i => GetSummary(i, user))
-                .ToList();
+                .ToArray();
 
             return ToOptimizedSerializedResultUsingCache(result);
         }
 
         private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
 
-        public object Get(GetPlayerIndex request)
-        {
-            var user = request.UserId == null ? null : _userManager.GetUserById(request.UserId);
-            var query = new InternalItemsQuery(user)
-            {
-                IncludeItemTypes = new[] { typeof(Game).Name },
-                DtoOptions = new DtoOptions(false)
-                {
-                    EnableImages = false
-                }
-            };
-            var games = _libraryManager.GetItemList(query)
-                .Cast<Game>()
-                .ToList();
-
-            var lookup = games
-                .ToLookup(i => i.PlayersSupported ?? -1)
-                .OrderBy(i => i.Key)
-                .Select(i => new ItemIndex
-                {
-                    ItemCount = i.Count(),
-                    Name = i.Key == -1 ? string.Empty : i.Key.ToString(UsCulture)
-                })
-                .ToList();
-
-            return ToOptimizedSerializedResultUsingCache(lookup);
-        }
-
         /// <summary>
         /// Gets the summary.
         /// </summary>
@@ -183,15 +139,15 @@ namespace MediaBrowser.Api
                     }
                 });
 
-            var games = items.Cast<Game>().ToList();
+            var games = items.Cast<Game>().ToArray();
 
             summary.ClientInstalledGameCount = games.Count(i => i.IsPlaceHolder);
 
-            summary.GameCount = games.Count;
+            summary.GameCount = games.Length;
 
             summary.GameFileExtensions = games.Where(i => !i.IsPlaceHolder).Select(i => Path.GetExtension(i.Path))
                 .Distinct(StringComparer.OrdinalIgnoreCase)
-                .ToList();
+                .ToArray();
 
             return summary;
         }
@@ -234,7 +190,7 @@ namespace MediaBrowser.Api
 
             var result = new QueryResult<BaseItemDto>
             {
-                Items = returnList.ToArray(returnList.Count),
+                Items = returnList,
 
                 TotalRecordCount = itemsResult.Count
             };

+ 2 - 2
MediaBrowser.Api/IHasItemFields.cs

@@ -27,7 +27,7 @@ namespace MediaBrowser.Api
         /// </summary>
         /// <param name="request">The request.</param>
         /// <returns>IEnumerable{ItemFields}.</returns>
-        public static IEnumerable<ItemFields> GetItemFields(this IHasItemFields request)
+        public static ItemFields[] GetItemFields(this IHasItemFields request)
         {
             var val = request.Fields;
 
@@ -46,7 +46,7 @@ namespace MediaBrowser.Api
                 }
                 return null;
 
-            }).Where(i => i.HasValue).Select(i => i.Value);
+            }).Where(i => i.HasValue).Select(i => i.Value).ToArray();
         }
     }
 }

+ 5 - 5
MediaBrowser.Api/Images/RemoteImageService.cs

@@ -150,7 +150,7 @@ namespace MediaBrowser.Api.Images
 
             }, CancellationToken.None).ConfigureAwait(false);
 
-            var imagesList = images.ToList();
+            var imagesList = images.ToArray();
 
             var allProviders = _providerManager.GetRemoteImageProviderInfo(item);
 
@@ -161,22 +161,22 @@ namespace MediaBrowser.Api.Images
 
             var result = new RemoteImageResult
             {
-                TotalRecordCount = imagesList.Count,
+                TotalRecordCount = imagesList.Length,
                 Providers = allProviders.Select(i => i.Name)
                 .Distinct(StringComparer.OrdinalIgnoreCase)
-                .ToList()
+                .ToArray()
             };
 
             if (request.StartIndex.HasValue)
             {
                 imagesList = imagesList.Skip(request.StartIndex.Value)
-                    .ToList();
+                    .ToArray();
             }
 
             if (request.Limit.HasValue)
             {
                 imagesList = imagesList.Take(request.Limit.Value)
-                    .ToList();
+                    .ToArray();
             }
 
             result.Images = imagesList;

+ 4 - 4
MediaBrowser.Api/ItemUpdateService.cs

@@ -64,8 +64,8 @@ namespace MediaBrowser.Api
 
             var info = new MetadataEditorInfo
             {
-                ParentalRatingOptions = _localizationManager.GetParentalRatings().ToList(),
-                ExternalIdInfos = _providerManager.GetExternalIdInfos(item).ToList(),
+                ParentalRatingOptions = _localizationManager.GetParentalRatings(),
+                ExternalIdInfos = _providerManager.GetExternalIdInfos(item).ToArray(),
                 Countries = _localizationManager.GetCountries(),
                 Cultures = _localizationManager.GetCultures()
             };
@@ -78,14 +78,14 @@ namespace MediaBrowser.Api
 
                 if (string.IsNullOrWhiteSpace(inheritedContentType) || !string.IsNullOrWhiteSpace(configuredContentType))
                 {
-                    info.ContentTypeOptions = GetContentTypeOptions(true);
+                    info.ContentTypeOptions = GetContentTypeOptions(true).ToArray();
                     info.ContentType = configuredContentType;
 
                     if (string.IsNullOrWhiteSpace(inheritedContentType) || string.Equals(inheritedContentType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
                     {
                         info.ContentTypeOptions = info.ContentTypeOptions
                             .Where(i => string.IsNullOrWhiteSpace(i.Value) || string.Equals(i.Value, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
-                            .ToList();
+                            .ToArray();
                     }
                 }
             }

+ 4 - 4
MediaBrowser.Api/Library/LibraryService.cs

@@ -227,7 +227,7 @@ namespace MediaBrowser.Api.Library
 
     [Route("/Library/MediaFolders", "GET", Summary = "Gets all user media folders.")]
     [Authenticated]
-    public class GetMediaFolders : IReturn<ItemsResult>
+    public class GetMediaFolders : IReturn<QueryResult<BaseItemDto>>
     {
         [ApiMember(Name = "IsHidden", Description = "Optional. Filter by folders that are marked hidden, or not.", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
         public bool? IsHidden { get; set; }
@@ -400,7 +400,7 @@ namespace MediaBrowser.Api.Library
                 });
             }
 
-            return new ItemsResult();
+            return new QueryResult<BaseItemDto>();
         }
 
         public object Get(GetMediaFolders request)
@@ -416,7 +416,7 @@ namespace MediaBrowser.Api.Library
 
             var dtoOptions = GetDtoOptions(_authContext, request);
 
-            var result = new ItemsResult
+            var result = new QueryResult<BaseItemDto>
             {
                 TotalRecordCount = items.Count,
 
@@ -615,7 +615,7 @@ namespace MediaBrowser.Api.Library
                 parent = parent.GetParent();
             }
 
-            return baseItemDtos.ToList();
+            return baseItemDtos;
         }
 
         private BaseItem TranslateParentItem(BaseItem item, User user)

+ 11 - 9
MediaBrowser.Api/LiveTv/LiveTvService.cs

@@ -648,7 +648,7 @@ namespace MediaBrowser.Api.LiveTv
     {
         public List<TunerChannelMapping> TunerChannels { get; set; }
         public List<NameIdPair> ProviderChannels { get; set; }
-        public List<NameValuePair> Mappings { get; set; }
+        public NameValuePair[] Mappings { get; set; }
         public string ProviderName { get; set; }
     }
 
@@ -789,7 +789,7 @@ namespace MediaBrowser.Api.LiveTv
             var providerChannels = await _liveTvManager.GetChannelsFromListingsProviderData(request.ProviderId, CancellationToken.None)
                      .ConfigureAwait(false);
 
-            var mappings = listingsProviderInfo.ChannelMappings.ToList();
+            var mappings = listingsProviderInfo.ChannelMappings;
 
             var result = new ChannelMappingOptions
             {
@@ -862,7 +862,7 @@ namespace MediaBrowser.Api.LiveTv
         {
             var config = GetConfiguration();
 
-            config.TunerHosts = config.TunerHosts.Where(i => !string.Equals(request.Id, i.Id, StringComparison.OrdinalIgnoreCase)).ToList();
+            config.TunerHosts = config.TunerHosts.Where(i => !string.Equals(request.Id, i.Id, StringComparison.OrdinalIgnoreCase)).ToArray();
 
             _config.SaveConfiguration("livetv", config);
         }
@@ -922,9 +922,8 @@ namespace MediaBrowser.Api.LiveTv
 
             options.AddCurrentProgram = request.AddCurrentProgram;
 
-            var returnList = (await _dtoService.GetBaseItemDtos(channelResult.Items, options, user)
+            var returnArray = (await _dtoService.GetBaseItemDtos(channelResult.Items, options, user)
                 .ConfigureAwait(false));
-            var returnArray = returnList.ToArray(returnList.Count);
 
             var result = new QueryResult<BaseItemDto>
             {
@@ -937,10 +936,13 @@ namespace MediaBrowser.Api.LiveTv
 
         private void RemoveFields(DtoOptions options)
         {
-            options.Fields.Remove(ItemFields.CanDelete);
-            options.Fields.Remove(ItemFields.CanDownload);
-            options.Fields.Remove(ItemFields.DisplayPreferencesId);
-            options.Fields.Remove(ItemFields.Etag);
+            var fields = options.Fields.ToList();
+
+            fields.Remove(ItemFields.CanDelete);
+            fields.Remove(ItemFields.CanDownload);
+            fields.Remove(ItemFields.DisplayPreferencesId);
+            fields.Remove(ItemFields.Etag);
+            options.Fields = fields.ToArray(fields.Count);
         }
 
         public object Get(GetChannel request)

+ 6 - 6
MediaBrowser.Api/LocalizationService.cs

@@ -11,7 +11,7 @@ namespace MediaBrowser.Api
     /// Class GetCultures
     /// </summary>
     [Route("/Localization/Cultures", "GET", Summary = "Gets known cultures")]
-    public class GetCultures : IReturn<List<CultureDto>>
+    public class GetCultures : IReturn<CultureDto[]>
     {
     }
 
@@ -19,7 +19,7 @@ namespace MediaBrowser.Api
     /// Class GetCountries
     /// </summary>
     [Route("/Localization/Countries", "GET", Summary = "Gets known countries")]
-    public class GetCountries : IReturn<List<CountryInfo>>
+    public class GetCountries : IReturn<CountryInfo[]>
     {
     }
 
@@ -27,7 +27,7 @@ namespace MediaBrowser.Api
     /// Class ParentalRatings
     /// </summary>
     [Route("/Localization/ParentalRatings", "GET", Summary = "Gets known parental ratings")]
-    public class GetParentalRatings : IReturn<List<ParentalRating>>
+    public class GetParentalRatings : IReturn<ParentalRating[]>
     {
     }
 
@@ -35,7 +35,7 @@ namespace MediaBrowser.Api
     /// Class ParentalRatings
     /// </summary>
     [Route("/Localization/Options", "GET", Summary = "Gets localization options")]
-    public class GetLocalizationOptions : IReturn<List<LocalizatonOption>>
+    public class GetLocalizationOptions : IReturn<LocalizatonOption[]>
     {
     }
 
@@ -66,14 +66,14 @@ namespace MediaBrowser.Api
         /// <returns>System.Object.</returns>
         public object Get(GetParentalRatings request)
         {
-            var result = _localization.GetParentalRatings().ToList();
+            var result = _localization.GetParentalRatings();
 
             return ToOptimizedResult(result);
         }
 
         public object Get(GetLocalizationOptions request)
         {
-            var result = _localization.GetLocalizationOptions().ToList();
+            var result = _localization.GetLocalizationOptions();
 
             return ToOptimizedResult(result);
         }

+ 0 - 1
MediaBrowser.Api/MediaBrowser.Api.csproj

@@ -97,7 +97,6 @@
     <Compile Include="Movies\MoviesService.cs" />
     <Compile Include="NewsService.cs" />
     <Compile Include="NotificationsService.cs" />
-    <Compile Include="PackageReviewService.cs" />
     <Compile Include="PackageService.cs" />
     <Compile Include="PluginService.cs" />
     <Compile Include="Images\RemoteImageService.cs" />

+ 4 - 4
MediaBrowser.Api/Movies/CollectionService.cs

@@ -71,8 +71,8 @@ namespace MediaBrowser.Api.Movies
                 IsLocked = request.IsLocked,
                 Name = request.Name,
                 ParentId = parentId,
-                ItemIdList = (request.Ids ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).Select(i => new Guid(i)).ToList(),
-                UserIds = new List<Guid> { new Guid(userId) }
+                ItemIdList = SplitValue(request.Ids, ','),
+                UserIds = new string[] { userId }
 
             }).ConfigureAwait(false);
 
@@ -88,14 +88,14 @@ namespace MediaBrowser.Api.Movies
 
         public void Post(AddToCollection request)
         {
-            var task = _collectionManager.AddToCollection(new Guid(request.Id), request.Ids.Split(',').Select(i => new Guid(i)));
+            var task = _collectionManager.AddToCollection(new Guid(request.Id), SplitValue(request.Ids, ','));
 
             Task.WaitAll(task);
         }
 
         public void Delete(RemoveFromCollection request)
         {
-            var task = _collectionManager.RemoveFromCollection(new Guid(request.Id), request.Ids.Split(',').Select(i => new Guid(i)));
+            var task = _collectionManager.RemoveFromCollection(new Guid(request.Id), SplitValue(request.Ids, ','));
 
             Task.WaitAll(task);
         }

+ 4 - 4
MediaBrowser.Api/Movies/MoviesService.cs

@@ -170,7 +170,7 @@ namespace MediaBrowser.Api.Movies
 
             var result = new QueryResult<BaseItemDto>
             {
-                Items = returnList.ToArray(returnList.Count),
+                Items = returnList,
 
                 TotalRecordCount = itemsResult.Count
             };
@@ -320,7 +320,7 @@ namespace MediaBrowser.Api.Movies
                         BaselineItemName = name,
                         CategoryId = name.GetMD5().ToString("N"),
                         RecommendationType = type,
-                        Items = returnItems.ToArray(returnItems.Count)
+                        Items = returnItems
                     };
                 }
             }
@@ -360,7 +360,7 @@ namespace MediaBrowser.Api.Movies
                         BaselineItemName = name,
                         CategoryId = name.GetMD5().ToString("N"),
                         RecommendationType = type,
-                        Items = returnItems.ToArray(returnItems.Count)
+                        Items = returnItems
                     };
                 }
             }
@@ -397,7 +397,7 @@ namespace MediaBrowser.Api.Movies
                         BaselineItemName = item.Name,
                         CategoryId = item.Id.ToString("N"),
                         RecommendationType = type,
-                        Items = returnItems.ToArray(returnItems.Count)
+                        Items = returnItems
                     };
                 }
             }

+ 2 - 1
MediaBrowser.Api/Movies/TrailersService.cs

@@ -4,6 +4,7 @@ using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Net;
 using MediaBrowser.Model.Querying;
 using MediaBrowser.Controller.Collections;
+using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Globalization;
 using MediaBrowser.Model.Serialization;
 using MediaBrowser.Model.Services;
@@ -11,7 +12,7 @@ using MediaBrowser.Model.Services;
 namespace MediaBrowser.Api.Movies
 {
     [Route("/Trailers", "GET", Summary = "Finds movies and trailers similar to a given trailer.")]
-    public class Getrailers : BaseItemsRequest, IReturn<ItemsResult>
+    public class Getrailers : BaseItemsRequest, IReturn<QueryResult<BaseItemDto>>
     {
     }
 

+ 9 - 3
MediaBrowser.Api/Music/InstantMixService.cs

@@ -8,6 +8,7 @@ using MediaBrowser.Model.Querying;
 using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
+using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Services;
 using MediaBrowser.Model.Extensions;
 
@@ -185,15 +186,20 @@ namespace MediaBrowser.Api.Music
         {
             var list = items;
 
-            var result = new ItemsResult
+            var result = new QueryResult<BaseItemDto>
             {
                 TotalRecordCount = list.Count
             };
 
-            var returnList = (await _dtoService.GetBaseItemDtos(list.Take(request.Limit ?? list.Count), dtoOptions, user)
+            if (request.Limit.HasValue)
+            {
+                list = list.Take(request.Limit.Value).ToList();
+            }
+
+            var returnList = (await _dtoService.GetBaseItemDtos(list, dtoOptions, user)
                 .ConfigureAwait(false));
 
-            result.Items = returnList.ToArray(returnList.Count);
+            result.Items = returnList;
 
             return ToOptimizedResult(result);
         }

+ 1 - 1
MediaBrowser.Api/NotificationsService.cs

@@ -99,7 +99,7 @@ namespace MediaBrowser.Api
 
         public object Get(GetNotificationTypes request)
         {
-            var result = _notificationManager.GetNotificationTypes().ToList();
+            var result = _notificationManager.GetNotificationTypes();
 
             return ToOptimizedResult(result);
         }

+ 0 - 162
MediaBrowser.Api/PackageReviewService.cs

@@ -1,162 +0,0 @@
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Serialization;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Net;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Model.Services;
-
-namespace MediaBrowser.Api
-{
-    /// <summary>
-    /// Class InstallPackage
-    /// </summary>
-    [Route("/Packages/Reviews/{Id}", "POST", Summary = "Creates or updates a package review")]
-    public class CreateReviewRequest : IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the Id.
-        /// </summary>
-        /// <value>The Id.</value>
-        [ApiMember(Name = "Id", Description = "Package Id", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "POST")]
-        public int Id { get; set; }
-
-        /// <summary>
-        /// Gets or sets the rating.
-        /// </summary>
-        /// <value>The review.</value>
-        [ApiMember(Name = "Rating", Description = "The rating value (1-5)", IsRequired = true, DataType = "int", ParameterType = "query", Verb = "POST")]
-        public int Rating { get; set; }
-
-        /// <summary>
-        /// Gets or sets the recommend value.
-        /// </summary>
-        /// <value>Whether or not this review recommends this item.</value>
-        [ApiMember(Name = "Recommend", Description = "Whether or not this review recommends this item", IsRequired = true, DataType = "bool", ParameterType = "query", Verb = "POST")]
-        public bool Recommend { get; set; }
-
-        /// <summary>
-        /// Gets or sets the title.
-        /// </summary>
-        /// <value>The title.</value>
-        [ApiMember(Name = "Title", Description = "Optional short description of review.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string Title { get; set; }
-
-        /// <summary>
-        /// Gets or sets the full review.
-        /// </summary>
-        /// <value>The full review.</value>
-        [ApiMember(Name = "Review", Description = "Optional full review.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string Review { get; set; }
-    }
-
-    /// <summary>
-    /// Class InstallPackage
-    /// </summary>
-    [Route("/Packages/{Id}/Reviews", "GET", Summary = "Gets reviews for a package")]
-    public class ReviewRequest : IReturn<List<PackageReviewInfo>>
-    {
-        /// <summary>
-        /// Gets or sets the Id.
-        /// </summary>
-        /// <value>The Id.</value>
-        [ApiMember(Name = "Id", Description = "Package Id", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "GET")]
-        public int Id { get; set; }
-
-        /// <summary>
-        /// Gets or sets the max rating.
-        /// </summary>
-        /// <value>The max rating.</value>
-        [ApiMember(Name = "MaxRating", Description = "Retrieve only reviews less than or equal to this", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int MaxRating { get; set; }
-
-        /// <summary>
-        /// Gets or sets the min rating.
-        /// </summary>
-        /// <value>The max rating.</value>
-        [ApiMember(Name = "MinRating", Description = "Retrieve only reviews greator than or equal to this", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int MinRating { get; set; }
-
-        /// <summary>
-        /// Only retrieve reviews with at least a short review.
-        /// </summary>
-        /// <value>True if should only get reviews with a title.</value>
-        [ApiMember(Name = "ForceTitle", Description = "Whether or not to restrict results to those with a title", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool ForceTitle { get; set; }
-
-        /// <summary>
-        /// Gets or sets the limit for the query.
-        /// </summary>
-        /// <value>The max rating.</value>
-        [ApiMember(Name = "Limit", Description = "Limit the result to this many reviews (ordered by latest)", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
-        public int Limit { get; set; }
-
-    }
-
-    [Authenticated]
-    public class PackageReviewService : BaseApiService
-    {
-        private readonly IHttpClient _httpClient;
-        private readonly IJsonSerializer _serializer;
-        private const string MbAdminUrl = "https://www.mb3admin.com/admin/";
-        private readonly IServerApplicationHost _appHost;
-
-        public PackageReviewService(IHttpClient httpClient, IJsonSerializer serializer, IServerApplicationHost appHost)
-        {
-            _httpClient = httpClient;
-            _serializer = serializer;
-            _appHost = appHost;
-        }
-
-        public async Task<object> Get(ReviewRequest request)
-        {
-            var parms = "?id=" + request.Id;
-
-            if (request.MaxRating > 0)
-            {
-                parms += "&max=" + request.MaxRating;
-            }
-            if (request.MinRating > 0)
-            {
-                parms += "&min=" + request.MinRating;
-            }
-            if (request.MinRating > 0)
-            {
-                parms += "&limit=" + request.Limit;
-            }
-            if (request.ForceTitle)
-            {
-                parms += "&title=true";
-            }
-
-            using (var result = await _httpClient.Get(MbAdminUrl + "/service/packageReview/retrieve" + parms, CancellationToken.None)
-                            .ConfigureAwait(false))
-            {
-                var reviews = _serializer.DeserializeFromStream<List<PackageReviewInfo>>(result);
-
-                return ToOptimizedResult(reviews);
-            }
-        }
-
-        public void Post(CreateReviewRequest request)
-        {
-            var reviewText = WebUtility.HtmlEncode(request.Review ?? string.Empty);
-            var title = WebUtility.HtmlEncode(request.Title ?? string.Empty);
-
-            var review = new Dictionary<string, string>
-                             { { "id", request.Id.ToString(CultureInfo.InvariantCulture) },
-                               { "mac", _appHost.SystemId },
-                               { "rating", request.Rating.ToString(CultureInfo.InvariantCulture) },
-                               { "recommend", request.Recommend.ToString() },
-                               { "title", title },
-                               { "review", reviewText },
-                             };
-
-            Task.WaitAll(_httpClient.Post(MbAdminUrl + "/service/packageReview/update", review, CancellationToken.None));
-        }
-    }
-}

+ 14 - 13
MediaBrowser.Api/PackageService.cs

@@ -40,7 +40,7 @@ namespace MediaBrowser.Api
     /// </summary>
     [Route("/Packages", "GET", Summary = "Gets available packages")]
     [Authenticated]
-    public class GetPackages : IReturn<List<PackageInfo>>
+    public class GetPackages : IReturn<PackageInfo[]>
     {
         /// <summary>
         /// Gets or sets the name.
@@ -66,7 +66,7 @@ namespace MediaBrowser.Api
     /// </summary>
     [Route("/Packages/Updates", "GET", Summary = "Gets available package updates for currently installed packages")]
     [Authenticated(Roles = "Admin")]
-    public class GetPackageVersionUpdates : IReturn<List<PackageVersionInfo>>
+    public class GetPackageVersionUpdates : IReturn<PackageVersionInfo[]>
     {
         /// <summary>
         /// Gets or sets the name.
@@ -148,24 +148,26 @@ namespace MediaBrowser.Api
         /// <returns>System.Object.</returns>
         public object Get(GetPackageVersionUpdates request)
         {
-            var result = new List<PackageVersionInfo>();
+            PackageVersionInfo[] result = null;
 
             if (string.Equals(request.PackageType, "UserInstalled", StringComparison.OrdinalIgnoreCase) || string.Equals(request.PackageType, "All", StringComparison.OrdinalIgnoreCase))
             {
-                result.AddRange(_installationManager.GetAvailablePluginUpdates(_appHost.ApplicationVersion, false, CancellationToken.None).Result.ToList());
+                result = _installationManager.GetAvailablePluginUpdates(_appHost.ApplicationVersion, false, CancellationToken.None).Result.ToArray();
             }
 
-            else if (string.Equals(request.PackageType, "System", StringComparison.OrdinalIgnoreCase) || string.Equals(request.PackageType, "All", StringComparison.OrdinalIgnoreCase))
+            else if (string.Equals(request.PackageType, "System", StringComparison.OrdinalIgnoreCase) ||
+                     string.Equals(request.PackageType, "All", StringComparison.OrdinalIgnoreCase))
             {
-                var updateCheckResult = _appHost.CheckForApplicationUpdate(CancellationToken.None, new SimpleProgress<double>()).Result;
+                var updateCheckResult = _appHost
+                    .CheckForApplicationUpdate(CancellationToken.None, new SimpleProgress<double>()).Result;
 
                 if (updateCheckResult.IsUpdateAvailable)
                 {
-                    result.Add(updateCheckResult.Package);
+                    result = new PackageVersionInfo[] {updateCheckResult.Package};
                 }
             }
 
-            return ToOptimizedResult(result);
+            return ToOptimizedResult(result ?? new PackageVersionInfo[] { });
         }
 
         /// <summary>
@@ -176,10 +178,9 @@ namespace MediaBrowser.Api
         public object Get(GetPackage request)
         {
             var packages = _installationManager.GetAvailablePackages(CancellationToken.None, applicationVersion: _appHost.ApplicationVersion).Result;
-            var list = packages.ToList();
 
-            var result = list.FirstOrDefault(p => string.Equals(p.guid, request.AssemblyGuid ?? "none", StringComparison.OrdinalIgnoreCase))
-                         ?? list.FirstOrDefault(p => p.name.Equals(request.Name, StringComparison.OrdinalIgnoreCase));
+            var result = packages.FirstOrDefault(p => string.Equals(p.guid, request.AssemblyGuid ?? "none", StringComparison.OrdinalIgnoreCase))
+                         ?? packages.FirstOrDefault(p => p.name.Equals(request.Name, StringComparison.OrdinalIgnoreCase));
 
             return ToOptimizedResult(result);
         }
@@ -191,7 +192,7 @@ namespace MediaBrowser.Api
         /// <returns>System.Object.</returns>
         public async Task<object> Get(GetPackages request)
         {
-            var packages = await _installationManager.GetAvailablePackages(CancellationToken.None, false, request.PackageType, _appHost.ApplicationVersion).ConfigureAwait(false);
+            IEnumerable<PackageInfo> packages = await _installationManager.GetAvailablePackages(CancellationToken.None, false, request.PackageType, _appHost.ApplicationVersion).ConfigureAwait(false);
 
             if (!string.IsNullOrEmpty(request.TargetSystems))
             {
@@ -215,7 +216,7 @@ namespace MediaBrowser.Api
                 packages = packages.Where(p => p.enableInAppStore == request.IsAppStoreEnabled.Value);
             }
 
-            return ToOptimizedResult(packages.ToList());
+            return ToOptimizedResult(packages.ToArray());
         }
 
         /// <summary>

+ 3 - 5
MediaBrowser.Api/PlaylistService.cs

@@ -149,7 +149,7 @@ namespace MediaBrowser.Api
             var result = await _playlistManager.CreatePlaylist(new PlaylistCreationRequest
             {
                 Name = request.Name,
-                ItemIdList = (request.Ids ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList(),
+                ItemIdList = SplitValue(request.Ids, ','),
                 UserId = request.UserId,
                 MediaType = request.MediaType
 
@@ -193,10 +193,8 @@ namespace MediaBrowser.Api
 
             var dtoOptions = GetDtoOptions(_authContext, request);
 
-            var returnList = (await _dtoService.GetBaseItemDtos(items.Select(i => i.Item2), dtoOptions, user)
+            var dtos = (await _dtoService.GetBaseItemDtos(items.Select(i => i.Item2).ToList(), dtoOptions, user)
                 .ConfigureAwait(false));
-            var dtos = returnList
-                   .ToArray(returnList.Count);
 
             var index = 0;
             foreach (var item in dtos)
@@ -205,7 +203,7 @@ namespace MediaBrowser.Api
                 index++;
             }
 
-            var result = new ItemsResult
+            var result = new QueryResult<BaseItemDto>
             {
                 Items = dtos,
                 TotalRecordCount = count

+ 5 - 6
MediaBrowser.Api/PluginService.cs

@@ -23,7 +23,7 @@ namespace MediaBrowser.Api
     /// </summary>
     [Route("/Plugins", "GET", Summary = "Gets a list of currently installed plugins")]
     [Authenticated]
-    public class GetPlugins : IReturn<List<PluginInfo>>
+    public class GetPlugins : IReturn<PluginInfo[]>
     {
         public bool? IsAppStoreEnabled { get; set; }
     }
@@ -195,14 +195,13 @@ namespace MediaBrowser.Api
         /// <returns>System.Object.</returns>
         public async Task<object> Get(GetPlugins request)
         {
-            var result = _appHost.Plugins.OrderBy(p => p.Name).Select(p => p.GetPluginInfo()).ToList();
+            var result = _appHost.Plugins.OrderBy(p => p.Name).Select(p => p.GetPluginInfo()).ToArray();
             var requireAppStoreEnabled = request.IsAppStoreEnabled.HasValue && request.IsAppStoreEnabled.Value;
 
             // Don't fail just on account of image url's
             try
             {
-                var packages = (await _installationManager.GetAvailablePackagesWithoutRegistrationInfo(CancellationToken.None))
-                    .ToList();
+                var packages = (await _installationManager.GetAvailablePackagesWithoutRegistrationInfo(CancellationToken.None));
 
                 foreach (var plugin in result)
                 {
@@ -223,7 +222,7 @@ namespace MediaBrowser.Api
                             return pkg != null && pkg.enableInAppStore;
                   
                         })
-                        .ToList();
+                        .ToArray();
                 }
             }
             catch
@@ -232,7 +231,7 @@ namespace MediaBrowser.Api
                 // Play it safe here
                 if (requireAppStoreEnabled)
                 {
-                    result = new List<PluginInfo>();
+                    result = new PluginInfo[] { };
                 }
             }
 

+ 2 - 2
MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs

@@ -27,7 +27,7 @@ namespace MediaBrowser.Api.ScheduledTasks
     /// Class GetScheduledTasks
     /// </summary>
     [Route("/ScheduledTasks", "GET", Summary = "Gets scheduled tasks")]
-    public class GetScheduledTasks : IReturn<List<TaskInfo>>
+    public class GetScheduledTasks : IReturn<TaskInfo[]>
     {
         [ApiMember(Name = "IsHidden", Description = "Optional filter tasks that are hidden, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
         public bool? IsHidden { get; set; }
@@ -158,7 +158,7 @@ namespace MediaBrowser.Api.ScheduledTasks
             
             var infos = result
                 .Select(ScheduledTaskHelpers.GetTaskInfo)
-                .ToList();
+                .ToArray();
 
             return ToOptimizedResult(infos);
         }

+ 4 - 4
MediaBrowser.Api/Session/SessionsService.cs

@@ -18,7 +18,7 @@ namespace MediaBrowser.Api.Session
     /// </summary>
     [Route("/Sessions", "GET", Summary = "Gets a list of sessions")]
     [Authenticated]
-    public class GetSessions : IReturn<List<SessionInfoDto>>
+    public class GetSessions : IReturn<SessionInfoDto[]>
     {
         [ApiMember(Name = "ControllableByUserId", Description = "Optional. Filter by sessions that a given user is allowed to remote control.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
         public string ControllableByUserId { get; set; }
@@ -396,7 +396,7 @@ namespace MediaBrowser.Api.Session
                 });
             }
 
-            return ToOptimizedResult(result.Select(_sessionManager.GetSessionInfoDto).ToList());
+            return ToOptimizedResult(result.Select(_sessionManager.GetSessionInfoDto).ToArray());
         }
 
         public void Post(SendPlaystateCommand request)
@@ -532,9 +532,9 @@ namespace MediaBrowser.Api.Session
             }
             _sessionManager.ReportCapabilities(request.Id, new ClientCapabilities
             {
-                PlayableMediaTypes = (request.PlayableMediaTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(),
+                PlayableMediaTypes = SplitValue(request.PlayableMediaTypes, ','),
 
-                SupportedCommands = (request.SupportedCommands ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(),
+                SupportedCommands = SplitValue(request.SupportedCommands, ','),
 
                 SupportsMediaControl = request.SupportsMediaControl,
 

+ 4 - 4
MediaBrowser.Api/SimilarItemsHelper.cs

@@ -30,7 +30,7 @@ namespace MediaBrowser.Api
         public string ExcludeArtistIds { get; set; }
     }
 
-    public class BaseGetSimilarItems : IReturn<ItemsResult>, IHasDtoOptions
+    public class BaseGetSimilarItems : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
     {
         [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
         public bool? EnableImages { get; set; }
@@ -97,18 +97,18 @@ namespace MediaBrowser.Api
             var items = GetSimilaritems(item, libraryManager, inputItems, getSimilarityScore)
                 .ToList();
 
-            IEnumerable<BaseItem> returnItems = items;
+            List<BaseItem> returnItems = items;
 
             if (request.Limit.HasValue)
             {
-                returnItems = returnItems.Take(request.Limit.Value);
+                returnItems = returnItems.Take(request.Limit.Value).ToList();
             }
 
             var dtos = await dtoService.GetBaseItemDtos(returnItems, dtoOptions, user).ConfigureAwait(false);
 
             return new QueryResult<BaseItemDto>
             {
-                Items = dtos.ToArray(dtos.Count),
+                Items = dtos,
 
                 TotalRecordCount = items.Count
             };

+ 2 - 4
MediaBrowser.Api/Subtitles/SubtitleService.cs

@@ -14,8 +14,6 @@ using System.Linq;
 using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
-
-using MediaBrowser.Controller.IO;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Services;
 using MimeTypes = MediaBrowser.Model.Net.MimeTypes;
@@ -39,7 +37,7 @@ namespace MediaBrowser.Api.Subtitles
 
     [Route("/Items/{Id}/RemoteSearch/Subtitles/{Language}", "GET")]
     [Authenticated]
-    public class SearchRemoteSubtitles : IReturn<List<RemoteSubtitleInfo>>
+    public class SearchRemoteSubtitles : IReturn<RemoteSubtitleInfo[]>
     {
         [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
         public string Id { get; set; }
@@ -52,7 +50,7 @@ namespace MediaBrowser.Api.Subtitles
 
     [Route("/Items/{Id}/RemoteSearch/Subtitles/Providers", "GET")]
     [Authenticated]
-    public class GetSubtitleProviders : IReturn<List<SubtitleProviderInfo>>
+    public class GetSubtitleProviders : IReturn<SubtitleProviderInfo[]>
     {
         [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
         public string Id { get; set; }

+ 1 - 1
MediaBrowser.Api/SuggestionsService.cs

@@ -72,7 +72,7 @@ namespace MediaBrowser.Api
             return new QueryResult<BaseItemDto>
             {
                 TotalRecordCount = result.TotalRecordCount,
-                Items = dtoList.ToArray(dtoList.Count)
+                Items = dtoList
             };
         }
 

+ 3 - 3
MediaBrowser.Api/System/SystemService.cs

@@ -60,7 +60,7 @@ namespace MediaBrowser.Api.System
 
     [Route("/System/Logs", "GET", Summary = "Gets a list of available server log files")]
     [Authenticated(Roles = "Admin")]
-    public class GetServerLogs : IReturn<List<LogFile>>
+    public class GetServerLogs : IReturn<LogFile[]>
     {
     }
 
@@ -126,7 +126,7 @@ namespace MediaBrowser.Api.System
             }
             catch (IOException)
             {
-                files = new List<FileSystemMetadata>();
+                files = new FileSystemMetadata[]{};
             }
 
             var result = files.Select(i => new LogFile
@@ -139,7 +139,7 @@ namespace MediaBrowser.Api.System
             }).OrderByDescending(i => i.DateModified)
                 .ThenByDescending(i => i.DateCreated)
                 .ThenBy(i => i.Name)
-                .ToList();
+                .ToArray();
 
             return ToOptimizedResult(result);
         }

+ 28 - 31
MediaBrowser.Api/TvShowsService.cs

@@ -22,7 +22,7 @@ namespace MediaBrowser.Api
     /// Class GetNextUpEpisodes
     /// </summary>
     [Route("/Shows/NextUp", "GET", Summary = "Gets a list of next up episodes")]
-    public class GetNextUpEpisodes : IReturn<ItemsResult>, IHasDtoOptions
+    public class GetNextUpEpisodes : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
     {
         /// <summary>
         /// Gets or sets the user id.
@@ -82,7 +82,7 @@ namespace MediaBrowser.Api
     }
 
     [Route("/Shows/Upcoming", "GET", Summary = "Gets a list of upcoming episodes")]
-    public class GetUpcomingEpisodes : IReturn<ItemsResult>, IHasDtoOptions
+    public class GetUpcomingEpisodes : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
     {
         /// <summary>
         /// Gets or sets the user id.
@@ -138,7 +138,7 @@ namespace MediaBrowser.Api
     }
 
     [Route("/Shows/{Id}/Episodes", "GET", Summary = "Gets episodes for a tv season")]
-    public class GetEpisodes : IReturn<ItemsResult>, IHasItemFields, IHasDtoOptions
+    public class GetEpisodes : IReturn<QueryResult<BaseItemDto>>, IHasItemFields, IHasDtoOptions
     {
         /// <summary>
         /// Gets or sets the user id.
@@ -206,7 +206,7 @@ namespace MediaBrowser.Api
     }
 
     [Route("/Shows/{Id}/Seasons", "GET", Summary = "Gets seasons for a tv series")]
-    public class GetSeasons : IReturn<ItemsResult>, IHasItemFields, IHasDtoOptions
+    public class GetSeasons : IReturn<QueryResult<BaseItemDto>>, IHasItemFields, IHasDtoOptions
     {
         /// <summary>
         /// Gets or sets the user id.
@@ -327,7 +327,7 @@ namespace MediaBrowser.Api
 
             var result = new QueryResult<BaseItemDto>
             {
-                Items = returnList.ToArray(returnList.Count),
+                Items = returnList,
 
                 TotalRecordCount = itemsResult.Count
             };
@@ -359,10 +359,9 @@ namespace MediaBrowser.Api
 
             });
 
-            var returnList = (await _dtoService.GetBaseItemDtos(itemsResult, options, user).ConfigureAwait(false));
-            var returnItems = returnList.ToArray(returnList.Count);
+            var returnItems = (await _dtoService.GetBaseItemDtos(itemsResult, options, user).ConfigureAwait(false));
 
-            var result = new ItemsResult
+            var result = new QueryResult<BaseItemDto>
             {
                 TotalRecordCount = itemsResult.Count,
                 Items = returnItems
@@ -392,10 +391,9 @@ namespace MediaBrowser.Api
 
             var user = _userManager.GetUserById(request.UserId);
 
-            var returnList = (await _dtoService.GetBaseItemDtos(result.Items, options, user).ConfigureAwait(false));
-            var returnItems = returnList.ToArray(returnList.Count);
+            var returnItems = (await _dtoService.GetBaseItemDtos(result.Items, options, user).ConfigureAwait(false));
 
-            return ToOptimizedSerializedResultUsingCache(new ItemsResult
+            return ToOptimizedSerializedResultUsingCache(new QueryResult<BaseItemDto>
             {
                 TotalRecordCount = result.TotalRecordCount,
                 Items = returnItems
@@ -443,14 +441,13 @@ namespace MediaBrowser.Api
                 IsSpecialSeason = request.IsSpecialSeason,
                 AdjacentTo = request.AdjacentTo
 
-            })).OfType<Season>();
+            }));
 
             var dtoOptions = GetDtoOptions(_authContext, request);
 
-            var returnList = (await _dtoService.GetBaseItemDtos(seasons, dtoOptions, user).ConfigureAwait(false));
-            var returnItems = returnList.ToArray(returnList.Count);
+            var returnItems = (await _dtoService.GetBaseItemDtos(seasons, dtoOptions, user).ConfigureAwait(false));
 
-            return new ItemsResult
+            return new QueryResult<BaseItemDto>
             {
                 TotalRecordCount = returnItems.Length,
                 Items = returnItems
@@ -471,7 +468,7 @@ namespace MediaBrowser.Api
         {
             var user = _userManager.GetUserById(request.UserId);
 
-            IEnumerable<Episode> episodes;
+            List<BaseItem> episodes;
 
             var dtoOptions = GetDtoOptions(_authContext, request);
 
@@ -499,11 +496,11 @@ namespace MediaBrowser.Api
 
                 if (season == null)
                 {
-                    episodes = new List<Episode>();
+                    episodes = new List<BaseItem>();
                 }
                 else
                 {
-                    episodes = season.GetEpisodes(user, dtoOptions);
+                    episodes = ((Season)season).GetEpisodes(user, dtoOptions);
                 }
             }
             else
@@ -515,44 +512,44 @@ namespace MediaBrowser.Api
                     throw new ResourceNotFoundException("Series not found");
                 }
 
-                episodes = series.GetEpisodes(user, dtoOptions);
+                episodes = series.GetEpisodes(user, dtoOptions).ToList();
             }
 
             // Filter after the fact in case the ui doesn't want them
             if (request.IsMissing.HasValue)
             {
                 var val = request.IsMissing.Value;
-                episodes = episodes.Where(i => i.IsMissingEpisode == val);
+                episodes = episodes.Where(i => ((Episode)i).IsMissingEpisode == val).ToList();
             }
 
             if (!string.IsNullOrWhiteSpace(request.StartItemId))
             {
-                episodes = episodes.SkipWhile(i => !string.Equals(i.Id.ToString("N"), request.StartItemId, StringComparison.OrdinalIgnoreCase));
+                episodes = episodes.SkipWhile(i => !string.Equals(i.Id.ToString("N"), request.StartItemId, StringComparison.OrdinalIgnoreCase)).ToList();
             }
 
-            IEnumerable<BaseItem> returnItems = episodes;
-
             // This must be the last filter
             if (!string.IsNullOrEmpty(request.AdjacentTo))
             {
-                returnItems = UserViewBuilder.FilterForAdjacency(returnItems, request.AdjacentTo);
+                episodes = UserViewBuilder.FilterForAdjacency(episodes, request.AdjacentTo).ToList();
             }
 
             if (string.Equals(request.SortBy, ItemSortBy.Random, StringComparison.OrdinalIgnoreCase))
             {
-                returnItems = returnItems.OrderBy(i => Guid.NewGuid());
+                episodes = episodes.OrderBy(i => Guid.NewGuid()).ToList();
             }
 
-            var returnList = returnItems.ToList();
+            var returnItems = episodes;
 
-            var pagedItems = ApplyPaging(returnList, request.StartIndex, request.Limit);
+            if (request.StartIndex.HasValue || request.Limit.HasValue)
+            {
+                returnItems = ApplyPaging(episodes, request.StartIndex, request.Limit).ToList();
+            }
 
-            var returnDtos = (await _dtoService.GetBaseItemDtos(pagedItems, dtoOptions, user).ConfigureAwait(false));
-            var dtos = returnDtos.ToArray(returnDtos.Count);
+            var dtos = (await _dtoService.GetBaseItemDtos(returnItems, dtoOptions, user).ConfigureAwait(false));
 
-            return new ItemsResult
+            return new QueryResult<BaseItemDto>
             {
-                TotalRecordCount = returnList.Count,
+                TotalRecordCount = episodes.Count,
                 Items = dtos
             };
         }

+ 8 - 8
MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs

@@ -88,7 +88,7 @@ namespace MediaBrowser.Api.UserLibrary
             return null;
         }
 
-        protected ItemsResult GetResultSlim(GetItemsByName request)
+        protected QueryResult<BaseItemDto> GetResultSlim(GetItemsByName request)
         {
             var dtoOptions = GetDtoOptions(AuthorizationContext, request);
 
@@ -209,7 +209,7 @@ namespace MediaBrowser.Api.UserLibrary
                 return dto;
             });
 
-            return new ItemsResult
+            return new QueryResult<BaseItemDto>
             {
                 Items = dtos.ToArray(result.Items.Length),
                 TotalRecordCount = result.TotalRecordCount
@@ -240,7 +240,7 @@ namespace MediaBrowser.Api.UserLibrary
         /// </summary>
         /// <param name="request">The request.</param>
         /// <returns>Task{ItemsResult}.</returns>
-        protected ItemsResult GetResult(GetItemsByName request)
+        protected QueryResult<BaseItemDto> GetResult(GetItemsByName request)
         {
             var dtoOptions = GetDtoOptions(AuthorizationContext, request);
 
@@ -305,7 +305,7 @@ namespace MediaBrowser.Api.UserLibrary
 
             IEnumerable<BaseItem> ibnItems = ibnItemsArray;
 
-            var result = new ItemsResult
+            var result = new QueryResult<BaseItemDto>
             {
                 TotalRecordCount = ibnItemsArray.Count
             };
@@ -357,13 +357,13 @@ namespace MediaBrowser.Api.UserLibrary
                 items = items.Where(i => string.Compare(request.NameLessThan, i.SortName, StringComparison.CurrentCultureIgnoreCase) == 1);
             }
 
-            var imageTypes = request.GetImageTypes().ToList();
-            if (imageTypes.Count > 0)
+            var imageTypes = request.GetImageTypes();
+            if (imageTypes.Length > 0)
             {
                 items = items.Where(item => imageTypes.Any(item.HasImage));
             }
 
-            var filters = request.GetFilters().ToList();
+            var filters = request.GetFilters();
 
             if (filters.Contains(ItemFilter.Dislikes))
             {
@@ -506,7 +506,7 @@ namespace MediaBrowser.Api.UserLibrary
     /// <summary>
     /// Class GetItemsByName
     /// </summary>
-    public class GetItemsByName : BaseItemsRequest, IReturn<ItemsResult>
+    public class GetItemsByName : BaseItemsRequest, IReturn<QueryResult<BaseItemDto>>
     {
         public GetItemsByName()
         {

+ 2 - 2
MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs

@@ -435,7 +435,7 @@ namespace MediaBrowser.Api.UserLibrary
         /// Gets the filters.
         /// </summary>
         /// <returns>IEnumerable{ItemFilter}.</returns>
-        public IEnumerable<ItemFilter> GetFilters()
+        public ItemFilter[] GetFilters()
         {
             var val = Filters;
 
@@ -444,7 +444,7 @@ namespace MediaBrowser.Api.UserLibrary
                 return new ItemFilter[] { };
             }
 
-            return val.Split(',').Select(v => (ItemFilter)Enum.Parse(typeof(ItemFilter), v, true));
+            return val.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(v => (ItemFilter)Enum.Parse(typeof(ItemFilter), v, true)).ToArray();
         }
 
         /// <summary>

+ 9 - 12
MediaBrowser.Api/UserLibrary/ItemsService.cs

@@ -10,6 +10,7 @@ using System.Globalization;
 using System.Linq;
 using System.Threading.Tasks;
 using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Globalization;
 using MediaBrowser.Model.Services;
 using MediaBrowser.Model.Extensions;
@@ -21,7 +22,7 @@ namespace MediaBrowser.Api.UserLibrary
     /// </summary>
     [Route("/Items", "GET", Summary = "Gets items based on a query.")]
     [Route("/Users/{UserId}/Items", "GET", Summary = "Gets items based on a query.")]
-    public class GetItems : BaseItemsRequest, IReturn<ItemsResult>
+    public class GetItems : BaseItemsRequest, IReturn<QueryResult<BaseItemDto>>
     {
     }
 
@@ -100,7 +101,7 @@ namespace MediaBrowser.Api.UserLibrary
         /// </summary>
         /// <param name="request">The request.</param>
         /// <returns>Task{ItemsResult}.</returns>
-        private async Task<ItemsResult> GetItems(GetItems request)
+        private async Task<QueryResult<BaseItemDto>> GetItems(GetItems request)
         {
             var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
 
@@ -125,10 +126,10 @@ namespace MediaBrowser.Api.UserLibrary
                 throw new InvalidOperationException("GetBaseItemDtos returned null");
             }
 
-            return new ItemsResult
+            return new QueryResult<BaseItemDto>
             {
                 TotalRecordCount = result.TotalRecordCount,
-                Items = dtoList.ToArray(dtoList.Count)
+                Items = dtoList
             };
         }
 
@@ -180,9 +181,7 @@ namespace MediaBrowser.Api.UserLibrary
                 return folder.GetItems(GetItemsQuery(request, dtoOptions, user));
             }
 
-            IEnumerable<BaseItem> items = folder.GetChildren(user, true);
-
-            var itemsArray = items.ToArray();
+            var itemsArray = folder.GetChildren(user, true).ToArray();
 
             return new QueryResult<BaseItem>
             {
@@ -332,13 +331,11 @@ namespace MediaBrowser.Api.UserLibrary
             if (!string.IsNullOrEmpty(request.LocationTypes))
             {
                 var requestedLocationTypes =
-                    request.LocationTypes.Split(',')
-                        .Select(d => (LocationType)Enum.Parse(typeof(LocationType), d, true))
-                        .ToList();
+                    request.LocationTypes.Split(',');
 
-                if (requestedLocationTypes.Count > 0 && requestedLocationTypes.Count < 4)
+                if (requestedLocationTypes.Length > 0 && requestedLocationTypes.Length < 4)
                 {
-                    query.IsVirtualItem = requestedLocationTypes.Contains(LocationType.Virtual);
+                    query.IsVirtualItem = requestedLocationTypes.Contains(LocationType.Virtual.ToString());
                 }
             }
 

+ 17 - 12
MediaBrowser.Api/UserLibrary/UserLibraryService.cs

@@ -59,7 +59,7 @@ namespace MediaBrowser.Api.UserLibrary
     /// Class GetIntros
     /// </summary>
     [Route("/Users/{UserId}/Items/{Id}/Intros", "GET", Summary = "Gets intros to play before the main media item plays")]
-    public class GetIntros : IReturn<ItemsResult>
+    public class GetIntros : IReturn<QueryResult<BaseItemDto>>
     {
         /// <summary>
         /// Gets or sets the user id.
@@ -171,7 +171,7 @@ namespace MediaBrowser.Api.UserLibrary
     /// Class GetLocalTrailers
     /// </summary>
     [Route("/Users/{UserId}/Items/{Id}/LocalTrailers", "GET", Summary = "Gets local trailers for an item")]
-    public class GetLocalTrailers : IReturn<List<BaseItemDto>>
+    public class GetLocalTrailers : IReturn<BaseItemDto[]>
     {
         /// <summary>
         /// Gets or sets the user id.
@@ -192,7 +192,7 @@ namespace MediaBrowser.Api.UserLibrary
     /// Class GetSpecialFeatures
     /// </summary>
     [Route("/Users/{UserId}/Items/{Id}/SpecialFeatures", "GET", Summary = "Gets special features for an item")]
-    public class GetSpecialFeatures : IReturn<List<BaseItemDto>>
+    public class GetSpecialFeatures : IReturn<BaseItemDto[]>
     {
         /// <summary>
         /// Gets or sets the user id.
@@ -210,7 +210,7 @@ namespace MediaBrowser.Api.UserLibrary
     }
 
     [Route("/Users/{UserId}/Items/Latest", "GET", Summary = "Gets latest media")]
-    public class GetLatestMedia : IReturn<List<BaseItemDto>>, IHasDtoOptions
+    public class GetLatestMedia : IReturn<BaseItemDto[]>, IHasDtoOptions
     {
         /// <summary>
         /// Gets or sets the user id.
@@ -338,10 +338,10 @@ namespace MediaBrowser.Api.UserLibrary
                 return dto;
             });
 
-            return ToOptimizedResult(dtos.ToList());
+            return ToOptimizedResult(dtos.ToArray());
         }
 
-        private List<BaseItemDto> GetAsync(GetSpecialFeatures request)
+        private BaseItemDto[] GetAsync(GetSpecialFeatures request)
         {
             var user = _userManager.GetUserById(request.UserId);
 
@@ -364,7 +364,7 @@ namespace MediaBrowser.Api.UserLibrary
                     .Where(i => i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == 0)
                     .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, currentUser));
 
-                return dtos.ToList();
+                return dtos.ToArray();
             }
 
             var movie = item as IHasSpecialFeatures;
@@ -379,10 +379,10 @@ namespace MediaBrowser.Api.UserLibrary
                     .OrderBy(i => i.SortName)
                     .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item));
 
-                return dtos.ToList();
+                return dtos.ToArray();
             }
 
-            return new List<BaseItemDto>();
+            return new BaseItemDto[] { };
         }
 
         /// <summary>
@@ -396,19 +396,24 @@ namespace MediaBrowser.Api.UserLibrary
 
             var item = string.IsNullOrEmpty(request.Id) ? user.RootFolder : _libraryManager.GetItemById(request.Id);
 
-            var trailerIds = new List<Guid>();
+            List<Guid> trailerIds = null;
 
             var hasTrailers = item as IHasTrailers;
             if (hasTrailers != null)
             {
                 trailerIds = hasTrailers.GetTrailerIds();
             }
+            else
+            {
+                trailerIds = new List<Guid>();
+            }
 
             var dtoOptions = GetDtoOptions(_authContext, request);
 
             var dtos = trailerIds
                 .Select(_libraryManager.GetItemById)
-                .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item));
+                .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item))
+                .ToArray();
 
             return ToOptimizedSerializedResultUsingCache(dtos);
         }
@@ -489,7 +494,7 @@ namespace MediaBrowser.Api.UserLibrary
 
             var dtos = items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user)).ToArray();
 
-            var result = new ItemsResult
+            var result = new QueryResult<BaseItemDto>
             {
                 Items = dtos,
                 TotalRecordCount = dtos.Length

+ 11 - 10
MediaBrowser.Api/UserLibrary/UserViewsService.cs

@@ -12,6 +12,7 @@ using System.Threading;
 using System.Threading.Tasks;
 using MediaBrowser.Controller.Net;
 using MediaBrowser.Model.Services;
+using MediaBrowser.Model.Extensions;
 
 namespace MediaBrowser.Api.UserLibrary
 {
@@ -32,7 +33,7 @@ namespace MediaBrowser.Api.UserLibrary
     }
 
     [Route("/Users/{UserId}/GroupingOptions", "GET")]
-    public class GetGroupingOptions : IReturn<List<SpecialViewOption>>
+    public class GetGroupingOptions : IReturn<SpecialViewOption[]>
     {
         /// <summary>
         /// Gets or sets the user id.
@@ -84,10 +85,13 @@ namespace MediaBrowser.Api.UserLibrary
             var folders = await _userViewManager.GetUserViews(query, CancellationToken.None).ConfigureAwait(false);
 
             var dtoOptions = GetDtoOptions(_authContext, request);
-            dtoOptions.Fields.Add(ItemFields.PrimaryImageAspectRatio);
-            dtoOptions.Fields.Add(ItemFields.DisplayPreferencesId);
-            dtoOptions.Fields.Remove(ItemFields.SyncInfo);
-            dtoOptions.Fields.Remove(ItemFields.BasicSyncInfo);
+            var fields = dtoOptions.Fields.ToList();
+
+            fields.Add(ItemFields.PrimaryImageAspectRatio);
+            fields.Add(ItemFields.DisplayPreferencesId);
+            fields.Remove(ItemFields.SyncInfo);
+            fields.Remove(ItemFields.BasicSyncInfo);
+            dtoOptions.Fields = fields.ToArray(fields.Count);
 
             var user = _userManager.GetUserById(request.UserId);
 
@@ -107,13 +111,10 @@ namespace MediaBrowser.Api.UserLibrary
         {
             var user = _userManager.GetUserById(request.UserId);
 
-            var views = user.RootFolder
+            var list = user.RootFolder
                 .GetChildren(user, true)
                 .OfType<Folder>()
                 .Where(UserView.IsEligibleForGrouping)
-                .ToList();
-
-            var list = views
                 .Select(i => new SpecialViewOption
                 {
                     Name = i.Name,
@@ -121,7 +122,7 @@ namespace MediaBrowser.Api.UserLibrary
 
                 })
             .OrderBy(i => i.Name)
-            .ToList();
+            .ToArray();
 
             return ToOptimizedResult(list);
         }

+ 3 - 3
MediaBrowser.Api/UserService.cs

@@ -22,7 +22,7 @@ namespace MediaBrowser.Api
     /// </summary>
     [Route("/Users", "GET", Summary = "Gets a list of users")]
     [Authenticated]
-    public class GetUsers : IReturn<List<UserDto>>
+    public class GetUsers : IReturn<UserDto[]>
     {
         [ApiMember(Name = "IsHidden", Description = "Optional filter by IsHidden=true or false", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
         public bool? IsHidden { get; set; }
@@ -35,7 +35,7 @@ namespace MediaBrowser.Api
     }
 
     [Route("/Users/Public", "GET", Summary = "Gets a list of publicly visible users for display on a login screen.")]
-    public class GetPublicUsers : IReturn<List<UserDto>>
+    public class GetPublicUsers : IReturn<UserDto[]>
     {
     }
 
@@ -329,7 +329,7 @@ namespace MediaBrowser.Api
             var result = users
                 .OrderBy(u => u.Name)
                 .Select(i => _userManager.GetUserDto(i, Request.RemoteIp))
-                .ToList();
+                .ToArray();
 
             return ToOptimizedResult(result);
         }

+ 2 - 2
MediaBrowser.Api/VideosService.cs

@@ -19,7 +19,7 @@ namespace MediaBrowser.Api
 {
     [Route("/Videos/{Id}/AdditionalParts", "GET", Summary = "Gets additional parts for a video.")]
     [Authenticated]
-    public class GetAdditionalParts : IReturn<ItemsResult>
+    public class GetAdditionalParts : IReturn<QueryResult<BaseItemDto>>
     {
         [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
         public string UserId { get; set; }
@@ -99,7 +99,7 @@ namespace MediaBrowser.Api
                 items = new BaseItemDto[] { };
             }
 
-            var result = new ItemsResult
+            var result = new QueryResult<BaseItemDto>
             {
                 Items = items,
                 TotalRecordCount = items.Length

+ 2 - 2
MediaBrowser.Common/Updates/IInstallationManager.cs

@@ -48,7 +48,7 @@ namespace MediaBrowser.Common.Updates
         /// <param name="packageType">Type of the package.</param>
         /// <param name="applicationVersion">The application version.</param>
         /// <returns>Task{List{PackageInfo}}.</returns>
-        Task<IEnumerable<PackageInfo>> GetAvailablePackages(CancellationToken cancellationToken,
+        Task<PackageInfo[]> GetAvailablePackages(CancellationToken cancellationToken,
             bool withRegistration = true,
                                                                                   string packageType = null,
                                                                                   Version applicationVersion = null);
@@ -58,7 +58,7 @@ namespace MediaBrowser.Common.Updates
         /// </summary>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task{List{PackageInfo}}.</returns>
-        Task<IEnumerable<PackageInfo>> GetAvailablePackagesWithoutRegistrationInfo(CancellationToken cancellationToken);
+        Task<PackageInfo[]> GetAvailablePackagesWithoutRegistrationInfo(CancellationToken cancellationToken);
 
         /// <summary>
         /// Gets the package.

+ 1 - 1
MediaBrowser.Controller/Channels/IChannelManager.cs

@@ -30,7 +30,7 @@ namespace MediaBrowser.Controller.Channels
         /// Gets all channel features.
         /// </summary>
         /// <returns>IEnumerable{ChannelFeatures}.</returns>
-        IEnumerable<ChannelFeatures> GetAllChannelFeatures();
+        ChannelFeatures[] GetAllChannelFeatures();
 
         /// <summary>
         /// Gets the channel.

+ 0 - 9
MediaBrowser.Controller/Channels/InternalChannelFeatures.cs

@@ -58,13 +58,4 @@ namespace MediaBrowser.Controller.Channels
             DefaultSortFields = new List<ChannelItemSortField>();
         }
     }
-
-    public class ChannelDownloadException : Exception
-    {
-        public ChannelDownloadException(string message)
-            : base(message)
-        {
-
-        }
-    }
 }

+ 4 - 4
MediaBrowser.Controller/Collections/CollectionCreationOptions.cs

@@ -14,14 +14,14 @@ namespace MediaBrowser.Controller.Collections
 
         public Dictionary<string, string> ProviderIds { get; set; }
 
-        public List<Guid> ItemIdList { get; set; }
-        public List<Guid> UserIds { get; set; }
+        public string[] ItemIdList { get; set; }
+        public string[] UserIds { get; set; }
 
         public CollectionCreationOptions()
         {
             ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
-            ItemIdList = new List<Guid>();
-            UserIds = new List<Guid>();
+            ItemIdList = new string[] { };
+            UserIds = new string[] { };
         }
     }
 }

+ 2 - 2
MediaBrowser.Controller/Collections/ICollectionManager.cs

@@ -36,7 +36,7 @@ namespace MediaBrowser.Controller.Collections
         /// <param name="collectionId">The collection identifier.</param>
         /// <param name="itemIds">The item ids.</param>
         /// <returns>Task.</returns>
-        Task AddToCollection(Guid collectionId, IEnumerable<Guid> itemIds);
+        Task AddToCollection(Guid collectionId, string[] itemIds);
 
         /// <summary>
         /// Removes from collection.
@@ -44,7 +44,7 @@ namespace MediaBrowser.Controller.Collections
         /// <param name="collectionId">The collection identifier.</param>
         /// <param name="itemIds">The item ids.</param>
         /// <returns>Task.</returns>
-        Task RemoveFromCollection(Guid collectionId, IEnumerable<Guid> itemIds);
+        Task RemoveFromCollection(Guid collectionId, string[] itemIds);
 
         /// <summary>
         /// Collapses the items within box sets.

+ 14 - 10
MediaBrowser.Controller/Dto/DtoOptions.cs

@@ -14,8 +14,8 @@ namespace MediaBrowser.Controller.Dto
             ItemFields.RefreshState
         };
 
-        public List<ItemFields> Fields { get; set; }
-        public List<ImageType> ImageTypes { get; set; }
+        public ItemFields[] Fields { get; set; }
+        public ImageType[] ImageTypes { get; set; }
         public int ImageTypeLimit { get; set; }
         public bool EnableImages { get; set; }
         public bool AddProgramRecordingInfo { get; set; }
@@ -28,6 +28,15 @@ namespace MediaBrowser.Controller.Dto
         {
         }
 
+        private static readonly ImageType[] AllImageTypes = Enum.GetNames(typeof(ImageType))
+            .Select(i => (ImageType)Enum.Parse(typeof(ImageType), i, true))
+            .ToArray();
+
+        private static readonly ItemFields[] AllItemFields = Enum.GetNames(typeof(ItemFields))
+            .Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
+            .Except(DefaultExcludedFields)
+            .ToArray();
+
         public DtoOptions(bool allFields)
         {
             ImageTypeLimit = int.MaxValue;
@@ -37,19 +46,14 @@ namespace MediaBrowser.Controller.Dto
 
             if (allFields)
             {
-                Fields = Enum.GetNames(typeof(ItemFields))
-                        .Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
-                        .Except(DefaultExcludedFields)
-                        .ToList();
+                Fields = AllItemFields;
             }
             else
             {
-                Fields = new List<ItemFields>();
+                Fields = new ItemFields[] { };
             }
 
-            ImageTypes = Enum.GetNames(typeof(ImageType))
-                .Select(i => (ImageType)Enum.Parse(typeof(ImageType), i, true))
-                .ToList();
+            ImageTypes = AllImageTypes;
         }
 
         public int GetImageLimit(ImageType type)

+ 5 - 4
MediaBrowser.Controller/Dto/IDtoService.cs

@@ -41,7 +41,7 @@ namespace MediaBrowser.Controller.Dto
         /// <param name="user">The user.</param>
         /// <param name="owner">The owner.</param>
         /// <returns>Task{BaseItemDto}.</returns>
-        BaseItemDto GetBaseItemDto(BaseItem item, List<ItemFields> fields, User user = null, BaseItem owner = null);
+        BaseItemDto GetBaseItemDto(BaseItem item, ItemFields[] fields, User user = null, BaseItem owner = null);
 
         /// <summary>
         /// Gets the base item dto.
@@ -61,9 +61,10 @@ namespace MediaBrowser.Controller.Dto
         /// <param name="user">The user.</param>
         /// <param name="owner">The owner.</param>
         /// <returns>IEnumerable&lt;BaseItemDto&gt;.</returns>
-        Task<List<BaseItemDto>> GetBaseItemDtos(IEnumerable<BaseItem> items, DtoOptions options, User user = null,
-            BaseItem owner = null);
-        
+        Task<BaseItemDto[]> GetBaseItemDtos(BaseItem[] items, DtoOptions options, User user = null, BaseItem owner = null);
+
+        Task<BaseItemDto[]> GetBaseItemDtos(List<BaseItem> items, DtoOptions options, User user = null, BaseItem owner = null);
+
         /// <summary>
         /// Gets the chapter information dto.
         /// </summary>

+ 1 - 1
MediaBrowser.Controller/Entities/BaseItem.cs

@@ -2265,7 +2265,7 @@ namespace MediaBrowser.Controller.Entities
             return path;
         }
 
-        public virtual void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user, List<ItemFields> fields)
+        public virtual void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user, ItemFields[] fields)
         {
             if (RunTimeTicks.HasValue)
             {

+ 10 - 10
MediaBrowser.Controller/Entities/Folder.cs

@@ -711,7 +711,7 @@ namespace MediaBrowser.Controller.Entities
             {
                 if (!(this is ICollectionFolder))
                 {
-                    return GetChildren(user, true).Count();
+                    return GetChildren(user, true).Count;
                 }
             }
 
@@ -792,16 +792,16 @@ namespace MediaBrowser.Controller.Entities
             query.StartIndex = null;
             query.Limit = null;
 
-            IEnumerable<BaseItem> itemsList = LibraryManager.GetItemList(query);
+            var itemsList = LibraryManager.GetItemList(query);
             var user = query.User;
 
             if (user != null)
             {
                 // needed for boxsets
-                itemsList = itemsList.Where(i => i.IsVisibleStandalone(query.User));
+                itemsList = itemsList.Where(i => i.IsVisibleStandalone(query.User)).ToList();
             }
 
-            IEnumerable<BaseItem> returnItems;
+            BaseItem[] returnItems;
             int totalCount = 0;
 
             if (query.EnableTotalRecordCount)
@@ -812,16 +812,16 @@ namespace MediaBrowser.Controller.Entities
             }
             else
             {
-                returnItems = itemsList;
+                returnItems = itemsList.ToArray();
             }
 
             if (limit.HasValue)
             {
-                returnItems = returnItems.Skip(startIndex ?? 0).Take(limit.Value);
+                returnItems = returnItems.Skip(startIndex ?? 0).Take(limit.Value).ToArray();
             }
             else if (startIndex.HasValue)
             {
-                returnItems = returnItems.Skip(startIndex.Value);
+                returnItems = returnItems.Skip(startIndex.Value).ToArray();
             }
 
             return new QueryResult<BaseItem>
@@ -1044,7 +1044,7 @@ namespace MediaBrowser.Controller.Entities
             return UserViewBuilder.PostFilterAndSort(items, this, null, query, LibraryManager, ConfigurationManager, collapseBoxSetItems, enableSorting);
         }
 
-        public virtual IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
+        public virtual List<BaseItem> GetChildren(User user, bool includeLinkedChildren)
         {
             if (user == null)
             {
@@ -1058,7 +1058,7 @@ namespace MediaBrowser.Controller.Entities
 
             AddChildren(user, includeLinkedChildren, result, false, null);
 
-            return result.Values;
+            return result.Values.ToList();
         }
 
         protected virtual IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user)
@@ -1477,7 +1477,7 @@ namespace MediaBrowser.Controller.Entities
             }
         }
 
-        public override void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user, List<ItemFields> fields)
+        public override void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user, ItemFields[] fields)
         {
             if (!SupportsUserDataFromChildren)
             {

+ 1 - 1
MediaBrowser.Controller/Entities/IHasUserData.cs

@@ -16,7 +16,7 @@ namespace MediaBrowser.Controller.Entities
         /// <summary>
         /// Fills the user data dto values.
         /// </summary>
-        void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user, List<ItemFields> fields);
+        void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user, ItemFields[] fields);
 
         bool EnableRememberingTrackSelections { get; }
 

+ 4 - 4
MediaBrowser.Controller/Entities/Movies/BoxSet.cs

@@ -170,24 +170,24 @@ namespace MediaBrowser.Controller.Entities.Movies
                 StringComparison.OrdinalIgnoreCase);
         }
 
-        public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
+        public override List<BaseItem> GetChildren(User user, bool includeLinkedChildren)
         {
             var children = base.GetChildren(user, includeLinkedChildren);
 
             if (string.Equals(DisplayOrder, ItemSortBy.SortName, StringComparison.OrdinalIgnoreCase))
             {
                 // Sort by name
-                return LibraryManager.Sort(children, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending);
+                return LibraryManager.Sort(children, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).ToList();
             }
 
             if (string.Equals(DisplayOrder, ItemSortBy.PremiereDate, StringComparison.OrdinalIgnoreCase))
             {
                 // Sort by release date
-                return LibraryManager.Sort(children, user, new[] { ItemSortBy.ProductionYear, ItemSortBy.PremiereDate, ItemSortBy.SortName }, SortOrder.Ascending);
+                return LibraryManager.Sort(children, user, new[] { ItemSortBy.ProductionYear, ItemSortBy.PremiereDate, ItemSortBy.SortName }, SortOrder.Ascending).ToList();
             }
 
             // Default sorting
-            return LibraryManager.Sort(children, user, new[] { ItemSortBy.ProductionYear, ItemSortBy.PremiereDate, ItemSortBy.SortName }, SortOrder.Ascending);
+            return LibraryManager.Sort(children, user, new[] { ItemSortBy.ProductionYear, ItemSortBy.PremiereDate, ItemSortBy.SortName }, SortOrder.Ascending).ToList();
         }
 
         public BoxSetInfo GetLookupInfo()

+ 5 - 5
MediaBrowser.Controller/Entities/TV/Season.cs

@@ -160,27 +160,27 @@ namespace MediaBrowser.Controller.Entities.TV
         /// <summary>
         /// Gets the episodes.
         /// </summary>
-        public IEnumerable<Episode> GetEpisodes(User user, DtoOptions options)
+        public List<BaseItem> GetEpisodes(User user, DtoOptions options)
         {
             return GetEpisodes(Series, user, options);
         }
 
-        public IEnumerable<Episode> GetEpisodes(Series series, User user, DtoOptions options)
+        public List<BaseItem> GetEpisodes(Series series, User user, DtoOptions options)
         {
             return GetEpisodes(series, user, null, options);
         }
 
-        public IEnumerable<Episode> GetEpisodes(Series series, User user, IEnumerable<Episode> allSeriesEpisodes, DtoOptions options)
+        public List<BaseItem> GetEpisodes(Series series, User user, IEnumerable<Episode> allSeriesEpisodes, DtoOptions options)
         {
             return series.GetSeasonEpisodes(this, user, allSeriesEpisodes, options);
         }
 
-        public IEnumerable<Episode> GetEpisodes()
+        public List<BaseItem> GetEpisodes()
         {
             return Series.GetSeasonEpisodes(this, null, null, new DtoOptions(true));
         }
 
-        public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
+        public override List<BaseItem> GetChildren(User user, bool includeLinkedChildren)
         {
             return GetEpisodes(user, new DtoOptions(true));
         }

+ 16 - 23
MediaBrowser.Controller/Entities/TV/Series.cs

@@ -152,12 +152,8 @@ namespace MediaBrowser.Controller.Entities.TV
                 IncludeItemTypes = new[] { typeof(Season).Name },
                 IsVirtualItem = false,
                 Limit = 0,
-                DtoOptions = new Dto.DtoOptions
+                DtoOptions = new Dto.DtoOptions(false)
                 {
-                    Fields = new List<ItemFields>
-                    {
-
-                    },
                     EnableImages = false
                 }
             });
@@ -173,12 +169,8 @@ namespace MediaBrowser.Controller.Entities.TV
             {
                 AncestorWithPresentationUniqueKey = null,
                 SeriesPresentationUniqueKey = seriesKey,
-                DtoOptions = new Dto.DtoOptions
+                DtoOptions = new Dto.DtoOptions(false)
                 {
-                    Fields = new List<ItemFields>
-                    {
-                        
-                    },
                     EnableImages = false
                 }
             };
@@ -226,12 +218,12 @@ namespace MediaBrowser.Controller.Entities.TV
             }
         }
 
-        public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
+        public override List<BaseItem> GetChildren(User user, bool includeLinkedChildren)
         {
             return GetSeasons(user, new DtoOptions(true));
         }
 
-        public IEnumerable<Season> GetSeasons(User user, DtoOptions options)
+        public List<BaseItem> GetSeasons(User user, DtoOptions options)
         {
             var query = new InternalItemsQuery(user)
             {
@@ -240,7 +232,7 @@ namespace MediaBrowser.Controller.Entities.TV
 
             SetSeasonQueryOptions(query, user);
 
-            return LibraryManager.GetItemList(query).Cast<Season>();
+            return LibraryManager.GetItemList(query);
         }
 
         private void SetSeasonQueryOptions(InternalItemsQuery query, User user)
@@ -292,7 +284,7 @@ namespace MediaBrowser.Controller.Entities.TV
             return LibraryManager.GetItemsResult(query);
         }
 
-        public IEnumerable<Episode> GetEpisodes(User user, DtoOptions options)
+        public IEnumerable<BaseItem> GetEpisodes(User user, DtoOptions options)
         {
             var seriesKey = GetUniqueSeriesKey(this);
 
@@ -312,7 +304,7 @@ namespace MediaBrowser.Controller.Entities.TV
 
             var allItems = LibraryManager.GetItemList(query);
 
-            var allSeriesEpisodes = allItems.OfType<Episode>();
+            var allSeriesEpisodes = allItems.OfType<Episode>().ToList();
 
             var allEpisodes = allItems.OfType<Season>()
                 .SelectMany(i => i.GetEpisodes(this, user, allSeriesEpisodes, options))
@@ -396,7 +388,7 @@ namespace MediaBrowser.Controller.Entities.TV
             await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false);
         }
 
-        public IEnumerable<Episode> GetSeasonEpisodes(Season parentSeason, User user, DtoOptions options)
+        public List<BaseItem> GetSeasonEpisodes(Season parentSeason, User user, DtoOptions options)
         {
             var queryFromSeries = ConfigurationManager.Configuration.DisplaySpecialsWithinSeasons;
 
@@ -422,12 +414,12 @@ namespace MediaBrowser.Controller.Entities.TV
                 }
             }
 
-            var allItems = LibraryManager.GetItemList(query).OfType<Episode>();
+            var allItems = LibraryManager.GetItemList(query);
 
             return GetSeasonEpisodes(parentSeason, user, allItems, options);
         }
 
-        public IEnumerable<Episode> GetSeasonEpisodes(Season parentSeason, User user, IEnumerable<Episode> allSeriesEpisodes, DtoOptions options)
+        public List<BaseItem> GetSeasonEpisodes(Season parentSeason, User user, IEnumerable<BaseItem> allSeriesEpisodes, DtoOptions options)
         {
             if (allSeriesEpisodes == null)
             {
@@ -438,14 +430,13 @@ namespace MediaBrowser.Controller.Entities.TV
 
             var sortBy = (parentSeason.IndexNumber ?? -1) == 0 ? ItemSortBy.SortName : ItemSortBy.AiredEpisodeOrder;
 
-            return LibraryManager.Sort(episodes, user, new[] { sortBy }, SortOrder.Ascending)
-                .Cast<Episode>();
+            return LibraryManager.Sort(episodes, user, new[] { sortBy }, SortOrder.Ascending).ToList();
         }
 
         /// <summary>
         /// Filters the episodes by season.
         /// </summary>
-        public static IEnumerable<Episode> FilterEpisodesBySeason(IEnumerable<Episode> episodes, Season parentSeason, bool includeSpecials)
+        public static IEnumerable<BaseItem> FilterEpisodesBySeason(IEnumerable<BaseItem> episodes, Season parentSeason, bool includeSpecials)
         {
             var seasonNumber = parentSeason.IndexNumber;
             var seasonPresentationKey = GetUniqueSeriesKey(parentSeason);
@@ -454,7 +445,9 @@ namespace MediaBrowser.Controller.Entities.TV
 
             return episodes.Where(episode =>
             {
-                var currentSeasonNumber = supportSpecialsInSeason ? episode.AiredSeasonNumber : episode.ParentIndexNumber;
+                var episodeItem = (Episode) episode;
+
+                var currentSeasonNumber = supportSpecialsInSeason ? episodeItem.AiredSeasonNumber : episode.ParentIndexNumber;
                 if (currentSeasonNumber.HasValue && seasonNumber.HasValue && currentSeasonNumber.Value == seasonNumber.Value)
                 {
                     return true;
@@ -465,7 +458,7 @@ namespace MediaBrowser.Controller.Entities.TV
                     return true;
                 }
 
-                var season = episode.Season;
+                var season = episodeItem.Season;
                 return season != null && string.Equals(GetUniqueSeriesKey(season), seasonPresentationKey, StringComparison.OrdinalIgnoreCase);
             });
         }

+ 1 - 1
MediaBrowser.Controller/Entities/UserRootFolder.cs

@@ -81,7 +81,7 @@ namespace MediaBrowser.Controller.Entities
 
         public override int GetChildCount(User user)
         {
-            return GetChildren(user, true).Count();
+            return GetChildren(user, true).Count;
         }
 
         [IgnoreDataMember]

+ 2 - 2
MediaBrowser.Controller/Entities/UserView.cs

@@ -80,7 +80,7 @@ namespace MediaBrowser.Controller.Entities
                 .GetUserItems(parent, this, ViewType, query).Result;
         }
 
-        public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
+        public override List<BaseItem> GetChildren(User user, bool includeLinkedChildren)
         {
             var result = GetItemList(new InternalItemsQuery
             {
@@ -90,7 +90,7 @@ namespace MediaBrowser.Controller.Entities
 
             });
 
-            return result;
+            return result.ToList();
         }
 
         public override bool CanDelete()

+ 3 - 5
MediaBrowser.Controller/Entities/UserViewBuilder.cs

@@ -533,7 +533,7 @@ namespace MediaBrowser.Controller.Entities
             return ConvertToResult(_libraryManager.GetItemList(query));
         }
 
-        private QueryResult<BaseItem> ConvertToResult(IEnumerable<BaseItem> items)
+        private QueryResult<BaseItem> ConvertToResult(List<BaseItem> items)
         {
             var arr = items.ToArray();
             return new QueryResult<BaseItem>
@@ -789,7 +789,7 @@ namespace MediaBrowser.Controller.Entities
             // This must be the last filter
             if (!string.IsNullOrEmpty(query.AdjacentTo))
             {
-                items = FilterForAdjacency(items, query.AdjacentTo);
+                items = FilterForAdjacency(items.ToList(), query.AdjacentTo);
             }
 
             return SortAndPage(items, totalRecordLimit, query, libraryManager, enableSorting);
@@ -1763,10 +1763,8 @@ namespace MediaBrowser.Controller.Entities
             return _userViewManager.GetUserSubView(parent.Id.ToString("N"), type, sortName, CancellationToken.None);
         }
 
-        public static IEnumerable<BaseItem> FilterForAdjacency(IEnumerable<BaseItem> items, string adjacentToId)
+        public static IEnumerable<BaseItem> FilterForAdjacency(List<BaseItem> list, string adjacentToId)
         {
-            var list = items.ToList();
-
             var adjacentToIdGuid = new Guid(adjacentToId);
             var adjacentToItem = list.FirstOrDefault(i => i.Id == adjacentToIdGuid);
 

+ 10 - 10
MediaBrowser.Controller/Entities/Video.cs

@@ -153,14 +153,14 @@ namespace MediaBrowser.Controller.Entities
         /// Gets the playable stream files.
         /// </summary>
         /// <returns>List{System.String}.</returns>
-        public List<string> GetPlayableStreamFiles()
+        public string[] GetPlayableStreamFiles()
         {
             return GetPlayableStreamFiles(Path);
         }
 
-        public List<string> GetPlayableStreamFileNames()
+        public string[] GetPlayableStreamFileNames()
         {
-            return GetPlayableStreamFiles().Select(System.IO.Path.GetFileName).ToList(); ;
+            return GetPlayableStreamFiles().Select(System.IO.Path.GetFileName).ToArray(); 
         }
 
         /// <summary>
@@ -389,11 +389,11 @@ namespace MediaBrowser.Controller.Entities
         /// </summary>
         /// <param name="rootPath">The root path.</param>
         /// <returns>List{System.String}.</returns>
-        public List<string> GetPlayableStreamFiles(string rootPath)
+        public string[] GetPlayableStreamFiles(string rootPath)
         {
             if (VideoType == VideoType.VideoFile)
             {
-                return new List<string>();
+                return new string[] { };
             }
 
             var allFiles = FileSystem.GetFilePaths(rootPath, true).ToList();
@@ -411,10 +411,10 @@ namespace MediaBrowser.Controller.Entities
 
             return QueryPlayableStreamFiles(rootPath, videoType).Select(name => allFiles.FirstOrDefault(f => string.Equals(System.IO.Path.GetFileName(f), name, StringComparison.OrdinalIgnoreCase)))
                 .Where(f => !string.IsNullOrEmpty(f))
-                .ToList();
+                .ToArray();
         }
 
-        public static List<string> QueryPlayableStreamFiles(string rootPath, VideoType videoType)
+        public static string[] QueryPlayableStreamFiles(string rootPath, VideoType videoType)
         {
             if (videoType == VideoType.Dvd)
             {
@@ -423,7 +423,7 @@ namespace MediaBrowser.Controller.Entities
                     .ThenBy(i => i.FullName)
                     .Take(1)
                     .Select(i => i.FullName)
-                    .ToList();
+                    .ToArray();
             }
             if (videoType == VideoType.BluRay)
             {
@@ -432,9 +432,9 @@ namespace MediaBrowser.Controller.Entities
                     .ThenBy(i => i.FullName)
                     .Take(1)
                     .Select(i => i.FullName)
-                    .ToList();
+                    .ToArray();
             }
-            return new List<string>();
+            return new string[] { };
         }
 
         /// <summary>

+ 1 - 1
MediaBrowser.Controller/Library/IUserDataManager.cs

@@ -40,7 +40,7 @@ namespace MediaBrowser.Controller.Library
         /// </summary>
         UserItemDataDto GetUserDataDto(IHasUserData item, User user);
 
-        UserItemDataDto GetUserDataDto(IHasUserData item, BaseItemDto itemDto, User user, List<ItemFields> fields);
+        UserItemDataDto GetUserDataDto(IHasUserData item, BaseItemDto itemDto, User user, ItemFields[] fields);
 
         /// <summary>
         /// Get all user data for the given user

+ 1 - 1
MediaBrowser.Controller/Library/IUserViewManager.cs

@@ -11,7 +11,7 @@ namespace MediaBrowser.Controller.Library
 {
     public interface IUserViewManager
     {
-        Task<IEnumerable<Folder>> GetUserViews(UserViewQuery query, CancellationToken cancellationToken);
+        Task<Folder[]> GetUserViews(UserViewQuery query, CancellationToken cancellationToken);
 
         Task<UserView> GetUserSubView(string name, string parentId, string type, string sortName, CancellationToken cancellationToken);
 

+ 3 - 3
MediaBrowser.Controller/LiveTv/ILiveTvManager.cs

@@ -243,7 +243,7 @@ namespace MediaBrowser.Controller.LiveTv
         /// Gets the recommended programs internal.
         /// </summary>
         /// <returns>Task&lt;QueryResult&lt;LiveTvProgram&gt;&gt;.</returns>
-        Task<QueryResult<LiveTvProgram>> GetRecommendedProgramsInternal(RecommendedProgramQuery query, DtoOptions options, CancellationToken cancellationToken);
+        Task<QueryResult<BaseItem>> GetRecommendedProgramsInternal(RecommendedProgramQuery query, DtoOptions options, CancellationToken cancellationToken);
 
         /// <summary>
         /// Gets the live tv information.
@@ -316,7 +316,7 @@ namespace MediaBrowser.Controller.LiveTv
         /// <param name="fields">The fields.</param>
         /// <param name="user">The user.</param>
         /// <returns>Task.</returns>
-        Task AddInfoToProgramDto(List<Tuple<BaseItem, BaseItemDto>> programs, List<ItemFields> fields, User user = null);
+        Task AddInfoToProgramDto(List<Tuple<BaseItem, BaseItemDto>> programs, ItemFields[] fields, User user = null);
 
         /// <summary>
         /// Saves the tuner host.
@@ -335,7 +335,7 @@ namespace MediaBrowser.Controller.LiveTv
 
         Task<TunerChannelMapping> SetChannelMapping(string providerId, string tunerChannelNumber, string providerChannelNumber);
 
-        TunerChannelMapping GetTunerChannelMapping(ChannelInfo channel, List<NameValuePair> mappings, List<ChannelInfo> providerChannels);
+        TunerChannelMapping GetTunerChannelMapping(ChannelInfo channel, NameValuePair[] mappings, List<ChannelInfo> providerChannels);
 
         /// <summary>
         /// Gets the lineups.

+ 3 - 3
MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs

@@ -1521,7 +1521,7 @@ namespace MediaBrowser.Controller.MediaEncoding
         {
             var inputModifier = string.Empty;
 
-            var numInputFiles = state.PlayableStreamFileNames.Count > 0 ? state.PlayableStreamFileNames.Count : 1;
+            var numInputFiles = state.PlayableStreamFileNames.Length > 0 ? state.PlayableStreamFileNames.Length : 1;
             var probeSizeArgument = GetProbeSizeArgument(numInputFiles);
 
             string analyzeDurationArgument;
@@ -1676,12 +1676,12 @@ namespace MediaBrowser.Controller.MediaEncoding
                 }
                 else
                 {
-                    state.PlayableStreamFileNames = new List<string>();
+                    state.PlayableStreamFileNames = new string[]{};
                 }
             }
             else
             {
-                state.PlayableStreamFileNames = new List<string>();
+                state.PlayableStreamFileNames = new string[] { };
             }
 
             if (mediaSource.Timestamp.HasValue)

+ 5 - 5
MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs

@@ -27,7 +27,7 @@ namespace MediaBrowser.Controller.MediaEncoding
         public string MediaPath { get; set; }
         public bool IsInputVideo { get; set; }
         public IIsoMount IsoMount { get; set; }
-        public List<string> PlayableStreamFileNames { get; set; }
+        public string[] PlayableStreamFileNames { get; set; }
         public string OutputAudioCodec { get; set; }
         public int? OutputVideoBitrate { get; set; }
         public MediaStream SubtitleStream { get; set; }
@@ -42,8 +42,8 @@ namespace MediaBrowser.Controller.MediaEncoding
 
         public bool ReadInputAtNativeFramerate { get; set; }
 
-        private List<TranscodeReason> _transcodeReasons = null;
-        public List<TranscodeReason> TranscodeReasons
+        private TranscodeReason[] _transcodeReasons = null;
+        public TranscodeReason[] TranscodeReasons
         {
             get
             {
@@ -53,7 +53,7 @@ namespace MediaBrowser.Controller.MediaEncoding
                         .Split(',')
                         .Where(i => !string.IsNullOrWhiteSpace(i))
                         .Select(v => (TranscodeReason)Enum.Parse(typeof(TranscodeReason), v, true))
-                        .ToList();
+                        .ToArray();
                 }
 
                 return _transcodeReasons;
@@ -164,7 +164,7 @@ namespace MediaBrowser.Controller.MediaEncoding
             _logger = logger;
             TranscodingType = jobType;
             RemoteHttpHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
-            PlayableStreamFileNames = new List<string>();
+            PlayableStreamFileNames = new string[]{};
             SupportedAudioCodecs = new List<string>();
             SupportedVideoCodecs = new List<string>();
             SupportedSubtitleCodecs = new List<string>();

+ 9 - 12
MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs

@@ -1,12 +1,9 @@
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.MediaInfo;
 using System;
-using System.Collections.Generic;
 using System.IO;
 using System.Linq;
 
-using MediaBrowser.Controller.IO;
-
 namespace MediaBrowser.Controller.MediaEncoding
 {
     /// <summary>
@@ -23,34 +20,34 @@ namespace MediaBrowser.Controller.MediaEncoding
         /// <param name="isoMount">The iso mount.</param>
         /// <param name="playableStreamFileNames">The playable stream file names.</param>
         /// <returns>System.String[][].</returns>
-        public static string[] GetInputArgument(IFileSystem fileSystem, string videoPath, MediaProtocol protocol, IIsoMount isoMount, List<string> playableStreamFileNames)
+        public static string[] GetInputArgument(IFileSystem fileSystem, string videoPath, MediaProtocol protocol, IIsoMount isoMount, string[] playableStreamFileNames)
         {
-            if (playableStreamFileNames.Count > 0)
+            if (playableStreamFileNames.Length > 0)
             {
                 if (isoMount == null)
                 {
-                    return GetPlayableStreamFiles(fileSystem, videoPath, playableStreamFileNames).ToArray();
+                    return GetPlayableStreamFiles(fileSystem, videoPath, playableStreamFileNames);
                 }
-                return GetPlayableStreamFiles(fileSystem, isoMount.MountedPath, playableStreamFileNames).ToArray();
+                return GetPlayableStreamFiles(fileSystem, isoMount.MountedPath, playableStreamFileNames);
             }
 
             return new[] {videoPath};
         }
 
-        private static List<string> GetPlayableStreamFiles(IFileSystem fileSystem, string rootPath, List<string> filenames)
+        private static string[] GetPlayableStreamFiles(IFileSystem fileSystem, string rootPath, string[] filenames)
         {
-            if (filenames.Count == 0)
+            if (filenames.Length == 0)
             {
-                return new List<string>();
+                return new string[]{};
             }
 
             var allFiles = fileSystem
                 .GetFilePaths(rootPath, true)
-                .ToList();
+                .ToArray();
 
             return filenames.Select(name => allFiles.FirstOrDefault(f => string.Equals(Path.GetFileName(f), name, StringComparison.OrdinalIgnoreCase)))
                 .Where(f => !string.IsNullOrEmpty(f))
-                .ToList();
+                .ToArray();
         }
     }
 }

+ 2 - 2
MediaBrowser.Controller/MediaEncoding/MediaInfoRequest.cs

@@ -14,12 +14,12 @@ namespace MediaBrowser.Controller.MediaEncoding
         public DlnaProfileType MediaType { get; set; }
         public IIsoMount MountedIso { get; set; }
         public VideoType VideoType { get; set; }
-        public List<string> PlayableStreamFileNames { get; set; }
+        public string[] PlayableStreamFileNames { get; set; }
         public int AnalyzeDurationMs { get; set; }
 
         public MediaInfoRequest()
         {
-            PlayableStreamFileNames = new List<string>();
+            PlayableStreamFileNames = new string[] { };
         }
     }
 }

+ 1 - 1
MediaBrowser.Controller/Notifications/INotificationManager.cs

@@ -26,7 +26,7 @@ namespace MediaBrowser.Controller.Notifications
         /// Gets the notification types.
         /// </summary>
         /// <returns>IEnumerable{NotificationTypeInfo}.</returns>
-        IEnumerable<NotificationTypeInfo> GetNotificationTypes();
+        List<NotificationTypeInfo> GetNotificationTypes();
 
         /// <summary>
         /// Gets the notification services.

+ 1 - 1
MediaBrowser.Controller/Playlists/Playlist.cs

@@ -89,7 +89,7 @@ namespace MediaBrowser.Controller.Playlists
             return new List<BaseItem>();
         }
 
-        public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
+        public override List<BaseItem> GetChildren(User user, bool includeLinkedChildren)
         {
             return GetPlayableItems(user, new DtoOptions(true));
         }

+ 1 - 1
MediaBrowser.Controller/Providers/IProviderManager.cs

@@ -97,7 +97,7 @@ namespace MediaBrowser.Controller.Providers
         /// Gets all metadata plugins.
         /// </summary>
         /// <returns>IEnumerable{MetadataPlugin}.</returns>
-        IEnumerable<MetadataPluginSummary> GetAllMetadataPlugins();
+        MetadataPluginSummary[] GetAllMetadataPlugins();
 
         /// <summary>
         /// Gets the external urls.

+ 6 - 6
MediaBrowser.Controller/Session/SessionInfo.cs

@@ -22,13 +22,13 @@ namespace MediaBrowser.Controller.Session
             _sessionManager = sessionManager;
             _logger = logger;
 
-            AdditionalUsers = new List<SessionUserInfo>();
+            AdditionalUsers = new SessionUserInfo[] { };
             PlayState = new PlayerStateInfo();
         }
 
         public PlayerStateInfo PlayState { get; set; }
 
-        public List<SessionUserInfo> AdditionalUsers { get; set; }
+        public SessionUserInfo[] AdditionalUsers { get; set; }
 
         public ClientCapabilities Capabilities { get; set; }
 
@@ -42,13 +42,13 @@ namespace MediaBrowser.Controller.Session
         /// Gets or sets the playable media types.
         /// </summary>
         /// <value>The playable media types.</value>
-        public List<string> PlayableMediaTypes
+        public string[] PlayableMediaTypes
         {
             get
             {
                 if (Capabilities == null)
                 {
-                    return new List<string>();
+                    return new string[] { };
                 }
                 return Capabilities.PlayableMediaTypes;
             }
@@ -138,13 +138,13 @@ namespace MediaBrowser.Controller.Session
         /// Gets or sets the supported commands.
         /// </summary>
         /// <value>The supported commands.</value>
-        public List<string> SupportedCommands
+        public string[] SupportedCommands
         {
             get
             {
                 if (Capabilities == null)
                 {
-                    return new List<string>();
+                    return new string[] { };
                 }
                 return Capabilities.SupportedCommands;
             }

+ 3 - 3
MediaBrowser.Controller/Subtitles/ISubtitleManager.cs

@@ -28,7 +28,7 @@ namespace MediaBrowser.Controller.Subtitles
         /// <summary>
         /// Searches the subtitles.
         /// </summary>
-        Task<IEnumerable<RemoteSubtitleInfo>> SearchSubtitles(Video video,
+        Task<RemoteSubtitleInfo[]> SearchSubtitles(Video video,
             string language,
             bool? isPerfectMatch,
             CancellationToken cancellationToken);
@@ -39,7 +39,7 @@ namespace MediaBrowser.Controller.Subtitles
         /// <param name="request">The request.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task{IEnumerable{RemoteSubtitleInfo}}.</returns>
-        Task<IEnumerable<RemoteSubtitleInfo>> SearchSubtitles(SubtitleSearchRequest request,
+        Task<RemoteSubtitleInfo[]> SearchSubtitles(SubtitleSearchRequest request,
             CancellationToken cancellationToken);
 
         /// <summary>
@@ -74,6 +74,6 @@ namespace MediaBrowser.Controller.Subtitles
         /// </summary>
         /// <param name="itemId">The item identifier.</param>
         /// <returns>IEnumerable{SubtitleProviderInfo}.</returns>
-        IEnumerable<SubtitleProviderInfo> GetProviders(string itemId);
+        SubtitleProviderInfo[] GetProviders(string itemId);
     }
 }

+ 7 - 11
MediaBrowser.Controller/Sync/ISyncManager.cs

@@ -79,7 +79,7 @@ namespace MediaBrowser.Controller.Sync
         /// <param name="targetId">The target identifier.</param>
         /// <param name="itemIds">The item ids.</param>
         /// <returns>Task.</returns>
-        Task CancelItems(string targetId, IEnumerable<string> itemIds);
+        Task CancelItems(string targetId, string[] itemIds);
 
         /// <summary>
         /// Adds the parts.
@@ -89,9 +89,9 @@ namespace MediaBrowser.Controller.Sync
         /// <summary>
         /// Gets the synchronize targets.
         /// </summary>
-        IEnumerable<SyncTarget> GetSyncTargets(string userId);
+        List<SyncTarget> GetSyncTargets(string userId);
 
-        IEnumerable<SyncTarget> GetSyncTargets(string userId, bool? supportsRemoteSync);
+        List<SyncTarget> GetSyncTargets(string userId, bool? supportsRemoteSync);
 
         /// <summary>
         /// Supportses the synchronize.
@@ -160,28 +160,24 @@ namespace MediaBrowser.Controller.Sync
         /// Gets the quality options.
         /// </summary>
         /// <param name="targetId">The target identifier.</param>
-        /// <returns>IEnumerable&lt;SyncQualityOption&gt;.</returns>
-        IEnumerable<SyncQualityOption> GetQualityOptions(string targetId);
+        List<SyncQualityOption> GetQualityOptions(string targetId);
         /// <summary>
         /// Gets the quality options.
         /// </summary>
         /// <param name="targetId">The target identifier.</param>
         /// <param name="user">The user.</param>
-        /// <returns>IEnumerable&lt;SyncQualityOption&gt;.</returns>
-        IEnumerable<SyncQualityOption> GetQualityOptions(string targetId, User user);
+        List<SyncQualityOption> GetQualityOptions(string targetId, User user);
 
         /// <summary>
         /// Gets the profile options.
         /// </summary>
         /// <param name="targetId">The target identifier.</param>
-        /// <returns>IEnumerable&lt;SyncQualityOption&gt;.</returns>
-        IEnumerable<SyncProfileOption> GetProfileOptions(string targetId);
+        List<SyncProfileOption> GetProfileOptions(string targetId);
         /// <summary>
         /// Gets the profile options.
         /// </summary>
         /// <param name="targetId">The target identifier.</param>
         /// <param name="user">The user.</param>
-        /// <returns>IEnumerable&lt;SyncProfileOption&gt;.</returns>
-        IEnumerable<SyncProfileOption> GetProfileOptions(string targetId, User user);
+        List<SyncProfileOption> GetProfileOptions(string targetId, User user);
     }
 }

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff