aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations/Library
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Server.Implementations/Library')
-rw-r--r--Emby.Server.Implementations/Library/LibraryManager.cs92
-rw-r--r--Emby.Server.Implementations/Library/MediaSourceManager.cs12
-rw-r--r--Emby.Server.Implementations/Library/PathExtensions.cs2
-rw-r--r--Emby.Server.Implementations/Library/ResolverHelper.cs59
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs5
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs3
-rw-r--r--Emby.Server.Implementations/Library/SearchEngine.cs1
-rw-r--r--Emby.Server.Implementations/Library/UserDataManager.cs10
-rw-r--r--Emby.Server.Implementations/Library/UserViewManager.cs1
9 files changed, 115 insertions, 70 deletions
diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs
index ac5028827..a44edad16 100644
--- a/Emby.Server.Implementations/Library/LibraryManager.cs
+++ b/Emby.Server.Implementations/Library/LibraryManager.cs
@@ -197,13 +197,13 @@ namespace Emby.Server.Implementations.Library
/// Gets or sets the postscan tasks.
/// </summary>
/// <value>The postscan tasks.</value>
- private ILibraryPostScanTask[] PostscanTasks { get; set; }
+ private ILibraryPostScanTask[] PostscanTasks { get; set; } = Array.Empty<ILibraryPostScanTask>();
/// <summary>
/// Gets or sets the intro providers.
/// </summary>
/// <value>The intro providers.</value>
- private IIntroProvider[] IntroProviders { get; set; }
+ private IIntroProvider[] IntroProviders { get; set; } = Array.Empty<IIntroProvider>();
/// <summary>
/// Gets or sets the list of entity resolution ignore rules.
@@ -215,15 +215,15 @@ namespace Emby.Server.Implementations.Library
/// Gets or sets the list of currently registered entity resolvers.
/// </summary>
/// <value>The entity resolvers enumerable.</value>
- private IItemResolver[] EntityResolvers { get; set; }
+ private IItemResolver[] EntityResolvers { get; set; } = Array.Empty<IItemResolver>();
- private IMultiItemResolver[] MultiItemResolvers { get; set; }
+ private IMultiItemResolver[] MultiItemResolvers { get; set; } = Array.Empty<IMultiItemResolver>();
/// <summary>
/// Gets or sets the comparers.
/// </summary>
/// <value>The comparers.</value>
- private IBaseItemComparer[] Comparers { get; set; }
+ private IBaseItemComparer[] Comparers { get; set; } = Array.Empty<IBaseItemComparer>();
public bool IsScanRunning { get; private set; }
@@ -559,7 +559,6 @@ namespace Emby.Server.Implementations.Library
var args = new ItemResolveArgs(_configurationManager.ApplicationPaths, directoryService)
{
Parent = parent,
- Path = fullPath,
FileInfo = fileInfo,
CollectionType = collectionType,
LibraryOptions = libraryOptions
@@ -685,7 +684,7 @@ namespace Emby.Server.Implementations.Library
foreach (var item in items)
{
- ResolverHelper.SetInitialItemValues(item, parent, _fileSystem, this, directoryService);
+ ResolverHelper.SetInitialItemValues(item, parent, this, directoryService);
}
items.AddRange(ResolveFileList(result.ExtraFiles, directoryService, parent, collectionType, resolvers, libraryOptions));
@@ -1164,7 +1163,7 @@ namespace Emby.Server.Implementations.Library
progress.Report(percent * 100);
}
- _itemRepository.UpdateInheritedValues(cancellationToken);
+ _itemRepository.UpdateInheritedValues();
progress.Report(100);
}
@@ -1915,12 +1914,17 @@ namespace Emby.Server.Implementations.Library
}
catch (ArgumentException)
{
- _logger.LogWarning("Cannot get image index for {0}", img.Path);
+ _logger.LogWarning("Cannot get image index for {ImagePath}", img.Path);
continue;
}
- catch (InvalidOperationException)
+ catch (Exception ex) when (ex is InvalidOperationException || ex is IOException)
{
- _logger.LogWarning("Cannot fetch image from {0}", img.Path);
+ _logger.LogWarning(ex, "Cannot fetch image from {ImagePath}", img.Path);
+ continue;
+ }
+ catch (HttpRequestException ex)
+ {
+ _logger.LogWarning(ex, "Cannot fetch image from {ImagePath}. Http status code: {HttpStatus}", img.Path, ex.StatusCode);
continue;
}
}
@@ -1933,7 +1937,7 @@ namespace Emby.Server.Implementations.Library
}
catch (Exception ex)
{
- _logger.LogError(ex, "Cannot get image dimensions for {0}", image.Path);
+ _logger.LogError(ex, "Cannot get image dimensions for {ImagePath}", image.Path);
image.Width = 0;
image.Height = 0;
continue;
@@ -1945,7 +1949,7 @@ namespace Emby.Server.Implementations.Library
}
catch (Exception ex)
{
- _logger.LogError(ex, "Cannot compute blurhash for {0}", image.Path);
+ _logger.LogError(ex, "Cannot compute blurhash for {ImagePath}", image.Path);
image.BlurHash = string.Empty;
}
@@ -1955,7 +1959,7 @@ namespace Emby.Server.Implementations.Library
}
catch (Exception ex)
{
- _logger.LogError(ex, "Cannot update DateModified for {0}", image.Path);
+ _logger.LogError(ex, "Cannot update DateModified for {ImagePath}", image.Path);
}
}
@@ -2891,12 +2895,20 @@ namespace Emby.Server.Implementations.Library
public void UpdatePeople(BaseItem item, List<PersonInfo> people)
{
+ UpdatePeopleAsync(item, people, CancellationToken.None).GetAwaiter().GetResult();
+ }
+
+ /// <inheritdoc />
+ public async Task UpdatePeopleAsync(BaseItem item, List<PersonInfo> people, CancellationToken cancellationToken)
+ {
if (!item.SupportsPeople)
{
return;
}
_itemRepository.UpdatePeople(item.Id, people);
+
+ await SavePeopleMetadataAsync(people, cancellationToken).ConfigureAwait(false);
}
public async Task<ItemImageInfo> ConvertImageToLocal(BaseItem item, ItemImageInfo image, int imageIndex)
@@ -3000,6 +3012,58 @@ namespace Emby.Server.Implementations.Library
}
}
+ private async Task SavePeopleMetadataAsync(IEnumerable<PersonInfo> people, CancellationToken cancellationToken)
+ {
+ var personsToSave = new List<BaseItem>();
+
+ foreach (var person in people)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ var itemUpdateType = ItemUpdateType.MetadataDownload;
+ var saveEntity = false;
+ var personEntity = GetPerson(person.Name);
+
+ // if PresentationUniqueKey is empty it's likely a new item.
+ if (string.IsNullOrEmpty(personEntity.PresentationUniqueKey))
+ {
+ personEntity.PresentationUniqueKey = personEntity.CreatePresentationUniqueKey();
+ saveEntity = true;
+ }
+
+ foreach (var id in person.ProviderIds)
+ {
+ if (!string.Equals(personEntity.GetProviderId(id.Key), id.Value, StringComparison.OrdinalIgnoreCase))
+ {
+ personEntity.SetProviderId(id.Key, id.Value);
+ saveEntity = true;
+ }
+ }
+
+ if (!string.IsNullOrWhiteSpace(person.ImageUrl) && !personEntity.HasImage(ImageType.Primary))
+ {
+ personEntity.SetImage(
+ new ItemImageInfo
+ {
+ Path = person.ImageUrl,
+ Type = ImageType.Primary
+ },
+ 0);
+
+ saveEntity = true;
+ itemUpdateType = ItemUpdateType.ImageUpdate;
+ }
+
+ if (saveEntity)
+ {
+ personsToSave.Add(personEntity);
+ await RunMetadataSavers(personEntity, itemUpdateType).ConfigureAwait(false);
+ }
+ }
+
+ CreateItems(personsToSave, null, CancellationToken.None);
+ }
+
private void StartScanInBackground()
{
Task.Run(() =>
diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs
index b2943020c..d0b85f07d 100644
--- a/Emby.Server.Implementations/Library/MediaSourceManager.cs
+++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs
@@ -199,10 +199,15 @@ namespace Emby.Server.Implementations.Library
{
source.SupportsTranscoding = user.HasPermission(PermissionKind.EnableAudioPlaybackTranscoding);
}
+ else if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase))
+ {
+ source.SupportsTranscoding = user.HasPermission(PermissionKind.EnableVideoPlaybackTranscoding);
+ source.SupportsDirectStream = user.HasPermission(PermissionKind.EnablePlaybackRemuxing);
+ }
}
}
- return SortMediaSources(list).Where(i => i.Type != MediaSourceType.Placeholder).ToList();
+ return SortMediaSources(list);
}
public MediaProtocol GetPathProtocol(string path)
@@ -436,7 +441,7 @@ namespace Emby.Server.Implementations.Library
}
}
- private static IEnumerable<MediaSourceInfo> SortMediaSources(IEnumerable<MediaSourceInfo> sources)
+ private static List<MediaSourceInfo> SortMediaSources(IEnumerable<MediaSourceInfo> sources)
{
return sources.OrderBy(i =>
{
@@ -451,8 +456,9 @@ namespace Emby.Server.Implementations.Library
{
var stream = i.VideoStream;
- return stream == null || stream.Width == null ? 0 : stream.Width.Value;
+ return stream?.Width ?? 0;
})
+ .Where(i => i.Type != MediaSourceType.Placeholder)
.ToList();
}
diff --git a/Emby.Server.Implementations/Library/PathExtensions.cs b/Emby.Server.Implementations/Library/PathExtensions.cs
index 6eaecff0f..770cf6bb0 100644
--- a/Emby.Server.Implementations/Library/PathExtensions.cs
+++ b/Emby.Server.Implementations/Library/PathExtensions.cs
@@ -2,8 +2,6 @@
using System;
using System.Diagnostics.CodeAnalysis;
-using System.IO;
-using System.Text.RegularExpressions;
using MediaBrowser.Common.Providers;
namespace Emby.Server.Implementations.Library
diff --git a/Emby.Server.Implementations/Library/ResolverHelper.cs b/Emby.Server.Implementations/Library/ResolverHelper.cs
index 4e4cac75b..b1a2e9284 100644
--- a/Emby.Server.Implementations/Library/ResolverHelper.cs
+++ b/Emby.Server.Implementations/Library/ResolverHelper.cs
@@ -1,3 +1,5 @@
+#nullable enable
+
using System;
using System.IO;
using System.Linq;
@@ -18,11 +20,10 @@ namespace Emby.Server.Implementations.Library
/// </summary>
/// <param name="item">The item.</param>
/// <param name="parent">The parent.</param>
- /// <param name="fileSystem">The file system.</param>
/// <param name="libraryManager">The library manager.</param>
/// <param name="directoryService">The directory service.</param>
- /// <exception cref="ArgumentException">Item must have a path</exception>
- public static void SetInitialItemValues(BaseItem item, Folder parent, IFileSystem fileSystem, ILibraryManager libraryManager, IDirectoryService directoryService)
+ /// <exception cref="ArgumentException">Item must have a path.</exception>
+ public static void SetInitialItemValues(BaseItem item, Folder? parent, ILibraryManager libraryManager, IDirectoryService directoryService)
{
// This version of the below method has no ItemResolveArgs, so we have to require the path already being set
if (string.IsNullOrEmpty(item.Path))
@@ -43,9 +44,9 @@ namespace Emby.Server.Implementations.Library
// Make sure DateCreated and DateModified have values
var fileInfo = directoryService.GetFile(item.Path);
- SetDateCreated(item, fileSystem, fileInfo);
+ SetDateCreated(item, fileInfo);
- EnsureName(item, item.Path, fileInfo);
+ EnsureName(item, fileInfo);
}
/// <summary>
@@ -72,9 +73,9 @@ namespace Emby.Server.Implementations.Library
item.Id = libraryManager.GetNewItemId(item.Path, item.GetType());
// Make sure the item has a name
- EnsureName(item, item.Path, args.FileInfo);
+ EnsureName(item, args.FileInfo);
- item.IsLocked = item.Path.IndexOf("[dontfetchmeta]", StringComparison.OrdinalIgnoreCase) != -1 ||
+ item.IsLocked = item.Path.Contains("[dontfetchmeta]", StringComparison.OrdinalIgnoreCase) ||
item.GetParents().Any(i => i.IsLocked);
// Make sure DateCreated and DateModified have values
@@ -84,29 +85,16 @@ namespace Emby.Server.Implementations.Library
/// <summary>
/// Ensures the name.
/// </summary>
- private static void EnsureName(BaseItem item, string fullPath, FileSystemMetadata fileInfo)
+ private static void EnsureName(BaseItem item, FileSystemMetadata fileInfo)
{
// If the subclass didn't supply a name, add it here
- if (string.IsNullOrEmpty(item.Name) && !string.IsNullOrEmpty(fullPath))
+ if (string.IsNullOrEmpty(item.Name) && !string.IsNullOrEmpty(item.Path))
{
- var fileName = fileInfo == null ? Path.GetFileName(fullPath) : fileInfo.Name;
-
- item.Name = GetDisplayName(fileName, fileInfo != null && fileInfo.IsDirectory);
+ item.Name = fileInfo.IsDirectory ? fileInfo.Name : Path.GetFileNameWithoutExtension(fileInfo.Name);
}
}
/// <summary>
- /// Gets the display name.
- /// </summary>
- /// <param name="path">The path.</param>
- /// <param name="isDirectory">if set to <c>true</c> [is directory].</param>
- /// <returns>System.String.</returns>
- private static string GetDisplayName(string path, bool isDirectory)
- {
- return isDirectory ? Path.GetFileName(path) : Path.GetFileNameWithoutExtension(path);
- }
-
- /// <summary>
/// Ensures DateCreated and DateModified have values.
/// </summary>
/// <param name="fileSystem">The file system.</param>
@@ -114,21 +102,6 @@ namespace Emby.Server.Implementations.Library
/// <param name="args">The args.</param>
private static void EnsureDates(IFileSystem fileSystem, BaseItem item, ItemResolveArgs args)
{
- if (fileSystem == null)
- {
- throw new ArgumentNullException(nameof(fileSystem));
- }
-
- if (item == null)
- {
- throw new ArgumentNullException(nameof(item));
- }
-
- if (args == null)
- {
- throw new ArgumentNullException(nameof(args));
- }
-
// See if a different path came out of the resolver than what went in
if (!fileSystem.AreEqual(args.Path, item.Path))
{
@@ -136,7 +109,7 @@ namespace Emby.Server.Implementations.Library
if (childData != null)
{
- SetDateCreated(item, fileSystem, childData);
+ SetDateCreated(item, childData);
}
else
{
@@ -144,17 +117,17 @@ namespace Emby.Server.Implementations.Library
if (fileData.Exists)
{
- SetDateCreated(item, fileSystem, fileData);
+ SetDateCreated(item, fileData);
}
}
}
else
{
- SetDateCreated(item, fileSystem, args.FileInfo);
+ SetDateCreated(item, args.FileInfo);
}
}
- private static void SetDateCreated(BaseItem item, IFileSystem fileSystem, FileSystemMetadata info)
+ private static void SetDateCreated(BaseItem item, FileSystemMetadata? info)
{
var config = BaseItem.ConfigurationManager.GetMetadataConfiguration();
@@ -163,7 +136,7 @@ namespace Emby.Server.Implementations.Library
// directoryService.getFile may return null
if (info != null)
{
- var dateCreated = fileSystem.GetCreationTimeUtc(info);
+ var dateCreated = info.CreationTimeUtc;
if (dateCreated.Equals(DateTime.MinValue))
{
diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs
index 90b6a8a7d..4ad84579d 100644
--- a/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs
@@ -201,6 +201,11 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
continue;
}
+ if (resolvedItem.Files.Count == 0)
+ {
+ continue;
+ }
+
var firstMedia = resolvedItem.Files[0];
var libraryItem = new T
diff --git a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs
index c76d41e5c..5f051321f 100644
--- a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs
@@ -63,7 +63,8 @@ namespace Emby.Server.Implementations.Library.Resolvers
{
Path = args.Path,
Name = Path.GetFileNameWithoutExtension(args.Path),
- IsInMixedFolder = true
+ IsInMixedFolder = true,
+ PlaylistMediaType = MediaType.Audio
};
}
}
diff --git a/Emby.Server.Implementations/Library/SearchEngine.cs b/Emby.Server.Implementations/Library/SearchEngine.cs
index 94602582b..bcdf854ca 100644
--- a/Emby.Server.Implementations/Library/SearchEngine.cs
+++ b/Emby.Server.Implementations/Library/SearchEngine.cs
@@ -12,7 +12,6 @@ using MediaBrowser.Controller.Extensions;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Search;
-using Microsoft.Extensions.Logging;
using Genre = MediaBrowser.Controller.Entities.Genre;
using Person = MediaBrowser.Controller.Entities.Person;
diff --git a/Emby.Server.Implementations/Library/UserDataManager.cs b/Emby.Server.Implementations/Library/UserDataManager.cs
index d16275b19..827e3c64b 100644
--- a/Emby.Server.Implementations/Library/UserDataManager.cs
+++ b/Emby.Server.Implementations/Library/UserDataManager.cs
@@ -13,8 +13,8 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
-using Book = MediaBrowser.Controller.Entities.Book;
using AudioBook = MediaBrowser.Controller.Entities.AudioBook;
+using Book = MediaBrowser.Controller.Entities.Book;
namespace Emby.Server.Implementations.Library
{
@@ -248,15 +248,15 @@ namespace Emby.Server.Implementations.Library
}
else if (positionTicks > 0 && hasRuntime && item is AudioBook)
{
- var minIn = TimeSpan.FromTicks(positionTicks).TotalMinutes;
- var minOut = TimeSpan.FromTicks(runtimeTicks - positionTicks).TotalMinutes;
+ var playbackPositionInMinutes = TimeSpan.FromTicks(positionTicks).TotalMinutes;
+ var remainingTimeInMinutes = TimeSpan.FromTicks(runtimeTicks - positionTicks).TotalMinutes;
- if (minIn > _config.Configuration.MinAudiobookResume)
+ if (playbackPositionInMinutes < _config.Configuration.MinAudiobookResume)
{
// ignore progress during the beginning
positionTicks = 0;
}
- else if (minOut < _config.Configuration.MaxAudiobookResume || positionTicks >= runtimeTicks)
+ else if (remainingTimeInMinutes < _config.Configuration.MaxAudiobookResume || positionTicks >= runtimeTicks)
{
// mark as completed close to the end
positionTicks = 0;
diff --git a/Emby.Server.Implementations/Library/UserViewManager.cs b/Emby.Server.Implementations/Library/UserViewManager.cs
index b6b7ea949..ac041bcf6 100644
--- a/Emby.Server.Implementations/Library/UserViewManager.cs
+++ b/Emby.Server.Implementations/Library/UserViewManager.cs
@@ -2,7 +2,6 @@
using System;
using System.Collections.Generic;
-using System.Globalization;
using System.Linq;
using System.Threading;
using Jellyfin.Data.Entities;