| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 | #nullable disable#pragma warning disable CS1591using System;using System.Collections.Generic;using System.IO;using System.Linq;using Emby.Naming.Audio;using Emby.Naming.AudioBook;using Emby.Naming.Common;using Emby.Naming.Video;using MediaBrowser.Controller.Entities;using MediaBrowser.Controller.Library;using MediaBrowser.Controller.Providers;using MediaBrowser.Controller.Resolvers;using MediaBrowser.Model.Entities;using MediaBrowser.Model.IO;namespace Emby.Server.Implementations.Library.Resolvers.Audio{    /// <summary>    /// Class AudioResolver.    /// </summary>    public class AudioResolver : ItemResolver<MediaBrowser.Controller.Entities.Audio.Audio>, IMultiItemResolver    {        private readonly NamingOptions _namingOptions;        public AudioResolver(NamingOptions namingOptions)        {            _namingOptions = namingOptions;        }        /// <summary>        /// Gets the priority.        /// </summary>        /// <value>The priority.</value>        public override ResolverPriority Priority => ResolverPriority.Fifth;        public MultiItemResolverResult ResolveMultiple(            Folder parent,            List<FileSystemMetadata> files,            string collectionType,            IDirectoryService directoryService)        {            var result = ResolveMultipleInternal(parent, files, collectionType);            if (result is not 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)        {            if (string.Equals(collectionType, CollectionType.Books, StringComparison.OrdinalIgnoreCase))            {                return ResolveMultipleAudio(parent, files, 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 collectionType = args.GetCollectionType();            var isBooksCollectionType = string.Equals(collectionType, CollectionType.Books, StringComparison.OrdinalIgnoreCase);            if (args.IsDirectory)            {                if (!isBooksCollectionType)                {                    return null;                }                return FindAudioBook(args, false);            }            if (AudioFileParser.IsAudioFile(args.Path, _namingOptions))            {                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 && VideoResolver.IsVideoFile(args.Path, _namingOptions))                {                    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 is null ||                    isMusicCollectionType)                {                    item = new MediaBrowser.Controller.Entities.Audio.Audio();                }                else if (isBooksCollectionType)                {                    item = new AudioBook();                }                if (item is not null)                {                    item.IsShortcut = string.Equals(extension, ".strm", StringComparison.OrdinalIgnoreCase);                    item.IsInMixedFolder = true;                }                return item;            }            return null;        }        private AudioBook FindAudioBook(ItemResolveArgs args, bool parseName)        {            // TODO: Allow GetMultiDiscMovie in here            var result = ResolveMultipleAudio(args.Parent, args.GetActualFileSystemChildren(), parseName);            if (result is null || result.Items.Count != 1 || result.Items[0] is not AudioBook item)            {                return null;            }            // If we were supporting this we'd be checking filesFromOtherItems            item.IsInMixedFolder = false;            item.Name = Path.GetFileName(item.ContainingFolderPath);            return item;        }        private MultiItemResolverResult ResolveMultipleAudio(Folder parent, IEnumerable<FileSystemMetadata> fileSystemEntries, bool parseName)        {            var files = new List<FileSystemMetadata>();            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                {                    files.Add(child);                }            }            var resolver = new AudioBookListResolver(_namingOptions);            var resolverResult = resolver.Resolve(files).ToList();            var result = new MultiItemResolverResult            {                ExtraFiles = leftOver,                Items = new List<BaseItem>()            };            var isInMixedFolder = resolverResult.Count > 1 || (parent is not 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;                }                // Until multi-part books are handled letting files stack hides them from browsing in the client                if (resolvedItem.Files.Count == 0 || resolvedItem.Extras.Count > 0 || resolvedItem.AlternateVersions.Count > 0)                {                    continue;                }                var firstMedia = resolvedItem.Files[0];                var libraryItem = new AudioBook                {                    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 static bool ContainsFile(IEnumerable<AudioBookInfo> result, FileSystemMetadata file)        {            return result.Any(i => ContainsFile(i, file));        }        private static 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);        }    }}
 |