using System;
using System.Collections.Generic;
using Emby.Naming.Audio;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library.Resolvers.Audio
{
///
/// Class MusicAlbumResolver.
///
public class MusicAlbumResolver : ItemResolver
{
private readonly ILogger _logger;
private readonly IFileSystem _fileSystem;
private readonly ILibraryManager _libraryManager;
///
/// Initializes a new instance of the class.
///
/// The logger.
/// The file system.
/// The library manager.
public MusicAlbumResolver(ILogger logger, IFileSystem fileSystem, ILibraryManager libraryManager)
{
_logger = logger;
_fileSystem = fileSystem;
_libraryManager = libraryManager;
}
///
/// Gets the priority.
///
/// The priority.
public override ResolverPriority Priority => ResolverPriority.Second;
///
/// Resolves the specified args.
///
/// The args.
/// MusicAlbum.
protected override MusicAlbum Resolve(ItemResolveArgs args)
{
var collectionType = args.GetCollectionType();
var isMusicMediaFolder = string.Equals(collectionType, CollectionType.Music, StringComparison.OrdinalIgnoreCase);
// If there's a collection type and it's not music, don't allow it.
if (!isMusicMediaFolder)
{
return null;
}
if (!args.IsDirectory)
{
return null;
}
// Avoid mis-identifying top folders
if (args.HasParent())
{
return null;
}
if (args.Parent.IsRoot)
{
return null;
}
return IsMusicAlbum(args) ? new MusicAlbum() : null;
}
///
/// Determine if the supplied file data points to a music album
///
public bool IsMusicAlbum(string path, IDirectoryService directoryService, LibraryOptions libraryOptions)
{
return ContainsMusic(directoryService.GetFileSystemEntries(path), true, directoryService, _logger, _fileSystem, libraryOptions, _libraryManager);
}
///
/// Determine if the supplied resolve args should be considered a music album
///
/// The args.
/// true if [is music album] [the specified args]; otherwise, false.
private bool IsMusicAlbum(ItemResolveArgs args)
{
// Args points to an album if parent is an Artist folder or it directly contains music
if (args.IsDirectory)
{
// if (args.Parent is MusicArtist) return true; //saves us from testing children twice
if (ContainsMusic(args.FileSystemChildren, true, args.DirectoryService, _logger, _fileSystem, args.GetLibraryOptions(), _libraryManager))
{
return true;
}
}
return false;
}
///
/// Determine if the supplied list contains what we should consider music
///
private bool ContainsMusic(
IEnumerable list,
bool allowSubfolders,
IDirectoryService directoryService,
ILogger logger,
IFileSystem fileSystem,
LibraryOptions libraryOptions,
ILibraryManager libraryManager)
{
var discSubfolderCount = 0;
var notMultiDisc = false;
foreach (var fileSystemInfo in list)
{
if (fileSystemInfo.IsDirectory)
{
if (allowSubfolders)
{
if (notMultiDisc)
{
continue;
}
var path = fileSystemInfo.FullName;
var hasMusic = ContainsMusic(directoryService.GetFileSystemEntries(path), false, directoryService, logger, fileSystem, libraryOptions, libraryManager);
if (hasMusic)
{
if (IsMultiDiscFolder(path, libraryOptions))
{
logger.LogDebug("Found multi-disc folder: " + path);
discSubfolderCount++;
}
else
{
// If there are folders underneath with music that are not multidisc, then this can't be a multi-disc album
notMultiDisc = true;
}
}
}
}
else
{
var fullName = fileSystemInfo.FullName;
if (libraryManager.IsAudioFile(fullName, libraryOptions))
{
return true;
}
}
}
if (notMultiDisc)
{
return false;
}
return discSubfolderCount > 0;
}
private bool IsMultiDiscFolder(string path, LibraryOptions libraryOptions)
{
var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions();
var parser = new AlbumParser(namingOptions);
var result = parser.ParseMultiPart(path);
return result.IsMultiPart;
}
}
}