/// <summary> /// Returns all files in the given directory. /// </summary> /// <remarks> /// This method simply returns the files files of the given <paramref name="directoryAccessor"/>, filtered /// if <paramref name="showSystemResources"/> is set to <c>true</c>. /// </remarks> /// <param name="directoryAccessor">Directory resource accessor to get all files for.</param> /// <param name="showSystemResources">If set to <c>true</c>, system resources like the virtual drives and directories of the /// <see cref="IResourceMountingService"/> will also be returned, else removed from the result value.</param> /// <returns>Collection of accessors for all files or <c>null</c>, /// if the given <paramref name="directoryAccessor"/> is not a <see cref="IFileSystemResourceAccessor"/>.</returns> public static ICollection <IFileSystemResourceAccessor> GetFiles(IFileSystemResourceAccessor directoryAccessor, bool showSystemResources, bool showChainedDirectories = true) { IResourceMountingService resourceMountingService = ServiceRegistration.Get <IResourceMountingService>(); IFileSystemResourceAccessor chainedResourceAccesor; // Needed in multiple source locations, that's why we declare it here ICollection <IFileSystemResourceAccessor> result = new List <IFileSystemResourceAccessor>(); foreach (IFileSystemResourceAccessor fileAccessor in directoryAccessor.GetFiles()) { if (!showSystemResources && resourceMountingService.IsVirtualResource(fileAccessor.CanonicalLocalResourcePath)) { fileAccessor.Dispose(); continue; } // We try to chain up chained resource providers if (!showChainedDirectories && TryUnfold(fileAccessor, out chainedResourceAccesor)) { if (chainedResourceAccesor.IsFile) { result.Add(chainedResourceAccesor); } else { chainedResourceAccesor.Dispose(); } fileAccessor.Dispose(); } else { result.Add(fileAccessor); } } return(result); }
/// <summary> /// Returns all child directories of the given directory. /// </summary> /// <remarks> /// This will return all native child directories of the given directory together with all virtual child /// directories. The native child directories are taken directly from the given <paramref name="directoryAccessor"/>, /// the virtual child directories are obtained by taking the root directories of each chained resource provider applied /// to the child files of the given directory. /// If, for example, the given <paramref name="directoryAccessor"/> contains a child directory "A" and a child /// archive file "B" which can work as input for an installed archive provider, providing the root directory "C" /// of that archive, this method will return the resource accessors for directories "A" and "C". /// </remarks> /// <param name="directoryAccessor">Directory resource accessor to get all child directories for.</param> /// <param name="showSystemResources">If set to <c>true</c>, system resources like the virtual drives and directories of the /// <see cref="IResourceMountingService"/> will also be returned, else removed from the result value.</param> /// <returns>Collection of directory accessors for all native and virtual child directories or <c>null</c>, /// if the given <paramref name="directoryAccessor"/> does not point to a directory and /// if there is no chained resource provider to unfold the given file.</returns> public static ICollection<IFileSystemResourceAccessor> GetChildDirectories(IFileSystemResourceAccessor directoryAccessor, bool showSystemResources) { IResourceMountingService resourceMountingService = ServiceRegistration.Get<IResourceMountingService>(); IFileSystemResourceAccessor chainedResourceAccesor; // Needed in multiple source locations, that's why we declare it here // If directoryAccessor points to a directory, we return all actual subdirectories and the virtual subdirectories // we can create by using all available ChainedResourceProviders on all contained files. if (!directoryAccessor.IsFile) { ICollection<IFileSystemResourceAccessor> childDirectories = directoryAccessor.GetChildDirectories(); ICollection<IFileSystemResourceAccessor> result = new List<IFileSystemResourceAccessor>(); if (childDirectories != null) // Directories are maybe filtered and then just added foreach (IFileSystemResourceAccessor childDirectoryAccessor in childDirectories) { if (!showSystemResources && resourceMountingService.IsVirtualResource(childDirectoryAccessor.CanonicalLocalResourcePath)) { childDirectoryAccessor.Dispose(); continue; } result.Add(childDirectoryAccessor); } ICollection<IFileSystemResourceAccessor> files = directoryAccessor.GetFiles(); if (files != null) // For files, we try to chain up chained resource providers foreach (IFileSystemResourceAccessor fileAccessor in files) using (fileAccessor) { if (!showSystemResources && resourceMountingService.IsVirtualResource(fileAccessor.CanonicalLocalResourcePath)) continue; if (TryUnfold(fileAccessor, out chainedResourceAccesor)) if (!chainedResourceAccesor.IsFile) result.Add(chainedResourceAccesor); else chainedResourceAccesor.Dispose(); // Simply ignore files because we only want to return directories } return result; } // Try to unfold file resource if (TryUnfold(directoryAccessor, out chainedResourceAccesor)) { if (!chainedResourceAccesor.IsFile) return new List<IFileSystemResourceAccessor>(new IFileSystemResourceAccessor[] {chainedResourceAccesor}); chainedResourceAccesor.Dispose(); return new List<IFileSystemResourceAccessor>(); } return null; }
/// <summary> /// Returns all files in the given directory. /// </summary> /// <remarks> /// This method simply returns the files files of the given <paramref name="directoryAccessor"/>, filtered /// if <paramref name="showSystemResources"/> is set to <c>true</c>. /// </remarks> /// <param name="directoryAccessor">Directory resource accessor to get all files for.</param> /// <param name="showSystemResources">If set to <c>true</c>, system resources like the virtual drives and directories of the /// <see cref="IResourceMountingService"/> will also be returned, else removed from the result value.</param> /// <returns>Collection of accessors for all files or <c>null</c>, /// if the given <paramref name="directoryAccessor"/> is not a <see cref="IFileSystemResourceAccessor"/>.</returns> public static ICollection <IFileSystemResourceAccessor> GetFiles(IFileSystemResourceAccessor directoryAccessor, bool showSystemResources) { IResourceMountingService resourceMountingService = ServiceRegistration.Get <IResourceMountingService>(); ICollection <IFileSystemResourceAccessor> result = new List <IFileSystemResourceAccessor>(); foreach (IFileSystemResourceAccessor fileAccessor in directoryAccessor.GetFiles()) { if (!showSystemResources && resourceMountingService.IsVirtualResource(fileAccessor.CanonicalLocalResourcePath)) { fileAccessor.Dispose(); continue; } result.Add(fileAccessor); } return(result); }
private List <ResourcePath> GetPotentialFanArtFiles(IFileSystemResourceAccessor directoryAccessor) { var result = new List <ResourcePath>(); if (directoryAccessor.IsFile) { return(result); } foreach (var file in directoryAccessor.GetFiles()) { using (file) { var path = file.CanonicalLocalResourcePath; if (IMG_EXTENSIONS.Contains(ResourcePathHelper.GetExtension(path.ToString()))) { result.Add(path); } } } return(result); }
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); }
/// <summary> /// Returns all files in the given directory. /// </summary> /// <remarks> /// This method simply returns the files files of the given <paramref name="directoryAccessor"/>, filtered /// if <paramref name="showSystemResources"/> is set to <c>true</c>. /// </remarks> /// <param name="directoryAccessor">Directory resource accessor to get all files for.</param> /// <param name="showSystemResources">If set to <c>true</c>, system resources like the virtual drives and directories of the /// <see cref="IResourceMountingService"/> will also be returned, else removed from the result value.</param> /// <returns>Collection of accessors for all files or <c>null</c>, /// if the given <paramref name="directoryAccessor"/> is not a <see cref="IFileSystemResourceAccessor"/>.</returns> public static ICollection<IFileSystemResourceAccessor> GetFiles(IFileSystemResourceAccessor directoryAccessor, bool showSystemResources) { IResourceMountingService resourceMountingService = ServiceRegistration.Get<IResourceMountingService>(); ICollection<IFileSystemResourceAccessor> result = new List<IFileSystemResourceAccessor>(); foreach (IFileSystemResourceAccessor fileAccessor in directoryAccessor.GetFiles()) { if (!showSystemResources && resourceMountingService.IsVirtualResource(fileAccessor.CanonicalLocalResourcePath)) { fileAccessor.Dispose(); continue; } result.Add(fileAccessor); } return result; }
public override async Task <AsyncResult <ContentDirectoryMessaging.MediaItemChangeType> > ProcessAsync(MediaItem mediaItem) { IContentDirectory cd = ServiceRegistration.Get <IServerConnectionManager>().ContentDirectory; bool removeFromML = IsManagedByMediaLibrary(mediaItem) && cd != null; var falseResult = new AsyncResult <ContentDirectoryMessaging.MediaItemChangeType>(false, ContentDirectoryMessaging.MediaItemChangeType.None); // Support multi-resource media items and secondary resources IList <MultipleMediaItemAspect> providerAspects; if (!MediaItemAspect.TryGetAspects(mediaItem.Aspects, ProviderResourceAspect.Metadata, out providerAspects)) { return(falseResult); } foreach (MultipleMediaItemAspect providerAspect in providerAspects) { string systemId = (string)providerAspect[ProviderResourceAspect.ATTR_SYSTEM_ID]; string resourceAccessorPath = (string)providerAspect[ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH]; var rl = new ResourceLocator(systemId, ResourcePath.Deserialize(resourceAccessorPath)); using (var ra = rl.CreateAccessor()) { var rad = ra as IResourceDeletor; if (rad == null) { return(falseResult); } // First try to delete the file from storage. if (!rad.Delete()) { return(falseResult); } // If the MediaItem was loaded from ML, remove it there as well. if (removeFromML) { await cd.DeleteMediaItemOrPathAsync(rl.NativeSystemId, rl.NativeResourcePath, true); } } } // Check for special cases here: // 1) Recordings have an additional .xml attached // 2) Deleting files could lead to empty folders that should be also removed foreach (DeleteRule rule in _defaultRules.Where(r => r.IsEnabled)) { if (mediaItem.Aspects.ContainsKey(rule.HasAspectGuid)) { var tsPath = mediaItem.GetResourceLocator().NativeResourcePath.ToString(); foreach (string otherExtension in rule.DeleteOtherExtensions) { string otherFilePath = ProviderPathHelper.ChangeExtension(tsPath, otherExtension); IResourceAccessor ra; if (!ResourcePath.Deserialize(otherFilePath).TryCreateLocalResourceAccessor(out ra)) { continue; } // Delete other file. We do not check here for existance of file, the Delete needs to handle this. using (ra) { var rad = ra as IResourceDeletor; rad?.Delete(); } } if (rule.DeleteEmptyFolders) { var folderPath = ProviderPathHelper.GetDirectoryName(tsPath); IResourceAccessor ra; if (!ResourcePath.Deserialize(folderPath).TryCreateLocalResourceAccessor(out ra)) { continue; } // Delete folder if empty using (ra) { IFileSystemResourceAccessor fsra = ra as IFileSystemResourceAccessor; if (fsra != null) { var isEmpty = fsra.GetFiles().Count == 0 && fsra.GetChildDirectories().Count == 0; if (isEmpty) { var rad = ra as IResourceDeletor; rad?.Delete(); } } } } } } return(new AsyncResult <ContentDirectoryMessaging.MediaItemChangeType>(true, ContentDirectoryMessaging.MediaItemChangeType.Deleted)); }
/// <summary> /// Returns a list of ResourcePaths to all potential FanArt files in a given directory /// </summary> /// <param name="directoryAccessor">ResourceAccessor pointing to the directory where FanArt files should be searched</param> /// <returns>List of ResourcePaths to potential FanArt files</returns> private List<ResourcePath> GetPotentialFanArtFiles(IFileSystemResourceAccessor directoryAccessor) { var result = new List<ResourcePath>(); if(directoryAccessor.IsFile) return result; foreach (var file in directoryAccessor.GetFiles()) using (file) { var path = file.CanonicalLocalResourcePath; if(EXTENSIONS.Contains(ResourcePathHelper.GetExtension(path.ToString()))) result.Add(path); } return result; }
/// <summary> /// Returns all child directories of the given directory. /// </summary> /// <remarks> /// This will return all native child directories of the given directory together with all virtual child /// directories. The native child directories are taken directly from the given <paramref name="directoryAccessor"/>, /// the virtual child directories are obtained by taking the root directories of each chained resource provider applied /// to the child files of the given directory. /// If, for example, the given <paramref name="directoryAccessor"/> contains a child directory "A" and a child /// archive file "B" which can work as input for an installed archive provider, providing the root directory "C" /// of that archive, this method will return the resource accessors for directories "A" and "C". /// </remarks> /// <param name="directoryAccessor">Directory resource accessor to get all child directories for.</param> /// <param name="showSystemResources">If set to <c>true</c>, system resources like the virtual drives and directories of the /// <see cref="IResourceMountingService"/> will also be returned, else removed from the result value.</param> /// <returns>Collection of directory accessors for all native and virtual child directories or <c>null</c>, /// if the given <paramref name="directoryAccessor"/> is not a <see cref="IFileSystemResourceAccessor"/> and /// if there is no chained resource provider to unfold the given directory.</returns> public static ICollection <IFileSystemResourceAccessor> GetChildDirectories(IFileSystemResourceAccessor directoryAccessor, bool showSystemResources) { IResourceMountingService resourceMountingService = ServiceRegistration.Get <IResourceMountingService>(); IFileSystemResourceAccessor chainedResourceAccesor; // Needed in multiple source locations, that's why we declare it here ICollection <IFileSystemResourceAccessor> childDirectories = directoryAccessor.GetChildDirectories(); ICollection <IFileSystemResourceAccessor> result = new List <IFileSystemResourceAccessor>(); if (childDirectories != null) { // Directories are maybe filtered and then just added foreach (IFileSystemResourceAccessor childDirectoryAccessor in childDirectories) { if (!showSystemResources && resourceMountingService.IsVirtualResource(childDirectoryAccessor.CanonicalLocalResourcePath)) { childDirectoryAccessor.Dispose(); continue; } result.Add(childDirectoryAccessor); } } ICollection <IFileSystemResourceAccessor> files = directoryAccessor.GetFiles(); if (files != null) { // For files, we try to chain up chained resource providers foreach (IFileSystemResourceAccessor fileAccessor in files) { using (fileAccessor) { if (!showSystemResources && resourceMountingService.IsVirtualResource(fileAccessor.CanonicalLocalResourcePath)) { continue; } if (TryUnfold(fileAccessor, out chainedResourceAccesor)) { if (!chainedResourceAccesor.IsFile) { result.Add(chainedResourceAccesor); } else { chainedResourceAccesor.Dispose(); } } // Simply ignore files because we only want to return directories } } } if (result.Count > 0) { return(result); } // Try to unfold simple resource if (TryUnfold(directoryAccessor, out chainedResourceAccesor)) { if (!chainedResourceAccesor.IsFile) { return(new List <IFileSystemResourceAccessor>(new IFileSystemResourceAccessor[] { chainedResourceAccesor })); } chainedResourceAccesor.Dispose(); } 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) { 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> /// Returns all child directories of the given directory. /// </summary> /// <remarks> /// This will return all native child directories of the given directory together with all virtual child /// directories. The native child directories are taken directly from the given <paramref name="directoryAccessor"/>, /// the virtual child directories are obtained by taking the root directories of each chained resource provider applied /// to the child files of the given directory. /// If, for example, the given <paramref name="directoryAccessor"/> contains a child directory "A" and a child /// archive file "B" which can work as input for an installed archive provider, providing the root directory "C" /// of that archive, this method will return the resource accessors for directories "A" and "C". /// </remarks> /// <param name="directoryAccessor">Directory resource accessor to get all child directories for.</param> /// <param name="showSystemResources">If set to <c>true</c>, system resources like the virtual drives and directories of the /// <see cref="IResourceMountingService"/> will also be returned, else removed from the result value.</param> /// <returns>Collection of directory accessors for all native and virtual child directories or <c>null</c>, /// if the given <paramref name="directoryAccessor"/> is not a <see cref="IFileSystemResourceAccessor"/> and /// if there is no chained resource provider to unfold the given directory.</returns> public static ICollection <IFileSystemResourceAccessor> GetChildDirectories(IResourceAccessor directoryAccessor, bool showSystemResources) { IResourceMountingService resourceMountingService = ServiceRegistration.Get <IResourceMountingService>(); IResourceAccessor chainedResourceAccesor; // Needed in multiple source locations, that's why we declare it here if (directoryAccessor is IFileSystemResourceAccessor) { IFileSystemResourceAccessor dirFsra = (IFileSystemResourceAccessor)directoryAccessor; ICollection <IFileSystemResourceAccessor> childDirectories = dirFsra.GetChildDirectories(); ICollection <IFileSystemResourceAccessor> result = new List <IFileSystemResourceAccessor>(); if (childDirectories != null) { // Directories are maybe filtered and then just added foreach (IFileSystemResourceAccessor childDirectoryAccessor in childDirectories) { if (!showSystemResources && resourceMountingService.IsVirtualResource(childDirectoryAccessor.CanonicalLocalResourcePath)) { childDirectoryAccessor.Dispose(); continue; } result.Add(childDirectoryAccessor); } } ICollection <IFileSystemResourceAccessor> files = dirFsra.GetFiles(); if (files != null) { // For files, we try to chain up chained resource providers foreach (IFileSystemResourceAccessor fileAccessor in files) { if (!showSystemResources && resourceMountingService.IsVirtualResource(fileAccessor.CanonicalLocalResourcePath)) { fileAccessor.Dispose(); continue; } if (TryUnfold(fileAccessor, out chainedResourceAccesor)) { IFileSystemResourceAccessor chainedFsra = chainedResourceAccesor as IFileSystemResourceAccessor; if (chainedFsra != null) { result.Add(chainedFsra); } else { chainedResourceAccesor.Dispose(); } } else { fileAccessor.Dispose(); } } } return(result); } // Try to unfold simple resource IResourceAccessor dra = directoryAccessor.Clone(); try { if (TryUnfold(dra, out chainedResourceAccesor)) { IFileSystemResourceAccessor chainedFsra = chainedResourceAccesor as IFileSystemResourceAccessor; if (chainedFsra != null) { return(new List <IFileSystemResourceAccessor>(new IFileSystemResourceAccessor[] { chainedFsra })); } chainedResourceAccesor.Dispose(); } else { dra.Dispose(); } } catch { dra.Dispose(); throw; } return(null); }
/// <summary> /// Tries to read a valid IMDB id from additional .nfo or .txt files. /// </summary> /// <param name="fsra">FileSystemResourceAccessor</param> /// <param name="imdbId">Returns a valid IMDB or <c>null</c></param> /// <returns>true if matched</returns> public static bool TryMatchImdbId(IFileSystemResourceAccessor fsra, out string imdbId) { imdbId = null; if (fsra == null) { return(false); } // First try to find a nfo file that has the same name as our main movie. if (fsra.IsFile) { foreach (string extension in NFO_EXTENSIONS) { string metaFilePath = ResourcePathHelper.ChangeExtension(fsra.CanonicalLocalResourcePath.ToString(), extension); if (TryRead(metaFilePath, out imdbId)) { return(true); } } } // Prepare a list of paths to check: for chained resource path we will also check relative parent paths (like for DVD-ISO files) List <string> pathsToCheck = new List <string> { fsra.CanonicalLocalResourcePath.ToString() }; if (fsra.CanonicalLocalResourcePath.PathSegments.Count > 1) { string canocialPath = fsra.CanonicalLocalResourcePath.ToString(); pathsToCheck.Add(canocialPath.Substring(0, canocialPath.LastIndexOf('>'))); } // Then test for special named files, like "movie.nfo" foreach (string path in pathsToCheck) { foreach (string fileName in NFO_FILENAMES) { string metaFilePath = ResourcePathHelper.GetDirectoryName(path); metaFilePath = ResourcePathHelper.Combine(metaFilePath, fileName); if (TryRead(metaFilePath, out imdbId)) { return(true); } } } // Now check siblings of movie for any IMDB id containing filename. IFileSystemResourceAccessor directoryFsra = null; if (fsra.IsDirectory) { directoryFsra = fsra.Clone() as IFileSystemResourceAccessor; } if (fsra.IsFile) { directoryFsra = GetContainingDirectory(fsra); } if (directoryFsra == null) { return(false); } using (directoryFsra) foreach (IFileSystemResourceAccessor file in directoryFsra.GetFiles()) { using (file) if (ImdbIdMatcher.TryMatchImdbId(file.ResourceName, out imdbId)) { return(true); } } return(false); }
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(); }