コード例 #1
0
    public async Task<bool> TryExtractRelationshipsAsync(IResourceAccessor mediaItemAccessor, IDictionary<Guid, IList<MediaItemAspect>> aspects, IList<IDictionary<Guid, IList<MediaItemAspect>>> extractedLinkedAspects)
    {
      if (BaseInfo.IsVirtualResource(aspects))
        return false;

      MovieInfo movieInfo = new MovieInfo();
      if (!movieInfo.FromMetadata(aspects))
        return false;

      if (RelationshipExtractorUtils.TryCreateInfoFromLinkedAspects(extractedLinkedAspects, out List<PersonInfo> writers))
        movieInfo.Writers = writers;

      if (MovieMetadataExtractor.IncludeWriterDetails && !MovieMetadataExtractor.SkipOnlineSearches)
        await OnlineMatcherService.Instance.UpdatePersonsAsync(movieInfo, PersonAspect.OCCUPATION_WRITER).ConfigureAwait(false);
      
      foreach (PersonInfo person in movieInfo.Writers)
      {
        if (person.LinkedAspects != null)
          person.SetLinkedMetadata();
        else
        {
          IDictionary<Guid, IList<MediaItemAspect>> personAspects = new Dictionary<Guid, IList<MediaItemAspect>>();
          if (person.SetMetadata(personAspects) && personAspects.ContainsKey(ExternalIdentifierAspect.ASPECT_ID))
            extractedLinkedAspects.Add(personAspects);
        }
      }
      return extractedLinkedAspects.Count > 0;
    }
コード例 #2
0
        /// <summary>
        /// Constructor.
        /// </summary>
        public MovingPicturesInfo(MediaItem mediaItem)
        {
            try
            {
                MovieInfo movie = new MovieInfo();
                movie.FromMetadata(mediaItem.Aspects);

                ItemId          = mediaItem.MediaItemId;
                Title           = movie.MovieName.Text;
                AlternateTitles = movie.OriginalName;
                Directors       = String.Join(", ", movie.Directors);
                Writers         = String.Join(", ", movie.Writers);
                Actors          = String.Join(", ", movie.Actors);
                Genres          = String.Join(", ", movie.Genres.Select(g => g.Name));
                Rating          = Convert.ToString(movie.Rating.RatingValue ?? 0);
                RatingCount     = Convert.ToString(movie.Rating.VoteCount ?? 0);
                Year            = movie.ReleaseDate.Value.Year;
                Certification   = movie.Certification;
                Tagline         = movie.Tagline;
                Summary         = movie.Summary.Text;
                ImageName       = Helper.GetImageBaseURL(mediaItem, FanArtMediaTypes.Movie, FanArtTypes.Cover);
            }
            catch (Exception e)
            {
                ServiceRegistration.Get <ILogger>().Error("WifiRemote: Error getting movie info", e);
            }
        }
コード例 #3
0
ファイル: VideoInfo.cs プロジェクト: zmshan2008/MediaPortal-2
        /// <summary>
        /// Constructor
        /// </summary>
        public VideoInfo(MediaItem mediaItem)
        {
            MovieInfo movie = new MovieInfo();

            movie.FromMetadata(mediaItem.Aspects);

            ItemId    = mediaItem.MediaItemId;
            Title     = movie.MovieName.Text;
            Directors = String.Join(", ", movie.Directors);
            Writers   = String.Join(", ", movie.Writers);
            Actors    = String.Join(", ", movie.Actors);
            Summary   = movie.Summary.Text;
            ImageName = Helper.GetImageBaseURL(mediaItem, FanArtMediaTypes.Undefined, FanArtTypes.Thumbnail);
        }
コード例 #4
0
        private void ExtractFanArt(Guid mediaItemId, IDictionary <Guid, IList <MediaItemAspect> > aspects)
        {
            if (aspects.ContainsKey(VideoAspect.ASPECT_ID))
            {
                if (BaseInfo.IsVirtualResource(aspects))
                {
                    return;
                }

                MovieInfo movieInfo = new MovieInfo();
                movieInfo.FromMetadata(aspects);
                bool forceFanart = !movieInfo.IsRefreshed;
                ExtractLocalImages(aspects, mediaItemId, movieInfo.ToString());
            }
        }
コード例 #5
0
        public bool TryExtractRelationships(IDictionary <Guid, IList <MediaItemAspect> > aspects, bool importOnly, out IList <RelationshipItem> extractedLinkedAspects)
        {
            extractedLinkedAspects = null;

            if (!NfoMovieMetadataExtractor.IncludeActorDetails)
            {
                return(false);
            }

            //Only run during import
            if (!importOnly)
            {
                return(false);
            }

            MovieInfo movieInfo = new MovieInfo();

            if (!movieInfo.FromMetadata(aspects))
            {
                return(false);
            }

            if (!UpdatePersons(aspects, movieInfo.Actors, false))
            {
                return(false);
            }

            if (movieInfo.Actors.Count == 0)
            {
                return(false);
            }

            extractedLinkedAspects = new List <RelationshipItem>();
            foreach (PersonInfo person in movieInfo.Actors)
            {
                person.AssignNameId();
                person.HasChanged = movieInfo.HasChanged;
                IDictionary <Guid, IList <MediaItemAspect> > personAspects = new Dictionary <Guid, IList <MediaItemAspect> >();
                person.SetMetadata(personAspects);

                if (personAspects.ContainsKey(ExternalIdentifierAspect.ASPECT_ID))
                {
                    extractedLinkedAspects.Add(new RelationshipItem(personAspects, Guid.Empty));
                }
            }
            return(extractedLinkedAspects.Count > 0);
        }
コード例 #6
0
        public async Task <bool> TryExtractRelationshipsAsync(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > aspects, IList <IDictionary <Guid, IList <MediaItemAspect> > > extractedLinkedAspects)
        {
            if (!NfoMovieMetadataExtractor.IncludeDirectorDetails)
            {
                return(false);
            }

            MovieInfo reimport = null;

            if (aspects.ContainsKey(ReimportAspect.ASPECT_ID))
            {
                reimport = new MovieInfo();
                reimport.FromMetadata(aspects);
            }

            IList <IDictionary <Guid, IList <MediaItemAspect> > > nfoLinkedAspects = new List <IDictionary <Guid, IList <MediaItemAspect> > >();

            if (!await TryExtractMovieDirectorMetadataAsync(mediaItemAccessor, nfoLinkedAspects, reimport).ConfigureAwait(false))
            {
                return(false);
            }

            List <PersonInfo> directors;

            if (!RelationshipExtractorUtils.TryCreateInfoFromLinkedAspects(nfoLinkedAspects, out directors))
            {
                return(false);
            }

            directors = directors.Where(p => p != null && !string.IsNullOrEmpty(p.Name)).ToList();
            if (directors.Count == 0)
            {
                return(false);
            }

            extractedLinkedAspects.Clear();
            foreach (PersonInfo person in directors)
            {
                if (person.SetLinkedMetadata() && person.LinkedAspects.ContainsKey(ExternalIdentifierAspect.ASPECT_ID))
                {
                    extractedLinkedAspects.Add(person.LinkedAspects);
                }
            }
            return(extractedLinkedAspects.Count > 0);
        }
        public bool TryExtractRelationships(IDictionary <Guid, IList <MediaItemAspect> > aspects, bool importOnly, out IList <RelationshipItem> extractedLinkedAspects)
        {
            extractedLinkedAspects = null;

            if (!importOnly) //Only during import
            {
                return(false);
            }

            MovieInfo movieInfo = new MovieInfo();

            if (!movieInfo.FromMetadata(aspects))
            {
                return(false);
            }

            MovieCollectionInfo collectionInfo = movieInfo.CloneBasicInstance <MovieCollectionInfo>();

            if (collectionInfo.CollectionName.IsEmpty || collectionInfo.HasExternalId)
            {
                return(false);
            }

            extractedLinkedAspects = new List <RelationshipItem>();

            IDictionary <Guid, IList <MediaItemAspect> > collectionAspects = new Dictionary <Guid, IList <MediaItemAspect> >();

            //Create custom collection
            collectionInfo.AssignNameId();
            collectionInfo.SetMetadata(collectionAspects);

            bool movieVirtual = true;

            if (MediaItemAspect.TryGetAttribute(aspects, MediaAspect.ATTR_ISVIRTUAL, false, out movieVirtual))
            {
                MediaItemAspect.SetAttribute(collectionAspects, MediaAspect.ATTR_ISVIRTUAL, movieVirtual);
            }

            if (collectionAspects.ContainsKey(ExternalIdentifierAspect.ASPECT_ID))
            {
                extractedLinkedAspects.Add(new RelationshipItem(collectionAspects, Guid.Empty));
            }

            return(extractedLinkedAspects.Count > 0);
        }
コード例 #8
0
        public async Task <bool> TryExtractRelationshipsAsync(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > aspects, IList <IDictionary <Guid, IList <MediaItemAspect> > > extractedLinkedAspects)
        {
            if (!NfoMovieMetadataExtractor.IncludeCharacterDetails)
            {
                return(false);
            }

            MovieInfo reimport = null;

            if (aspects.ContainsKey(ReimportAspect.ASPECT_ID))
            {
                reimport = new MovieInfo();
                reimport.FromMetadata(aspects);
            }

            IList <IDictionary <Guid, IList <MediaItemAspect> > > nfoLinkedAspects = new List <IDictionary <Guid, IList <MediaItemAspect> > >();

            if (!await TryExtractMovieCharactersMetadataAsync(mediaItemAccessor, nfoLinkedAspects, reimport).ConfigureAwait(false))
            {
                return(false);
            }

            List <CharacterInfo> characters;

            if (!RelationshipExtractorUtils.TryCreateInfoFromLinkedAspects(nfoLinkedAspects, out characters))
            {
                return(false);
            }

            characters = characters.Where(c => c != null && !string.IsNullOrEmpty(c.Name)).ToList();
            if (characters.Count == 0)
            {
                return(false);
            }

            extractedLinkedAspects.Clear();
            foreach (CharacterInfo character in characters.Take(NfoMovieMetadataExtractor.MaximumCharacterCount))
            {
                if (character.SetLinkedMetadata() && character.LinkedAspects.ContainsKey(ExternalIdentifierAspect.ASPECT_ID))
                {
                    extractedLinkedAspects.Add(character.LinkedAspects);
                }
            }
            return(extractedLinkedAspects.Count > 0);
        }
コード例 #9
0
        public bool TryGetRelationshipIndex(IDictionary <Guid, IList <MediaItemAspect> > aspects, IDictionary <Guid, IList <MediaItemAspect> > linkedAspects, out int index)
        {
            index = -1;

            MovieInfo movieInfo = new MovieInfo();

            if (!movieInfo.FromMetadata(aspects))
            {
                return(false);
            }

            if (movieInfo.ReleaseDate.HasValue)
            {
                index = movieInfo.ReleaseDate.Value.Year;
            }

            return(index >= 0);
        }
コード例 #10
0
        public override void Update(MediaItem mediaItem)
        {
            base.Update(mediaItem);

            MovieInfo movieInfo = new MovieInfo();

            if (!movieInfo.FromMetadata(mediaItem.Aspects))
            {
                return;
            }

            MovieName      = movieInfo.MovieName.Text ?? "";
            CollectionName = movieInfo.CollectionName.Text ?? "";
            StoryPlot      = movieInfo.Summary.Text ?? "";
            Year           = movieInfo.ReleaseDate.HasValue ? movieInfo.ReleaseDate.Value.Year.ToString() : "";

            FireChange();
        }
コード例 #11
0
        public async Task <bool> TryExtractRelationshipsAsync(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > aspects, IList <IDictionary <Guid, IList <MediaItemAspect> > > extractedLinkedAspects)
        {
            MovieInfo reimport = null;

            if (aspects.ContainsKey(ReimportAspect.ASPECT_ID))
            {
                reimport = new MovieInfo();
                reimport.FromMetadata(aspects);
            }

            IList <IDictionary <Guid, IList <MediaItemAspect> > > nfoLinkedAspects = new List <IDictionary <Guid, IList <MediaItemAspect> > >();

            if (!await TryExtractMovieCollectionMetadataAsync(mediaItemAccessor, nfoLinkedAspects, reimport).ConfigureAwait(false))
            {
                return(false);
            }

            List <MovieCollectionInfo> collections;

            if (!RelationshipExtractorUtils.TryCreateInfoFromLinkedAspects(nfoLinkedAspects, out collections))
            {
                return(false);
            }

            collections = collections.Where(c => c != null && !c.CollectionName.IsEmpty).ToList();

            bool movieVirtual;

            if (MediaItemAspect.TryGetAttribute(aspects, MediaAspect.ATTR_ISVIRTUAL, false, out movieVirtual))
            {
                movieVirtual = false;
            }

            extractedLinkedAspects.Clear();
            foreach (MovieCollectionInfo collection in collections)
            {
                if (collection.SetLinkedMetadata() && collection.LinkedAspects.ContainsKey(ExternalIdentifierAspect.ASPECT_ID))
                {
                    MediaItemAspect.SetAttribute(collection.LinkedAspects, MediaAspect.ATTR_ISVIRTUAL, movieVirtual);
                    extractedLinkedAspects.Add(collection.LinkedAspects);
                }
            }
            return(extractedLinkedAspects.Count > 0);
        }
コード例 #12
0
        /// <summary>
        /// Verifies if the movie being reimported matches the movie in the nfo file
        /// </summary>
        /// <param name="reader">Reader used read the movie information from the nfo file</param>
        /// <param name="reimport">The movie being reimported</param>
        /// <returns>Result of the verification</returns>
        protected bool VerifyMovieReimport(NfoMovieReader reader, MovieInfo reimport)
        {
            if (reimport == null)
            {
                return(true);
            }

            IDictionary <Guid, IList <MediaItemAspect> > aspectData = new Dictionary <Guid, IList <MediaItemAspect> >();

            if (reader.TryWriteMetadata(aspectData))
            {
                MovieInfo info = new MovieInfo();
                info.FromMetadata(aspectData);
                if (reimport.Equals(info))
                {
                    return(true);
                }
            }
            return(false);
        }
コード例 #13
0
        public async Task <bool> TryExtractRelationshipsAsync(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > aspects, IList <IDictionary <Guid, IList <MediaItemAspect> > > extractedLinkedAspects)
        {
            if (BaseInfo.IsVirtualResource(aspects))
            {
                return(false);
            }

            MovieInfo movieInfo = new MovieInfo();

            if (!movieInfo.FromMetadata(aspects))
            {
                return(false);
            }

            if (RelationshipExtractorUtils.TryCreateInfoFromLinkedAspects(extractedLinkedAspects, out List <CharacterInfo> characters))
            {
                movieInfo.Characters = characters;
            }

            if (MovieMetadataExtractor.IncludeCharacterDetails && !MovieMetadataExtractor.SkipOnlineSearches)
            {
                await OnlineMatcherService.Instance.UpdateCharactersAsync(movieInfo).ConfigureAwait(false);
            }

            foreach (CharacterInfo character in movieInfo.Characters)
            {
                if (character.LinkedAspects != null)
                {
                    character.SetLinkedMetadata();
                }
                else
                {
                    IDictionary <Guid, IList <MediaItemAspect> > characterAspects = new Dictionary <Guid, IList <MediaItemAspect> >();
                    if (character.SetMetadata(characterAspects) && characterAspects.ContainsKey(ExternalIdentifierAspect.ASPECT_ID))
                    {
                        extractedLinkedAspects.Add(characterAspects);
                    }
                }
            }
            return(extractedLinkedAspects.Count > 0);
        }
コード例 #14
0
        public async Task <bool> TryExtractRelationshipsAsync(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > aspects, IList <IDictionary <Guid, IList <MediaItemAspect> > > extractedLinkedAspects)
        {
            if (BaseInfo.IsVirtualResource(aspects))
            {
                return(false);
            }

            MovieInfo movieInfo = new MovieInfo();

            if (!movieInfo.FromMetadata(aspects))
            {
                return(false);
            }

            if (RelationshipExtractorUtils.TryCreateInfoFromLinkedAspects(extractedLinkedAspects, out List <PersonInfo> actors))
            {
                movieInfo.Actors = actors;
            }

            if (MovieMetadataExtractor.IncludeActorDetails && !MovieMetadataExtractor.SkipOnlineSearches)
            {
                await OnlineMatcherService.Instance.UpdatePersonsAsync(movieInfo, PersonAspect.OCCUPATION_ACTOR, _category).ConfigureAwait(false);
            }

            foreach (PersonInfo person in movieInfo.Actors.Take(MovieMetadataExtractor.MaximumActorCount))
            {
                if (person.LinkedAspects != null)
                {
                    person.SetLinkedMetadata();
                }
                else
                {
                    IDictionary <Guid, IList <MediaItemAspect> > personAspects = new Dictionary <Guid, IList <MediaItemAspect> >();
                    if (person.SetMetadata(personAspects) && personAspects.ContainsKey(ExternalIdentifierAspect.ASPECT_ID))
                    {
                        extractedLinkedAspects.Add(personAspects);
                    }
                }
            }
            return(extractedLinkedAspects.Count > 0);
        }
コード例 #15
0
        public async Task <bool> TryExtractRelationshipsAsync(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > aspects, IList <IDictionary <Guid, IList <MediaItemAspect> > > extractedLinkedAspects)
        {
            MovieInfo movieInfo = new MovieInfo();

            if (!movieInfo.FromMetadata(aspects))
            {
                return(false);
            }

            MovieCollectionInfo collectionInfo = RelationshipExtractorUtils.TryCreateInfoFromLinkedAspects(extractedLinkedAspects, out List <MovieCollectionInfo> collection) ?
                                                 collection[0] : movieInfo.CloneBasicInstance <MovieCollectionInfo>();

            if (!MovieMetadataExtractor.SkipOnlineSearches && collectionInfo.HasExternalId)
            {
                await OnlineMatcherService.Instance.UpdateCollectionAsync(collectionInfo, false).ConfigureAwait(false);
            }

            IDictionary <Guid, IList <MediaItemAspect> > collectionAspects = collectionInfo.LinkedAspects != null ?
                                                                             collectionInfo.LinkedAspects : new Dictionary <Guid, IList <MediaItemAspect> >();

            collectionInfo.SetMetadata(collectionAspects);

            bool movieVirtual = true;

            if (MediaItemAspect.TryGetAttribute(aspects, MediaAspect.ATTR_ISVIRTUAL, false, out movieVirtual))
            {
                MediaItemAspect.SetAttribute(collectionAspects, MediaAspect.ATTR_ISVIRTUAL, movieVirtual);
            }

            if (!collectionAspects.ContainsKey(ExternalIdentifierAspect.ASPECT_ID))
            {
                return(false);
            }

            if (collectionInfo.LinkedAspects == null)
            {
                extractedLinkedAspects.Add(collectionAspects);
            }
            return(extractedLinkedAspects.Count > 0);
        }
コード例 #16
0
        public override async Task CollectFanArtAsync(Guid mediaItemId, IDictionary <Guid, IList <MediaItemAspect> > aspects)
        {
            //Virtual resources won't have local fanart
            if (BaseInfo.IsVirtualResource(aspects))
            {
                return;
            }

            //Don't process the same item again
            if (!AddToCache(mediaItemId))
            {
                return;
            }

            IResourceLocator mediaItemLocator = GetResourceLocator(aspects);

            if (mediaItemLocator == null)
            {
                return;
            }

            //Only needed for the name used in the fanart cache
            MovieInfo movieInfo = new MovieInfo();

            movieInfo.FromMetadata(aspects);
            string title = movieInfo.ToString();

            //Fanart files in the local directory
            if (ShouldCacheLocalFanArt(mediaItemLocator.NativeResourcePath, VideoMetadataExtractor.CacheLocalFanArt, VideoMetadataExtractor.CacheOfflineFanArt))
            {
                await ExtractFolderFanArt(mediaItemLocator, mediaItemId, title).ConfigureAwait(false);
            }

            //Fanart in MKV tags
            if (MKV_EXTENSIONS.Contains(ResourcePathHelper.GetExtension(mediaItemLocator.NativeResourcePath.FileName)))
            {
                await ExtractMkvFanArt(mediaItemLocator, mediaItemId, title).ConfigureAwait(false);
            }
        }
コード例 #17
0
        public bool TryMatch(IDictionary <Guid, IList <MediaItemAspect> > extractedAspects, IDictionary <Guid, IList <MediaItemAspect> > existingAspects)
        {
            if (!existingAspects.ContainsKey(MovieAspect.ASPECT_ID))
            {
                return(false);
            }

            MovieInfo linkedMovie = new MovieInfo();

            if (!linkedMovie.FromMetadata(extractedAspects))
            {
                return(false);
            }

            MovieInfo existingMovie = new MovieInfo();

            if (!existingMovie.FromMetadata(existingAspects))
            {
                return(false);
            }

            return(linkedMovie.Equals(existingMovie));
        }
コード例 #18
0
        public async Task <bool> TryExtractRelationshipsAsync(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > aspects, IList <IDictionary <Guid, IList <MediaItemAspect> > > extractedLinkedAspects)
        {
            if (BaseInfo.IsVirtualResource(aspects))
            {
                return(false);
            }

            MovieInfo movieInfo = new MovieInfo();

            if (!movieInfo.FromMetadata(aspects))
            {
                return(false);
            }

            if (MovieMetadataExtractor.IncludeProductionCompanyDetails && !MovieMetadataExtractor.SkipOnlineSearches)
            {
                await OnlineMatcherService.Instance.UpdateCompaniesAsync(movieInfo, CompanyAspect.COMPANY_PRODUCTION, _category).ConfigureAwait(false);
            }

            foreach (CompanyInfo company in movieInfo.ProductionCompanies)
            {
                if (company.LinkedAspects != null)
                {
                    company.SetLinkedMetadata();
                }
                else
                {
                    IDictionary <Guid, IList <MediaItemAspect> > companyAspects = new Dictionary <Guid, IList <MediaItemAspect> >();
                    if (company.SetMetadata(companyAspects) && companyAspects.ContainsKey(ExternalIdentifierAspect.ASPECT_ID))
                    {
                        extractedLinkedAspects.Add(companyAspects);
                    }
                }
            }
            return(extractedLinkedAspects.Count > 0);
        }
コード例 #19
0
        private void ExtractFanArt(Guid mediaItemId, IDictionary <Guid, IList <MediaItemAspect> > aspects, Guid?collectionMediaItemId, IDictionary <Guid, string> actorMediaItems)
        {
            if (aspects.ContainsKey(MovieAspect.ASPECT_ID))
            {
                if (BaseInfo.IsVirtualResource(aspects))
                {
                    return;
                }

                MovieInfo movieInfo = new MovieInfo();
                movieInfo.FromMetadata(aspects);
                bool forceFanart = !movieInfo.IsRefreshed;
                MovieCollectionInfo collectionInfo = movieInfo.CloneBasicInstance <MovieCollectionInfo>();
                ExtractLocalImages(aspects, mediaItemId, collectionMediaItemId, movieInfo.ToString(), collectionInfo.ToString(), actorMediaItems);
                if (!MovieMetadataExtractor.SkipFanArtDownload)
                {
                    OnlineMatcherService.Instance.DownloadMovieFanArt(mediaItemId, movieInfo, forceFanart);
                }

                //Take advantage of the movie language being known and download collection too
                if (collectionMediaItemId.HasValue && !_checkCache.Contains(collectionMediaItemId.Value))
                {
                    if (!MovieMetadataExtractor.SkipFanArtDownload)
                    {
                        OnlineMatcherService.Instance.DownloadMovieFanArt(collectionMediaItemId.Value, collectionInfo, forceFanart);
                    }
                    _checkCache.Add(collectionMediaItemId.Value);
                }
            }
            else if (aspects.ContainsKey(PersonAspect.ASPECT_ID))
            {
                PersonInfo personInfo = new PersonInfo();
                personInfo.FromMetadata(aspects);
                if (personInfo.Occupation == PersonAspect.OCCUPATION_ACTOR || personInfo.Occupation == PersonAspect.OCCUPATION_DIRECTOR ||
                    personInfo.Occupation == PersonAspect.OCCUPATION_WRITER)
                {
                    if (!MovieMetadataExtractor.SkipFanArtDownload)
                    {
                        OnlineMatcherService.Instance.DownloadMovieFanArt(mediaItemId, personInfo, !personInfo.IsRefreshed);
                    }
                }
            }
            else if (aspects.ContainsKey(CharacterAspect.ASPECT_ID))
            {
                CharacterInfo characterInfo = new CharacterInfo();
                characterInfo.FromMetadata(aspects);
                if (!MovieMetadataExtractor.SkipFanArtDownload)
                {
                    OnlineMatcherService.Instance.DownloadMovieFanArt(mediaItemId, characterInfo, !characterInfo.IsRefreshed);
                }
            }
            else if (aspects.ContainsKey(CompanyAspect.ASPECT_ID))
            {
                CompanyInfo companyInfo = new CompanyInfo();
                companyInfo.FromMetadata(aspects);
                if (companyInfo.Type == CompanyAspect.COMPANY_PRODUCTION)
                {
                    if (!MovieMetadataExtractor.SkipFanArtDownload)
                    {
                        OnlineMatcherService.Instance.DownloadMovieFanArt(mediaItemId, companyInfo, !companyInfo.IsRefreshed);
                    }
                }
            }
        }
コード例 #20
0
        protected async Task ExtractMovieFanArt(Guid mediaItemId, IDictionary <Guid, IList <MediaItemAspect> > aspects)
        {
            bool             shouldCacheLocal = false;
            IResourceLocator mediaItemLocator = null;

            if (!BaseInfo.IsVirtualResource(aspects))
            {
                mediaItemLocator = GetResourceLocator(aspects);

                //Whether local fanart should be stored in the fanart cache
                shouldCacheLocal = ShouldCacheLocalFanArt(mediaItemLocator.NativeResourcePath,
                                                          MovieMetadataExtractor.CacheLocalFanArt, MovieMetadataExtractor.CacheOfflineFanArt);
            }

            if (mediaItemLocator == null)
            {
                return;
            }

            if (!shouldCacheLocal && MovieMetadataExtractor.SkipFanArtDownload)
            {
                return; //Nothing to do
            }
            MovieInfo movieInfo = new MovieInfo();

            movieInfo.FromMetadata(aspects);

            //Movie fanart
            if (AddToCache(mediaItemId))
            {
                //Actor fanart may be stored in the movie directory, so get the actors now
                IList <Tuple <Guid, string> > actors = null;
                if (MediaItemAspect.TryGetAspect(aspects, VideoAspect.Metadata, out SingleMediaItemAspect videoAspect))
                {
                    var actorNames = videoAspect.GetCollectionAttribute <string>(VideoAspect.ATTR_ACTORS);
                    if (actorNames != null)
                    {
                        RelationshipExtractorUtils.TryGetMappedLinkedIds(PersonAspect.ROLE_ACTOR, aspects, actorNames.ToList(), out actors);
                    }
                }
                if (shouldCacheLocal)
                {
                    await ExtractMovieFolderFanArt(mediaItemLocator, mediaItemId, movieInfo.ToString(), actors).ConfigureAwait(false);
                }
                if (!MovieMetadataExtractor.SkipFanArtDownload)
                {
                    await OnlineMatcherService.Instance.DownloadMovieFanArtAsync(mediaItemId, movieInfo).ConfigureAwait(false);
                }

                //Find central actor information folder
                var          seriesDirectory        = ResourcePathHelper.Combine(mediaItemLocator.NativeResourcePath, "../../");
                ResourcePath centralActorFolderPath = LocalFanartHelper.GetCentralPersonFolder(seriesDirectory, CentralPersonFolderType.MovieActors);
                if (shouldCacheLocal && centralActorFolderPath != null && actors != null)
                {
                    foreach (var actor in actors)
                    {
                        // Check if we already processed this actor
                        if (!AddToCache(actor.Item1))
                        {
                            continue;
                        }

                        // First get the ResourcePath of the central directory
                        var artistFolderPath = ResourcePathHelper.Combine(centralActorFolderPath, $"{LocalFanartHelper.GetSafePersonFolderName(actor.Item2)}/");
                        using (IResourceAccessor accessor = new ResourceLocator(mediaItemLocator.NativeSystemId, artistFolderPath).CreateAccessor())
                        {
                            if (accessor is IFileSystemResourceAccessor directoryAccessor)
                            {
                                FanArtPathCollection paths = new FanArtPathCollection();
                                List <ResourcePath>  potentialFanArtFiles = LocalFanartHelper.GetPotentialFanArtFiles(directoryAccessor);
                                ExtractAllFanArtImages(potentialFanArtFiles, paths);
                                await SaveFolderImagesToCache(mediaItemLocator.NativeSystemId, paths, actor.Item1, actor.Item2).ConfigureAwait(false);
                            }
                        }
                    }
                }
            }

            //Collection fanart
            if (RelationshipExtractorUtils.TryGetLinkedId(MovieCollectionAspect.ROLE_MOVIE_COLLECTION, aspects, out Guid collectionMediaItemId) &&
                AddToCache(collectionMediaItemId))
            {
                MovieCollectionInfo collectionInfo = movieInfo.CloneBasicInstance <MovieCollectionInfo>();
                if (shouldCacheLocal)
                {
                    await ExtractCollectionFolderFanArt(mediaItemLocator, collectionMediaItemId, collectionInfo.ToString()).ConfigureAwait(false);
                }
                if (!MovieMetadataExtractor.SkipFanArtDownload)
                {
                    await OnlineMatcherService.Instance.DownloadMovieFanArtAsync(collectionMediaItemId, collectionInfo).ConfigureAwait(false);
                }
            }
        }
コード例 #21
0
        public bool TryExtractRelationships(IDictionary <Guid, IList <MediaItemAspect> > aspects, bool importOnly, out IList <RelationshipItem> extractedLinkedAspects)
        {
            extractedLinkedAspects = null;

            if (!MovieMetadataExtractor.IncludeWriterDetails)
            {
                return(false);
            }

            if (importOnly)
            {
                return(false);
            }

            if (BaseInfo.IsVirtualResource(aspects))
            {
                return(false);
            }

            MovieInfo movieInfo = new MovieInfo();

            if (!movieInfo.FromMetadata(aspects))
            {
                return(false);
            }

            if (CheckCacheContains(movieInfo))
            {
                return(false);
            }

            int count = 0;

            if (!MovieMetadataExtractor.SkipOnlineSearches)
            {
                OnlineMatcherService.Instance.UpdatePersons(movieInfo, PersonAspect.OCCUPATION_WRITER, importOnly);
                count = movieInfo.Writers.Where(p => p.HasExternalId).Count();
                if (!movieInfo.IsRefreshed)
                {
                    movieInfo.HasChanged = true; //Force save to update external Ids for metadata found by other MDEs
                }
            }
            else
            {
                count = movieInfo.Writers.Where(p => !string.IsNullOrEmpty(p.Name)).Count();
            }

            if (movieInfo.Writers.Count == 0)
            {
                return(false);
            }

            if (BaseInfo.CountRelationships(aspects, LinkedRole) < count || (BaseInfo.CountRelationships(aspects, LinkedRole) == 0 && movieInfo.Writers.Count > 0))
            {
                movieInfo.HasChanged = true; //Force save if no relationship exists
            }
            if (!movieInfo.HasChanged)
            {
                return(false);
            }

            AddToCheckCache(movieInfo);

            extractedLinkedAspects = new List <RelationshipItem>();
            foreach (PersonInfo person in movieInfo.Writers)
            {
                person.AssignNameId();
                person.HasChanged = movieInfo.HasChanged;
                IDictionary <Guid, IList <MediaItemAspect> > personAspects = new Dictionary <Guid, IList <MediaItemAspect> >();
                person.SetMetadata(personAspects);

                if (personAspects.ContainsKey(ExternalIdentifierAspect.ASPECT_ID))
                {
                    Guid existingId;
                    if (TryGetIdFromCache(person, out existingId))
                    {
                        extractedLinkedAspects.Add(new RelationshipItem(personAspects, existingId));
                    }
                    else
                    {
                        extractedLinkedAspects.Add(new RelationshipItem(personAspects, Guid.Empty));
                    }
                }
            }
            return(extractedLinkedAspects.Count > 0);
        }
コード例 #22
0
        private bool ExtractMovieData(ILocalFsResourceAccessor lfsra, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData, bool importOnly)
        {
            // Calling EnsureLocalFileSystemAccess not necessary; only string operation
            string[] pathsToTest = new[] { lfsra.LocalFileSystemPath, lfsra.CanonicalLocalResourcePath.ToString() };
            string   title       = null;
            string   sortTitle   = null;

            // VideoAspect must be present to be sure it is actually a video resource.
            if (!extractedAspectData.ContainsKey(VideoStreamAspect.ASPECT_ID) && !extractedAspectData.ContainsKey(SubtitleAspect.ASPECT_ID))
            {
                return(false);
            }

            if (extractedAspectData.ContainsKey(SubtitleAspect.ASPECT_ID) && !importOnly)
            {
                return(false); //Subtitles can only be imported not refreshed
            }
            bool refresh = false;

            if (extractedAspectData.ContainsKey(MovieAspect.ASPECT_ID))
            {
                refresh = true;
            }

            MovieInfo movieInfo = new MovieInfo();

            if (refresh)
            {
                movieInfo.FromMetadata(extractedAspectData);
            }

            if (movieInfo.MovieName.IsEmpty)
            {
                //Try to get title
                if (MediaItemAspect.TryGetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, out title) &&
                    !string.IsNullOrEmpty(title) && !lfsra.ResourceName.StartsWith(title, StringComparison.InvariantCultureIgnoreCase))
                {
                    movieInfo.MovieName = title;
                    /* Clear the names from unwanted strings */
                    MovieNameMatcher.CleanupTitle(movieInfo);
                }
            }
            if (movieInfo.MovieNameSort.IsEmpty)
            {
                //Try to get sort title
                if (MediaItemAspect.TryGetAttribute(extractedAspectData, MediaAspect.ATTR_SORT_TITLE, out sortTitle) && !string.IsNullOrEmpty(sortTitle))
                {
                    movieInfo.MovieNameSort = sortTitle;
                }
            }

            if (movieInfo.MovieDbId == 0)
            {
                try
                {
                    // Try to use an existing TMDB id for exact mapping
                    string tmdbId;
                    if (MatroskaMatcher.TryMatchTmdbId(lfsra, out tmdbId))
                    {
                        movieInfo.MovieDbId = Convert.ToInt32(tmdbId);
                    }
                }
                catch (Exception ex)
                {
                    ServiceRegistration.Get <ILogger>().Debug("MoviesMetadataExtractor: Exception reading TMDB ID for '{0}'", ex, lfsra.CanonicalLocalResourcePath);
                }
            }

            if (string.IsNullOrEmpty(movieInfo.ImdbId))
            {
                try
                {
                    // Try to use an existing IMDB id for exact mapping
                    string imdbId = null;
                    if (pathsToTest.Any(path => MatroskaMatcher.TryMatchImdbId(lfsra, out imdbId)))
                    {
                        movieInfo.ImdbId = imdbId;
                    }
                    else if (pathsToTest.Any(path => ImdbIdMatcher.TryMatchImdbId(path, out imdbId)))
                    {
                        movieInfo.ImdbId = imdbId;
                    }
                }
                catch (Exception ex)
                {
                    ServiceRegistration.Get <ILogger>().Debug("MoviesMetadataExtractor: Exception reading IMDB ID for '{0}'", ex, lfsra.CanonicalLocalResourcePath);
                }
            }

            if (!movieInfo.IsBaseInfoPresent)
            {
                // Also test the full path year. This is useful if the path contains the real name and year.
                foreach (string path in pathsToTest)
                {
                    if (MovieNameMatcher.MatchTitleYear(path, movieInfo))
                    {
                        break;
                    }
                }
                //Fall back to MediaAspect.ATTR_TITLE
                if (movieInfo.MovieName.IsEmpty && !string.IsNullOrEmpty(title))
                {
                    movieInfo.MovieName = title;
                }

                /* Clear the names from unwanted strings */
                MovieNameMatcher.CleanupTitle(movieInfo);
            }

            if (!movieInfo.ReleaseDate.HasValue && !movieInfo.HasExternalId)
            {
                // When searching movie title, the year can be relevant for multiple titles with same name but different years
                DateTime recordingDate;
                if (MediaItemAspect.TryGetAttribute(extractedAspectData, MediaAspect.ATTR_RECORDINGTIME, out recordingDate))
                {
                    movieInfo.ReleaseDate = recordingDate;
                }
            }

            // Allow the online lookup to choose best matching language for metadata
            if (movieInfo.Languages.Count == 0)
            {
                IList <MultipleMediaItemAspect> audioAspects;
                if (MediaItemAspect.TryGetAspects(extractedAspectData, VideoAudioStreamAspect.Metadata, out audioAspects))
                {
                    foreach (MultipleMediaItemAspect aspect in audioAspects)
                    {
                        string language = (string)aspect.GetAttributeValue(VideoAudioStreamAspect.ATTR_AUDIOLANGUAGE);
                        if (!string.IsNullOrEmpty(language) && !movieInfo.Languages.Contains(language))
                        {
                            movieInfo.Languages.Add(language);
                        }
                    }
                }
            }

            if (importOnly)
            {
                try
                {
                    MatroskaMatcher.ExtractFromTags(lfsra, movieInfo);
                    MP4Matcher.ExtractFromTags(lfsra, movieInfo);
                }
                catch (Exception ex)
                {
                    ServiceRegistration.Get <ILogger>().Debug("MoviesMetadataExtractor: Exception reading tags for '{0}'", ex, lfsra.CanonicalLocalResourcePath);
                }
            }

            if (SkipOnlineSearches && !SkipFanArtDownload)
            {
                MovieInfo tempInfo = movieInfo.Clone();
                OnlineMatcherService.Instance.FindAndUpdateMovie(tempInfo, importOnly);
                movieInfo.CopyIdsFrom(tempInfo);
                movieInfo.HasChanged = tempInfo.HasChanged;
            }
            else if (!SkipOnlineSearches)
            {
                OnlineMatcherService.Instance.FindAndUpdateMovie(movieInfo, importOnly);
            }

            //Send it to the videos section
            if (!SkipOnlineSearches && !movieInfo.HasExternalId)
            {
                return(false);
            }

            if (importOnly)
            {
                //Create custom collection (overrides online collection)
                MovieCollectionInfo collectionInfo = movieInfo.CloneBasicInstance <MovieCollectionInfo>();
                string collectionName;
                if (string.IsNullOrEmpty(collectionInfo.NameId) && CollectionFolderHasFanArt(lfsra, out collectionName))
                {
                    collectionInfo = new MovieCollectionInfo();
                    collectionInfo.CollectionName = collectionName;
                    if (!collectionInfo.CollectionName.IsEmpty)
                    {
                        movieInfo.CollectionName = collectionInfo.CollectionName;
                        movieInfo.CopyIdsFrom(collectionInfo); //Reset ID's
                        movieInfo.HasChanged = true;
                    }
                }
            }
            movieInfo.AssignNameId();

            if (refresh)
            {
                if ((IncludeActorDetails && !BaseInfo.HasRelationship(extractedAspectData, PersonAspect.ROLE_ACTOR) && movieInfo.Actors.Count > 0) ||
                    (IncludeCharacterDetails && !BaseInfo.HasRelationship(extractedAspectData, CharacterAspect.ROLE_CHARACTER) && movieInfo.Characters.Count > 0) ||
                    (IncludeDirectorDetails && !BaseInfo.HasRelationship(extractedAspectData, PersonAspect.ROLE_DIRECTOR) && movieInfo.Directors.Count > 0) ||
                    (IncludeWriterDetails && !BaseInfo.HasRelationship(extractedAspectData, PersonAspect.ROLE_WRITER) && movieInfo.Writers.Count > 0) ||
                    (IncludeProductionCompanyDetails && !BaseInfo.HasRelationship(extractedAspectData, CompanyAspect.ROLE_COMPANY) && movieInfo.ProductionCompanies.Count > 0))
                {
                    movieInfo.HasChanged = true;
                }
            }

            if (!movieInfo.HasChanged && !importOnly)
            {
                return(false);
            }

            movieInfo.SetMetadata(extractedAspectData);

            return(movieInfo.IsBaseInfoPresent);
        }
コード例 #23
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> 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);
            }
        }
コード例 #24
0
        protected async Task ExtractMovieFanArt(Guid mediaItemId, IDictionary <Guid, IList <MediaItemAspect> > aspects)
        {
            bool             shouldCacheLocal = false;
            IResourceLocator mediaItemLocator = null;

            if (!BaseInfo.IsVirtualResource(aspects))
            {
                mediaItemLocator = GetResourceLocator(aspects);
                if (mediaItemLocator == null)
                {
                    return;
                }

                //Whether local fanart should be stored in the fanart cache
                shouldCacheLocal = ShouldCacheLocalFanArt(mediaItemLocator.NativeResourcePath,
                                                          MovieMetadataExtractor.CacheLocalFanArt, MovieMetadataExtractor.CacheOfflineFanArt);
            }

            if (!shouldCacheLocal && MovieMetadataExtractor.SkipFanArtDownload)
            {
                return; //Nothing to do
            }
            MovieInfo movieInfo = new MovieInfo();

            movieInfo.FromMetadata(aspects);

            //Movie fanart
            if (AddToCache(mediaItemId))
            {
                //Actor fanart may be stored in the movie directory, so get the actors now
                IList <Tuple <Guid, string> > actors = null;
                if (MediaItemAspect.TryGetAspect(aspects, VideoAspect.Metadata, out SingleMediaItemAspect videoAspect))
                {
                    var actorNames = videoAspect.GetCollectionAttribute <string>(VideoAspect.ATTR_ACTORS);
                    if (actorNames != null)
                    {
                        RelationshipExtractorUtils.TryGetMappedLinkedIds(PersonAspect.ROLE_ACTOR, aspects, actorNames.ToList(), out actors);
                    }
                }
                if (shouldCacheLocal)
                {
                    await ExtractMovieFolderFanArt(mediaItemLocator, mediaItemId, movieInfo.ToString(), actors).ConfigureAwait(false);
                }
                if (!MovieMetadataExtractor.SkipFanArtDownload)
                {
                    await OnlineMatcherService.Instance.DownloadMovieFanArtAsync(mediaItemId, movieInfo).ConfigureAwait(false);
                }
            }

            //Collection fanart
            if (RelationshipExtractorUtils.TryGetLinkedId(MovieCollectionAspect.ROLE_MOVIE_COLLECTION, aspects, out Guid collectionMediaItemId) &&
                AddToCache(collectionMediaItemId))
            {
                MovieCollectionInfo collectionInfo = movieInfo.CloneBasicInstance <MovieCollectionInfo>();
                if (shouldCacheLocal)
                {
                    await ExtractCollectionFolderFanArt(mediaItemLocator, collectionMediaItemId, collectionInfo.ToString()).ConfigureAwait(false);
                }
                if (!MovieMetadataExtractor.SkipFanArtDownload)
                {
                    await OnlineMatcherService.Instance.DownloadMovieFanArtAsync(collectionMediaItemId, collectionInfo).ConfigureAwait(false);
                }
            }
        }
コード例 #25
0
        public bool TryMerge(IDictionary <Guid, IList <MediaItemAspect> > extractedAspects, IDictionary <Guid, IList <MediaItemAspect> > existingAspects)
        {
            try
            {
                MovieInfo existing  = new MovieInfo();
                MovieInfo extracted = new MovieInfo();

                //Extracted aspects
                IList <MultipleMediaItemAspect> providerResourceAspects;
                if (!MediaItemAspect.TryGetAspects(extractedAspects, ProviderResourceAspect.Metadata, out providerResourceAspects))
                {
                    return(false);
                }

                //Existing aspects
                IList <MultipleMediaItemAspect> existingProviderResourceAspects;
                MediaItemAspect.TryGetAspects(existingAspects, ProviderResourceAspect.Metadata, out existingProviderResourceAspects);

                //Don't merge virtual resources
                if (!providerResourceAspects.Where(p => p.GetAttributeValue <int>(ProviderResourceAspect.ATTR_TYPE) == ProviderResourceAspect.TYPE_VIRTUAL).Any())
                {
                    //Replace if existing is a virtual resource
                    if (existingProviderResourceAspects.Where(p => p.GetAttributeValue <int>(ProviderResourceAspect.ATTR_TYPE) == ProviderResourceAspect.TYPE_VIRTUAL).Any())
                    {
                        //Don't allow merge of subtitles into virtual item
                        if (extractedAspects.ContainsKey(SubtitleAspect.ASPECT_ID) && !extractedAspects.ContainsKey(VideoStreamAspect.ASPECT_ID))
                        {
                            return(false);
                        }

                        MediaItemAspect.SetAttribute(existingAspects, MediaAspect.ATTR_ISVIRTUAL, false);
                        MediaItemAspect.SetAttribute(existingAspects, MediaAspect.ATTR_ISSTUB,
                                                     providerResourceAspects.Where(p => p.GetAttributeValue <int>(ProviderResourceAspect.ATTR_TYPE) == ProviderResourceAspect.TYPE_STUB).Any());
                        var now = DateTime.Now;
                        MediaItemAspect.SetAttribute(existingAspects, ImporterAspect.ATTR_DATEADDED, now);
                        MediaItemAspect.SetAttribute(existingAspects, ImporterAspect.ATTR_LAST_IMPORT_DATE, now);
                        existingAspects.Remove(ProviderResourceAspect.ASPECT_ID);
                        foreach (Guid aspect in extractedAspects.Keys)
                        {
                            if (!existingAspects.ContainsKey(aspect))
                            {
                                existingAspects.Add(aspect, extractedAspects[aspect]);
                            }
                        }

                        existing.FromMetadata(existingAspects);
                        extracted.FromMetadata(extractedAspects);

                        existing.MergeWith(extracted, true);
                        existing.SetMetadata(existingAspects);
                        return(true);
                    }

                    //Merge
                    if (providerResourceAspects.Where(p => p.GetAttributeValue <int>(ProviderResourceAspect.ATTR_TYPE) == ProviderResourceAspect.TYPE_STUB).Any() ||
                        existingProviderResourceAspects.Where(p => p.GetAttributeValue <int>(ProviderResourceAspect.ATTR_TYPE) == ProviderResourceAspect.TYPE_STUB).Any())
                    {
                        MediaItemAspect.SetAttribute(existingAspects, MediaAspect.ATTR_ISVIRTUAL, false);
                        MediaItemAspect.SetAttribute(existingAspects, MediaAspect.ATTR_ISSTUB, true);
                        if (!ResourceAspectMerger.MergeVideoResourceAspects(extractedAspects, existingAspects))
                        {
                            return(false);
                        }
                    }
                }

                existing.FromMetadata(existingAspects);
                extracted.FromMetadata(extractedAspects);

                existing.MergeWith(extracted, true);
                existing.SetMetadata(existingAspects);
                if (!ResourceAspectMerger.MergeVideoResourceAspects(extractedAspects, existingAspects))
                {
                    return(false);
                }

                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("MovieMergeHandler: Exception merging resources (Text: '{0}')", e.Message);
                return(false);
            }
        }
コード例 #26
0
        public async Task <IList <MediaItemSearchResult> > SearchForMatchesAsync(IDictionary <Guid, IList <MediaItemAspect> > searchAspectData, ICollection <string> searchCategories)
        {
            try
            {
                if (!(searchCategories?.Contains(MEDIA_CATEGORY_NAME_MOVIE) ?? true))
                {
                    return(null);
                }

                string searchData     = null;
                var    reimportAspect = MediaItemAspect.GetAspect(searchAspectData, ReimportAspect.Metadata);
                if (reimportAspect != null)
                {
                    searchData = reimportAspect.GetAttributeValue <string>(ReimportAspect.ATTR_SEARCH);
                }

                ServiceRegistration.Get <ILogger>().Debug("MovieMetadataExtractor: Search aspects to use: '{0}'", string.Join(",", searchAspectData.Keys));

                //Prepare search info
                MovieInfo movieSearchinfo = null;
                List <MediaItemSearchResult> searchResults = new List <MediaItemSearchResult>();
                if (!string.IsNullOrEmpty(searchData))
                {
                    if (searchAspectData.ContainsKey(VideoAspect.ASPECT_ID))
                    {
                        movieSearchinfo = new MovieInfo();
                        if (searchData.StartsWith("tt", StringComparison.InvariantCultureIgnoreCase) && !searchData.Contains(" ") && int.TryParse(searchData.Substring(2), out int id))
                        {
                            movieSearchinfo.ImdbId = searchData;
                        }
                        else if (!searchData.Contains(" ") && int.TryParse(searchData, out int movieDbId))
                        {
                            movieSearchinfo.MovieDbId = movieDbId;
                        }
                        else //Fallabck to name search
                        {
                            searchData = searchData.Trim();
                            if (!MovieNameMatcher.MatchTitleYear(searchData, movieSearchinfo))
                            {
                                movieSearchinfo.MovieName = searchData;
                            }
                        }

                        ServiceRegistration.Get <ILogger>().Debug("MovieMetadataExtractor: Searching for movie matches on search: '{0}'", searchData);
                    }
                }
                else
                {
                    if (searchAspectData.ContainsKey(VideoAspect.ASPECT_ID))
                    {
                        movieSearchinfo = new MovieInfo();
                        movieSearchinfo.FromMetadata(searchAspectData);

                        ServiceRegistration.Get <ILogger>().Debug("MovieMetadataExtractor: Searching for movie matches on aspects");
                    }
                }

                //Perform online search
                if (movieSearchinfo != null)
                {
                    var matches = await OnlineMatcherService.Instance.FindMatchingMoviesAsync(movieSearchinfo).ConfigureAwait(false);

                    ServiceRegistration.Get <ILogger>().Debug("MoviesMetadataExtractor: Movie search returned {0} matches", matches.Count());
                    foreach (var match in matches)
                    {
                        var result = new MediaItemSearchResult
                        {
                            Name = $"{match.MovieName.Text}{(match.ReleaseDate == null ? "" : $" ({match.ReleaseDate.Value.Year})")}" +
                                   $"{(string.IsNullOrWhiteSpace(match.OriginalName) || string.Compare(match.MovieName.Text, match.OriginalName, true) == 0 ? "" : $" [{match.OriginalName}]")}",
                            Description = match.Summary.IsEmpty ? "" : match.Summary.Text,
                        };

                        //Add external Ids
                        if (!string.IsNullOrEmpty(match.ImdbId))
                        {
                            result.ExternalIds.Add("imdb.com", match.ImdbId);
                        }
                        if (match.MovieDbId > 0)
                        {
                            result.ExternalIds.Add("themoviedb.org", match.MovieDbId.ToString());
                        }

                        //Assign aspects and remove unwanted aspects
                        match.SetMetadata(result.AspectData, true);
                        CleanReimportAspects(result.AspectData);

                        searchResults.Add(result);
                    }
                    return(searchResults);
                }
コード例 #27
0
        private async Task <bool> ExtractMovieData(ILocalFsResourceAccessor lfsra, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData)
        {
            // VideoAspect must be present to be sure it is actually a video resource.
            if (!extractedAspectData.ContainsKey(VideoAspect.ASPECT_ID) && !extractedAspectData.ContainsKey(SubtitleAspect.ASPECT_ID))
            {
                return(false);
            }

            // Calling EnsureLocalFileSystemAccess not necessary; only string operation
            string[] pathsToTest = new[] { lfsra.LocalFileSystemPath, lfsra.CanonicalLocalResourcePath.ToString() };
            string   title       = null;
            string   sortTitle   = null;
            bool     isReimport  = extractedAspectData.ContainsKey(ReimportAspect.ASPECT_ID);

            MovieInfo movieInfo = new MovieInfo();

            if (extractedAspectData.ContainsKey(MovieAspect.ASPECT_ID))
            {
                movieInfo.FromMetadata(extractedAspectData);
            }

            if (movieInfo.MovieName.IsEmpty)
            {
                //Try to get title
                if (MediaItemAspect.TryGetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, out title) &&
                    !string.IsNullOrEmpty(title) && !lfsra.ResourceName.StartsWith(title, StringComparison.InvariantCultureIgnoreCase))
                {
                    //The title may still contain tags and other noise, try and parse it for a title and year.
                    MovieNameMatcher.MatchTitleYear(title, movieInfo);
                }
            }
            if (movieInfo.MovieNameSort.IsEmpty)
            {
                //Try to get sort title
                if (MediaItemAspect.TryGetAttribute(extractedAspectData, MediaAspect.ATTR_SORT_TITLE, out sortTitle) && !string.IsNullOrEmpty(sortTitle))
                {
                    movieInfo.MovieNameSort = sortTitle;
                }
            }

            if (!isReimport) //Ignore tags or file based information for reimport because they might be the cause of the wrong import
            {
                if (movieInfo.MovieDbId == 0)
                {
                    try
                    {
                        // Try to use an existing TMDB id for exact mapping
                        string tmdbId = await MatroskaMatcher.TryMatchTmdbIdAsync(lfsra).ConfigureAwait(false);

                        if (!string.IsNullOrEmpty(tmdbId))
                        {
                            movieInfo.MovieDbId = Convert.ToInt32(tmdbId);
                        }
                    }
                    catch (Exception ex)
                    {
                        ServiceRegistration.Get <ILogger>().Debug("MoviesMetadataExtractor: Exception reading TMDB ID for '{0}'", ex, lfsra.CanonicalLocalResourcePath);
                    }
                }

                if (string.IsNullOrEmpty(movieInfo.ImdbId))
                {
                    try
                    {
                        // Try to use an existing IMDB id for exact mapping
                        string imdbId = await MatroskaMatcher.TryMatchImdbIdAsync(lfsra).ConfigureAwait(false);

                        if (!string.IsNullOrEmpty(imdbId))
                        {
                            movieInfo.ImdbId = imdbId;
                        }
                        else if (pathsToTest.Any(path => ImdbIdMatcher.TryMatchImdbId(path, out imdbId)))
                        {
                            movieInfo.ImdbId = imdbId;
                        }
                    }
                    catch (Exception ex)
                    {
                        ServiceRegistration.Get <ILogger>().Debug("MoviesMetadataExtractor: Exception reading IMDB ID for '{0}'", ex, lfsra.CanonicalLocalResourcePath);
                    }
                }

                if (!movieInfo.IsBaseInfoPresent || !movieInfo.ReleaseDate.HasValue)
                {
                    // Also test the full path year. This is useful if the path contains the real name and year.
                    foreach (string path in pathsToTest)
                    {
                        if (MovieNameMatcher.MatchTitleYear(path, movieInfo))
                        {
                            break;
                        }
                    }
                    //Fall back to MediaAspect.ATTR_TITLE
                    if (movieInfo.MovieName.IsEmpty && !string.IsNullOrEmpty(title))
                    {
                        movieInfo.MovieName = title;
                    }

                    /* Clear the names from unwanted strings */
                    MovieNameMatcher.CleanupTitle(movieInfo);
                }

                if (!movieInfo.ReleaseDate.HasValue && !movieInfo.HasExternalId)
                {
                    // When searching movie title, the year can be relevant for multiple titles with same name but different years
                    DateTime recordingDate;
                    if (MediaItemAspect.TryGetAttribute(extractedAspectData, MediaAspect.ATTR_RECORDINGTIME, out recordingDate))
                    {
                        movieInfo.ReleaseDate = recordingDate;
                    }
                }

                try
                {
                    await MatroskaMatcher.ExtractFromTagsAsync(lfsra, movieInfo).ConfigureAwait(false);

                    MP4Matcher.ExtractFromTags(lfsra, movieInfo);
                }
                catch (Exception ex)
                {
                    ServiceRegistration.Get <ILogger>().Debug("MoviesMetadataExtractor: Exception reading tags for '{0}'", ex, lfsra.CanonicalLocalResourcePath);
                }
            }

            // Allow the online lookup to choose best matching language for metadata
            if (movieInfo.Languages.Count == 0)
            {
                IList <MultipleMediaItemAspect> audioAspects;
                if (MediaItemAspect.TryGetAspects(extractedAspectData, VideoAudioStreamAspect.Metadata, out audioAspects))
                {
                    foreach (MultipleMediaItemAspect aspect in audioAspects)
                    {
                        string language = (string)aspect.GetAttributeValue(VideoAudioStreamAspect.ATTR_AUDIOLANGUAGE);
                        if (!string.IsNullOrEmpty(language) && !movieInfo.Languages.Contains(language))
                        {
                            movieInfo.Languages.Add(language);
                        }
                    }
                }
            }

            if (SkipOnlineSearches && !SkipFanArtDownload)
            {
                MovieInfo tempInfo = movieInfo.Clone();
                if (await OnlineMatcherService.Instance.FindAndUpdateMovieAsync(tempInfo).ConfigureAwait(false))
                {
                    movieInfo.CopyIdsFrom(tempInfo);
                    movieInfo.HasChanged = tempInfo.HasChanged;
                }
            }
            else if (!SkipOnlineSearches)
            {
                await OnlineMatcherService.Instance.FindAndUpdateMovieAsync(movieInfo).ConfigureAwait(false);
            }

            //Asign genre ids
            if (movieInfo.Genres.Count > 0)
            {
                IGenreConverter converter = ServiceRegistration.Get <IGenreConverter>();
                foreach (var genre in movieInfo.Genres)
                {
                    if (!genre.Id.HasValue && converter.GetGenreId(genre.Name, GenreCategory.Movie, null, out int genreId))
                    {
                        genre.Id             = genreId;
                        movieInfo.HasChanged = true;
                    }
                }
            }

            //Send it to the videos section
            if (!SkipOnlineSearches && !movieInfo.HasExternalId)
            {
                return(false);
            }

            //Create custom collection (overrides online collection)
            MovieCollectionInfo collectionInfo = movieInfo.CloneBasicInstance <MovieCollectionInfo>();
            string collectionName;

            if (string.IsNullOrEmpty(collectionInfo.NameId) && CollectionFolderHasFanArt(lfsra, out collectionName))
            {
                collectionInfo = new MovieCollectionInfo();
                collectionInfo.CollectionName = collectionName;
                if (!collectionInfo.CollectionName.IsEmpty)
                {
                    movieInfo.CollectionName = collectionInfo.CollectionName;
                    movieInfo.CopyIdsFrom(collectionInfo); //Reset ID's
                    movieInfo.HasChanged = true;
                }
            }

            if (movieInfo.MovieNameSort.IsEmpty)
            {
                if (!movieInfo.CollectionName.IsEmpty && movieInfo.ReleaseDate.HasValue)
                {
                    movieInfo.MovieNameSort = $"{movieInfo.CollectionName.Text} {movieInfo.ReleaseDate.Value.Year}-{movieInfo.ReleaseDate.Value.Month.ToString("00")}";
                }
                else if (!movieInfo.MovieName.IsEmpty)
                {
                    movieInfo.MovieNameSort = BaseInfo.GetSortTitle(movieInfo.MovieName.Text);
                }
                else
                {
                    movieInfo.MovieNameSort = BaseInfo.GetSortTitle(title);
                }
            }
            movieInfo.SetMetadata(extractedAspectData);

            return(movieInfo.IsBaseInfoPresent);
        }
        public bool TryExtractRelationships(IDictionary <Guid, IList <MediaItemAspect> > aspects, bool importOnly, out IList <RelationshipItem> extractedLinkedAspects)
        {
            extractedLinkedAspects = null;

            MovieInfo movieInfo = new MovieInfo();

            if (!movieInfo.FromMetadata(aspects))
            {
                return(false);
            }

            MovieCollectionInfo cachedCollection;
            Guid collectionId;
            MovieCollectionInfo collectionInfo = movieInfo.CloneBasicInstance <MovieCollectionInfo>();

            if (TryGetInfoFromCache(collectionInfo, out cachedCollection, out collectionId))
            {
                collectionInfo = cachedCollection;
            }
            else if (!MovieMetadataExtractor.SkipOnlineSearches && collectionInfo.HasExternalId)
            {
                OnlineMatcherService.Instance.UpdateCollection(collectionInfo, false, false);
            }

            bool hasId = false;

            if (!MovieMetadataExtractor.SkipOnlineSearches)
            {
                hasId = collectionInfo.HasExternalId || !string.IsNullOrEmpty(movieInfo.CollectionNameId);
            }
            else
            {
                hasId = !string.IsNullOrEmpty(movieInfo.CollectionNameId);
            }

            if (!BaseInfo.HasRelationship(aspects, LinkedRole) && hasId)
            {
                collectionInfo.HasChanged = true; //Force save if no relationship exists
            }
            if (!collectionInfo.HasChanged && !importOnly)
            {
                return(false);
            }

            extractedLinkedAspects = new List <RelationshipItem>();

            IDictionary <Guid, IList <MediaItemAspect> > collectionAspects = new Dictionary <Guid, IList <MediaItemAspect> >();

            if (collectionId != Guid.Empty)
            {
                collectionInfo.SetMetadata(collectionAspects);

                bool movieVirtual = true;
                if (MediaItemAspect.TryGetAttribute(aspects, MediaAspect.ATTR_ISVIRTUAL, false, out movieVirtual))
                {
                    MediaItemAspect.SetAttribute(collectionAspects, MediaAspect.ATTR_ISVIRTUAL, movieVirtual);
                }

                if (collectionAspects.ContainsKey(ExternalIdentifierAspect.ASPECT_ID))
                {
                    extractedLinkedAspects.Add(new RelationshipItem(collectionAspects, collectionId));
                }
            }
            else
            {
                //Create custom collection
                if (!string.IsNullOrEmpty(movieInfo.CollectionNameId) && !collectionInfo.HasExternalId)
                {
                    collectionInfo            = movieInfo.CloneBasicInstance <MovieCollectionInfo>();
                    collectionInfo.HasChanged = true;
                }
                collectionInfo.SetMetadata(collectionAspects);

                bool movieVirtual = true;
                if (MediaItemAspect.TryGetAttribute(aspects, MediaAspect.ATTR_ISVIRTUAL, false, out movieVirtual))
                {
                    MediaItemAspect.SetAttribute(collectionAspects, MediaAspect.ATTR_ISVIRTUAL, movieVirtual);
                }

                if (collectionAspects.ContainsKey(ExternalIdentifierAspect.ASPECT_ID))
                {
                    extractedLinkedAspects.Add(new RelationshipItem(collectionAspects, Guid.Empty));
                }
            }

            return(extractedLinkedAspects.Count > 0);
        }