2
0
Эх сурвалжийг харах

add bottom up music refresh

Luke Pulverenti 11 жил өмнө
parent
commit
73677b94c6

+ 95 - 2
MediaBrowser.Controller/Entities/Audio/MusicArtist.cs

@@ -1,9 +1,11 @@
-using MediaBrowser.Controller.Providers;
+using MediaBrowser.Common.Progress;
+using MediaBrowser.Controller.Providers;
 using MediaBrowser.Model.Configuration;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Entities;
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using System.Runtime.Serialization;
 using System.Threading;
 using System.Threading.Tasks;
@@ -13,7 +15,7 @@ namespace MediaBrowser.Controller.Entities.Audio
     /// <summary>
     /// Class MusicArtist
     /// </summary>
-    public class MusicArtist : Folder, IItemByName, IHasMusicGenres, IHasDualAccess, IHasTags, IHasProductionLocations
+    public class MusicArtist : Folder, IMetadataContainer, IItemByName, IHasMusicGenres, IHasDualAccess, IHasTags, IHasProductionLocations
     {
         [IgnoreDataMember]
         public List<ItemByNameCounts> UserItemCountList { get; set; }
@@ -108,5 +110,96 @@ namespace MediaBrowser.Controller.Entities.Audio
         {
             return config.BlockUnratedMusic;
         }
+
+        public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken)
+        {
+            var items = RecursiveChildren.ToList();
+
+            var songs = items.OfType<Audio>().ToList();
+
+            var others = items.Except(songs).ToList();
+
+            var totalItems = songs.Count + others.Count;
+            var percentages = new Dictionary<Guid, double>(totalItems);
+
+            var tasks = new List<Task>();
+
+            // Refresh songs
+            foreach (var item in songs)
+            {
+                if (tasks.Count > 3)
+                {
+                    await Task.WhenAll(tasks).ConfigureAwait(false);
+                    tasks.Clear();
+                }
+
+                cancellationToken.ThrowIfCancellationRequested();
+                var innerProgress = new ActionableProgress<double>();
+
+                // Avoid implicitly captured closure
+                var currentChild = item;
+                innerProgress.RegisterAction(p =>
+                {
+                    lock (percentages)
+                    {
+                        percentages[currentChild.Id] = p / 100;
+
+                        var percent = percentages.Values.Sum();
+                        percent /= totalItems;
+                        percent *= 100;
+                        progress.Report(percent);
+                    }
+                });
+
+                tasks.Add(RefreshItem(item, refreshOptions, innerProgress, cancellationToken));
+            }
+
+            await Task.WhenAll(tasks).ConfigureAwait(false);
+            tasks.Clear();
+
+            // Refresh current item
+            await RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
+            
+            // Refresh all non-songs
+            foreach (var item in others)
+            {
+                if (tasks.Count > 3)
+                {
+                    await Task.WhenAll(tasks).ConfigureAwait(false);
+                    tasks.Clear();
+                }
+
+                cancellationToken.ThrowIfCancellationRequested();
+                var innerProgress = new ActionableProgress<double>();
+
+                // Avoid implicitly captured closure
+                var currentChild = item;
+                innerProgress.RegisterAction(p =>
+                {
+                    lock (percentages)
+                    {
+                        percentages[currentChild.Id] = p / 100;
+
+                        var percent = percentages.Values.Sum();
+                        percent /= totalItems;
+                        percent *= 100;
+                        progress.Report(percent);
+                    }
+                });
+
+                tasks.Add(RefreshItem(item, refreshOptions, innerProgress, cancellationToken));
+            }
+
+            await Task.WhenAll(tasks).ConfigureAwait(false);
+            
+            progress.Report(100);
+        }
+
+        private async Task RefreshItem(BaseItem item, MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken)
+        {
+            await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
+
+            progress.Report(100);
+        }
     }
 }

+ 1 - 5
MediaBrowser.Controller/Entities/Folder.cs

@@ -475,10 +475,6 @@ namespace MediaBrowser.Controller.Entities
                     await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
                 }
             }
-            else
-            {
-                validChildren.AddRange(ActualChildren);
-            }
 
             progress.Report(10);
 
@@ -486,7 +482,7 @@ namespace MediaBrowser.Controller.Entities
 
             if (recursive)
             {
-                await ValidateSubFolders(validChildren.OfType<Folder>().ToList(), progress, cancellationToken).ConfigureAwait(false);
+                await ValidateSubFolders(ActualChildren.OfType<Folder>().ToList(), progress, cancellationToken).ConfigureAwait(false);
             }
 
             progress.Report(20);

+ 18 - 14
MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs

@@ -82,26 +82,30 @@ namespace MediaBrowser.Providers.MediaInfo
 
             if (!File.Exists(path))
             {
-                using (var stream = await _mediaEncoder.ExtractImage(new[] { item.Path }, InputType.File, true, null, null, cancellationToken).ConfigureAwait(false))
-                {
-                    var semaphore = GetLock(path);
-
-                    Directory.CreateDirectory(Path.GetDirectoryName(path));
+                var semaphore = GetLock(path);
 
-                    // Acquire a lock
-                    await semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
+                // Acquire a lock
+                await semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
 
-                    try
+                try
+                {
+                    // Check again in case it was saved while waiting for the lock
+                    if (!File.Exists(path))
                     {
-                        using (var fileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true))
+                        Directory.CreateDirectory(Path.GetDirectoryName(path));
+
+                        using (var stream = await _mediaEncoder.ExtractImage(new[] { item.Path }, InputType.File, true, null, null, cancellationToken).ConfigureAwait(false))
                         {
-                            await stream.CopyToAsync(fileStream).ConfigureAwait(false);
+                            using (var fileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true))
+                            {
+                                await stream.CopyToAsync(fileStream).ConfigureAwait(false);
+                            }
                         }
                     }
-                    finally
-                    {
-                        semaphore.Release();
-                    }
+                }
+                finally
+                {
+                    semaphore.Release();
                 }
             }