aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicArtist.cs97
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs6
-rw-r--r--MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs32
3 files changed, 114 insertions, 21 deletions
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
index 7a67c0aa6..f7dbb43c0 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
+++ b/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);
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index 4676100f4..101244d45 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/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);
diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
index e22c94f5a..5f1299e31 100644
--- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
+++ b/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();
}
}