public override void OnActionExecuting(ActionExecutingContext filterContext) { var files = filterContext.HttpContext.Request.Files; foreach (var postedFile in files.Cast <string>().Select(file => files[file]).Where(postedFile => postedFile != null && postedFile.ContentLength != 0)) { if (_justImage) { if (!IsImageFile(postedFile)) { return; } } if (!CanUpload(postedFile.FileName)) { throw new InvalidOperationException( string.Format("You are not allowed to upload {0} file. Please upload only these files: {1}.", Path.GetFileName(postedFile.FileName), _extensionsWhiteList)); } var data = new byte[256]; postedFile.InputStream.Read(data, 0, 256); MimeTypeDetector.IsAllowMimeType(data, _justImage); } base.OnActionExecuting(filterContext); }
public virtual ActionResult FileUpload(HttpPostedFileBase excelFile) { try { var data = new byte[256]; excelFile.InputStream.Read(data, 0, 256); var detector = new MimeTypeDetector(); var mimeType = detector.GetMimeType(data); //if (CheckWhiteList(mimeType) == false) //{ // ModelState.AddModelError("InvalidFileContent", "فایل بارگزاری شده مورد پذیرش نیست."); //} //return View(); string savedFileName = "~/App_Data/"; CreateFolderIfNeeded(savedFileName); string filePath = Path.Combine(savedFileName, Path.GetFileName(excelFile.FileName)); var str = Server.MapPath(filePath); excelFile.SaveAs(Server.MapPath(filePath)); SaveFileToDatabase(filePath); return(Json(new { isError = false, Msg = "عمل انتقال به درستی انجام شد" })); //return View("Index"); } catch (Exception ex) { return(Json(new { isError = true, Msg = "خطا در انتقال کاربران" })); } }
public static async Task <bool> ProcessAsync(IOwinContext context, string path) { if (path == null) { if (context.Request.Uri.Segments.Length >= 3) { path = string.Join("", context.Request.Uri.Segments.Skip(2)); } } if (path == null) { throw new BadRequestException("GetHtmlResource: path is null"); } string skinPath = string.IsNullOrEmpty(MP2Extended.Settings.SkinName) ? "Default" : MP2Extended.Settings.SkinName; string resourceBasePath = Path.Combine(_localPath, "Skins", skinPath); string resourcePath = Path.GetFullPath(Path.Combine(resourceBasePath, path)); if (!File.Exists(resourcePath)) { resourceBasePath = Path.Combine(_appDataPath, "Skins", skinPath); resourcePath = Path.GetFullPath(Path.Combine(resourceBasePath, path)); } if (!resourcePath.StartsWith(resourceBasePath)) { throw new BadRequestException(string.Format("GetHtmlResource: Outside home dir! Requested Path: {0}", resourcePath)); } if (!File.Exists(resourcePath)) { throw new BadRequestException(string.Format("GetHtmlResource: File doesn't exist! Requested Path: {0}", resourcePath)); } Logger.Debug("GetHtmlResource: Serving file: {0}", resourcePath); // Content bool onlyHeaders = context.Request.Method == "HEAD"; context.Response.ContentType = MimeTypeDetector.GetMimeTypeFromExtension(Path.GetFileName(resourcePath)); Stream resourceStream = File.OpenRead(resourcePath); await SendWholeFileAsync(context, resourceStream, onlyHeaders); resourceStream.Close(); return(true); }
protected string GuessMimeType(Stream resourceStream, string fileName) { string mimeType = MimeTypeDetector.GetMimeType(resourceStream); resourceStream.Seek(0, SeekOrigin.Begin); if (mimeType != null) { return(mimeType); } string extension = GetFileExtension(fileName); string contentType; if (extension != null && _defaultMimeTypes.TryGetValue(extension, out contentType)) { return(contentType); } return(DEFAULT_MIME_TYPE); }
public void GetFile(string entitySchemaUId, string fileId) { using (var memoryStream = new MemoryStream()) { SetOutgoingResponseContentType(); IFileUploadInfo fileInfo = FileRepository.LoadFile(new Guid(entitySchemaUId), new Guid(fileId), new BinaryWriter(memoryStream)); if (fileInfo == null) { return; } SetOutgoingResponseContentLength(Convert.ToInt32(fileInfo.TotalFileLength)); string contentDisposition = GetResponseContentDisposition(fileInfo.FileName); CurrentContext.Response.AddHeader("Content-Disposition", contentDisposition); MimeTypeResult mimeTypeResult = MimeTypeDetector.GetMimeType(fileInfo.FileName); CurrentContext.Response.ContentType = mimeTypeResult.HasError ? "application/octet-stream" : mimeTypeResult.Type; memoryStream.Flush(); memoryStream.WriteTo(CurrentContext.Response.OutputStream); } }
public static string GetFileMime(ILocalFsResourceAccessor lfsra, string defaultMime = null) { // Impersonation using (ServiceRegistration.Get <IImpersonationService>().CheckImpersonationFor(lfsra.CanonicalLocalResourcePath)) { FileStream raf = null; try { raf = File.Open(lfsra.LocalFileSystemPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); return(MimeTypeDetector.GetMimeType(raf)); } catch { return(MimeTypeDetector.GetMimeTypeFromRegistry(lfsra.LocalFileSystemPath)); } finally { if (raf != null) { raf.Close(); } } } }
internal bool DoImportAttachment(Card card, string filePath, bool displaySizeWarning) { try { if (displaySizeWarning && new System.IO.FileInfo(filePath).Length > LargeFileSizeLimit) { if (MessageBox.Show( this, Language.Get("LargeAttachment", "The selected file is large. Attached files should generally be small files.\nUsing large files will increase disk and memory usage.\n\nContinue?"), this.ProgramName, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) == DialogResult.No) { return(false); } } UseWaitCursor = true; card.Attachment = new AttachmentFile(Path.GetFileName(filePath), MimeTypeDetector.DetectMime(filePath), File.ReadAllBytes(filePath)); return(true); } catch (IOException) { MessageBox.Show( this, Language.Get("CannotImportAttachment", "An error occurred while importing the attachment. Make sure you have access to the file you are trying to import."), this.ProgramName, MessageBoxButtons.OK, MessageBoxIcon.Hand); return(false); } finally { UseWaitCursor = false; } }
public bool TryExtractMetadata(IResourceAccessor mediaItemAccessor, IDictionary <Guid, MediaItemAspect> extractedAspectData, bool forceQuickMode) { string fileName = mediaItemAccessor.ResourceName; if (!HasImageExtension(fileName)) { return(false); } MediaItemAspect mediaAspect = MediaItemAspect.GetOrCreateAspect(extractedAspectData, MediaAspect.Metadata); MediaItemAspect imageAspect = MediaItemAspect.GetOrCreateAspect(extractedAspectData, ImageAspect.Metadata); MediaItemAspect thumbnailSmallAspect = MediaItemAspect.GetOrCreateAspect(extractedAspectData, ThumbnailSmallAspect.Metadata); MediaItemAspect thumbnailLargeAspect = MediaItemAspect.GetOrCreateAspect(extractedAspectData, ThumbnailLargeAspect.Metadata); try { if (!(mediaItemAccessor is IFileSystemResourceAccessor)) { return(false); } IFileSystemResourceAccessor fsra = mediaItemAccessor as IFileSystemResourceAccessor; // Open a stream for media item to detect mimeType. using (Stream mediaStream = fsra.OpenRead()) { string mimeType = MimeTypeDetector.GetMimeType(mediaStream); if (mimeType != null) { mediaAspect.SetAttribute(MediaAspect.ATTR_MIME_TYPE, mimeType); } } // Extract EXIF information from media item. using (ExifMetaInfo.ExifMetaInfo exif = new ExifMetaInfo.ExifMetaInfo(fsra)) { mediaAspect.SetAttribute(MediaAspect.ATTR_TITLE, ProviderPathHelper.GetFileNameWithoutExtension(fileName)); mediaAspect.SetAttribute(MediaAspect.ATTR_RECORDINGTIME, exif.OriginalDate != DateTime.MinValue ? exif.OriginalDate : fsra.LastChanged); mediaAspect.SetAttribute(MediaAspect.ATTR_COMMENT, StringUtils.TrimToNull(exif.ImageDescription)); if (exif.PixXDim.HasValue) { imageAspect.SetAttribute(ImageAspect.ATTR_WIDTH, (int)exif.PixXDim); } if (exif.PixYDim.HasValue) { imageAspect.SetAttribute(ImageAspect.ATTR_HEIGHT, (int)exif.PixYDim); } imageAspect.SetAttribute(ImageAspect.ATTR_MAKE, StringUtils.TrimToNull(exif.EquipMake)); imageAspect.SetAttribute(ImageAspect.ATTR_MODEL, StringUtils.TrimToNull(exif.EquipModel)); if (exif.ExposureBias.HasValue) { imageAspect.SetAttribute(ImageAspect.ATTR_EXPOSURE_BIAS, ((double)exif.ExposureBias).ToString()); } imageAspect.SetAttribute(ImageAspect.ATTR_EXPOSURE_TIME, exif.ExposureTime); imageAspect.SetAttribute(ImageAspect.ATTR_FLASH_MODE, StringUtils.TrimToNull(exif.FlashMode)); if (exif.FNumber.HasValue) { imageAspect.SetAttribute(ImageAspect.ATTR_FNUMBER, string.Format("F {0}", (double)exif.FNumber)); } imageAspect.SetAttribute(ImageAspect.ATTR_ISO_SPEED, StringUtils.TrimToNull(exif.ISOSpeed)); imageAspect.SetAttribute(ImageAspect.ATTR_ORIENTATION, (Int32)(exif.OrientationType ?? 0)); imageAspect.SetAttribute(ImageAspect.ATTR_METERING_MODE, exif.MeteringMode.ToString()); if (exif.Latitude.HasValue && exif.Longitude.HasValue) { imageAspect.SetAttribute(ImageAspect.ATTR_LATITUDE, exif.Latitude); imageAspect.SetAttribute(ImageAspect.ATTR_LONGITUDE, exif.Longitude); LocationInfo locationInfo; if (!forceQuickMode && GeoLocationMatcher.Instance.TryLookup(exif.Latitude.Value, exif.Longitude.Value, out locationInfo)) { imageAspect.SetAttribute(ImageAspect.ATTR_CITY, locationInfo.City); imageAspect.SetAttribute(ImageAspect.ATTR_STATE, locationInfo.State); imageAspect.SetAttribute(ImageAspect.ATTR_COUNTRY, locationInfo.Country); } } using (ILocalFsResourceAccessor lfsra = StreamedResourceToLocalFsAccessBridge.GetLocalFsResourceAccessor((IFileSystemResourceAccessor)fsra.Clone())) { string localFsResourcePath = lfsra.LocalFileSystemPath; if (localFsResourcePath != null) { // In quick mode only allow thumbs taken from cache. bool cachedOnly = forceQuickMode; // Thumbnail extraction IThumbnailGenerator generator = ServiceRegistration.Get <IThumbnailGenerator>(); byte[] thumbData; ImageType imageType; if (generator.GetThumbnail(localFsResourcePath, 96, 96, cachedOnly, out thumbData, out imageType)) { thumbnailSmallAspect.SetAttribute(ThumbnailSmallAspect.ATTR_THUMBNAIL, thumbData); } if (generator.GetThumbnail(localFsResourcePath, 256, 256, cachedOnly, out thumbData, out imageType)) { thumbnailLargeAspect.SetAttribute(ThumbnailLargeAspect.ATTR_THUMBNAIL, thumbData); } } } } return(true); } catch (Exception e) { // Only log at the info level here - And simply return false. This makes the importer know that we // couldn't perform our task here. ServiceRegistration.Get <ILogger>().Info("ImageMetadataExtractor: Exception reading resource '{0}' (Text: '{1}')", mediaItemAccessor.CanonicalLocalResourcePath, e.Message); } return(false); }
/// <summary> /// Asynchronously tries to extract episode metadata for the given <param name="mediaItemAccessor"></param> /// </summary> /// <param name="mediaItemAccessor">Points to the resource for which we try to extract metadata</param> /// <param name="extractedAspectData">Dictionary of <see cref="MediaItemAspect"/>s with the extracted metadata</param> /// <param name="forceQuickMode">If <c>true</c>, nothing is downloaded from the internet</param> /// <returns><c>true</c> if metadata was found and stored into <param name="extractedAspectData"></param>, else <c>false</c></returns> private async Task <bool> TryExtractEpsiodeMetadataAsync(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData, bool forceQuickMode) { // Get a unique number for this call to TryExtractMetadataAsync. We use this to make reading the debug log easier. // This MetadataExtractor is called in parallel for multiple MediaItems so that the respective debug log entries // for one call are not contained one after another in debug log. We therefore prepend this number before every log entry. var miNumber = Interlocked.Increment(ref _lastMediaItemNumber); bool isStub = extractedAspectData.ContainsKey(StubAspect.ASPECT_ID); try { _debugLogger.Info("[#{0}]: Start extracting metadata for resource '{1}' (forceQuickMode: {2})", miNumber, mediaItemAccessor, forceQuickMode); // This MetadataExtractor only works for MediaItems accessible by an IFileSystemResourceAccessor. // Otherwise it is not possible to find a nfo-file in the MediaItem's directory or parent directory. if (!(mediaItemAccessor is IFileSystemResourceAccessor)) { _debugLogger.Info("[#{0}]: Cannot extract metadata; mediaItemAccessor is not an IFileSystemResourceAccessor", miNumber); return(false); } // We only extract metadata with this MetadataExtractor, if another MetadataExtractor that was applied before // has identified this MediaItem as a video and therefore added a VideoAspect. if (!extractedAspectData.ContainsKey(VideoAspect.ASPECT_ID)) { _debugLogger.Info("[#{0}]: Cannot extract metadata; this resource is not a video", miNumber); return(false); } // Here we try to find an IFileSystemResourceAccessor pointing to the episode nfo-file. // If we don't find one, we cannot extract any metadata. IFileSystemResourceAccessor episodeNfoFsra; NfoSeriesEpisodeReader episodeNfoReader = null; bool episodeDetailsFound = false; if (TryGetEpisodeNfoSResourceAccessor(miNumber, mediaItemAccessor as IFileSystemResourceAccessor, out episodeNfoFsra)) { episodeDetailsFound = true; // Now we (asynchronously) extract the metadata into a stub object. // If no metadata was found, nothing can be stored in the MediaItemAspects. episodeNfoReader = new NfoSeriesEpisodeReader(_debugLogger, miNumber, forceQuickMode, isStub, _httpClient, _settings); using (episodeNfoFsra) { if (!await episodeNfoReader.TryReadMetadataAsync(episodeNfoFsra).ConfigureAwait(false)) { _debugLogger.Warn("[#{0}]: No valid metadata found in episode nfo-file", miNumber); return(false); } } } // Then we try to find an IFileSystemResourceAccessor pointing to the series nfo-file. IFileSystemResourceAccessor seriesNfoFsra; if (TryGetSeriesNfoSResourceAccessor(miNumber, mediaItemAccessor as IFileSystemResourceAccessor, out seriesNfoFsra)) { // If we found one, we (asynchronously) extract the metadata into a stub object and, if metadata was found, // we store it into the episodeNfoReader so that the latter can store metadata from series and episode level into the MediaItemAspects. var seriesNfoReader = new NfoSeriesReader(_debugLogger, miNumber, forceQuickMode, !episodeDetailsFound, isStub, _httpClient, _settings); using (seriesNfoFsra) { if (await seriesNfoReader.TryReadMetadataAsync(seriesNfoFsra).ConfigureAwait(false)) { //Check reimport if (extractedAspectData.ContainsKey(ReimportAspect.ASPECT_ID)) { SeriesInfo reimport = new SeriesInfo(); reimport.FromMetadata(extractedAspectData); if (!VerifySeriesReimport(seriesNfoReader, reimport)) { ServiceRegistration.Get <ILogger>().Info("NfoSeriesMetadataExtractor: Nfo series metadata from resource '{0}' ignored because it does not match reimport {1}", mediaItemAccessor, reimport); return(false); } } Stubs.SeriesStub series = seriesNfoReader.GetSeriesStubs().FirstOrDefault(); // Check if episode should be found if (isStub || !episodeDetailsFound) { if (series != null && series.Episodes?.Count > 0) { List <Stubs.SeriesEpisodeStub> episodeStubs = null; if (extractedAspectData.ContainsKey(EpisodeAspect.ASPECT_ID)) { int? seasonNo = 0; IEnumerable episodes; if (MediaItemAspect.TryGetAttribute(extractedAspectData, EpisodeAspect.ATTR_SEASON, out seasonNo) && MediaItemAspect.TryGetAttribute(extractedAspectData, EpisodeAspect.ATTR_EPISODE, out episodes)) { List <int> episodeNos = new List <int>(); CollectionUtils.AddAll(episodeNos, episodes.Cast <int>()); if (seasonNo.HasValue && episodeNos.Count > 0) { episodeStubs = series.Episodes.Where(e => e.Season == seasonNo.Value && episodeNos.Intersect(e.Episodes).Any()).ToList(); } } } else { string title = null; if (MediaItemAspect.TryGetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, out title)) { Regex regex = new Regex(@"(?<series>[^\\]+).S(?<seasonnum>\d+)[\s|\.|\-|_]{0,1}E((?<episodenum>\d+)_?)+(?<episode>.*)"); Match match = regex.Match(title); if (match.Success && match.Groups["seasonnum"].Length > 0 && match.Groups["episodenum"].Length > 0) { episodeStubs = series.Episodes.Where(e => e.Season == Convert.ToInt32(match.Groups["seasonnum"].Value) && e.Episodes.Contains(Convert.ToInt32(match.Groups["episodenum"].Value))).ToList(); } } } if (episodeStubs != null && episodeStubs.Count > 0) { Stubs.SeriesEpisodeStub mergedEpisode = null; if (isStub) { if (episodeStubs.Count == 1) { mergedEpisode = episodeStubs.First(); } else { Stubs.SeriesEpisodeStub episode = episodeStubs.First(); mergedEpisode = new Stubs.SeriesEpisodeStub(); mergedEpisode.Actors = episode.Actors; mergedEpisode.Aired = episode.Aired; mergedEpisode.Credits = episode.Credits; mergedEpisode.Director = episode.Director; mergedEpisode.DisplayEpisode = episode.DisplayEpisode; mergedEpisode.DisplaySeason = episode.DisplaySeason; mergedEpisode.EpBookmark = episode.EpBookmark; mergedEpisode.FileInfo = episode.FileInfo; mergedEpisode.LastPlayed = episode.LastPlayed; mergedEpisode.Mpaa = episode.Mpaa; mergedEpisode.PlayCount = episode.PlayCount; mergedEpisode.Premiered = episode.Premiered; mergedEpisode.ProductionCodeNumber = episode.ProductionCodeNumber; mergedEpisode.ResumePosition = episode.ResumePosition; mergedEpisode.Season = episode.Season; mergedEpisode.Sets = episode.Sets; mergedEpisode.ShowTitle = episode.ShowTitle; mergedEpisode.Status = episode.Status; mergedEpisode.Studio = episode.Studio; mergedEpisode.Tagline = episode.Tagline; mergedEpisode.Thumb = episode.Thumb; mergedEpisode.Top250 = episode.Top250; mergedEpisode.Trailer = episode.Trailer; mergedEpisode.Watched = episode.Watched; mergedEpisode.Year = episode.Year; mergedEpisode.Id = episode.Id; mergedEpisode.UniqueId = episode.UniqueId; //Merge episodes mergedEpisode.Title = string.Join("; ", episodeStubs.OrderBy(e => e.Episodes.First()).Select(e => e.Title).ToArray()); mergedEpisode.Rating = episodeStubs.Where(e => e.Rating.HasValue).Sum(e => e.Rating.Value) / episodeStubs.Where(e => e.Rating.HasValue).Count(); // Average rating mergedEpisode.Votes = episodeStubs.Where(e => e.Votes.HasValue).Sum(e => e.Votes.Value) / episodeStubs.Where(e => e.Votes.HasValue).Count(); mergedEpisode.Runtime = TimeSpan.FromSeconds(episodeStubs.Where(e => e.Runtime.HasValue).Sum(e => e.Runtime.Value.TotalSeconds)); mergedEpisode.Plot = string.Join("\r\n\r\n", episodeStubs.OrderBy(e => e.Episodes.First()). Select(e => string.Format("{0,02}) {1}", e.Episodes.First(), e.Plot)).ToArray()); mergedEpisode.Outline = string.Join("\r\n\r\n", episodeStubs.OrderBy(e => e.Episodes.First()). Select(e => string.Format("{0,02}) {1}", e.Episodes.First(), e.Outline)).ToArray()); mergedEpisode.Episodes = new HashSet <int>(episodeStubs.SelectMany(x => x.Episodes).ToList()); mergedEpisode.DvdEpisodes = new HashSet <decimal>(episodeStubs.SelectMany(x => x.DvdEpisodes).ToList()); } IList <MultipleMediaItemAspect> providerResourceAspects; if (MediaItemAspect.TryGetAspects(extractedAspectData, ProviderResourceAspect.Metadata, out providerResourceAspects)) { MultipleMediaItemAspect providerResourceAspect = providerResourceAspects.First(pa => pa.GetAttributeValue <int>(ProviderResourceAspect.ATTR_TYPE) == ProviderResourceAspect.TYPE_STUB); string mime = null; if (mergedEpisode.FileInfo != null && mergedEpisode.FileInfo.Count > 0) { mime = MimeTypeDetector.GetMimeTypeFromExtension("file" + mergedEpisode.FileInfo.First().Container); } if (mime != null) { providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, mime); } } MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, string.Format("{0} S{1:00}{2} {3}", series.ShowTitle, mergedEpisode.Season, mergedEpisode.Episodes.Select(e => "E" + e.ToString("00")), mergedEpisode.Title)); MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_SORT_TITLE, BaseInfo.GetSortTitle(mergedEpisode.Title)); MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_RECORDINGTIME, mergedEpisode.Premiered.HasValue ? mergedEpisode.Premiered.Value : mergedEpisode.Year.HasValue ? mergedEpisode.Year.Value : (DateTime?)null); if (mergedEpisode.FileInfo != null && mergedEpisode.FileInfo.Count > 0) { extractedAspectData.Remove(VideoStreamAspect.ASPECT_ID); extractedAspectData.Remove(VideoAudioStreamAspect.ASPECT_ID); extractedAspectData.Remove(SubtitleAspect.ASPECT_ID); StubParser.ParseFileInfo(extractedAspectData, mergedEpisode.FileInfo, mergedEpisode.Title); } } episodeNfoReader = new NfoSeriesEpisodeReader(_debugLogger, miNumber, forceQuickMode, isStub, _httpClient, _settings); episodeNfoReader.SetEpisodeStubs(new List <Stubs.SeriesEpisodeStub> { mergedEpisode }); } } } if (series != null) { if (episodeNfoReader != null) { episodeNfoReader.SetSeriesStubs(new List <Stubs.SeriesStub> { series }); // Then we store the found metadata in the MediaItemAspects. If we only found metadata that is // not (yet) supported by our MediaItemAspects, this MetadataExtractor returns false. if (!episodeNfoReader.TryWriteMetadata(extractedAspectData)) { _debugLogger.Warn("[#{0}]: No metadata was written into MediaItemsAspects", miNumber); return(false); } } else { EpisodeInfo episode = new EpisodeInfo(); if (series.Id.HasValue) { episode.SeriesTvdbId = series.Id.Value; } if (series.Premiered.HasValue) { episode.SeriesFirstAired = series.Premiered.Value; } episode.SeriesName = series.ShowTitle; episode.SetMetadata(extractedAspectData); } } } else { _debugLogger.Warn("[#{0}]: No valid metadata found in series nfo-file", miNumber); } } } else if (episodeNfoReader != null) { //Check reimport if (extractedAspectData.ContainsKey(ReimportAspect.ASPECT_ID)) { EpisodeInfo reimport = new EpisodeInfo(); reimport.FromMetadata(extractedAspectData); if (!VerifyEpisodeReimport(episodeNfoReader, reimport)) { ServiceRegistration.Get <ILogger>().Info("NfoSeriesMetadataExtractor: Nfo episode metadata from resource '{0}' ignored because it does not match reimport {1}", mediaItemAccessor, reimport); return(false); } } // Then we store the found metadata in the MediaItemAspects. If we only found metadata that is // not (yet) supported by our MediaItemAspects, this MetadataExtractor returns false. if (!episodeNfoReader.TryWriteMetadata(extractedAspectData)) { _debugLogger.Warn("[#{0}]: No metadata was written into MediaItemsAspects", miNumber); return(false); } } _debugLogger.Info("[#{0}]: Successfully finished extracting metadata", miNumber); ServiceRegistration.Get <ILogger>().Debug("NfoSeriesMetadataExtractor: Assigned nfo episode metadata for resource '{0}'", mediaItemAccessor); return(true); } catch (Exception e) { ServiceRegistration.Get <ILogger>().Warn("NfoSeriesMetadataExtractor: Exception while extracting metadata for resource '{0}'; enable debug logging for more details.", mediaItemAccessor); _debugLogger.Error("[#{0}]: Exception while extracting metadata", e, miNumber); return(false); } }
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); }
public bool TryExtractMetadata(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData, bool importOnly, bool forceQuickMode) { string fileName = mediaItemAccessor.ResourceName; if (!HasImageExtension(fileName)) { return(false); } bool refresh = false; if (extractedAspectData.ContainsKey(ImageAspect.ASPECT_ID)) { refresh = true; } try { IFileSystemResourceAccessor fsra = mediaItemAccessor as IFileSystemResourceAccessor; if (!refresh) { MultipleMediaItemAspect providerResourceAspect = MediaItemAspect.CreateAspect(extractedAspectData, ProviderResourceAspect.Metadata); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_INDEX, 0); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_PRIMARY, true); if (!(mediaItemAccessor is IFileSystemResourceAccessor)) { return(false); } // Open a stream for media item to detect mimeType. using (Stream mediaStream = fsra.OpenRead()) { string mimeType = MimeTypeDetector.GetMimeType(mediaStream) ?? DEFAULT_MIMETYPE; providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, mimeType); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_SIZE, fsra.Size); } } MediaItemAspect mediaAspect = MediaItemAspect.GetOrCreateAspect(extractedAspectData, MediaAspect.Metadata); mediaAspect.SetAttribute(MediaAspect.ATTR_ISVIRTUAL, false); MediaItemAspect imageAspect = MediaItemAspect.GetOrCreateAspect(extractedAspectData, ImageAspect.Metadata); if (!refresh) { // Extract EXIF information from media item. using (ExifMetaInfo.ExifMetaInfo exif = new ExifMetaInfo.ExifMetaInfo(fsra)) { mediaAspect.SetAttribute(MediaAspect.ATTR_TITLE, ProviderPathHelper.GetFileNameWithoutExtension(fileName)); mediaAspect.SetAttribute(MediaAspect.ATTR_RECORDINGTIME, exif.OriginalDate != DateTime.MinValue ? exif.OriginalDate : fsra.LastChanged); mediaAspect.SetAttribute(MediaAspect.ATTR_COMMENT, StringUtils.TrimToNull(exif.ImageDescription)); if (exif.PixXDim.HasValue) { imageAspect.SetAttribute(ImageAspect.ATTR_WIDTH, (int)exif.PixXDim); } if (exif.PixYDim.HasValue) { imageAspect.SetAttribute(ImageAspect.ATTR_HEIGHT, (int)exif.PixYDim); } imageAspect.SetAttribute(ImageAspect.ATTR_MAKE, StringUtils.TrimToNull(exif.EquipMake)); imageAspect.SetAttribute(ImageAspect.ATTR_MODEL, StringUtils.TrimToNull(exif.EquipModel)); if (exif.ExposureBias.HasValue) { imageAspect.SetAttribute(ImageAspect.ATTR_EXPOSURE_BIAS, ((double)exif.ExposureBias).ToString()); } imageAspect.SetAttribute(ImageAspect.ATTR_EXPOSURE_TIME, exif.ExposureTime); imageAspect.SetAttribute(ImageAspect.ATTR_FLASH_MODE, StringUtils.TrimToNull(exif.FlashMode)); if (exif.FNumber.HasValue) { imageAspect.SetAttribute(ImageAspect.ATTR_FNUMBER, string.Format("F {0}", (double)exif.FNumber)); } imageAspect.SetAttribute(ImageAspect.ATTR_ISO_SPEED, StringUtils.TrimToNull(exif.ISOSpeed)); imageAspect.SetAttribute(ImageAspect.ATTR_ORIENTATION, (Int32)(exif.OrientationType ?? 0)); imageAspect.SetAttribute(ImageAspect.ATTR_METERING_MODE, exif.MeteringMode.ToString()); if (exif.Latitude.HasValue && exif.Longitude.HasValue) { imageAspect.SetAttribute(ImageAspect.ATTR_LATITUDE, exif.Latitude); imageAspect.SetAttribute(ImageAspect.ATTR_LONGITUDE, exif.Longitude); } } byte[] thumbData; // We only want to create missing thumbnails here, so check for existing ones first if (MediaItemAspect.TryGetAttribute(extractedAspectData, ThumbnailLargeAspect.ATTR_THUMBNAIL, out thumbData) && thumbData != null) { return(true); } using (LocalFsResourceAccessorHelper rah = new LocalFsResourceAccessorHelper(mediaItemAccessor)) using (rah.LocalFsResourceAccessor.EnsureLocalFileSystemAccess()) { string localFsResourcePath = rah.LocalFsResourceAccessor.LocalFileSystemPath; if (localFsResourcePath != null) { // Thumbnail extraction IThumbnailGenerator generator = ServiceRegistration.Get <IThumbnailGenerator>(); ImageType imageType; if (generator.GetThumbnail(localFsResourcePath, true, out thumbData, out imageType)) { MediaItemAspect.SetAttribute(extractedAspectData, ThumbnailLargeAspect.ATTR_THUMBNAIL, thumbData); } } } return(true); } else { bool updated = false; double?latitude = imageAspect.GetAttributeValue <double?>(ImageAspect.ATTR_LATITUDE); double?longitude = imageAspect.GetAttributeValue <double?>(ImageAspect.ATTR_LONGITUDE); if (IncludeGeoLocationDetails && !importOnly && latitude.HasValue && longitude.HasValue && string.IsNullOrEmpty(imageAspect.GetAttributeValue <string>(ImageAspect.ATTR_COUNTRY))) { CivicAddress locationInfo; if (!forceQuickMode && GeoLocationService.Instance.TryLookup(new GeoCoordinate(latitude.Value, longitude.Value), out locationInfo)) { imageAspect.SetAttribute(ImageAspect.ATTR_CITY, locationInfo.City); imageAspect.SetAttribute(ImageAspect.ATTR_STATE, locationInfo.StateProvince); imageAspect.SetAttribute(ImageAspect.ATTR_COUNTRY, locationInfo.CountryRegion); updated = true; } } byte[] thumbData; // We only want to create missing thumbnails here, so check for existing ones first if (MediaItemAspect.TryGetAttribute(extractedAspectData, ThumbnailLargeAspect.ATTR_THUMBNAIL, out thumbData) && thumbData != null) { return(updated); } using (LocalFsResourceAccessorHelper rah = new LocalFsResourceAccessorHelper(mediaItemAccessor)) using (rah.LocalFsResourceAccessor.EnsureLocalFileSystemAccess()) { string localFsResourcePath = rah.LocalFsResourceAccessor.LocalFileSystemPath; if (localFsResourcePath != null) { // In quick mode only allow thumbs taken from cache. bool cachedOnly = forceQuickMode; // Thumbnail extraction IThumbnailGenerator generator = ServiceRegistration.Get <IThumbnailGenerator>(); ImageType imageType; if (generator.GetThumbnail(localFsResourcePath, cachedOnly, out thumbData, out imageType)) { MediaItemAspect.SetAttribute(extractedAspectData, ThumbnailLargeAspect.ATTR_THUMBNAIL, thumbData); updated = true; } } } return(updated); } } catch (Exception e) { // Only log at the info level here - And simply return false. This makes the importer know that we // couldn't perform our task here. ServiceRegistration.Get <ILogger>().Info("ImageMetadataExtractor: Exception reading resource '{0}' (Text: '{1}')", mediaItemAccessor.CanonicalLocalResourcePath, e.Message); } return(false); }
/// <summary> /// Asynchronously tries to extract metadata for the given <param name="mediaItemAccessor"></param> /// </summary> /// <param name="mediaItemAccessor">Points to the resource for which we try to extract metadata</param> /// <param name="extractedAspectData">Dictionary of <see cref="MediaItemAspect"/>s with the extracted metadata</param> /// <param name="forceQuickMode">If <c>true</c>, nothing is downloaded from the internet</param> /// <returns><c>true</c> if metadata was found and stored into <param name="extractedAspectData"></param>, else <c>false</c></returns> private async Task <bool> TryExtractMovieMetadataAsync(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData, bool forceQuickMode) { // Get a unique number for this call to TryExtractMetadataAsync. We use this to make reading the debug log easier. // This MetadataExtractor is called in parallel for multiple MediaItems so that the respective debug log entries // for one call are not contained one after another in debug log. We therefore prepend this number before every log entry. var miNumber = Interlocked.Increment(ref _lastMediaItemNumber); bool isStub = extractedAspectData.ContainsKey(StubAspect.ASPECT_ID); try { _debugLogger.Info("[#{0}]: Start extracting metadata for resource '{1}' (forceQuickMode: {2})", miNumber, mediaItemAccessor, forceQuickMode); // This MetadataExtractor only works for MediaItems accessible by an IFileSystemResourceAccessor. // Otherwise it is not possible to find a nfo-file in the MediaItem's directory. if (!(mediaItemAccessor is IFileSystemResourceAccessor)) { _debugLogger.Info("[#{0}]: Cannot extract metadata; mediaItemAccessor is not an IFileSystemResourceAccessor", miNumber); return(false); } // We only extract metadata with this MetadataExtractor, if another MetadataExtractor that was applied before // has identified this MediaItem as a video and therefore added a VideoAspect. if (!extractedAspectData.ContainsKey(VideoAspect.ASPECT_ID)) { _debugLogger.Info("[#{0}]: Cannot extract metadata; this resource is not a video", miNumber); return(false); } // Here we try to find an IFileSystemResourceAccessor pointing to the nfo-file. // If we don't find one, we cannot extract any metadata. IFileSystemResourceAccessor nfoFsra; if (!TryGetNfoSResourceAccessor(miNumber, mediaItemAccessor as IFileSystemResourceAccessor, out nfoFsra)) { return(false); } // Now we (asynchronously) extract the metadata into a stub object. // If there is an error parsing the nfo-file with XmlNfoReader, we at least try to parse for a valid IMDB-ID. // If no metadata was found, nothing can be stored in the MediaItemAspects. NfoMovieReader nfoReader = new NfoMovieReader(_debugLogger, miNumber, false, forceQuickMode, isStub, _httpClient, _settings); using (nfoFsra) { if (!await nfoReader.TryReadMetadataAsync(nfoFsra).ConfigureAwait(false) && !await nfoReader.TryParseForImdbId(nfoFsra).ConfigureAwait(false)) { _debugLogger.Warn("[#{0}]: No valid metadata found", miNumber); return(false); } else if (isStub) { Stubs.MovieStub movie = nfoReader.GetMovieStubs().FirstOrDefault(); if (movie != null) { IList <MultipleMediaItemAspect> providerResourceAspects; if (MediaItemAspect.TryGetAspects(extractedAspectData, ProviderResourceAspect.Metadata, out providerResourceAspects)) { MultipleMediaItemAspect providerResourceAspect = providerResourceAspects.First(pa => pa.GetAttributeValue <int>(ProviderResourceAspect.ATTR_TYPE) == ProviderResourceAspect.TYPE_STUB); string mime = null; if (movie.FileInfo != null && movie.FileInfo.Count > 0) { mime = MimeTypeDetector.GetMimeTypeFromExtension("file" + movie.FileInfo.First().Container); } if (mime != null) { providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, mime); } } MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, movie.Title); MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_SORT_TITLE, movie.SortTitle != null ? movie.SortTitle : BaseInfo.GetSortTitle(movie.Title)); MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_RECORDINGTIME, movie.Premiered.HasValue ? movie.Premiered.Value : movie.Year.HasValue ? movie.Year.Value : (DateTime?)null); if (movie.FileInfo != null && movie.FileInfo.Count > 0) { extractedAspectData.Remove(VideoStreamAspect.ASPECT_ID); extractedAspectData.Remove(VideoAudioStreamAspect.ASPECT_ID); extractedAspectData.Remove(SubtitleAspect.ASPECT_ID); StubParser.ParseFileInfo(extractedAspectData, movie.FileInfo, movie.Title, movie.Fps); } } } } //Check reimport if (extractedAspectData.ContainsKey(ReimportAspect.ASPECT_ID)) { MovieInfo reimport = new MovieInfo(); reimport.FromMetadata(extractedAspectData); if (!VerifyMovieReimport(nfoReader, reimport)) { ServiceRegistration.Get <ILogger>().Info("NfoMovieMetadataExtractor: Nfo movie metadata from resource '{0}' ignored because it does not match reimport {1}", mediaItemAccessor, reimport); return(false); } } // Then we store the found metadata in the MediaItemAspects. If we only found metadata that is // not (yet) supported by our MediaItemAspects, this MetadataExtractor returns false. if (!nfoReader.TryWriteMetadata(extractedAspectData)) { _debugLogger.Warn("[#{0}]: No metadata was written into MediaItemsAspects", miNumber); return(false); } _debugLogger.Info("[#{0}]: Successfully finished extracting metadata", miNumber); ServiceRegistration.Get <ILogger>().Debug("NfoMovieMetadataExtractor: Assigned nfo movie metadata for resource '{0}'", mediaItemAccessor); return(true); } catch (Exception e) { ServiceRegistration.Get <ILogger>().Warn("NfoMovieMetadataExtractor: Exception while extracting metadata for resource '{0}'; enable debug logging for more details.", mediaItemAccessor); _debugLogger.Error("[#{0}]: Exception while extracting metadata", e, miNumber); return(false); } }
/// <summary> /// Asynchronously tries to extract metadata for the given <param name="mediaItemAccessor"></param> /// </summary> /// <param name="mediaItemAccessor">Points to the resource for which we try to extract metadata</param> /// <param name="extractedAspectData">Dictionary of <see cref="MediaItemAspect"/>s with the extracted metadata</param> /// <param name="forceQuickMode">If <c>true</c>, nothing is downloaded from the internet</param> /// <returns><c>true</c> if metadata was found and stored into <param name="extractedAspectData"></param>, else <c>false</c></returns> private async Task <bool> TryExtractAudioMetadataAsync(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData, bool forceQuickMode) { // Get a unique number for this call to TryExtractMetadataAsync. We use this to make reading the debug log easier. // This MetadataExtractor is called in parallel for multiple MediaItems so that the respective debug log entries // for one call are not contained one after another in debug log. We therefore prepend this number before every log entry. var miNumber = Interlocked.Increment(ref _lastMediaItemNumber); bool isStub = extractedAspectData.ContainsKey(StubAspect.ASPECT_ID); if (!isStub) { _debugLogger.Info("[#{0}]: Ignoring non-stub track", miNumber); return(false); } try { _debugLogger.Info("[#{0}]: Start extracting metadata for resource '{1}' (forceQuickMode: {2})", miNumber, mediaItemAccessor, forceQuickMode); // We only extract metadata with this MetadataExtractor, if another MetadataExtractor that was applied before // has identified this MediaItem as a video and therefore added a VideoAspect. if (!extractedAspectData.ContainsKey(AudioAspect.ASPECT_ID)) { _debugLogger.Info("[#{0}]: Cannot extract metadata; this resource is not audio", miNumber); return(false); } // This MetadataExtractor only works for MediaItems accessible by an IFileSystemResourceAccessor. // Otherwise it is not possible to find a nfo-file in the MediaItem's directory. if (!(mediaItemAccessor is IFileSystemResourceAccessor)) { _debugLogger.Info("[#{0}]: Cannot extract metadata; mediaItemAccessor is not an IFileSystemResourceAccessor", miNumber); return(false); } // First we try to find an IFileSystemResourceAccessor pointing to the album nfo-file. IFileSystemResourceAccessor albumNfoFsra; if (TryGetAlbumNfoSResourceAccessor(miNumber, mediaItemAccessor as IFileSystemResourceAccessor, out albumNfoFsra)) { // If we found one, we (asynchronously) extract the metadata into a stub object and, if metadata was found, // we store it into the MediaItemAspects. var albumNfoReader = new NfoAlbumReader(_debugLogger, miNumber, forceQuickMode, isStub, _httpClient, _settings); using (albumNfoFsra) { if (await albumNfoReader.TryReadMetadataAsync(albumNfoFsra).ConfigureAwait(false)) { //Check reimport if (extractedAspectData.ContainsKey(ReimportAspect.ASPECT_ID)) { AlbumInfo reimport = new AlbumInfo(); reimport.FromMetadata(extractedAspectData); if (!VerifyAlbumReimport(albumNfoReader, reimport)) { ServiceRegistration.Get <ILogger>().Info("NfoMovieMetadataExtractor: Nfo album metadata from resource '{0}' ignored because it does not match reimport {1}", mediaItemAccessor, reimport); return(false); } } Stubs.AlbumStub album = albumNfoReader.GetAlbumStubs().FirstOrDefault(); if (album != null) { int trackNo = 0; if (album.Tracks != null && album.Tracks.Count > 0 && MediaItemAspect.TryGetAttribute(extractedAspectData, AudioAspect.ATTR_TRACK, out trackNo)) { var track = album.Tracks.FirstOrDefault(t => t.TrackNumber.HasValue && trackNo == t.TrackNumber.Value); if (track != null) { TrackInfo trackInfo = new TrackInfo(); string title; string sortTitle; title = track.Title.Trim(); sortTitle = BaseInfo.GetSortTitle(title); IEnumerable <string> artists; if (track.Artists.Count > 0) { artists = track.Artists; } IList <MultipleMediaItemAspect> providerResourceAspects; if (MediaItemAspect.TryGetAspects(extractedAspectData, ProviderResourceAspect.Metadata, out providerResourceAspects)) { MultipleMediaItemAspect providerResourceAspect = providerResourceAspects.First(pa => pa.GetAttributeValue <int>(ProviderResourceAspect.ATTR_TYPE) == ProviderResourceAspect.TYPE_STUB); string mime = null; if (track.FileInfo != null && track.FileInfo.Count > 0) { mime = MimeTypeDetector.GetMimeTypeFromExtension("file" + track.FileInfo.First().Container); } if (mime != null) { providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, mime); } } trackInfo.TrackName = title; trackInfo.TrackNameSort = sortTitle; trackInfo.Duration = track.Duration.HasValue ? Convert.ToInt64(track.Duration.Value.TotalSeconds) : 0; trackInfo.Album = !string.IsNullOrEmpty(album.Title) ? album.Title.Trim() : null; trackInfo.TrackNum = track.TrackNumber.HasValue ? track.TrackNumber.Value : 0; trackInfo.TotalTracks = album.Tracks.Count; trackInfo.MusicBrainzId = track.MusicBrainzId; trackInfo.IsrcId = track.Isrc; trackInfo.AudioDbId = track.AudioDbId.HasValue ? track.AudioDbId.Value : 0; trackInfo.AlbumMusicBrainzId = album.MusicBrainzAlbumId; trackInfo.AlbumMusicBrainzGroupId = album.MusicBrainzReleaseGroupId; trackInfo.ReleaseDate = album.ReleaseDate; if (track.FileInfo != null && track.FileInfo.Count > 0 && track.FileInfo.First().AudioStreams != null && track.FileInfo.First().AudioStreams.Count > 0) { var audio = track.FileInfo.First().AudioStreams.First(); trackInfo.Encoding = audio.Codec; trackInfo.BitRate = audio.Bitrate != null?Convert.ToInt32(audio.Bitrate / 1000) : 0; trackInfo.Channels = audio.Channels != null ? audio.Channels.Value : 0; } trackInfo.Artists = new List <PersonInfo>(); if (track.Artists != null && track.Artists.Count > 0) { foreach (string artistName in track.Artists) { trackInfo.Artists.Add(new PersonInfo() { Name = artistName.Trim(), Occupation = PersonAspect.OCCUPATION_ARTIST, ParentMediaName = trackInfo.Album, MediaName = trackInfo.TrackName }); } } trackInfo.AlbumArtists = new List <PersonInfo>(); if (album.Artists != null && album.Artists.Count > 0) { foreach (string artistName in album.Artists) { trackInfo.AlbumArtists.Add(new PersonInfo() { Name = artistName.Trim(), Occupation = PersonAspect.OCCUPATION_ARTIST, ParentMediaName = trackInfo.Album, MediaName = trackInfo.TrackName }); } } if (album.Genres != null && album.Genres.Count > 0) { trackInfo.Genres = album.Genres.Where(s => !string.IsNullOrEmpty(s?.Trim())).Select(s => new GenreInfo { Name = s.Trim() }).ToList(); IGenreConverter converter = ServiceRegistration.Get <IGenreConverter>(); foreach (var genre in trackInfo.Genres) { if (!genre.Id.HasValue && converter.GetGenreId(genre.Name, GenreCategory.Music, null, out int genreId)) { genre.Id = genreId; } } } if (album.Thumb != null && album.Thumb.Length > 0) { try { using (MemoryStream stream = new MemoryStream(album.Thumb)) { trackInfo.Thumbnail = stream.ToArray(); trackInfo.HasChanged = true; } } // Decoding of invalid image data can fail, but main MediaItem is correct. catch { } } //Determine compilation if (trackInfo.AlbumArtists.Count > 0 && (trackInfo.AlbumArtists[0].Name.IndexOf("Various", StringComparison.InvariantCultureIgnoreCase) >= 0 || trackInfo.AlbumArtists[0].Name.Equals("VA", StringComparison.InvariantCultureIgnoreCase))) { trackInfo.Compilation = true; } else { //Look for itunes compilation folder var mediaItemPath = mediaItemAccessor.CanonicalLocalResourcePath; var artistMediaItemDirectoryPath = ResourcePathHelper.Combine(mediaItemPath, "../../"); if (artistMediaItemDirectoryPath.FileName.IndexOf("Compilation", StringComparison.InvariantCultureIgnoreCase) >= 0) { trackInfo.Compilation = true; } } trackInfo.SetMetadata(extractedAspectData); } } } } else { _debugLogger.Warn("[#{0}]: No valid metadata found in album nfo-file", miNumber); } } } _debugLogger.Info("[#{0}]: Successfully finished extracting metadata", miNumber); ServiceRegistration.Get <ILogger>().Debug("NfoAudioMetadataExtractor: Assigned nfo audio metadata for resource '{0}'", mediaItemAccessor); return(true); } catch (Exception e) { ServiceRegistration.Get <ILogger>().Warn("NfoAudioMetadataExtractor: Exception while extracting metadata for resource '{0}'; enable debug logging for more details.", mediaItemAccessor); _debugLogger.Error("[#{0}]: Exception while extracting metadata", e, miNumber); return(false); } }
private bool TryCreateInsertVideoMediaMediaItem(MediaItem origMi, out MediaItem subMi) { subMi = null; IPathManager pathManager = ServiceRegistration.Get <IPathManager>(); string resourceDirectory = pathManager.GetPath(@"<DATA>\Resources\"); string[] files = Directory.GetFiles(resourceDirectory, "InsertVideoMedia.*"); if (files == null || files.Length == 0) { return(false); } IDictionary <Guid, IList <MediaItemAspect> > aspects = new Dictionary <Guid, IList <MediaItemAspect> >(); foreach (var aspect in origMi.Aspects) { if (aspect.Key != ProviderResourceAspect.ASPECT_ID) { aspects.Add(aspect.Key, aspect.Value); } } MediaItemAspect providerResourceAspect = MediaItemAspect.CreateAspect(aspects, ProviderResourceAspect.Metadata); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_INDEX, 0); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_TYPE, ProviderResourceAspect.TYPE_PRIMARY); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH, ResourcePath.BuildBaseProviderPath(LocalFsResourceProviderBase.LOCAL_FS_RESOURCE_PROVIDER_ID, files[0]).Serialize()); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, MimeTypeDetector.GetMimeType(files[0], "video/unknown")); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_SYSTEM_ID, ServiceRegistration.Get <ISystemResolver>().LocalSystemId); subMi = new MediaItem(Guid.Empty, aspects); return(true); }
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); }