mirror of
				https://github.com/jellyfin/jellyfin.git
				synced 2025-11-03 19:17:24 -05:00 
			
		
		
		
	reduce scanning overhead a bit
This commit is contained in:
		
							parent
							
								
									3d9b862430
								
							
						
					
					
						commit
						2b8b98b590
					
				@ -664,22 +664,6 @@ namespace MediaBrowser.Controller.Dto
 | 
				
			|||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					 | 
				
			||||||
        /// Gets the library update info.
 | 
					 | 
				
			||||||
        /// </summary>
 | 
					 | 
				
			||||||
        /// <param name="changeEvent">The <see cref="ChildrenChangedEventArgs" /> instance containing the event data.</param>
 | 
					 | 
				
			||||||
        /// <returns>LibraryUpdateInfo.</returns>
 | 
					 | 
				
			||||||
        public static LibraryUpdateInfo GetLibraryUpdateInfo(ChildrenChangedEventArgs changeEvent)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return new LibraryUpdateInfo
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                Folder = GetBaseItemInfo(changeEvent.Folder),
 | 
					 | 
				
			||||||
                ItemsAdded = changeEvent.ItemsAdded.Select(GetBaseItemInfo),
 | 
					 | 
				
			||||||
                ItemsRemoved = changeEvent.ItemsRemoved.Select(i => i.Id),
 | 
					 | 
				
			||||||
                ItemsUpdated = changeEvent.ItemsUpdated.Select(i => i.Id)
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Converts a UserItemData to a DTOUserItemData
 | 
					        /// Converts a UserItemData to a DTOUserItemData
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
 | 
				
			|||||||
@ -659,7 +659,7 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            foreach (var tuple in list)
 | 
					            foreach (var tuple in list)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                if (tasks.Count > 50)
 | 
					                if (tasks.Count > 5)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    await Task.WhenAll(tasks).ConfigureAwait(false);
 | 
					                    await Task.WhenAll(tasks).ConfigureAwait(false);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
				
			|||||||
@ -49,8 +49,17 @@ namespace MediaBrowser.Controller.Providers
 | 
				
			|||||||
                throw new ArgumentNullException();
 | 
					                throw new ArgumentNullException();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var settings = new XmlReaderSettings
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                CheckCharacters = false,
 | 
				
			||||||
 | 
					                IgnoreProcessingInstructions = true,
 | 
				
			||||||
 | 
					                IgnoreComments = true,
 | 
				
			||||||
 | 
					                IgnoreWhitespace = true,
 | 
				
			||||||
 | 
					                ValidationType = ValidationType.None
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Use XmlReader for best performance
 | 
					            // Use XmlReader for best performance
 | 
				
			||||||
            using (var reader = XmlReader.Create(metadataFile))
 | 
					            using (var reader = XmlReader.Create(metadataFile, settings))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                reader.MoveToContent();
 | 
					                reader.MoveToContent();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -93,7 +102,7 @@ namespace MediaBrowser.Controller.Providers
 | 
				
			|||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        var type = reader.ReadElementContentAsString();
 | 
					                        var type = reader.ReadElementContentAsString();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        if (!string.IsNullOrWhiteSpace(type) && !type.Equals("none",StringComparison.OrdinalIgnoreCase))
 | 
					                        if (!string.IsNullOrWhiteSpace(type) && !type.Equals("none", StringComparison.OrdinalIgnoreCase))
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            item.DisplayMediaType = type;
 | 
					                            item.DisplayMediaType = type;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
				
			|||||||
@ -31,6 +31,8 @@ namespace MediaBrowser.Controller.Providers
 | 
				
			|||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        protected readonly Guid Id;
 | 
					        protected readonly Guid Id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected static readonly SemaphoreSlim XmlParsingResourcePool = new SemaphoreSlim(5, 5);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Supportses the specified item.
 | 
					        /// Supportses the specified item.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
 | 
				
			|||||||
@ -58,7 +58,7 @@ namespace MediaBrowser.Controller.Providers
 | 
				
			|||||||
        /// <returns>Task{System.Boolean}.</returns>
 | 
					        /// <returns>Task{System.Boolean}.</returns>
 | 
				
			||||||
        public override Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken)
 | 
					        public override Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return Task.Run(() => Fetch(item, cancellationToken));
 | 
					            return Fetch(item, cancellationToken);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
@ -67,7 +67,7 @@ namespace MediaBrowser.Controller.Providers
 | 
				
			|||||||
        /// <param name="item">The item.</param>
 | 
					        /// <param name="item">The item.</param>
 | 
				
			||||||
        /// <param name="cancellationToken">The cancellation token.</param>
 | 
					        /// <param name="cancellationToken">The cancellation token.</param>
 | 
				
			||||||
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
 | 
					        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
 | 
				
			||||||
        private bool Fetch(BaseItem item, CancellationToken cancellationToken)
 | 
					        private async Task<bool> Fetch(BaseItem item, CancellationToken cancellationToken)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            cancellationToken.ThrowIfCancellationRequested();
 | 
					            cancellationToken.ThrowIfCancellationRequested();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -76,7 +76,18 @@ namespace MediaBrowser.Controller.Providers
 | 
				
			|||||||
            if (metadataFile.HasValue)
 | 
					            if (metadataFile.HasValue)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var path = metadataFile.Value.Path;
 | 
					                var path = metadataFile.Value.Path;
 | 
				
			||||||
                new BaseItemXmlParser<Folder>(Logger).Fetch((Folder)item, path, cancellationToken);
 | 
					
 | 
				
			||||||
 | 
					                await XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                try
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    new BaseItemXmlParser<Folder>(Logger).Fetch((Folder)item, path, cancellationToken);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                finally
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    XmlParsingResourcePool.Release();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                SetLastRefreshed(item, DateTime.UtcNow);
 | 
					                SetLastRefreshed(item, DateTime.UtcNow);
 | 
				
			||||||
                return true;
 | 
					                return true;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -58,7 +58,7 @@ namespace MediaBrowser.Controller.Providers.Movies
 | 
				
			|||||||
        /// <returns>Task{System.Boolean}.</returns>
 | 
					        /// <returns>Task{System.Boolean}.</returns>
 | 
				
			||||||
        public override Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken)
 | 
					        public override Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return Task.Run(() => Fetch(item, cancellationToken));
 | 
					            return Fetch(item, cancellationToken);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
@ -67,7 +67,7 @@ namespace MediaBrowser.Controller.Providers.Movies
 | 
				
			|||||||
        /// <param name="item">The item.</param>
 | 
					        /// <param name="item">The item.</param>
 | 
				
			||||||
        /// <param name="cancellationToken">The cancellation token.</param>
 | 
					        /// <param name="cancellationToken">The cancellation token.</param>
 | 
				
			||||||
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
 | 
					        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
 | 
				
			||||||
        private bool Fetch(BaseItem item, CancellationToken cancellationToken)
 | 
					        private async Task<bool> Fetch(BaseItem item, CancellationToken cancellationToken)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            cancellationToken.ThrowIfCancellationRequested();
 | 
					            cancellationToken.ThrowIfCancellationRequested();
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
@ -77,14 +77,25 @@ namespace MediaBrowser.Controller.Providers.Movies
 | 
				
			|||||||
            {
 | 
					            {
 | 
				
			||||||
                var path = metadataFile.Value.Path;
 | 
					                var path = metadataFile.Value.Path;
 | 
				
			||||||
                var boxset = item as BoxSet;
 | 
					                var boxset = item as BoxSet;
 | 
				
			||||||
                if (boxset != null)
 | 
					
 | 
				
			||||||
 | 
					                await XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                try
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    new BaseItemXmlParser<BoxSet>(Logger).Fetch(boxset, path, cancellationToken);
 | 
					                    if (boxset != null)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        new BaseItemXmlParser<BoxSet>(Logger).Fetch(boxset, path, cancellationToken);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    else
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        new BaseItemXmlParser<Movie>(Logger).Fetch((Movie)item, path, cancellationToken);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else
 | 
					                finally
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    new BaseItemXmlParser<Movie>(Logger).Fetch((Movie)item, path, cancellationToken);
 | 
					                    XmlParsingResourcePool.Release();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                SetLastRefreshed(item, DateTime.UtcNow);
 | 
					                SetLastRefreshed(item, DateTime.UtcNow);
 | 
				
			||||||
                return true;
 | 
					                return true;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -15,7 +15,8 @@ namespace MediaBrowser.Controller.Providers.TV
 | 
				
			|||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    public class EpisodeProviderFromXml : BaseMetadataProvider
 | 
					    public class EpisodeProviderFromXml : BaseMetadataProvider
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public EpisodeProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager) : base(logManager, configurationManager)
 | 
					        public EpisodeProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager)
 | 
				
			||||||
 | 
					            : base(logManager, configurationManager)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -55,7 +56,7 @@ namespace MediaBrowser.Controller.Providers.TV
 | 
				
			|||||||
        /// <returns>Task{System.Boolean}.</returns>
 | 
					        /// <returns>Task{System.Boolean}.</returns>
 | 
				
			||||||
        public override Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken)
 | 
					        public override Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return Task.Run(() => Fetch(item, cancellationToken));
 | 
					            return Fetch(item, cancellationToken);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
@ -84,42 +85,31 @@ namespace MediaBrowser.Controller.Providers.TV
 | 
				
			|||||||
        /// <param name="item">The item.</param>
 | 
					        /// <param name="item">The item.</param>
 | 
				
			||||||
        /// <param name="cancellationToken">The cancellation token.</param>
 | 
					        /// <param name="cancellationToken">The cancellation token.</param>
 | 
				
			||||||
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
 | 
					        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
 | 
				
			||||||
        private bool Fetch(BaseItem item, CancellationToken cancellationToken)
 | 
					        private async Task<bool> Fetch(BaseItem item, CancellationToken cancellationToken)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            cancellationToken.ThrowIfCancellationRequested();
 | 
					            cancellationToken.ThrowIfCancellationRequested();
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
            var metadataFile = Path.Combine(item.MetaLocation, Path.ChangeExtension(Path.GetFileName(item.Path), ".xml"));
 | 
					            var metadataFile = Path.Combine(item.MetaLocation, Path.ChangeExtension(Path.GetFileName(item.Path), ".xml"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var episode = (Episode)item;
 | 
					            var file = item.ResolveArgs.Parent.ResolveArgs.GetMetaFileByPath(metadataFile);
 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (!FetchMetadata(episode, item.ResolveArgs.Parent, metadataFile, cancellationToken))
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                // Don't set last refreshed if we didn't do anything
 | 
					 | 
				
			||||||
                return false;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            SetLastRefreshed(item, DateTime.UtcNow);
 | 
					 | 
				
			||||||
            return true;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /// <summary>
 | 
					 | 
				
			||||||
        /// Fetches the metadata.
 | 
					 | 
				
			||||||
        /// </summary>
 | 
					 | 
				
			||||||
        /// <param name="item">The item.</param>
 | 
					 | 
				
			||||||
        /// <param name="parent">The parent.</param>
 | 
					 | 
				
			||||||
        /// <param name="metadataFile">The metadata file.</param>
 | 
					 | 
				
			||||||
        /// <param name="cancellationToken">The cancellation token.</param>
 | 
					 | 
				
			||||||
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
 | 
					 | 
				
			||||||
        private bool FetchMetadata(Episode item, Folder parent, string metadataFile, CancellationToken cancellationToken)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            var file = parent.ResolveArgs.GetMetaFileByPath(metadataFile);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!file.HasValue)
 | 
					            if (!file.HasValue)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return false;
 | 
					                return false;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            new EpisodeXmlParser(Logger).Fetch(item, metadataFile, cancellationToken);
 | 
					            await XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            try
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                new EpisodeXmlParser(Logger).Fetch((Episode)item, metadataFile, cancellationToken);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            finally
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                XmlParsingResourcePool.Release();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            SetLastRefreshed(item, DateTime.UtcNow);
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -59,7 +59,7 @@ namespace MediaBrowser.Controller.Providers.TV
 | 
				
			|||||||
        /// <returns>Task{System.Boolean}.</returns>
 | 
					        /// <returns>Task{System.Boolean}.</returns>
 | 
				
			||||||
        public override Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken)
 | 
					        public override Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return Task.Run(() => Fetch(item, cancellationToken));
 | 
					            return Fetch(item, cancellationToken);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
@ -68,7 +68,7 @@ namespace MediaBrowser.Controller.Providers.TV
 | 
				
			|||||||
        /// <param name="item">The item.</param>
 | 
					        /// <param name="item">The item.</param>
 | 
				
			||||||
        /// <param name="cancellationToken">The cancellation token.</param>
 | 
					        /// <param name="cancellationToken">The cancellation token.</param>
 | 
				
			||||||
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
 | 
					        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
 | 
				
			||||||
        private bool Fetch(BaseItem item, CancellationToken cancellationToken)
 | 
					        private async Task<bool> Fetch(BaseItem item, CancellationToken cancellationToken)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            cancellationToken.ThrowIfCancellationRequested();
 | 
					            cancellationToken.ThrowIfCancellationRequested();
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
@ -78,7 +78,17 @@ namespace MediaBrowser.Controller.Providers.TV
 | 
				
			|||||||
            {
 | 
					            {
 | 
				
			||||||
                var path = metadataFile.Value.Path;
 | 
					                var path = metadataFile.Value.Path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                new SeriesXmlParser(Logger).Fetch((Series)item, path, cancellationToken);
 | 
					                await XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                try
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    new SeriesXmlParser(Logger).Fetch((Series)item, path, cancellationToken);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                finally
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    XmlParsingResourcePool.Release();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                SetLastRefreshed(item, DateTime.UtcNow);
 | 
					                SetLastRefreshed(item, DateTime.UtcNow);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return true;
 | 
					                return true;
 | 
				
			||||||
 | 
				
			|||||||
@ -9,27 +9,35 @@ namespace MediaBrowser.Model.Entities
 | 
				
			|||||||
    public class LibraryUpdateInfo
 | 
					    public class LibraryUpdateInfo
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Gets or sets the folder.
 | 
					        /// Gets or sets the folders.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        /// <value>The folder.</value>
 | 
					        /// <value>The folders.</value>
 | 
				
			||||||
        public BaseItemInfo Folder { get; set; }
 | 
					        public List<Guid> Folders { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Gets or sets the items added.
 | 
					        /// Gets or sets the items added.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        /// <value>The items added.</value>
 | 
					        /// <value>The items added.</value>
 | 
				
			||||||
        public IEnumerable<BaseItemInfo> ItemsAdded { get; set; }
 | 
					        public List<Guid> ItemsAdded { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Gets or sets the items removed.
 | 
					        /// Gets or sets the items removed.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        /// <value>The items removed.</value>
 | 
					        /// <value>The items removed.</value>
 | 
				
			||||||
        public IEnumerable<Guid> ItemsRemoved { get; set; }
 | 
					        public List<Guid> ItemsRemoved { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Gets or sets the items updated.
 | 
					        /// Gets or sets the items updated.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        /// <value>The items updated.</value>
 | 
					        /// <value>The items updated.</value>
 | 
				
			||||||
        public IEnumerable<Guid> ItemsUpdated { get; set; }
 | 
					        public List<Guid> ItemsUpdated { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public LibraryUpdateInfo()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Folders = new List<Guid>();
 | 
				
			||||||
 | 
					            ItemsAdded = new List<Guid>();
 | 
				
			||||||
 | 
					            ItemsRemoved = new List<Guid>();
 | 
				
			||||||
 | 
					            ItemsUpdated = new List<Guid>();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -21,5 +21,13 @@ namespace MediaBrowser.Model.Weather
 | 
				
			|||||||
        /// <value>The forecasts.</value>
 | 
					        /// <value>The forecasts.</value>
 | 
				
			||||||
        [ProtoMember(2)]
 | 
					        [ProtoMember(2)]
 | 
				
			||||||
        public WeatherForecast[] Forecasts { get; set; }
 | 
					        public WeatherForecast[] Forecasts { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Initializes a new instance of the <see cref="WeatherInfo"/> class.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public WeatherInfo()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Forecasts = new WeatherForecast[] {};
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -55,7 +55,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
 | 
				
			|||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// The audio image resource pool
 | 
					        /// The audio image resource pool
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        private readonly SemaphoreSlim _audioImageResourcePool = new SemaphoreSlim(2, 2);
 | 
					        private readonly SemaphoreSlim _audioImageResourcePool = new SemaphoreSlim(1, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// The _subtitle extraction resource pool
 | 
					        /// The _subtitle extraction resource pool
 | 
				
			||||||
 | 
				
			|||||||
@ -147,6 +147,8 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks
 | 
				
			|||||||
                {
 | 
					                {
 | 
				
			||||||
                    // Image is already in the cache
 | 
					                    // Image is already in the cache
 | 
				
			||||||
                    item.PrimaryImagePath = path;
 | 
					                    item.PrimaryImagePath = path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    await _libraryManager.SaveItem(item, cancellationToken).ConfigureAwait(false);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,7 @@
 | 
				
			|||||||
using MediaBrowser.Controller;
 | 
					using MediaBrowser.Controller;
 | 
				
			||||||
using MediaBrowser.Controller.Entities;
 | 
					using MediaBrowser.Controller.Entities;
 | 
				
			||||||
using MediaBrowser.Controller.Library;
 | 
					using MediaBrowser.Controller.Library;
 | 
				
			||||||
 | 
					using MediaBrowser.Model.Entities;
 | 
				
			||||||
using MediaBrowser.Model.Logging;
 | 
					using MediaBrowser.Model.Logging;
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
@ -60,40 +61,27 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks
 | 
				
			|||||||
        /// <param name="cancellationToken">The cancellation token.</param>
 | 
					        /// <param name="cancellationToken">The cancellation token.</param>
 | 
				
			||||||
        /// <param name="progress">The progress.</param>
 | 
					        /// <param name="progress">The progress.</param>
 | 
				
			||||||
        /// <returns>Task.</returns>
 | 
					        /// <returns>Task.</returns>
 | 
				
			||||||
        public Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
 | 
					        public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var videos = _libraryManager.RootFolder.RecursiveChildren.OfType<Video>().Where(v => v.Chapters != null).ToList();
 | 
					            var videos = _libraryManager.RootFolder.RecursiveChildren
 | 
				
			||||||
 | 
					                .OfType<Video>()
 | 
				
			||||||
 | 
					                .Where(v => v.Chapters != null && v.Chapters.Count != 0)
 | 
				
			||||||
 | 
					                .ToList();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var numComplete = 0;
 | 
					            var numComplete = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var tasks = videos.Select(v => Task.Run(async () =>
 | 
					            foreach (var video in videos)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                try
 | 
					                cancellationToken.ThrowIfCancellationRequested();
 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    await _kernel.FFMpegManager.PopulateChapterImages(v, cancellationToken, true, true);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                catch (OperationCanceledException)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    throw;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                catch (Exception ex)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    _logger.ErrorException("Error creating chapter images for {0}", ex, v.Name);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                finally
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    lock (progress)
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        numComplete++;
 | 
					 | 
				
			||||||
                        double percent = numComplete;
 | 
					 | 
				
			||||||
                        percent /= videos.Count;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        progress.Report(100 * percent);
 | 
					                await _kernel.FFMpegManager.PopulateChapterImages(video, cancellationToken, true, true);
 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return Task.WhenAll(tasks);
 | 
					                numComplete++;
 | 
				
			||||||
 | 
					                double percent = numComplete;
 | 
				
			||||||
 | 
					                percent /= videos.Count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                progress.Report(100 * percent);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
 | 
				
			|||||||
@ -176,6 +176,8 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks
 | 
				
			|||||||
                {
 | 
					                {
 | 
				
			||||||
                    // Image is already in the cache
 | 
					                    // Image is already in the cache
 | 
				
			||||||
                    item.PrimaryImagePath = path;
 | 
					                    item.PrimaryImagePath = path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    await _libraryManager.SaveItem(item, cancellationToken).ConfigureAwait(false);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,6 @@
 | 
				
			|||||||
using MediaBrowser.Common.Events;
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading;
 | 
				
			||||||
 | 
					using MediaBrowser.Common.Events;
 | 
				
			||||||
using MediaBrowser.Common.Net;
 | 
					using MediaBrowser.Common.Net;
 | 
				
			||||||
using MediaBrowser.Common.Plugins;
 | 
					using MediaBrowser.Common.Plugins;
 | 
				
			||||||
using MediaBrowser.Common.ScheduledTasks;
 | 
					using MediaBrowser.Common.ScheduledTasks;
 | 
				
			||||||
@ -8,6 +10,7 @@ using MediaBrowser.Controller.Entities;
 | 
				
			|||||||
using MediaBrowser.Controller.Library;
 | 
					using MediaBrowser.Controller.Library;
 | 
				
			||||||
using MediaBrowser.Controller.Plugins;
 | 
					using MediaBrowser.Controller.Plugins;
 | 
				
			||||||
using MediaBrowser.Controller.Updates;
 | 
					using MediaBrowser.Controller.Updates;
 | 
				
			||||||
 | 
					using MediaBrowser.Model.Entities;
 | 
				
			||||||
using MediaBrowser.Model.Logging;
 | 
					using MediaBrowser.Model.Logging;
 | 
				
			||||||
using MediaBrowser.Model.Tasks;
 | 
					using MediaBrowser.Model.Tasks;
 | 
				
			||||||
using MediaBrowser.Model.Updates;
 | 
					using MediaBrowser.Model.Updates;
 | 
				
			||||||
@ -49,8 +52,33 @@ namespace MediaBrowser.ServerApplication.EntryPoints
 | 
				
			|||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        private readonly IServerApplicationHost _appHost;
 | 
					        private readonly IServerApplicationHost _appHost;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// The _task manager
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
        private readonly ITaskManager _taskManager;
 | 
					        private readonly ITaskManager _taskManager;
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// The _library changed sync lock
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        private readonly object _libraryChangedSyncLock = new object();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Gets or sets the library update info.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <value>The library update info.</value>
 | 
				
			||||||
 | 
					        private LibraryUpdateInfo LibraryUpdateInfo { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Gets or sets the library update timer.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <value>The library update timer.</value>
 | 
				
			||||||
 | 
					        private Timer LibraryUpdateTimer { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// The library update duration
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        private const int LibraryUpdateDuration = 60000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Initializes a new instance of the <see cref="WebSocketEvents" /> class.
 | 
					        /// Initializes a new instance of the <see cref="WebSocketEvents" /> class.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
@ -145,7 +173,47 @@ namespace MediaBrowser.ServerApplication.EntryPoints
 | 
				
			|||||||
        /// <param name="e">The <see cref="ChildrenChangedEventArgs" /> instance containing the event data.</param>
 | 
					        /// <param name="e">The <see cref="ChildrenChangedEventArgs" /> instance containing the event data.</param>
 | 
				
			||||||
        void libraryManager_LibraryChanged(object sender, ChildrenChangedEventArgs e)
 | 
					        void libraryManager_LibraryChanged(object sender, ChildrenChangedEventArgs e)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _serverManager.SendWebSocketMessage("LibraryChanged", () => DtoBuilder.GetLibraryUpdateInfo(e));
 | 
					            lock (_libraryChangedSyncLock)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (LibraryUpdateInfo == null)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    LibraryUpdateInfo = new LibraryUpdateInfo();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (LibraryUpdateTimer == null)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration,
 | 
				
			||||||
 | 
					                                                   Timeout.Infinite);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                LibraryUpdateInfo.Folders.Add(e.Folder.Id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                LibraryUpdateInfo.ItemsAdded.AddRange(e.ItemsAdded.Select(i => i.Id));
 | 
				
			||||||
 | 
					                LibraryUpdateInfo.ItemsUpdated.AddRange(e.ItemsUpdated.Select(i => i.Id));
 | 
				
			||||||
 | 
					                LibraryUpdateInfo.ItemsRemoved.AddRange(e.ItemsRemoved.Select(i => i.Id));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Libraries the update timer callback.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="state">The state.</param>
 | 
				
			||||||
 | 
					        private void LibraryUpdateTimerCallback(object state)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            lock (_libraryChangedSyncLock)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _serverManager.SendWebSocketMessage("LibraryChanged", LibraryUpdateInfo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (LibraryUpdateTimer != null)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    LibraryUpdateTimer.Dispose();
 | 
				
			||||||
 | 
					                    LibraryUpdateTimer = null;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
@ -206,6 +274,12 @@ namespace MediaBrowser.ServerApplication.EntryPoints
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            if (dispose)
 | 
					            if (dispose)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 | 
					                if (LibraryUpdateTimer != null)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    LibraryUpdateTimer.Dispose();
 | 
				
			||||||
 | 
					                    LibraryUpdateTimer = null;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
                _userManager.UserDeleted -= userManager_UserDeleted;
 | 
					                _userManager.UserDeleted -= userManager_UserDeleted;
 | 
				
			||||||
                _userManager.UserUpdated -= userManager_UserUpdated;
 | 
					                _userManager.UserUpdated -= userManager_UserUpdated;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -205,4 +205,7 @@ Global
 | 
				
			|||||||
	GlobalSection(SolutionProperties) = preSolution
 | 
						GlobalSection(SolutionProperties) = preSolution
 | 
				
			||||||
		HideSolutionNode = FALSE
 | 
							HideSolutionNode = FALSE
 | 
				
			||||||
	EndGlobalSection
 | 
						EndGlobalSection
 | 
				
			||||||
 | 
						GlobalSection(Performance) = preSolution
 | 
				
			||||||
 | 
							HasPerformanceSessions = true
 | 
				
			||||||
 | 
						EndGlobalSection
 | 
				
			||||||
EndGlobal
 | 
					EndGlobal
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user