Browse Source

allow request header overrides

Luke Pulverenti 11 years ago
parent
commit
60780399c5
34 changed files with 213 additions and 140 deletions
  1. 2 7
      MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs
  2. 30 3
      MediaBrowser.Common/Net/HttpRequestOptions.cs
  3. 9 2
      MediaBrowser.Controller/Drawing/ImageExtensions.cs
  4. 14 10
      MediaBrowser.Controller/Drawing/ImageHeader.cs
  5. 8 5
      MediaBrowser.Controller/IO/FileData.cs
  6. 19 9
      MediaBrowser.Controller/Providers/BaseMetadataProvider.cs
  7. 5 0
      MediaBrowser.Model/Querying/ItemFields.cs
  8. 3 1
      MediaBrowser.Model/Web/QueryStringDictionary.cs
  9. 2 2
      MediaBrowser.Providers/ImageFromMediaLocationProvider.cs
  10. 41 6
      MediaBrowser.Providers/MediaInfo/FFProbeVideoInfoProvider.cs
  11. 5 1
      MediaBrowser.Server.Implementations/Dto/DtoService.cs
  12. 1 1
      MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifier.cs
  13. 1 2
      MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs
  14. 1 0
      MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs
  15. 8 0
      MediaBrowser.Server.Implementations/Library/LibraryManager.cs
  16. 11 2
      MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs
  17. 8 0
      MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs
  18. 1 1
      MediaBrowser.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs
  19. 2 5
      MediaBrowser.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs
  20. 3 1
      MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs
  21. 0 26
      MediaBrowser.Server.Implementations/Library/UserManager.cs
  22. 13 13
      MediaBrowser.Server.Implementations/Library/Validators/ArtistsValidator.cs
  23. 1 1
      MediaBrowser.Server.Implementations/Library/Validators/CountHelpers.cs
  24. 2 6
      MediaBrowser.Server.Implementations/Library/Validators/PeoplePostScanTask.cs
  25. 2 2
      MediaBrowser.Server.Implementations/Providers/ImageSaver.cs
  26. 14 3
      MediaBrowser.Server.Implementations/Providers/ProviderManager.cs
  27. 2 3
      MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs
  28. 0 1
      MediaBrowser.Server.Implementations/Session/SessionManager.cs
  29. 1 6
      MediaBrowser.Server.Implementations/Sorting/AlbumCountComparer.cs
  30. 1 2
      MediaBrowser.Server.Implementations/Sorting/ArtistComparer.cs
  31. 1 6
      MediaBrowser.Server.Implementations/Sorting/EpisodeCountComparer.cs
  32. 1 6
      MediaBrowser.Server.Implementations/Sorting/MusicVideoCountComparer.cs
  33. 1 6
      MediaBrowser.Server.Implementations/Sorting/SongCountComparer.cs
  34. 0 1
      MediaBrowser.Server.Implementations/Udp/UdpServer.cs

+ 2 - 7
MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs

@@ -470,14 +470,9 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
         {
             var message = new HttpRequestMessage(HttpMethod.Get, options.Url);
 
-            if (!string.IsNullOrEmpty(options.UserAgent))
+            foreach (var pair in options.RequestHeaders.ToArray())
             {
-                message.Headers.Add("User-Agent", options.UserAgent);
-            }
-
-            if (!string.IsNullOrEmpty(options.AcceptHeader))
-            {
-                message.Headers.Add("Accept", options.AcceptHeader);
+                message.Headers.Add(pair.Key, pair.Value);
             }
 
             return message;

+ 30 - 3
MediaBrowser.Common/Net/HttpRequestOptions.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Generic;
 using System.Threading;
 
 namespace MediaBrowser.Common.Net
@@ -18,8 +19,14 @@ namespace MediaBrowser.Common.Net
         /// Gets or sets the accept header.
         /// </summary>
         /// <value>The accept header.</value>
-        public string AcceptHeader { get; set; }
-
+        public string AcceptHeader
+        {
+            get { return GetHeaderValue("Accept"); }
+            set
+            {
+                RequestHeaders["Accept"] = value;
+            }
+        }
         /// <summary>
         /// Gets or sets the cancellation token.
         /// </summary>
@@ -36,7 +43,14 @@ namespace MediaBrowser.Common.Net
         /// Gets or sets the user agent.
         /// </summary>
         /// <value>The user agent.</value>
-        public string UserAgent { get; set; }
+        public string UserAgent
+        {
+            get { return GetHeaderValue("User-Agent"); }
+            set
+            {
+                RequestHeaders["User-Agent"] = value;
+            }
+        }
 
         /// <summary>
         /// Gets or sets the progress.
@@ -50,12 +64,25 @@ namespace MediaBrowser.Common.Net
         /// <value><c>true</c> if [enable HTTP compression]; otherwise, <c>false</c>.</value>
         public bool EnableHttpCompression { get; set; }
 
+        public Dictionary<string, string> RequestHeaders { get; private set; }
+
+        private string GetHeaderValue(string name)
+        {
+            string value;
+
+            RequestHeaders.TryGetValue(name, out value);
+
+            return value;
+        }
+
         /// <summary>
         /// Initializes a new instance of the <see cref="HttpRequestOptions"/> class.
         /// </summary>
         public HttpRequestOptions()
         {
             EnableHttpCompression = true;
+
+            RequestHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
         }
     }
 }

+ 9 - 2
MediaBrowser.Controller/Drawing/ImageExtensions.cs

@@ -3,7 +3,6 @@ using System.Drawing;
 using System.Drawing.Drawing2D;
 using System.Drawing.Imaging;
 using System.IO;
-using System.Linq;
 
 namespace MediaBrowser.Controller.Drawing
 {
@@ -61,7 +60,15 @@ namespace MediaBrowser.Controller.Drawing
         /// <returns>ImageCodecInfo.</returns>
         private static ImageCodecInfo GetImageCodecInfo(string mimeType)
         {
-            return Encoders.FirstOrDefault(i => i.MimeType.Equals(mimeType, StringComparison.OrdinalIgnoreCase)) ?? Encoders.FirstOrDefault();
+            foreach (var encoder in Encoders)
+            {
+                if (string.Equals(encoder.MimeType, mimeType, StringComparison.OrdinalIgnoreCase))
+                {
+                    return encoder;
+                }
+            }
+
+            return Encoders.Length == 0 ? null : Encoders[0];
         }
 
         /// <summary>

+ 14 - 10
MediaBrowser.Controller/Drawing/ImageHeader.cs

@@ -18,19 +18,22 @@ namespace MediaBrowser.Controller.Drawing
         /// <summary>
         /// The error message
         /// </summary>
-        const string errorMessage = "Could not recognize image format.";
+        const string ErrorMessage = "Could not recognize image format.";
 
         /// <summary>
         /// The image format decoders
         /// </summary>
-        private static readonly Dictionary<byte[], Func<BinaryReader, Size>> imageFormatDecoders = new Dictionary<byte[], Func<BinaryReader, Size>>
+        private static readonly KeyValuePair<byte[], Func<BinaryReader, Size>>[] ImageFormatDecoders = new Dictionary<byte[], Func<BinaryReader, Size>>
         { 
             { new byte[] { 0x42, 0x4D }, DecodeBitmap }, 
             { new byte[] { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 }, DecodeGif }, 
             { new byte[] { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 }, DecodeGif }, 
             { new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }, DecodePng },
-            { new byte[] { 0xff, 0xd8 }, DecodeJfif }, 
-        };
+            { new byte[] { 0xff, 0xd8 }, DecodeJfif }
+
+        }.ToArray();
+
+        private static readonly int MaxMagicBytesLength = ImageFormatDecoders.Select(i => i.Key.Length).OrderByDescending(i => i).First();
 
         /// <summary>
         /// Gets the dimensions of an image.
@@ -81,12 +84,13 @@ namespace MediaBrowser.Controller.Drawing
         /// <exception cref="ArgumentException">The image was of an unrecognized format.</exception>
         private static Size GetDimensions(BinaryReader binaryReader)
         {
-            int maxMagicBytesLength = imageFormatDecoders.Keys.OrderByDescending(x => x.Length).First().Length;
-            var magicBytes = new byte[maxMagicBytesLength];
-            for (int i = 0; i < maxMagicBytesLength; i += 1)
+            var magicBytes = new byte[MaxMagicBytesLength];
+
+            for (var i = 0; i < MaxMagicBytesLength; i += 1)
             {
                 magicBytes[i] = binaryReader.ReadByte();
-                foreach (var kvPair in imageFormatDecoders)
+
+                foreach (var kvPair in ImageFormatDecoders)
                 {
                     if (StartsWith(magicBytes, kvPair.Key))
                     {
@@ -95,7 +99,7 @@ namespace MediaBrowser.Controller.Drawing
                 }
             }
 
-            throw new ArgumentException(errorMessage, "binaryReader");
+            throw new ArgumentException(ErrorMessage, "binaryReader");
         }
 
         /// <summary>
@@ -217,7 +221,7 @@ namespace MediaBrowser.Controller.Drawing
                 }
             }
 
-            throw new ArgumentException(errorMessage);
+            throw new ArgumentException(ErrorMessage);
         }
     }
 }

+ 8 - 5
MediaBrowser.Controller/IO/FileData.cs

@@ -3,8 +3,6 @@ using MediaBrowser.Model.Logging;
 using System;
 using System.Collections.Generic;
 using System.IO;
-using System.Linq;
-using MoreLinq;
 
 namespace MediaBrowser.Controller.IO
 {
@@ -40,9 +38,14 @@ namespace MediaBrowser.Controller.IO
             if (!resolveShortcuts && flattenFolderDepth == 0)
             {
                 // Seeing dupes on some users file system for some reason
-                return entries
-                    .DistinctBy(i => i.FullName, StringComparer.OrdinalIgnoreCase)
-                    .ToDictionary(i => i.FullName, StringComparer.OrdinalIgnoreCase);
+                var dictionary = new Dictionary<string, FileSystemInfo>(StringComparer.OrdinalIgnoreCase);
+
+                foreach (var info in entries)
+                {
+                    dictionary[info.FullName] = info;
+                }
+
+                return dictionary;
             }
 
             var dict = new Dictionary<string, FileSystemInfo>(StringComparer.OrdinalIgnoreCase);

+ 19 - 9
MediaBrowser.Controller/Providers/BaseMetadataProvider.cs

@@ -1,14 +1,14 @@
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Extensions;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Logging;
 using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
 
@@ -330,6 +330,16 @@ namespace MediaBrowser.Controller.Providers
             return GetFileSystemStamp(item);
         }
 
+        private Dictionary<string, string> _fileStampExtensionsDictionary;
+        private  Dictionary<string, string> FileStampExtensionsDictionary
+        {
+            get
+            {
+                return _fileStampExtensionsDictionary ??
+                       (_fileStampExtensionsDictionary =
+                        FilestampExtensions.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase));
+            }
+        }
         /// <summary>
         /// Gets the file system stamp.
         /// </summary>
@@ -362,20 +372,20 @@ namespace MediaBrowser.Controller.Providers
 
             var sb = new StringBuilder();
 
-            var extensionsList = FilestampExtensions;
-            var extensions = extensionsList.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
+            var extensions = FileStampExtensionsDictionary;
+            var numExtensions = extensions.Count;
 
             // Record the name of each file 
             // Need to sort these because accoring to msdn docs, our i/o methods are not guaranteed in any order
             foreach (var file in resolveArgs.FileSystemChildren
-                .Where(i => IncludeInFileStamp(i, extensions, extensionsList.Length))
+                .Where(i => IncludeInFileStamp(i, extensions, numExtensions))
                 .OrderBy(f => f.Name))
             {
                 sb.Append(file.Name);
             }
 
             foreach (var file in resolveArgs.MetadataFiles
-                .Where(i => IncludeInFileStamp(i, extensions, extensionsList.Length))
+                .Where(i => IncludeInFileStamp(i, extensions, numExtensions))
                 .OrderBy(f => f.Name))
             {
                 sb.Append(file.Name);

+ 5 - 0
MediaBrowser.Model/Querying/ItemFields.cs

@@ -116,6 +116,11 @@ namespace MediaBrowser.Model.Querying
         /// </summary>
         Revenue,
 
+        /// <summary>
+        /// The screenshot image tags
+        /// </summary>
+        ScreenshotImageTags,
+
         /// <summary>
         /// The soundtrack ids
         /// </summary>

+ 3 - 1
MediaBrowser.Model/Web/QueryStringDictionary.cs

@@ -208,7 +208,9 @@ namespace MediaBrowser.Model.Web
                 throw new ArgumentNullException("value");
             }
 
-            Add(name, string.Join(",", value.Select(v => v.ToString()).ToArray()));
+            var paramValue = string.Join(",", value.ToArray());
+
+            Add(name, paramValue);
         }
 
         /// <summary>

+ 2 - 2
MediaBrowser.Providers/ImageFromMediaLocationProvider.cs

@@ -1,5 +1,4 @@
-using System.Globalization;
-using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Movies;
 using MediaBrowser.Controller.Entities.TV;
@@ -9,6 +8,7 @@ using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Logging;
 using System;
 using System.Collections.Generic;
+using System.Globalization;
 using System.IO;
 using System.Linq;
 using System.Threading;

+ 41 - 6
MediaBrowser.Providers/MediaInfo/FFProbeVideoInfoProvider.cs

@@ -140,14 +140,25 @@ namespace MediaBrowser.Providers.MediaInfo
 
         public override async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken)
         {
-            var myItem = (Video)item;
+            var video = (Video)item;
 
-            var isoMount = await MountIsoIfNeeded(myItem, cancellationToken).ConfigureAwait(false);
+            var isoMount = await MountIsoIfNeeded(video, cancellationToken).ConfigureAwait(false);
 
             try
             {
-                OnPreFetch(myItem, isoMount);
+                OnPreFetch(video, isoMount);
 
+                // If we didn't find any satisfying the min length, just take them all
+                if (video.VideoType == VideoType.Dvd || (video.IsoType.HasValue && video.IsoType == IsoType.Dvd))
+                {
+                    if (video.PlayableStreamFileNames.Count == 0)
+                    {
+                        Logger.Error("No playable vobs found in dvd structure, skipping ffprobe.");
+                        SetLastRefreshed(item, DateTime.UtcNow);
+                        return true;
+                    }
+                }
+                
                 var result = await GetMediaInfo(item, isoMount, cancellationToken).ConfigureAwait(false);
 
                 cancellationToken.ThrowIfCancellationRequested();
@@ -156,9 +167,8 @@ namespace MediaBrowser.Providers.MediaInfo
 
                 cancellationToken.ThrowIfCancellationRequested();
 
-                await Fetch(myItem, force, cancellationToken, result, isoMount).ConfigureAwait(false);
+                await Fetch(video, force, cancellationToken, result, isoMount).ConfigureAwait(false);
 
-                SetLastRefreshed(item, DateTime.UtcNow);
             }
             finally
             {
@@ -222,7 +232,25 @@ namespace MediaBrowser.Providers.MediaInfo
 
             // Try to eliminate menus and intros by skipping all files at the front of the list that are less than the minimum size
             // Once we reach a file that is at least the minimum, return all subsequent ones
-            var files = Directory.EnumerateFiles(root, "*.vob", SearchOption.AllDirectories).SkipWhile(f => new FileInfo(f).Length < minPlayableSize).ToList();
+            var allVobs = Directory.EnumerateFiles(root, "*.vob", SearchOption.AllDirectories).ToList();
+
+            // If we didn't find any satisfying the min length, just take them all
+            if (allVobs.Count == 0)
+            {
+                Logger.Error("No vobs found in dvd structure.");
+                return;
+            }
+            
+            var files = allVobs
+                .SkipWhile(f => new FileInfo(f).Length < minPlayableSize)
+                .ToList();
+
+            // If we didn't find any satisfying the min length, just take them all
+            if (files.Count == 0)
+            {
+                Logger.Warn("Vob size filter resulted in zero matches. Taking all vobs.");
+                files = allVobs;
+            }
 
             // Assuming they're named "vts_05_01", take all files whose second part matches that of the first file
             if (files.Count > 0)
@@ -240,6 +268,13 @@ namespace MediaBrowser.Providers.MediaInfo
                         return fileParts.Length == 3 && string.Equals(title, fileParts[1], StringComparison.OrdinalIgnoreCase);
 
                     }).ToList();
+
+                    // If this resulted in not getting any vobs, just take them all
+                    if (files.Count == 0)
+                    {
+                        Logger.Warn("Vob filename filter resulted in zero matches. Taking all vobs.");
+                        files = allVobs;
+                    }
                 }
             }
 

+ 5 - 1
MediaBrowser.Server.Implementations/Dto/DtoService.cs

@@ -759,7 +759,11 @@ namespace MediaBrowser.Server.Implementations.Dto
             dto.AspectRatio = item.AspectRatio;
 
             dto.BackdropImageTags = GetBackdropImageTags(item);
-            dto.ScreenshotImageTags = GetScreenshotImageTags(item);
+
+            if (fields.Contains(ItemFields.ScreenshotImageTags))
+            {
+                dto.ScreenshotImageTags = GetScreenshotImageTags(item);
+            }
 
             if (fields.Contains(ItemFields.Genres))
             {

+ 1 - 1
MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifier.cs

@@ -8,10 +8,10 @@ using MediaBrowser.Controller.Notifications;
 using MediaBrowser.Controller.Plugins;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Notifications;
+using MediaBrowser.Model.Tasks;
 using System;
 using System.Linq;
 using System.Threading;
-using MediaBrowser.Model.Tasks;
 
 namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
 {

+ 1 - 2
MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs

@@ -4,7 +4,6 @@ using System;
 using System.Collections.Generic;
 using System.Globalization;
 using System.IO;
-using System.Linq;
 using System.Net;
 using System.Threading.Tasks;
 
@@ -84,7 +83,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
         /// </summary>
         private void SetRangeValues()
         {
-            var requestedRange = RequestedRanges.First();
+            var requestedRange = RequestedRanges[0];
 
             TotalContentLength = SourceStream.Length;
 

+ 1 - 0
MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs

@@ -107,6 +107,7 @@ namespace MediaBrowser.Server.Implementations.Library
             {
                 if (args.Parent != null)
                 {
+                    // Don't resolve these into audio files
                     if (string.Equals(Path.GetFileNameWithoutExtension(filename), BaseItem.ThemeSongFilename) && EntityResolutionHelper.IsAudioFile(filename))
                     {
                         return true;

+ 8 - 0
MediaBrowser.Server.Implementations/Library/LibraryManager.cs

@@ -1036,6 +1036,10 @@ namespace MediaBrowser.Server.Implementations.Library
                 {
                     await i.Run(innerProgress, cancellationToken);
                 }
+                catch (OperationCanceledException)
+                {
+                    _logger.Info("Pre-scan task cancelled: {0}", i.GetType().Name);
+                }
                 catch (Exception ex)
                 {
                     _logger.ErrorException("Error running prescan task", ex);
@@ -1077,6 +1081,10 @@ namespace MediaBrowser.Server.Implementations.Library
                 {
                     await i.Run(innerProgress, cancellationToken);
                 }
+                catch (OperationCanceledException)
+                {
+                    _logger.Info("Post-scan task cancelled: {0}", i.GetType().Name);
+                }
                 catch (Exception ex)
                 {
                     _logger.ErrorException("Error running postscan task", ex);

+ 11 - 2
MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs

@@ -1,11 +1,12 @@
 using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Controller.Entities.TV;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Resolvers;
 using MediaBrowser.Model.Entities;
 using System;
 using System.Collections.Generic;
 using System.IO;
-using System.Linq;
 
 namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
 {
@@ -37,6 +38,12 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
             if (args.Parent.IsRoot) return null;
             if (args.Parent is MusicAlbum) return null;
 
+            // Optimization
+            if (args.Parent is BoxSet || args.Parent is Series || args.Parent is Season)
+            {
+                return null;
+            }
+            
             var collectionType = args.GetCollectionType();
 
             // If there's a collection type and it's not music, it can't be a series
@@ -102,8 +109,10 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
             // If list contains at least 2 audio files or at least one and no video files consider it to contain music
             var foundAudio = 0;
 
-            foreach (var fullName in list.Select(file => file.FullName))
+            foreach (var file in list)
             {
+                var fullName = file.FullName;
+
                 if (EntityResolutionHelper.IsAudioFile(fullName)) foundAudio++;
                 if (foundAudio >= 2)
                 {

+ 8 - 0
MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs

@@ -1,4 +1,6 @@
 using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Controller.Entities.TV;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Resolvers;
 using MediaBrowser.Model.Entities;
@@ -41,6 +43,12 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
                 return null;
             }
 
+            // Optimization
+            if (args.Parent is BoxSet || args.Parent is Series || args.Parent is Season)
+            {
+                return null;
+            }
+
             var collectionType = args.GetCollectionType();
 
             // If there's a collection type and it's not music, it can't be a series

+ 1 - 1
MediaBrowser.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs

@@ -2,9 +2,9 @@
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Movies;
 using MediaBrowser.Controller.Library;
+using MediaBrowser.Model.Entities;
 using System;
 using System.IO;
-using MediaBrowser.Model.Entities;
 
 namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
 {

+ 2 - 5
MediaBrowser.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs

@@ -20,7 +20,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
             var season = args.Parent as Season;
 
             // If the parent is a Season or Series, then this is an Episode if the VideoResolver returns something
-            if (season != null || args.Parent is Series)
+            if (season != null)
             {
                 Episode episode = null;
 
@@ -51,10 +51,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
 
                 if (episode != null)
                 {
-                    if (season != null)
-                    {
-                        episode.ParentIndexNumber = season.IndexNumber;
-                    }
+                    episode.ParentIndexNumber = season.IndexNumber;
                     
                     if (episode.ParentIndexNumber == null)
                     {

+ 3 - 1
MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs

@@ -1,4 +1,6 @@
 using MediaBrowser.Common.Extensions;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Entities.Movies;
 using MediaBrowser.Controller.Entities.TV;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Resolvers;
@@ -41,7 +43,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
                 }
                 
                 // Optimization to avoid running these tests against Seasons
-                if (args.Parent is Series)
+                if (args.Parent is Series || args.Parent is MusicArtist || args.Parent is MusicAlbum || args.Parent is BoxSet)
                 {
                     return null;
                 }

+ 0 - 26
MediaBrowser.Server.Implementations/Library/UserManager.cs

@@ -4,10 +4,8 @@ using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Persistence;
-using MediaBrowser.Controller.Session;
 using MediaBrowser.Model.Logging;
 using System;
-using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
@@ -23,12 +21,6 @@ namespace MediaBrowser.Server.Implementations.Library
     /// </summary>
     public class UserManager : IUserManager
     {
-        /// <summary>
-        /// The _active connections
-        /// </summary>
-        private readonly ConcurrentDictionary<string, SessionInfo> _activeConnections =
-            new ConcurrentDictionary<string, SessionInfo>(StringComparer.OrdinalIgnoreCase);
-
         /// <summary>
         /// The _users
         /// </summary>
@@ -64,24 +56,6 @@ namespace MediaBrowser.Server.Implementations.Library
             }
         }
 
-        /// <summary>
-        /// Gets all connections.
-        /// </summary>
-        /// <value>All connections.</value>
-        public IEnumerable<SessionInfo> AllConnections
-        {
-            get { return _activeConnections.Values.OrderByDescending(c => c.LastActivityDate); }
-        }
-
-        /// <summary>
-        /// Gets the active connections.
-        /// </summary>
-        /// <value>The active connections.</value>
-        public IEnumerable<SessionInfo> RecentConnections
-        {
-            get { return AllConnections.Where(c => (DateTime.UtcNow - c.LastActivityDate).TotalMinutes <= 5); }
-        }
-
         /// <summary>
         /// The _logger
         /// </summary>

+ 13 - 13
MediaBrowser.Server.Implementations/Library/Validators/ArtistsValidator.cs

@@ -57,10 +57,10 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
         /// <returns>Task.</returns>
         public async Task Run(IProgress<double> progress, CancellationToken cancellationToken)
         {
-            var allItems = _libraryManager.RootFolder.RecursiveChildren.ToList();
+            var allItems = _libraryManager.RootFolder.RecursiveChildren.ToArray();
 
-            var allMusicArtists = allItems.OfType<MusicArtist>().ToList();
-            var allSongs = allItems.OfType<Audio>().ToList();
+            var allMusicArtists = allItems.OfType<MusicArtist>().ToArray();
+            var allSongs = allItems.OfType<Audio>().ToArray();
 
             var innerProgress = new ActionableProgress<double>();
 
@@ -73,8 +73,8 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
             var numComplete = 0;
 
             var userLibraries = _userManager.Users
-                .Select(i => new Tuple<Guid, List<IHasArtist>>(i.Id, i.RootFolder.GetRecursiveChildren(i).OfType<IHasArtist>().ToList()))
-                .ToList();
+                .Select(i => new Tuple<Guid, IHasArtist[]>(i.Id, i.RootFolder.GetRecursiveChildren(i).OfType<IHasArtist>().ToArray()))
+                .ToArray();
 
             foreach (var artist in allArtists)
             {
@@ -117,7 +117,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
 
                 numComplete++;
                 double percent = numComplete;
-                percent /= allArtists.Count;
+                percent /= allArtists.Length;
                 percent *= 20;
 
                 progress.Report(80 + percent);
@@ -138,11 +138,11 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
 
             var items = allItems
                 .Where(i => i.HasArtist(name))
-                .ToList();
+                .ToArray();
 
             var counts = new ItemByNameCounts
             {
-                TotalCount = items.Count,
+                TotalCount = items.Length,
 
                 SongCount = items.OfType<Audio>().Count(),
 
@@ -165,7 +165,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
         private void MergeImages(Dictionary<ImageType, string> source, Dictionary<ImageType, string> target)
         {
             foreach (var key in source.Keys
-                .ToList()
+                .ToArray()
                 .Where(k => !target.ContainsKey(k)))
             {
                 string path;
@@ -184,7 +184,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <param name="progress">The progress.</param>
         /// <returns>Task{Artist[]}.</returns>
-        private async Task<List<Artist>> GetAllArtists(IEnumerable<Audio> allSongs, CancellationToken cancellationToken, IProgress<double> progress)
+        private async Task<Artist[]> GetAllArtists(IEnumerable<Audio> allSongs, CancellationToken cancellationToken, IProgress<double> progress)
         {
             var allArtists = allSongs
                 .SelectMany(i =>
@@ -200,7 +200,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
                     return list;
                 })
                 .Distinct(StringComparer.OrdinalIgnoreCase)
-                .ToList();
+                .ToArray();
 
             const int maxTasks = 3;
 
@@ -246,7 +246,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
                     {
                         numComplete++;
                         double percent = numComplete;
-                        percent /= allArtists.Count;
+                        percent /= allArtists.Length;
 
                         progress.Report(100 * percent);
                     }
@@ -255,7 +255,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
 
             await Task.WhenAll(tasks).ConfigureAwait(false);
 
-            return returnArtists.ToList();
+            return returnArtists.ToArray();
         }
 
         /// <summary>

+ 1 - 1
MediaBrowser.Server.Implementations/Library/Validators/CountHelpers.cs

@@ -127,7 +127,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
         /// <param name="media">The media.</param>
         /// <param name="names">The names.</param>
         /// <param name="masterDictionary">The master dictionary.</param>
-        internal static void SetItemCounts(Guid userId, BaseItem media, List<string> names, Dictionary<string, Dictionary<Guid, Dictionary<CountType, int>>> masterDictionary)
+        internal static void SetItemCounts(Guid userId, BaseItem media, IEnumerable<string> names, Dictionary<string, Dictionary<Guid, Dictionary<CountType, int>>> masterDictionary)
         {
             foreach (var name in names)
             {

+ 2 - 6
MediaBrowser.Server.Implementations/Library/Validators/PeoplePostScanTask.cs

@@ -46,14 +46,10 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
 
         private void RunInternal(IProgress<double> progress, CancellationToken cancellationToken)
         {
-            var allItems = _libraryManager.RootFolder.RecursiveChildren.ToList();
-
             var userLibraries = _userManager.Users
-                .Select(i => new Tuple<Guid, List<BaseItem>>(i.Id, i.RootFolder.GetRecursiveChildren(i).ToList()))
+                .Select(i => new Tuple<Guid, BaseItem[]>(i.Id, i.RootFolder.GetRecursiveChildren(i).ToArray()))
                 .ToList();
 
-            var allLibraryItems = allItems;
-
             var masterDictionary = new Dictionary<string, Dictionary<Guid, Dictionary<CountType, int>>>(StringComparer.OrdinalIgnoreCase);
 
             // Populate counts of items
@@ -122,7 +118,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
                 var names = media
                     .People.Select(i => i.Name)
                     .Distinct(StringComparer.OrdinalIgnoreCase)
-                    .ToList();
+                    .ToArray();
 
                 CountHelpers.SetItemCounts(userId, media, names, masterDictionary);
             }

+ 2 - 2
MediaBrowser.Server.Implementations/Providers/ImageSaver.cs

@@ -1,5 +1,4 @@
-using System.Globalization;
-using MediaBrowser.Common.IO;
+using MediaBrowser.Common.IO;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Audio;
@@ -7,6 +6,7 @@ using MediaBrowser.Controller.Entities.TV;
 using MediaBrowser.Controller.IO;
 using MediaBrowser.Model.Entities;
 using System;
+using System.Globalization;
 using System.IO;
 using System.Linq;
 using System.Threading;

+ 14 - 3
MediaBrowser.Server.Implementations/Providers/ProviderManager.cs

@@ -92,13 +92,21 @@ namespace MediaBrowser.Server.Implementations.Providers
 
             cancellationToken.ThrowIfCancellationRequested();
 
+            var enableInternetProviders = ConfigurationManager.Configuration.EnableInternetProviders;
+            var excludeTypes = ConfigurationManager.Configuration.InternetProviderExcludeTypes;
+
             // Run the normal providers sequentially in order of priority
-            foreach (var provider in MetadataProviders.Where(p => ProviderSupportsItem(p, item)))
+            foreach (var provider in MetadataProviders)
             {
                 cancellationToken.ThrowIfCancellationRequested();
 
+                if (!ProviderSupportsItem(provider, item))
+                {
+                    continue;
+                }
+
                 // Skip if internet providers are currently disabled
-                if (provider.RequiresInternet && !ConfigurationManager.Configuration.EnableInternetProviders)
+                if (provider.RequiresInternet && !enableInternetProviders)
                 {
                     continue;
                 }
@@ -110,7 +118,10 @@ namespace MediaBrowser.Server.Implementations.Providers
                 }
 
                 // Skip if internet provider and this type is not allowed
-                if (provider.RequiresInternet && ConfigurationManager.Configuration.EnableInternetProviders && ConfigurationManager.Configuration.InternetProviderExcludeTypes.Contains(item.GetType().Name, StringComparer.OrdinalIgnoreCase))
+                if (provider.RequiresInternet &&
+                    enableInternetProviders &&
+                    excludeTypes.Length > 0 &&
+                    excludeTypes.Contains(item.GetType().Name, StringComparer.OrdinalIgnoreCase))
                 {
                     continue;
                 }

+ 2 - 3
MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs

@@ -1,6 +1,4 @@
-using System.Net.Sockets;
-using MediaBrowser.Common;
-using MediaBrowser.Common.Net;
+using MediaBrowser.Common.Net;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Model.Logging;
@@ -10,6 +8,7 @@ using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Net;
+using System.Net.Sockets;
 using System.Threading;
 using System.Threading.Tasks;
 

+ 0 - 1
MediaBrowser.Server.Implementations/Session/SessionManager.cs

@@ -1,5 +1,4 @@
 using MediaBrowser.Common.Events;
-using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Audio;

+ 1 - 6
MediaBrowser.Server.Implementations/Sorting/AlbumCountComparer.cs

@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Persistence;
 using MediaBrowser.Controller.Sorting;

+ 1 - 2
MediaBrowser.Server.Implementations/Sorting/ArtistComparer.cs

@@ -3,7 +3,6 @@ using MediaBrowser.Controller.Entities.Audio;
 using MediaBrowser.Controller.Sorting;
 using MediaBrowser.Model.Querying;
 using System;
-using System.Linq;
 
 namespace MediaBrowser.Server.Implementations.Sorting
 {
@@ -37,7 +36,7 @@ namespace MediaBrowser.Server.Implementations.Sorting
                 return string.Empty;
             }
 
-            return audio.Artists.FirstOrDefault() ?? string.Empty;
+            return audio.Artists.Count == 0 ? null : audio.Artists[0];
         }
 
         /// <summary>

+ 1 - 6
MediaBrowser.Server.Implementations/Sorting/EpisodeCountComparer.cs

@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Persistence;
 using MediaBrowser.Controller.Sorting;

+ 1 - 6
MediaBrowser.Server.Implementations/Sorting/MusicVideoCountComparer.cs

@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Persistence;
 using MediaBrowser.Controller.Sorting;

+ 1 - 6
MediaBrowser.Server.Implementations/Sorting/SongCountComparer.cs

@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Persistence;
 using MediaBrowser.Controller.Sorting;

+ 0 - 1
MediaBrowser.Server.Implementations/Udp/UdpServer.cs

@@ -8,7 +8,6 @@ using System.Net;
 using System.Net.Sockets;
 using System.Reactive.Linq;
 using System.Text;
-using System.Threading;
 using System.Threading.Tasks;
 
 namespace MediaBrowser.Server.Implementations.Udp