|
|
|
@ -78,6 +78,7 @@ namespace Emby.Server.Implementations.Library
|
|
|
|
|
private readonly NamingOptions _namingOptions;
|
|
|
|
|
private readonly IPeopleRepository _peopleRepository;
|
|
|
|
|
private readonly ExtraResolver _extraResolver;
|
|
|
|
|
private readonly IPathManager _pathManager;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// The _root folder sync lock.
|
|
|
|
@ -113,7 +114,8 @@ namespace Emby.Server.Implementations.Library
|
|
|
|
|
/// <param name="imageProcessor">The image processor.</param>
|
|
|
|
|
/// <param name="namingOptions">The naming options.</param>
|
|
|
|
|
/// <param name="directoryService">The directory service.</param>
|
|
|
|
|
/// <param name="peopleRepository">The People Repository.</param>
|
|
|
|
|
/// <param name="peopleRepository">The people repository.</param>
|
|
|
|
|
/// <param name="pathManager">The path manager.</param>
|
|
|
|
|
public LibraryManager(
|
|
|
|
|
IServerApplicationHost appHost,
|
|
|
|
|
ILoggerFactory loggerFactory,
|
|
|
|
@ -130,7 +132,8 @@ namespace Emby.Server.Implementations.Library
|
|
|
|
|
IImageProcessor imageProcessor,
|
|
|
|
|
NamingOptions namingOptions,
|
|
|
|
|
IDirectoryService directoryService,
|
|
|
|
|
IPeopleRepository peopleRepository)
|
|
|
|
|
IPeopleRepository peopleRepository,
|
|
|
|
|
IPathManager pathManager)
|
|
|
|
|
{
|
|
|
|
|
_appHost = appHost;
|
|
|
|
|
_logger = loggerFactory.CreateLogger<LibraryManager>();
|
|
|
|
@ -148,6 +151,7 @@ namespace Emby.Server.Implementations.Library
|
|
|
|
|
_cache = new ConcurrentDictionary<Guid, BaseItem>();
|
|
|
|
|
_namingOptions = namingOptions;
|
|
|
|
|
_peopleRepository = peopleRepository;
|
|
|
|
|
_pathManager = pathManager;
|
|
|
|
|
_extraResolver = new ExtraResolver(loggerFactory.CreateLogger<ExtraResolver>(), namingOptions, directoryService);
|
|
|
|
|
|
|
|
|
|
_configurationManager.ConfigurationUpdated += ConfigurationUpdated;
|
|
|
|
@ -200,33 +204,33 @@ namespace Emby.Server.Implementations.Library
|
|
|
|
|
/// Gets or sets the postscan tasks.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <value>The postscan tasks.</value>
|
|
|
|
|
private ILibraryPostScanTask[] PostscanTasks { get; set; } = Array.Empty<ILibraryPostScanTask>();
|
|
|
|
|
private ILibraryPostScanTask[] PostscanTasks { get; set; } = [];
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets or sets the intro providers.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <value>The intro providers.</value>
|
|
|
|
|
private IIntroProvider[] IntroProviders { get; set; } = Array.Empty<IIntroProvider>();
|
|
|
|
|
private IIntroProvider[] IntroProviders { get; set; } = [];
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets or sets the list of entity resolution ignore rules.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <value>The entity resolution ignore rules.</value>
|
|
|
|
|
private IResolverIgnoreRule[] EntityResolutionIgnoreRules { get; set; } = Array.Empty<IResolverIgnoreRule>();
|
|
|
|
|
private IResolverIgnoreRule[] EntityResolutionIgnoreRules { get; set; } = [];
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets or sets the list of currently registered entity resolvers.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <value>The entity resolvers enumerable.</value>
|
|
|
|
|
private IItemResolver[] EntityResolvers { get; set; } = Array.Empty<IItemResolver>();
|
|
|
|
|
private IItemResolver[] EntityResolvers { get; set; } = [];
|
|
|
|
|
|
|
|
|
|
private IMultiItemResolver[] MultiItemResolvers { get; set; } = Array.Empty<IMultiItemResolver>();
|
|
|
|
|
private IMultiItemResolver[] MultiItemResolvers { get; set; } = [];
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets or sets the comparers.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <value>The comparers.</value>
|
|
|
|
|
private IBaseItemComparer[] Comparers { get; set; } = Array.Empty<IBaseItemComparer>();
|
|
|
|
|
private IBaseItemComparer[] Comparers { get; set; } = [];
|
|
|
|
|
|
|
|
|
|
public bool IsScanRunning { get; private set; }
|
|
|
|
|
|
|
|
|
@ -359,7 +363,7 @@ namespace Emby.Server.Implementations.Library
|
|
|
|
|
|
|
|
|
|
var children = item.IsFolder
|
|
|
|
|
? ((Folder)item).GetRecursiveChildren(false)
|
|
|
|
|
: Array.Empty<BaseItem>();
|
|
|
|
|
: [];
|
|
|
|
|
|
|
|
|
|
foreach (var metadataPath in GetMetadataPaths(item, children))
|
|
|
|
|
{
|
|
|
|
@ -465,14 +469,28 @@ namespace Emby.Server.Implementations.Library
|
|
|
|
|
ReportItemRemoved(item, parent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static List<string> GetMetadataPaths(BaseItem item, IEnumerable<BaseItem> children)
|
|
|
|
|
private List<string> GetMetadataPaths(BaseItem item, IEnumerable<BaseItem> children)
|
|
|
|
|
{
|
|
|
|
|
var list = GetInternalMetadataPaths(item);
|
|
|
|
|
foreach (var child in children)
|
|
|
|
|
{
|
|
|
|
|
list.AddRange(GetInternalMetadataPaths(child));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private List<string> GetInternalMetadataPaths(BaseItem item)
|
|
|
|
|
{
|
|
|
|
|
var list = new List<string>
|
|
|
|
|
{
|
|
|
|
|
item.GetInternalMetadataPath()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
list.AddRange(children.Select(i => i.GetInternalMetadataPath()));
|
|
|
|
|
if (item is Video video)
|
|
|
|
|
{
|
|
|
|
|
list.Add(_pathManager.GetTrickplayDirectory(video));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
@ -593,7 +611,7 @@ namespace Emby.Server.Implementations.Library
|
|
|
|
|
{
|
|
|
|
|
_logger.LogError(ex, "Error in GetFilteredFileSystemEntries isPhysicalRoot: {0} IsVf: {1}", isPhysicalRoot, isVf);
|
|
|
|
|
|
|
|
|
|
files = Array.Empty<FileSystemMetadata>();
|
|
|
|
|
files = [];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
@ -1463,7 +1481,7 @@ namespace Emby.Server.Implementations.Library
|
|
|
|
|
|
|
|
|
|
// Optimize by querying against top level views
|
|
|
|
|
query.TopParentIds = parents.SelectMany(i => GetTopParentIdsForQuery(i, query.User)).ToArray();
|
|
|
|
|
query.AncestorIds = Array.Empty<Guid>();
|
|
|
|
|
query.AncestorIds = [];
|
|
|
|
|
|
|
|
|
|
// Prevent searching in all libraries due to empty filter
|
|
|
|
|
if (query.TopParentIds.Length == 0)
|
|
|
|
@ -1583,7 +1601,7 @@ namespace Emby.Server.Implementations.Library
|
|
|
|
|
return GetTopParentIdsForQuery(displayParent, user);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Array.Empty<Guid>();
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!view.ParentId.IsEmpty())
|
|
|
|
@ -1594,7 +1612,7 @@ namespace Emby.Server.Implementations.Library
|
|
|
|
|
return GetTopParentIdsForQuery(displayParent, user);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Array.Empty<Guid>();
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Handle grouping
|
|
|
|
@ -1609,7 +1627,7 @@ namespace Emby.Server.Implementations.Library
|
|
|
|
|
.SelectMany(i => GetTopParentIdsForQuery(i, user));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Array.Empty<Guid>();
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (item is CollectionFolder collectionFolder)
|
|
|
|
@ -1623,7 +1641,7 @@ namespace Emby.Server.Implementations.Library
|
|
|
|
|
return new[] { topParent.Id };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Array.Empty<Guid>();
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
@ -1667,7 +1685,7 @@ namespace Emby.Server.Implementations.Library
|
|
|
|
|
{
|
|
|
|
|
_logger.LogError(ex, "Error getting intros");
|
|
|
|
|
|
|
|
|
|
return Enumerable.Empty<IntroInfo>();
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2894,7 +2912,7 @@ namespace Emby.Server.Implementations.Library
|
|
|
|
|
{
|
|
|
|
|
var path = Path.Combine(virtualFolderPath, collectionType.ToString()!.ToLowerInvariant() + ".collection"); // Can't be null with legal values?
|
|
|
|
|
|
|
|
|
|
await File.WriteAllBytesAsync(path, Array.Empty<byte>()).ConfigureAwait(false);
|
|
|
|
|
await File.WriteAllBytesAsync(path, []).ConfigureAwait(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CollectionFolder.SaveLibraryOptions(virtualFolderPath, options);
|
|
|
|
|