jellyfin/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs
Erwin de Haan ec1f5dc317 Mayor code cleanup
Add Argument*Exceptions now use proper nameof operators.

Added exception messages to quite a few Argument*Exceptions.

Fixed rethorwing to be proper syntax.

Added a ton of null checkes. (This is only a start, there are about 500 places that need proper null handling)

Added some TODOs to log certain exceptions.

Fix sln again.

Fixed all AssemblyInfo's and added proper copyright (where I could find them)

We live in *current year*.

Fixed the use of braces.

Fixed a ton of properties, and made a fair amount of functions static that should be and can be static.

Made more Methods that should be static static.

You can now use static to find bad functions!

Removed unused variable. And added one more proper XML comment.
2019-01-10 20:38:53 +01:00

274 lines
9.7 KiB
C#

using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Model.Entities;
using System;
using MediaBrowser.Controller.Entities;
using System.IO;
using System.Linq;
using MediaBrowser.Controller.Providers;
using System.Collections.Generic;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Extensions;
using Emby.Naming.Video;
using Emby.Naming.AudioBook;
namespace Emby.Server.Implementations.Library.Resolvers.Audio
{
/// <summary>
/// Class AudioResolver
/// </summary>
public class AudioResolver : ItemResolver<MediaBrowser.Controller.Entities.Audio.Audio>, IMultiItemResolver
{
private readonly ILibraryManager LibraryManager;
public AudioResolver(ILibraryManager libraryManager)
{
LibraryManager = libraryManager;
}
/// <summary>
/// Gets the priority.
/// </summary>
/// <value>The priority.</value>
public override ResolverPriority Priority => ResolverPriority.Fourth;
public MultiItemResolverResult ResolveMultiple(Folder parent,
List<FileSystemMetadata> files,
string collectionType,
IDirectoryService directoryService)
{
var result = ResolveMultipleInternal(parent, files, collectionType, directoryService);
if (result != null)
{
foreach (var item in result.Items)
{
SetInitialItemValues((MediaBrowser.Controller.Entities.Audio.Audio)item, null);
}
}
return result;
}
private MultiItemResolverResult ResolveMultipleInternal(Folder parent,
List<FileSystemMetadata> files,
string collectionType,
IDirectoryService directoryService)
{
if (string.Equals(collectionType, CollectionType.Books, StringComparison.OrdinalIgnoreCase))
{
return ResolveMultipleAudio<AudioBook>(parent, files, directoryService, false, collectionType, true);
}
return null;
}
/// <summary>
/// Resolves the specified args.
/// </summary>
/// <param name="args">The args.</param>
/// <returns>Entities.Audio.Audio.</returns>
protected override MediaBrowser.Controller.Entities.Audio.Audio Resolve(ItemResolveArgs args)
{
// Return audio if the path is a file and has a matching extension
var libraryOptions = args.GetLibraryOptions();
var collectionType = args.GetCollectionType();
var isBooksCollectionType = string.Equals(collectionType, CollectionType.Books, StringComparison.OrdinalIgnoreCase);
if (args.IsDirectory)
{
if (!isBooksCollectionType)
{
return null;
}
var files = args.FileSystemChildren
.Where(i => !LibraryManager.IgnoreFile(i, args.Parent))
.ToList();
if (isBooksCollectionType)
{
return FindAudio<AudioBook>(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, false);
}
return null;
}
if (LibraryManager.IsAudioFile(args.Path, libraryOptions))
{
var extension = Path.GetExtension(args.Path);
if (string.Equals(extension, ".cue", StringComparison.OrdinalIgnoreCase))
{
// if audio file exists of same name, return null
return null;
}
var isMixedCollectionType = string.IsNullOrEmpty(collectionType);
// For conflicting extensions, give priority to videos
if (isMixedCollectionType && LibraryManager.IsVideoFile(args.Path, libraryOptions))
{
return null;
}
MediaBrowser.Controller.Entities.Audio.Audio item = null;
var isMusicCollectionType = string.Equals(collectionType, CollectionType.Music, StringComparison.OrdinalIgnoreCase);
// Use regular audio type for mixed libraries, owned items and music
if (isMixedCollectionType ||
args.Parent == null ||
isMusicCollectionType)
{
item = new MediaBrowser.Controller.Entities.Audio.Audio();
}
else if (isBooksCollectionType)
{
item = new AudioBook();
}
if (item != null)
{
item.IsShortcut = string.Equals(extension, ".strm", StringComparison.OrdinalIgnoreCase);
item.IsInMixedFolder = true;
}
return item;
}
return null;
}
private T FindAudio<T>(ItemResolveArgs args, string path, Folder parent, List<FileSystemMetadata> fileSystemEntries, IDirectoryService directoryService, string collectionType, bool parseName)
where T : MediaBrowser.Controller.Entities.Audio.Audio, new()
{
var multiDiscFolders = new List<FileSystemMetadata>();
var libraryOptions = args.GetLibraryOptions();
var filesFromOtherItems = new List<FileSystemMetadata>();
// TODO: Allow GetMultiDiscMovie in here
var supportsMultiVersion = false;
var result = ResolveMultipleAudio<T>(parent, fileSystemEntries, directoryService, supportsMultiVersion, collectionType, parseName) ??
new MultiItemResolverResult();
if (result.Items.Count == 1)
{
var videoPath = result.Items[0].Path;
// If we were supporting this we'd be checking filesFromOtherItems
var hasOtherItems = false;
if (!hasOtherItems)
{
var item = (T)result.Items[0];
item.IsInMixedFolder = false;
item.Name = Path.GetFileName(item.ContainingFolderPath);
return item;
}
}
if (result.Items.Count == 0 && multiDiscFolders.Count > 0)
{
//return GetMultiDiscAudio<T>(multiDiscFolders, directoryService);
}
return null;
}
private MultiItemResolverResult ResolveMultipleAudio<T>(Folder parent, IEnumerable<FileSystemMetadata> fileSystemEntries, IDirectoryService directoryService, bool suppportMultiEditions, string collectionType, bool parseName)
where T : MediaBrowser.Controller.Entities.Audio.Audio, new()
{
var files = new List<FileSystemMetadata>();
var items = new List<BaseItem>();
var leftOver = new List<FileSystemMetadata>();
// Loop through each child file/folder and see if we find a video
foreach (var child in fileSystemEntries)
{
if (child.IsDirectory)
{
leftOver.Add(child);
}
else if (IsIgnored(child.Name))
{
}
else
{
files.Add(child);
}
}
var namingOptions = ((LibraryManager)LibraryManager).GetNamingOptions();
var resolver = new AudioBookListResolver(namingOptions);
var resolverResult = resolver.Resolve(files).ToList();
var result = new MultiItemResolverResult
{
ExtraFiles = leftOver,
Items = items
};
var isInMixedFolder = resolverResult.Count > 1 || (parent != null && parent.IsTopParent);
foreach (var resolvedItem in resolverResult)
{
if (resolvedItem.Files.Count > 1)
{
// For now, until we sort out naming for multi-part books
continue;
}
var firstMedia = resolvedItem.Files.First();
var libraryItem = new T
{
Path = firstMedia.Path,
IsInMixedFolder = isInMixedFolder,
ProductionYear = resolvedItem.Year,
Name = parseName ?
resolvedItem.Name :
Path.GetFileNameWithoutExtension(firstMedia.Path),
//AdditionalParts = resolvedItem.Files.Skip(1).Select(i => i.Path).ToArray(),
//LocalAlternateVersions = resolvedItem.AlternateVersions.Select(i => i.Path).ToArray()
};
result.Items.Add(libraryItem);
}
result.ExtraFiles.AddRange(files.Where(i => !ContainsFile(resolverResult, i)));
return result;
}
private bool ContainsFile(List<AudioBookInfo> result, FileSystemMetadata file)
{
return result.Any(i => ContainsFile(i, file));
}
private bool ContainsFile(AudioBookInfo result, FileSystemMetadata file)
{
return result.Files.Any(i => ContainsFile(i, file)) ||
result.AlternateVersions.Any(i => ContainsFile(i, file)) ||
result.Extras.Any(i => ContainsFile(i, file));
}
private static bool ContainsFile(AudioBookFileInfo result, FileSystemMetadata file)
{
return string.Equals(result.Path, file.FullName, StringComparison.OrdinalIgnoreCase);
}
private static bool IsIgnored(string filename)
{
return false;
}
}
}