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);
        }
示例#2
0
 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 = "خطا در انتقال کاربران" }));
     }
 }
示例#3
0
        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);
        }
示例#4
0
        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);
     }
 }
示例#6
0
 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();
             }
         }
     }
 }
示例#7
0
 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;
     }
 }
示例#8
0
        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);
        }
示例#11
0
        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);
            }
        }
示例#13
0
        /// <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);
            }
        }
示例#14
0
        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);
        }
示例#15
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);
        }