/// <summary>
        /// Gets a <see cref="FanArtPathCollection"/> containing all matching season fanart paths in the specified <see cref="ResourcePath"/>.
        /// </summary>
        /// <param name="seasonDirectory"><see cref="IFileSystemResourceAccessor"/> that points to the season directory.</param>
        /// <param name="seasonNumber">Season number.</param>
        /// <returns><see cref="FanArtPathCollection"/> containing all matching paths.</returns>
        protected FanArtPathCollection GetSeasonFolderFanArt(IFileSystemResourceAccessor seasonDirectory, int?seasonNumber, bool isSeriesFolder)
        {
            FanArtPathCollection paths = new FanArtPathCollection();

            if (seasonDirectory == null)
            {
                return(paths);
            }

            List <ResourcePath> potentialFanArtFiles = LocalFanartHelper.GetPotentialFanArtFiles(seasonDirectory);

            if (!isSeriesFolder)
            {
                ExtractAllFanArtImages(potentialFanArtFiles, paths);

                if (!seasonNumber.HasValue || !seasonDirectory.ResourceExists("../"))
                {
                    return(paths);
                }

                //Try and populate any missing fanart from the series directory
                using (IFileSystemResourceAccessor seriesDirectory = seasonDirectory.GetResource("../"))
                    potentialFanArtFiles = LocalFanartHelper.GetPotentialFanArtFiles(seriesDirectory);
            }
            GetAdditionalSeasonFolderFanArt(paths, potentialFanArtFiles, seasonNumber);

            return(paths);
        }
Beispiel #2
0
        /// <summary>
        /// Gets a <see cref="FanArtPathCollection"/> containing all matching fanart paths in the specified <see cref="ResourcePath"/>.
        /// </summary>
        /// <param name="albumDirectory"><see cref="IFileSystemResourceAccessor"/> that points to the album directory.</param>
        /// <returns><see cref="FanArtPathCollection"/> containing all matching paths.</returns>
        protected FanArtPathCollection GetAlbumFolderFanArt(IFileSystemResourceAccessor albumDirectory)
        {
            FanArtPathCollection paths = new FanArtPathCollection();

            if (albumDirectory == null)
            {
                return(paths);
            }

            //Get all fanart in the current directory
            List <ResourcePath> potentialFanArtFiles = LocalFanartHelper.GetPotentialFanArtFiles(albumDirectory);

            ExtractAllFanArtImages(potentialFanArtFiles, paths);

            //Add extra backdrops in ExtraFanArt directory
            if (albumDirectory.ResourceExists("ExtraFanArt/"))
            {
                using (IFileSystemResourceAccessor extraFanArtDirectory = albumDirectory.GetResource("ExtraFanArt/"))
                    paths.AddRange(FanArtTypes.FanArt, LocalFanartHelper.GetPotentialFanArtFiles(extraFanArtDirectory));
            }

            List <ResourcePath> covers;

            //Albums store posters as covers so switch the fanart type
            if (paths.Paths.TryGetValue(FanArtTypes.Poster, out covers))
            {
                paths.Paths.Remove(FanArtTypes.Poster);
                paths.AddRange(FanArtTypes.Cover, covers);
            }

            return(paths);
        }
        private IEnumerable <ResourcePath> GetCollectionFanart(string fanArtType, IFileSystemResourceAccessor directoryFsra)
        {
            var fanArtPaths = new List <ResourcePath>();

            if (directoryFsra != null)
            {
                var potentialFanArtFiles = LocalFanartHelper.GetPotentialFanArtFiles(directoryFsra);

                if (fanArtType == FanArtTypes.Poster || fanArtType == FanArtTypes.Thumbnail)
                {
                    fanArtPaths.AddRange(LocalFanartHelper.FilterPotentialFanArtFilesByName(potentialFanArtFiles, LocalFanartHelper.THUMB_FILENAMES.Select(f => "movieset-" + f)));
                    fanArtPaths.AddRange(LocalFanartHelper.FilterPotentialFanArtFilesByName(potentialFanArtFiles, LocalFanartHelper.POSTER_FILENAMES.Select(f => "movieset-" + f)));
                    fanArtPaths.AddRange(LocalFanartHelper.FilterPotentialFanArtFilesByName(potentialFanArtFiles, LocalFanartHelper.THUMB_FILENAMES));
                    fanArtPaths.AddRange(LocalFanartHelper.FilterPotentialFanArtFilesByName(potentialFanArtFiles, LocalFanartHelper.POSTER_FILENAMES));
                }

                if (fanArtType == FanArtTypes.Banner)
                {
                    fanArtPaths.AddRange(LocalFanartHelper.FilterPotentialFanArtFilesByName(potentialFanArtFiles, LocalFanartHelper.BANNER_FILENAMES.Select(f => "movieset-" + f)));
                    fanArtPaths.AddRange(LocalFanartHelper.FilterPotentialFanArtFilesByName(potentialFanArtFiles, LocalFanartHelper.BANNER_FILENAMES));
                }

                if (fanArtType == FanArtTypes.Logo)
                {
                    fanArtPaths.AddRange(LocalFanartHelper.FilterPotentialFanArtFilesByName(potentialFanArtFiles, LocalFanartHelper.LOGO_FILENAMES.Select(f => "movieset-" + f)));
                    fanArtPaths.AddRange(LocalFanartHelper.FilterPotentialFanArtFilesByName(potentialFanArtFiles, LocalFanartHelper.LOGO_FILENAMES));
                }

                if (fanArtType == FanArtTypes.ClearArt)
                {
                    fanArtPaths.AddRange(LocalFanartHelper.FilterPotentialFanArtFilesByName(potentialFanArtFiles, LocalFanartHelper.CLEARART_FILENAMES.Select(f => "movieset-" + f)));
                    fanArtPaths.AddRange(LocalFanartHelper.FilterPotentialFanArtFilesByName(potentialFanArtFiles, LocalFanartHelper.CLEARART_FILENAMES));
                }

                if (fanArtType == FanArtTypes.FanArt)
                {
                    fanArtPaths.AddRange(LocalFanartHelper.FilterPotentialFanArtFilesByPrefix(potentialFanArtFiles, LocalFanartHelper.BACKDROP_FILENAMES.Select(f => "movieset-" + f)));
                    fanArtPaths.AddRange(LocalFanartHelper.FilterPotentialFanArtFilesByPrefix(potentialFanArtFiles, LocalFanartHelper.BACKDROP_FILENAMES));

                    if (directoryFsra.ResourceExists("ExtraFanArt/"))
                    {
                        using (var extraFanArtDirectoryFsra = directoryFsra.GetResource("ExtraFanArt/"))
                            fanArtPaths.AddRange(LocalFanartHelper.GetPotentialFanArtFiles(extraFanArtDirectoryFsra));
                    }
                }
            }
            return(fanArtPaths);
        }
        /// <summary>
        /// Gets a <see cref="FanArtPathCollection"/> containing all matching series fanart paths in the specified <see cref="ResourcePath"/>.
        /// </summary>
        /// <param name="seriesDirectory"><see cref="IFileSystemResourceAccessor"/> that points to the series directory.</param>
        /// <returns><see cref="FanArtPathCollection"/> containing all matching paths.</returns>
        protected FanArtPathCollection GetSeriesFolderFanArt(IFileSystemResourceAccessor seriesDirectory)
        {
            FanArtPathCollection paths = new FanArtPathCollection();

            if (seriesDirectory != null)
            {
                List <ResourcePath> potentialFanArtFiles = LocalFanartHelper.GetPotentialFanArtFiles(seriesDirectory);
                ExtractAllFanArtImages(potentialFanArtFiles, paths);

                if (seriesDirectory.ResourceExists("ExtraFanArt/"))
                {
                    using (IFileSystemResourceAccessor extraFanArtDirectory = seriesDirectory.GetResource("ExtraFanArt/"))
                        paths.AddRange(FanArtTypes.FanArt, LocalFanartHelper.GetPotentialFanArtFiles(extraFanArtDirectory));
                }
            }

            return(paths);
        }
Beispiel #5
0
        public bool IsDirectorySingleResource(IResourceAccessor mediaItemAccessor)
        {
            IFileSystemResourceAccessor fsra = mediaItemAccessor as IFileSystemResourceAccessor;

            if (fsra == null)
            {
                return(false);
            }

            if (!fsra.IsFile && fsra.ResourceExists("BDMV"))
            {
                using (IFileSystemResourceAccessor fsraBDMV = fsra.GetResource("BDMV"))
                {
                    if (fsraBDMV != null && fsraBDMV.ResourceExists("index.bdmv"))
                    {
                        // Video Blu-ray
                        return(true);
                    }
                }
            }
            return(false);
        }
Beispiel #6
0
        /// <summary>
        /// Gets a <see cref="FanArtPathCollection"/> containing all matching fanart paths in the specified <see cref="ResourcePath"/>.
        /// </summary>
        /// <param name="artistDirectory"><see cref="IFileSystemResourceAccessor"/> that points to the artist directory.</param>
        /// <returns><see cref="FanArtPathCollection"/> containing all matching paths.</returns>
        protected FanArtPathCollection GetArtistFolderFanArt(IFileSystemResourceAccessor artistDirectory)
        {
            FanArtPathCollection paths = new FanArtPathCollection();

            if (artistDirectory == null)
            {
                return(paths);
            }

            //Get all fanart in the current directory
            List <ResourcePath> potentialFanArtFiles = LocalFanartHelper.GetPotentialFanArtFiles(artistDirectory);

            ExtractAllFanArtImages(potentialFanArtFiles, paths);

            //Add extra backdrops in ExtraFanArt directory
            if (artistDirectory.ResourceExists("ExtraFanArt/"))
            {
                using (IFileSystemResourceAccessor extraFanArtDirectory = artistDirectory.GetResource("ExtraFanArt/"))
                    paths.AddRange(FanArtTypes.FanArt, LocalFanartHelper.GetPotentialFanArtFiles(extraFanArtDirectory));
            }

            return(paths);
        }
        /// <summary>
        /// Gets a <see cref="FanArtPathCollection"/> containing all matching fanart paths in the specified <see cref="ResourcePath"/>.
        /// </summary>
        /// <param name="videoDirectory"><see cref="IFileSystemResourceAccessor"/> that points to the episode directory.</param>
        /// <param name="filename">The file name of the media item to extract images for.</param>
        /// <returns><see cref="FanArtPathCollection"/> containing all matching paths.</returns>
        protected FanArtPathCollection GetFolderFanArt(IFileSystemResourceAccessor videoDirectory, string filename, IDictionary <Guid, IList <MediaItemAspect> > aspects)
        {
            FanArtPathCollection paths = new FanArtPathCollection();

            if (videoDirectory == null)
            {
                return(paths);
            }

            //Get all fanart in the current directory
            List <ResourcePath> potentialFanArtFiles = LocalFanartHelper.GetPotentialFanArtFiles(videoDirectory);

            ExtractAllFanArtImages(potentialFanArtFiles, paths, filename);

            //Add extra backdrops in ExtraFanArt directory
            if (videoDirectory.ResourceExists("ExtraFanArt/"))
            {
                using (IFileSystemResourceAccessor extraFanArtDirectory = videoDirectory.GetResource("ExtraFanArt/"))
                    paths.AddRange(FanArtTypes.FanArt, LocalFanartHelper.GetPotentialFanArtFiles(extraFanArtDirectory));
            }

            return(paths);
        }
Beispiel #8
0
        static UPnPError OnConcatenatePaths(DvAction action, IList <object> inParams, out IList <object> outParams,
                                            CallContext context)
        {
            outParams = null;
            ResourcePath      path            = ResourcePath.Deserialize((string)inParams[0]);
            string            relativePathStr = (string)inParams[1];
            IResourceAccessor ra;

            if (!path.TryCreateLocalResourceAccessor(out ra))
            {
                return(new UPnPError(600, "The given path is not accessible"));
            }
            string serializedPath = null;

            using (ra)
            {
                IFileSystemResourceAccessor fsra = ra as IFileSystemResourceAccessor;
                if (fsra != null)
                {
                    IFileSystemResourceAccessor ra2 = fsra.GetResource(relativePathStr);
                    if (ra2 != null)
                    {
                        using (ra2)
                            serializedPath = ra2.CanonicalLocalResourcePath.Serialize();
                    }
                }
                else
                {
                    return(new UPnPError(600, "The given paths cannot be concatenated"));
                }
            }
            outParams = new List <object> {
                serializedPath
            };
            return(null);
        }
        public bool TryExtractMetadata(IResourceAccessor mediaItemAccessor, IDictionary <Guid, MediaItemAspect> extractedAspectData, bool forceQuickMode)
        {
            try
            {
                VideoResult result = null;
                IFileSystemResourceAccessor fsra = mediaItemAccessor as IFileSystemResourceAccessor;
                if (fsra != null && fsra.IsDirectory && fsra.ResourceExists("VIDEO_TS"))
                {
                    IFileSystemResourceAccessor fsraVideoTs = fsra.GetResource("VIDEO_TS");
                    if (fsraVideoTs != null && fsraVideoTs.ResourceExists("VIDEO_TS.IFO"))
                    {
                        // Video DVD
                        using (MediaInfoWrapper videoTsInfo = ReadMediaInfo(fsraVideoTs.GetResource("VIDEO_TS.IFO")))
                        {
                            if (!videoTsInfo.IsValid || videoTsInfo.GetVideoCount() == 0)
                            {
                                return(false); // Invalid video_ts.ifo file
                            }
                            result = VideoResult.CreateDVDInfo(fsra.ResourceName, videoTsInfo);
                        }
                        // Iterate over all video files; MediaInfo finds different audio/video metadata for each .ifo file
                        ICollection <IFileSystemResourceAccessor> files = fsraVideoTs.GetFiles();
                        if (files != null)
                        {
                            foreach (IFileSystemResourceAccessor file in files)
                            {
                                string lowerPath = (file.ResourcePathName ?? string.Empty).ToLowerInvariant();
                                if (!lowerPath.EndsWith(".ifo") || lowerPath.EndsWith("video_ts.ifo"))
                                {
                                    continue;
                                }
                                using (MediaInfoWrapper mediaInfo = ReadMediaInfo(file))
                                {
                                    // Before we start evaluating the file, check if it is a video at all
                                    if (mediaInfo.IsValid && mediaInfo.GetVideoCount() == 0)
                                    {
                                        continue;
                                    }
                                    result.AddMediaInfo(mediaInfo);
                                }
                            }
                        }
                    }
                }
                else if (mediaItemAccessor.IsFile)
                {
                    string filePath = mediaItemAccessor.ResourcePathName;
                    if (!HasVideoExtension(filePath))
                    {
                        return(false);
                    }
                    using (MediaInfoWrapper fileInfo = ReadMediaInfo(mediaItemAccessor))
                    {
                        // Before we start evaluating the file, check if it is a video at all
                        if (!fileInfo.IsValid || (fileInfo.GetVideoCount() == 0 && !IsWorkaroundRequired(filePath)))
                        {
                            return(false);
                        }

                        string mediaTitle = DosPathHelper.GetFileNameWithoutExtension(mediaItemAccessor.ResourceName);
                        result = VideoResult.CreateFileInfo(mediaTitle, fileInfo);
                    }
                    using (Stream stream = mediaItemAccessor.OpenRead())
                        result.MimeType = MimeTypeDetector.GetMimeType(stream);
                }
                if (result != null)
                {
                    result.UpdateMetadata(extractedAspectData);

                    ILocalFsResourceAccessor disposeLfsra = null;
                    try
                    {
                        ILocalFsResourceAccessor lfsra = mediaItemAccessor as ILocalFsResourceAccessor;
                        if (lfsra == null && !forceQuickMode)
                        { // In case forceQuickMode, we only want local browsing
                            IResourceAccessor ra = mediaItemAccessor.Clone();
                            try
                            {
                                lfsra        = StreamedResourceToLocalFsAccessBridge.GetLocalFsResourceAccessor(ra);
                                disposeLfsra = lfsra; // Remember to dispose the extra resource accessor instance
                            }
                            catch (Exception)
                            {
                                ra.Dispose();
                            }
                        }
                        if (lfsra != null)
                        {
                            string localFsPath = lfsra.LocalFileSystemPath;
                            ExtractMatroskaTags(localFsPath, extractedAspectData, forceQuickMode);
                            ExtractThumbnailData(localFsPath, extractedAspectData, forceQuickMode);
                        }
                    }
                    finally
                    {
                        if (disposeLfsra != null)
                        {
                            disposeLfsra.Dispose();
                        }
                    }
                    return(true);
                }
            }
            catch (Exception e)
            {
                // Only log at the info level here - And simply return false. This lets the caller know that we
                // couldn't perform our task here.
                ServiceRegistration.Get <ILogger>().Info("VideoMetadataExtractor: Exception reading resource '{0}' (Text: '{1}')", mediaItemAccessor.CanonicalLocalResourcePath, e.Message);
            }
            return(false);
        }
Beispiel #10
0
        public bool TryExtractMetadata(IResourceAccessor mediaItemAccessor, IDictionary <Guid, MediaItemAspect> extractedAspectData, bool forceQuickMode)
        {
            try
            {
                VideoResult result = null;
                IFileSystemResourceAccessor fsra = mediaItemAccessor as IFileSystemResourceAccessor;
                if (fsra == null)
                {
                    return(false);
                }
                if (!fsra.IsFile && fsra.ResourceExists("VIDEO_TS"))
                {
                    IFileSystemResourceAccessor fsraVideoTs = fsra.GetResource("VIDEO_TS");
                    if (fsraVideoTs != null && fsraVideoTs.ResourceExists("VIDEO_TS.IFO"))
                    {
                        // Video DVD
                        using (MediaInfoWrapper videoTsInfo = ReadMediaInfo(fsraVideoTs.GetResource("VIDEO_TS.IFO")))
                        {
                            if (!videoTsInfo.IsValid || videoTsInfo.GetVideoCount() == 0)
                            {
                                return(false); // Invalid video_ts.ifo file
                            }
                            result = VideoResult.CreateDVDInfo(fsra.ResourceName, videoTsInfo);
                        }
                        // Iterate over all video files; MediaInfo finds different audio/video metadata for each .ifo file
                        ICollection <IFileSystemResourceAccessor> files = fsraVideoTs.GetFiles();
                        if (files != null)
                        {
                            foreach (IFileSystemResourceAccessor file in files)
                            {
                                string lowerPath = (file.ResourcePathName ?? string.Empty).ToLowerInvariant();
                                if (!lowerPath.EndsWith(".ifo") || lowerPath.EndsWith("video_ts.ifo"))
                                {
                                    continue;
                                }
                                using (MediaInfoWrapper mediaInfo = ReadMediaInfo(file))
                                {
                                    // Before we start evaluating the file, check if it is a video at all
                                    if (mediaInfo.IsValid && mediaInfo.GetVideoCount() == 0)
                                    {
                                        continue;
                                    }
                                    result.AddMediaInfo(mediaInfo);
                                }
                            }
                        }
                    }
                }
                else if (fsra.IsFile)
                {
                    string filePath = fsra.ResourcePathName;
                    if (!HasVideoExtension(filePath))
                    {
                        return(false);
                    }
                    using (MediaInfoWrapper fileInfo = ReadMediaInfo(fsra))
                    {
                        // Before we start evaluating the file, check if it is a video at all
                        if (!fileInfo.IsValid || (fileInfo.GetVideoCount() == 0 && !IsWorkaroundRequired(filePath)))
                        {
                            return(false);
                        }

                        string mediaTitle = DosPathHelper.GetFileNameWithoutExtension(fsra.ResourceName);
                        result = VideoResult.CreateFileInfo(mediaTitle, fileInfo);
                    }
                    using (Stream stream = fsra.OpenRead())
                        result.MimeType = MimeTypeDetector.GetMimeType(stream, DEFAULT_MIMETYPE);
                }
                if (result != null)
                {
                    result.UpdateMetadata(extractedAspectData);

                    using (LocalFsResourceAccessorHelper rah = new LocalFsResourceAccessorHelper(mediaItemAccessor))
                    {
                        ILocalFsResourceAccessor lfsra = rah.LocalFsResourceAccessor;
                        if (lfsra != null)
                        {
                            MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_SIZE, lfsra.Size);
                            MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_RECORDINGTIME, lfsra.LastChanged);
                            ExtractMatroskaTags(lfsra, extractedAspectData, forceQuickMode);
                            ExtractMp4Tags(lfsra, extractedAspectData, forceQuickMode);
                            ExtractThumbnailData(lfsra, extractedAspectData, forceQuickMode);
                        }
                        return(true);
                    }
                }
            }
            catch (Exception e)
            {
                // Only log at the info level here - And simply return false. This lets the caller know that we
                // couldn't perform our task here.
                ServiceRegistration.Get <ILogger>().Info("VideoMetadataExtractor: Exception reading resource '{0}' (Text: '{1}')", mediaItemAccessor.CanonicalLocalResourcePath, e.Message);
            }
            return(false);
        }
        /// <summary>
        /// Tries to read a simple image from <paramref name="element"/>.Value
        /// </summary>
        /// <param name="element"><see cref="XElement"/> to read from</param>
        /// <param name="nfoDirectoryFsra"><see cref="IFileSystemResourceAccessor"/> pointing to the parent directory of the nfo-file</param>
        /// <returns>
        /// <c>null</c> if
        ///   - <see cref="_importOnly"/> is <c>true</c>; or
        ///   - <see cref="_forceQuickMode"/> is <c>true</c>; or
        ///   - a call to <see cref="ParseSimpleString"/> for <paramref name="element"/> returns <c>null</c>
        ///   - <paramref name="element"/>.Value does not contain a valid and existing (absolute) http URL to an image; or
        ///   - <paramref name="element"/>.Value does contain a valid and existing (relative) file path or <paramref name="nfoDirectoryFsra"/> is <c>null</c>;
        /// otherwise the image file read as byte array.
        /// </returns>
        /// <remarks>
        /// <paramref name="element.Value"/> can be
        ///   - a file name:
        ///     <example>folder.jpg</example>
        ///     The file must then be in the same directory as the nfo-file
        ///   - a relative file path:
        ///     <example>extrafanart\fanart1.jpg</example>
        ///     <example>..\thumbs\fanart.jpg</example>
        ///     The path must be relative to the parent directory of the nfo-file
        ///   - an absolute http URL
        ///     <example>http://image.tmdb.org/t/p/original/1rre3m7WsI2QavNZD4aUa8LzzcK.jpg</example>
        /// </remarks>
        protected async Task <byte[]> ParseSimpleImageAsync(XElement element, IFileSystemResourceAccessor nfoDirectoryFsra)
        {
            if (_forceQuickMode)
            {
                return(null);
            }
            if (_importOnly)
            {
                return(null);
            }

            var imageFileString = ParseSimpleString(element);

            if (imageFileString == null)
            {
                return(null);
            }

            // First check whether it is a local file
            if (nfoDirectoryFsra != null)
            {
                var imageFsra = nfoDirectoryFsra.GetResource(imageFileString);
                if (imageFsra != null)
                {
                    using (imageFsra)
                        using (var imageStream = await imageFsra.OpenReadAsync().ConfigureAwait(false))
                        {
                            var result = new byte[imageStream.Length];
                            await imageStream.ReadAsync(result, 0, (int)imageStream.Length).ConfigureAwait(false);

                            return(result);
                        }
                }
            }
            else
            {
                _debugLogger.Error("[#{0}]: The nfo-file's parent directory's fsra could not be created", _miNumber);
            }

            // Then check if we have a valid http URL
            Uri imageFileUri;

            if (!Uri.TryCreate(imageFileString, UriKind.Absolute, out imageFileUri) || imageFileUri.Scheme != Uri.UriSchemeHttp)
            {
                _debugLogger.Warn("[#{0}]: The following element does neither contain an exsisting file name nor a valid http URL: {1}", _miNumber, element);
                return(null);
            }

            // Finally try to download the image from the internet
            try
            {
                var response = await _httpDownloadClient.GetAsync(imageFileUri).ConfigureAwait(false);

                if (response.IsSuccessStatusCode)
                {
                    return(await response.Content.ReadAsByteArrayAsync().ConfigureAwait(false));
                }
                _debugLogger.Warn("[#{0}]: Http status code {1} ({2}) when trying to download image file: {3}", _miNumber, (int)response.StatusCode, response.StatusCode, element);
            }
            catch (Exception e)
            {
                _debugLogger.Warn("[#{0}]: The following image file could not be downloaded: {1}", e, _miNumber, element);
            }
            return(null);
        }
        public async Task <MetadataContainer> ParseMediaItemAsync(MediaItem media, int?editionId = null, bool cache = true)
        {
            try
            {
                if (media.IsStub)
                {
                    return(null);
                }

                string            category = null;
                MetadataContainer info     = null;

                //Check for live items
                if (media.Aspects.ContainsKey(AudioAspect.ASPECT_ID))
                {
                    category = AUDIO_CATEGORY;
                    if (media.IsLiveRadioItem() && media is LiveTvMediaItem ltmi)
                    {
                        info = await ParseSlimTvItemAsync(ltmi).ConfigureAwait(false);

                        if (info != null)
                        {
                            info.Metadata[Editions.DEFAULT_EDITION].Live = true;
                            info.Metadata[Editions.DEFAULT_EDITION].Size = 0;
                        }
                        return(info);
                    }
                }
                else if (media.Aspects.ContainsKey(VideoAspect.ASPECT_ID))
                {
                    category = VIDEO_CATEGORY;
                    if (media.IsLiveTvItem() && media is LiveTvMediaItem ltmi)
                    {
                        info = await ParseSlimTvItemAsync(ltmi).ConfigureAwait(false);

                        if (info != null)
                        {
                            info.Metadata[Editions.DEFAULT_EDITION].Live = true;
                            info.Metadata[Editions.DEFAULT_EDITION].Size = 0;
                        }
                        return(info);
                    }
                }
                else if (media.Aspects.ContainsKey(ImageAspect.ASPECT_ID))
                {
                    category = IMAGE_CATEGORY;
                }

                info = await LoadAnalysisAsync(media, category, media.MediaItemId);

                if (info != null)
                {
                    return(info);
                }

                IList <MultipleMediaItemAspect> providerAspects;
                if (!MediaItemAspect.TryGetAspects(media.Aspects, ProviderResourceAspect.Metadata, out providerAspects))
                {
                    return(null);
                }

                IDictionary <int, ResourceLocator> resources = null;
                if (media.HasEditions)
                {
                    IEnumerable <int> praIdxs = null;
                    if (editionId.HasValue)
                    {
                        praIdxs = media.Editions.First(e => e.Key == editionId.Value).Value.PrimaryResourceIndexes;
                    }
                    else
                    {
                        praIdxs = media.Editions.SelectMany(e => e.Value.PrimaryResourceIndexes).Distinct();
                    }

                    resources = providerAspects.Where(pra => praIdxs.Contains(pra.GetAttributeValue <int>(ProviderResourceAspect.ATTR_RESOURCE_INDEX))).
                                ToDictionary(pra => pra.GetAttributeValue <int>(ProviderResourceAspect.ATTR_RESOURCE_INDEX), pra => new ResourceLocator(pra.GetAttributeValue <string>(ProviderResourceAspect.ATTR_SYSTEM_ID), ResourcePath.Deserialize(pra.GetAttributeValue <string>(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH))));
                }
                else
                {
                    resources = providerAspects.Where(pra => pra.GetAttributeValue <int>(ProviderResourceAspect.ATTR_TYPE) == ProviderResourceAspect.TYPE_PRIMARY).
                                ToDictionary(pra => pra.GetAttributeValue <int>(ProviderResourceAspect.ATTR_RESOURCE_INDEX), pra => new ResourceLocator(pra.GetAttributeValue <string>(ProviderResourceAspect.ATTR_SYSTEM_ID), ResourcePath.Deserialize(pra.GetAttributeValue <string>(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH))));
                }

                //Process media resources
                Dictionary <int, Dictionary <int, IResourceAccessor> > editions = new Dictionary <int, Dictionary <int, IResourceAccessor> >();
                foreach (var res in resources)
                {
                    int edition = Editions.DEFAULT_EDITION;
                    if (media.HasEditions)
                    {
                        edition = media.Editions.FirstOrDefault(e => e.Value.PrimaryResourceIndexes.Contains(res.Key)).Value.SetNo;
                    }

                    if (!editions.ContainsKey(edition))
                    {
                        editions.Add(edition, new Dictionary <int, IResourceAccessor>());
                    }
                    IResourceAccessor mia = res.Value.CreateAccessor();

                    if (mia is IFileSystemResourceAccessor fileRes && !fileRes.IsFile)
                    {
                        if (fileRes.ResourceExists("VIDEO_TS"))
                        {
                            using (IFileSystemResourceAccessor fsraVideoTs = fileRes.GetResource("VIDEO_TS"))
                            {
                                if (fsraVideoTs != null && fsraVideoTs.ResourceExists("VIDEO_TS.IFO"))
                                {
                                    //Find all titles and add each of them
                                    var titles = GetDvdTitleFiles(fsraVideoTs);
                                    foreach (var title in titles)
                                    {
                                        int fileNo = 0;
                                        foreach (var file in title.Value)
                                        {
                                            fileNo++;
                                            int titleKey = MetadataContainer.GetDvdResource(res.Key, title.Key, fileNo);
                                            editions[edition].Add(titleKey, file);
                                        }
                                    }
                                }
                            }
                        }
                        else if (fileRes.ResourceExists("BDMV"))
                        {
                            using (IFileSystemResourceAccessor fsraBDMV = fileRes.GetResource("BDMV"))
                            {
                                if (fsraBDMV != null && fsraBDMV.ResourceExists("index.bdmv") && fsraBDMV.ResourceExists("STREAM"))
                                {
                                    using (IFileSystemResourceAccessor fsraStream = fsraBDMV.GetResource("STREAM"))
                                    {
                                        var orderedFileList = fsraStream.GetFiles().Where(f => f.ResourceName.EndsWith(".m2ts", StringComparison.InvariantCultureIgnoreCase)).OrderByDescending(f => f.Size);
                                        //Use the largest file which is probably the main stream
                                        var mainStream = orderedFileList.First();
                                        editions[edition].Add(res.Key, mainStream);
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        editions[edition].Add(res.Key, mia);
                    }
                    mia.Dispose();
                }