Ejemplo n.º 1
0
        public static async Task <string> TryMatchTmdbIdAsync(ILocalFsResourceAccessor folderOrFileLfsra)
        {
            // Calling EnsureLocalFileSystemAccess not necessary; only string operation
            string extensionLower = StringUtils.TrimToEmpty(Path.GetExtension(folderOrFileLfsra.LocalFileSystemPath)).ToLower();

            if (!MatroskaConsts.MATROSKA_VIDEO_EXTENSIONS.Contains(extensionLower))
            {
                return(null);
            }

            MatroskaBinaryReader mkvReader = new MatroskaBinaryReader(folderOrFileLfsra);
            // Add keys to be extracted to tags dictionary, matching results will returned as value
            Dictionary <string, IList <string> > tagsToExtract = MatroskaConsts.DefaultVideoTags;
            await mkvReader.ReadTagsAsync(tagsToExtract).ConfigureAwait(false);

            if (tagsToExtract[MatroskaConsts.TAG_MOVIE_TMDB_ID] != null)
            {
                foreach (string candidate in tagsToExtract[MatroskaConsts.TAG_MOVIE_TMDB_ID])
                {
                    if (int.TryParse(candidate, out int tmdbIdInt))
                    {
                        return(tmdbIdInt.ToString());
                    }
                }
            }

            return(null);
        }
Ejemplo n.º 2
0
        public void TestMatroskaBinaryStereoscopicInfo()
        {
            // Arrange
            MatroskaBinaryReader matroskaInfoReader = GetMatroskaBinaryFileReader();

            // Act
            MatroskaConsts.StereoMode actualStereoMode = matroskaInfoReader.ReadStereoModeAsync().Result;

            // Assert
            Assert.AreEqual(MatroskaConsts.StereoMode.SBSLeftEyeFirst, actualStereoMode);
        }
Ejemplo n.º 3
0
        public void TestMatroskaBinaryAttachmentInfo()
        {
            // Arrange
            MatroskaBinaryReader matroskaInfoReader = GetMatroskaBinaryFileReader();

            // Act
            matroskaInfoReader.ReadAttachmentsAsync().Wait();

            // Assert
            Assert.IsTrue(matroskaInfoReader.GetAttachmentByNameAsync("cover.").Result.Length > 0);
            Assert.IsTrue(matroskaInfoReader.GetAttachmentByNameAsync("banner.").Result.Length > 0);
            Assert.IsTrue(matroskaInfoReader.GetAttachmentByNameAsync("poster.").Result.Length > 0);
            Assert.IsTrue(matroskaInfoReader.GetAttachmentByNameAsync("fanart.").Result.Length > 0);
            Assert.IsTrue(matroskaInfoReader.GetAttachmentByNameAsync("clearart.").Result.Length > 0);
            Assert.IsTrue(matroskaInfoReader.GetAttachmentByNameAsync("clearlogo.").Result.Length > 0);
        }
Ejemplo n.º 4
0
        public void TestMatroskaBinaryTagInfo()
        {
            // Arrange
            MatroskaBinaryReader matroskaInfoReader = GetMatroskaBinaryFileReader();
            var tags = MatroskaConsts.DefaultVideoTags;

            // Act
            matroskaInfoReader.ReadTagsAsync(tags).Wait();

            // Assert
            Assert.AreEqual("Test Title", tags[MatroskaConsts.TAG_SIMPLE_TITLE].First());
            Assert.AreEqual("Doctor Who", tags[MatroskaConsts.TAG_SERIES_TITLE].First());
            Assert.AreEqual("76107", tags[MatroskaConsts.TAG_SERIES_TVDB_ID].First());
            Assert.IsTrue(tags[MatroskaConsts.TAG_EPISODE_SUMMARY].First().Length > 0);
            Assert.AreEqual("1963-11-23", tags[MatroskaConsts.TAG_EPISODE_YEAR].First());
            Assert.AreEqual("Doctor Who", tags[MatroskaConsts.TAG_EPISODE_TITLE].First());
            Assert.AreEqual("1", tags[MatroskaConsts.TAG_EPISODE_NUMBER].First());
            Assert.AreEqual("tt0056751", tags[MatroskaConsts.TAG_MOVIE_IMDB_ID].First());
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Reads all mkv tag images and caches them in the <see cref="IFanArtCache"/> service.
        /// </summary>
        /// <param name="lfsra"><see cref="ILocalFsResourceAccessor>"/> for the file.</param>
        /// <param name="mediaItemId">Id of the media item.</param>
        /// <param name="title">Title of the media item.</param>
        /// <returns><see cref="Task"/> that completes when the images have been cached.</returns>
        protected async Task ExtractMkvFanArt(ILocalFsResourceAccessor lfsra, Guid mediaItemId, string title)
        {
            if (lfsra == null)
            {
                return;
            }

            MatroskaBinaryReader mkvReader   = new MatroskaBinaryReader(lfsra);
            IFanArtCache         fanArtCache = ServiceRegistration.Get <IFanArtCache>();

            foreach (var pattern in MKV_PATTERNS)
            {
                byte[] binaryData = await mkvReader.GetAttachmentByNameAsync(pattern.Item1).ConfigureAwait(false);

                if (binaryData == null)
                {
                    continue;
                }
                string filename = pattern + Path.GetFileNameWithoutExtension(lfsra.LocalFileSystemPath);
                await fanArtCache.TrySaveFanArt(mediaItemId, title, pattern.Item2, p => TrySaveFileImage(binaryData, p, filename)).ConfigureAwait(false);
            }
        }
Ejemplo n.º 6
0
        public bool TryGetFanArt(string mediaType, string fanArtType, string name, int maxWidth, int maxHeight, bool singleRandom, out IList <FanArtImage> result)
        {
            result = null;
            Guid mediaItemId;

            if (!Guid.TryParse(name, out mediaItemId))
            {
                return(false);
            }

            IMediaLibrary mediaLibrary = ServiceRegistration.Get <IMediaLibrary>(false);

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

            IFilter           filter = new MediaItemIdFilter(mediaItemId);
            IList <MediaItem> items  = mediaLibrary.Search(new MediaItemQuery(NECESSARY_MIAS, filter), false, null, true);

            if (items == null || items.Count == 0)
            {
                return(false);
            }

            MediaItem mediaItem = items.First();

            // Virtual resources won't have any local fanart
            if (mediaItem.IsVirtual)
            {
                return(false);
            }
            var            resourceLocator = mediaItem.GetResourceLocator();
            string         fileSystemPath  = string.Empty;
            IList <string> patterns        = new List <string>();

            switch (fanArtType)
            {
            case FanArtTypes.Banner:
                patterns.Add("banner.");
                break;

            case FanArtTypes.ClearArt:
                patterns.Add("clearart.");
                break;

            case FanArtTypes.Poster:
            case FanArtTypes.Thumbnail:
                patterns.Add("cover.");
                patterns.Add("poster.");
                patterns.Add("folder.");
                break;

            case FanArtTypes.FanArt:
                patterns.Add("backdrop.");
                patterns.Add("fanart.");
                break;

            case FanArtTypes.Logo:
                patterns.Add("clearlogo.");
                break;

            default:
                return(false);
            }
            // File based access
            try
            {
                using (var accessor = resourceLocator?.CreateAccessor())
                {
                    ILocalFsResourceAccessor fsra = accessor as ILocalFsResourceAccessor;
                    if (fsra != null)
                    {
                        var ext = Path.GetExtension(fsra.LocalFileSystemPath);
                        if (!SUPPORTED_EXTENSIONS.Contains(ext))
                        {
                            return(false);
                        }

                        MatroskaBinaryReader mkvReader = new MatroskaBinaryReader(fsra);
                        foreach (string pattern in patterns)
                        {
                            byte[] binaryData = mkvReader.GetAttachmentByNameAsync(pattern).Result;
                            if (binaryData != null)
                            {
                                result = new List <FanArtImage> {
                                    new FanArtImage(name, binaryData)
                                };
                                return(true);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                ServiceRegistration.Get <ILogger>().Warn("MkvAttachmentsProvider: Exception while reading mkv attachment of type '{0}' from '{1}'", ex, fanArtType, fileSystemPath);
            }
            return(false);
        }
Ejemplo n.º 7
0
        public static async Task <bool> ExtractFromTagsAsync(ILocalFsResourceAccessor folderOrFileLfsra, MovieInfo movieInfo)
        {
            // Calling EnsureLocalFileSystemAccess not necessary; only string operation
            string extensionLower = StringUtils.TrimToEmpty(Path.GetExtension(folderOrFileLfsra.LocalFileSystemPath)).ToLower();

            if (!MatroskaConsts.MATROSKA_VIDEO_EXTENSIONS.Contains(extensionLower))
            {
                return(false);
            }

            // Try to get extended information out of matroska files)
            MatroskaBinaryReader mkvReader = new MatroskaBinaryReader(folderOrFileLfsra);
            // Add keys to be extracted to tags dictionary, matching results will returned as value
            Dictionary <string, IList <string> > tagsToExtract = MatroskaConsts.DefaultVideoTags;
            await mkvReader.ReadTagsAsync(tagsToExtract).ConfigureAwait(false);

            // Read plot
            IList <string> tags = tagsToExtract[MatroskaConsts.TAG_EPISODE_SUMMARY];
            string         plot = tags != null?tags.FirstOrDefault() : string.Empty;

            if (!string.IsNullOrEmpty(plot))
            {
                movieInfo.HasChanged |= MetadataUpdater.SetOrUpdateString(ref movieInfo.Summary, plot, true);
            }

            // Read genre
            tags = tagsToExtract[MatroskaConsts.TAG_SERIES_GENRE];
            if (tags != null)
            {
                List <GenreInfo> genreList = tags.Where(s => !string.IsNullOrEmpty(s?.Trim())).Select(s => new GenreInfo {
                    Name = s.Trim()
                }).ToList();
                movieInfo.HasChanged |= MetadataUpdater.SetOrUpdateList(movieInfo.Genres, genreList, movieInfo.Genres.Count == 0);
            }

            // Read actors
            tags = tagsToExtract[MatroskaConsts.TAG_ACTORS];
            if (tags != null)
            {
                movieInfo.HasChanged |= MetadataUpdater.SetOrUpdateList(movieInfo.Actors,
                                                                        tags.Select(t => new PersonInfo()
                {
                    Name = t, Occupation = PersonAspect.OCCUPATION_ACTOR, MediaName = movieInfo.MovieName.Text
                }).ToList(), false);
            }

            tags = tagsToExtract[MatroskaConsts.TAG_DIRECTORS];
            if (tags != null)
            {
                movieInfo.HasChanged |= MetadataUpdater.SetOrUpdateList(movieInfo.Directors,
                                                                        tags.Select(t => new PersonInfo()
                {
                    Name = t, Occupation = PersonAspect.OCCUPATION_DIRECTOR, MediaName = movieInfo.MovieName.Text
                }).ToList(), false);
            }

            tags = tagsToExtract[MatroskaConsts.TAG_WRITTEN_BY];
            if (tags != null)
            {
                movieInfo.HasChanged |= MetadataUpdater.SetOrUpdateList(movieInfo.Writers,
                                                                        tags.Select(t => new PersonInfo()
                {
                    Name = t, Occupation = PersonAspect.OCCUPATION_WRITER, MediaName = movieInfo.MovieName.Text
                }).ToList(), false);
            }

            if (tagsToExtract[MatroskaConsts.TAG_MOVIE_IMDB_ID] != null)
            {
                string imdbId;
                foreach (string candidate in tagsToExtract[MatroskaConsts.TAG_MOVIE_IMDB_ID])
                {
                    if (ImdbIdMatcher.TryMatchImdbId(candidate, out imdbId))
                    {
                        movieInfo.HasChanged |= MetadataUpdater.SetOrUpdateId(ref movieInfo.ImdbId, imdbId);
                        break;
                    }
                }
            }
            if (tagsToExtract[MatroskaConsts.TAG_MOVIE_TMDB_ID] != null)
            {
                int tmp;
                foreach (string candidate in tagsToExtract[MatroskaConsts.TAG_MOVIE_TMDB_ID])
                {
                    if (int.TryParse(candidate, out tmp) == true)
                    {
                        movieInfo.HasChanged |= MetadataUpdater.SetOrUpdateId(ref movieInfo.MovieDbId, tmp);
                        break;
                    }
                }
            }

            return(true);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Tries to match series by reading matroska tags from <paramref name="folderOrFileLfsra"/>.
        /// </summary>
        /// <param name="folderOrFileLfsra"><see cref="ILocalFsResourceAccessor"/> to file or folder</param>
        /// <param name="episodeInfo">Returns the parsed EpisodeInfo</param>
        /// <param name="extractedAspectData">Dictionary containing a mapping of media item aspect ids to
        /// already present media item aspects, this metadata extractor should edit. If a media item aspect is not present
        /// in this dictionary but found by this metadata extractor, it will add it to the dictionary.</param>
        /// <returns><c>true</c> if successful.</returns>
        public async Task <bool> MatchSeriesAsync(ILocalFsResourceAccessor folderOrFileLfsra, EpisodeInfo episodeInfo)
        {
            // Calling EnsureLocalFileSystemAccess not necessary; only string operation
            string extensionLower = StringUtils.TrimToEmpty(Path.GetExtension(folderOrFileLfsra.LocalFileSystemPath)).ToLower();

            if (!MatroskaConsts.MATROSKA_VIDEO_EXTENSIONS.Contains(extensionLower))
            {
                return(false);
            }

            MatroskaBinaryReader mkvReader = new MatroskaBinaryReader(folderOrFileLfsra);
            // Add keys to be extracted to tags dictionary, matching results will returned as value
            Dictionary <string, IList <string> > tagsToExtract = MatroskaConsts.DefaultVideoTags;
            await mkvReader.ReadTagsAsync(tagsToExtract).ConfigureAwait(false);

            IList <string> tags = tagsToExtract[MatroskaConsts.TAG_EPISODE_SUMMARY];
            string         plot = tags != null?tags.FirstOrDefault() : string.Empty;

            if (!string.IsNullOrEmpty(plot))
            {
                episodeInfo.HasChanged |= MetadataUpdater.SetOrUpdateString(ref episodeInfo.Summary, plot, true);
            }

            // Series and episode handling. Prefer information from tags.
            if (tagsToExtract[MatroskaConsts.TAG_EPISODE_TITLE] != null)
            {
                string title = tagsToExtract[MatroskaConsts.TAG_EPISODE_TITLE].FirstOrDefault();
                if (!string.IsNullOrEmpty(title))
                {
                    title = CultureInfo.InvariantCulture.TextInfo.ToTitleCase(title);
                    episodeInfo.HasChanged |= MetadataUpdater.SetOrUpdateString(ref episodeInfo.EpisodeName, title, true);
                }
            }

            if (tagsToExtract[MatroskaConsts.TAG_SERIES_TITLE] != null)
            {
                string title = tagsToExtract[MatroskaConsts.TAG_SERIES_TITLE].FirstOrDefault();
                if (!string.IsNullOrEmpty(title))
                {
                    title = CultureInfo.InvariantCulture.TextInfo.ToTitleCase(title);
                    episodeInfo.HasChanged |= MetadataUpdater.SetOrUpdateString(ref episodeInfo.SeriesName, title, true);
                }
            }

            if (tagsToExtract[MatroskaConsts.TAG_SERIES_IMDB_ID] != null)
            {
                string imdbId;
                foreach (string candidate in tagsToExtract[MatroskaConsts.TAG_SERIES_IMDB_ID])
                {
                    if (ImdbIdMatcher.TryMatchImdbId(candidate, out imdbId))
                    {
                        episodeInfo.HasChanged |= MetadataUpdater.SetOrUpdateId(ref episodeInfo.SeriesImdbId, imdbId);
                        break;
                    }
                }
            }

            if (tagsToExtract[MatroskaConsts.TAG_SERIES_ACTORS] != null)
            {
                episodeInfo.HasChanged |= MetadataUpdater.SetOrUpdateList(episodeInfo.Actors,
                                                                          tagsToExtract[MatroskaConsts.TAG_SERIES_ACTORS].Select(t => new PersonInfo()
                {
                    Name      = t, Occupation = PersonAspect.OCCUPATION_ACTOR,
                    MediaName = episodeInfo.EpisodeName.Text, ParentMediaName = episodeInfo.SeriesName.Text
                }).ToList(), false);
            }

            // On Series, the counting tag is "TVDB"
            if (tagsToExtract[MatroskaConsts.TAG_SERIES_TVDB_ID] != null)
            {
                int tmp;
                foreach (string candidate in tagsToExtract[MatroskaConsts.TAG_SERIES_TVDB_ID])
                {
                    if (int.TryParse(candidate, out tmp) == true)
                    {
                        episodeInfo.HasChanged |= MetadataUpdater.SetOrUpdateId(ref episodeInfo.SeriesTvdbId, tmp);
                        break;
                    }
                }
            }

            int tmpInt;

            if (tagsToExtract[MatroskaConsts.TAG_SEASON_NUMBER] != null && int.TryParse(tagsToExtract[MatroskaConsts.TAG_SEASON_NUMBER].FirstOrDefault(), out tmpInt))
            {
                episodeInfo.HasChanged |= MetadataUpdater.SetOrUpdateValue(ref episodeInfo.SeasonNumber, tmpInt);
            }

            if (tagsToExtract[MatroskaConsts.TAG_EPISODE_NUMBER] != null)
            {
                int episodeNum;

                foreach (string s in tagsToExtract[MatroskaConsts.TAG_EPISODE_NUMBER])
                {
                    if (int.TryParse(s, out episodeNum))
                    {
                        if (!episodeInfo.EpisodeNumbers.Contains(episodeNum))
                        {
                            episodeInfo.EpisodeNumbers.Add(episodeNum);
                        }
                    }
                }
            }

            return(true);
        }