mirror of
				https://github.com/jellyfin/jellyfin.git
				synced 2025-11-03 19:17:24 -05:00 
			
		
		
		
	allow request header overrides
This commit is contained in:
		
							parent
							
								
									06c611dd50
								
							
						
					
					
						commit
						60780399c5
					
				@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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>
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
@ -116,6 +116,11 @@ namespace MediaBrowser.Model.Querying
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        Revenue,
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// The screenshot image tags
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        ScreenshotImageTags,
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// The soundtrack ids
 | 
			
		||||
        /// </summary>
 | 
			
		||||
 | 
			
		||||
@ -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>
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -140,13 +140,24 @@ 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);
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -759,7 +759,11 @@ namespace MediaBrowser.Server.Implementations.Dto
 | 
			
		||||
            dto.AspectRatio = item.AspectRatio;
 | 
			
		||||
 | 
			
		||||
            dto.BackdropImageTags = GetBackdropImageTags(item);
 | 
			
		||||
 | 
			
		||||
            if (fields.Contains(ItemFields.ScreenshotImageTags))
 | 
			
		||||
            {
 | 
			
		||||
                dto.ScreenshotImageTags = GetScreenshotImageTags(item);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (fields.Contains(ItemFields.Genres))
 | 
			
		||||
            {
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
                {
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -50,11 +50,8 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (episode != null)
 | 
			
		||||
                {
 | 
			
		||||
                    if (season != null)
 | 
			
		||||
                {
 | 
			
		||||
                    episode.ParentIndexNumber = season.IndexNumber;
 | 
			
		||||
                    }
 | 
			
		||||
                    
 | 
			
		||||
                    if (episode.ParentIndexNumber == null)
 | 
			
		||||
                    {
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@ -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>
 | 
			
		||||
 | 
			
		||||
@ -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>
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
            {
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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,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;
 | 
			
		||||
 | 
			
		||||
@ -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,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,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,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;
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user