public MockedDatabaseMovie(MediaLibraryMovie movie, int playPercentage) { IDictionary <Guid, IList <MediaItemAspect> > movieAspects = new Dictionary <Guid, IList <MediaItemAspect> >(); MultipleMediaItemAspect resourceAspect = new MultipleMediaItemAspect(ProviderResourceAspect.Metadata); resourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH, "c:\\" + movie.Title + ".mkv"); MediaItemAspect.AddOrUpdateAspect(movieAspects, resourceAspect); MediaItemAspect.AddOrUpdateExternalIdentifier(movieAspects, ExternalIdentifierAspect.SOURCE_IMDB, ExternalIdentifierAspect.TYPE_MOVIE, movie.Imdb); MediaItemAspect.SetAttribute(movieAspects, MovieAspect.ATTR_MOVIE_NAME, movie.Title); SingleMediaItemAspect mediaItemAspect = new SingleMediaItemAspect(MediaAspect.Metadata); mediaItemAspect.SetAttribute(MediaAspect.ATTR_PLAYCOUNT, 1); mediaItemAspect.SetAttribute(MediaAspect.ATTR_LASTPLAYED, DateTime.Now); MediaItemAspect.SetAspect(movieAspects, mediaItemAspect); SingleMediaItemAspect importerAspect = new SingleMediaItemAspect(ImporterAspect.Metadata); importerAspect.SetAttribute(ImporterAspect.ATTR_DATEADDED, DateTime.Now); IDictionary <string, string> userData = new Dictionary <string, string>(); userData.Add(UserDataKeysKnown.KEY_PLAY_PERCENTAGE, playPercentage.ToString()); MediaItemAspect.SetAspect(movieAspects, importerAspect); Movie = new MediaItem(Guid.NewGuid(), movieAspects, userData); }
public void TestAudioItem() { IList <IDirectoryObject> objects = new List <IDirectoryObject>(); Guid id = new Guid("11111111-aaaa-aaaa-aaaa-111111111111"); IDictionary <Guid, IList <MediaItemAspect> > aspects = new Dictionary <Guid, IList <MediaItemAspect> >(); SingleMediaItemAspect aspect1 = new SingleMediaItemAspect(MediaAspect.Metadata); aspect1.SetAttribute(MediaAspect.ATTR_TITLE, "The Track"); MediaItemAspect.SetAspect(aspects, aspect1); MultipleMediaItemAspect aspect2 = new MultipleMediaItemAspect(ProviderResourceAspect.Metadata); aspect2.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH, "c:\\file.mp3"); MediaItemAspect.AddOrUpdateAspect(aspects, aspect2); SingleMediaItemAspect aspect3 = new SingleMediaItemAspect(AudioAspect.Metadata); MediaItemAspect.SetAspect(aspects, aspect3); MediaItem item = new MediaItem(id, aspects); objects.Add(MediaLibraryHelper.InstansiateMediaLibraryObject(item, null, null)); GenericDidlMessageBuilder builder = new GenericDidlMessageBuilder(); builder.BuildAll("*", objects); string xml = builder.ToString(); Console.WriteLine("XML: {0}", xml); }
private static void TransferTransientAspects(IDictionary <Guid, IList <MediaItemAspect> > aspects, IEnumerable <MediaItem> destinationMediaItems) { var transientAspects = MediaItemAspect.GetAspects(aspects).Where(mia => mia.Metadata.IsTransientAspect); foreach (MediaItemAspect aspect in transientAspects) { SingleMediaItemAspect singleAspect = aspect as SingleMediaItemAspect; if (singleAspect != null) { foreach (MediaItem destination in destinationMediaItems) { MediaItemAspect.SetAspect(destination.Aspects, singleAspect); } } else { MultipleMediaItemAspect multiAspect = aspect as MultipleMediaItemAspect; if (multiAspect != null) { foreach (MediaItem destination in destinationMediaItems) { MediaItemAspect.AddOrUpdateAspect(destination.Aspects, multiAspect); } } } } }
public void TestExtractThumbnail() { // Arrange string testFileName = "Test Media.mkv"; string testDataDir = TestContext.CurrentContext.TestDirectory + "\\VideoThumbnailer\\TestData\\"; ILocalFsResourceAccessor lfsra = new LocalFsResourceAccessor(new LocalFsResourceProvider(), "/" + Path.Combine(testDataDir, testFileName)); IDictionary <Guid, IList <MediaItemAspect> > aspects = new Dictionary <Guid, IList <MediaItemAspect> >(); MultipleMediaItemAspect videoStreamAspect = new MultipleMediaItemAspect(VideoStreamAspect.Metadata); videoStreamAspect.SetAttribute(VideoStreamAspect.ATTR_RESOURCE_INDEX, 0); videoStreamAspect.SetAttribute(VideoStreamAspect.ATTR_STREAM_INDEX, 1); videoStreamAspect.SetAttribute(VideoStreamAspect.ATTR_DURATION, (long)1); videoStreamAspect.SetAttribute(VideoStreamAspect.ATTR_WIDTH, 1076); videoStreamAspect.SetAttribute(VideoStreamAspect.ATTR_HEIGHT, 1916); MediaItemAspect.AddOrUpdateAspect(aspects, videoStreamAspect); MultipleMediaItemAspect resourceAspect = new MultipleMediaItemAspect(ProviderResourceAspect.Metadata); resourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_INDEX, 0); resourceAspect.SetAttribute(ProviderResourceAspect.ATTR_TYPE, ProviderResourceAspect.TYPE_PRIMARY); resourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH, lfsra.CanonicalLocalResourcePath.Serialize()); MediaItemAspect.AddOrUpdateAspect(aspects, resourceAspect); // Act bool success = new OCVVideoThumbnailer().TryExtractMetadataAsync(lfsra, aspects, false).Result; // Assert Assert.IsTrue(success); Assert.IsTrue(aspects.ContainsKey(ThumbnailLargeAspect.ASPECT_ID)); }
/// <summary> /// Copies the contained person information into MediaItemAspect. /// </summary> /// <param name="aspectData">Dictionary with extracted aspects.</param> public override bool SetMetadata(IDictionary <Guid, IList <MediaItemAspect> > aspectData, bool force = false) { if (!force && !IsBaseInfoPresent) { return(false); } SingleMediaItemAspect subtitleAspect = MediaItemAspect.GetOrCreateAspect(aspectData, TempSubtitleAspect.Metadata); subtitleAspect.SetAttribute(TempSubtitleAspect.ATTR_PROVIDER, string.Join(";", DataProviders)); subtitleAspect.SetAttribute(TempSubtitleAspect.ATTR_CATEGORY, string.Join(";", Categories)); subtitleAspect.SetAttribute(TempSubtitleAspect.ATTR_NAME, Name); subtitleAspect.SetAttribute(TempSubtitleAspect.ATTR_DISPLAY_NAME, DisplayName); subtitleAspect.SetAttribute(TempSubtitleAspect.ATTR_SUBTITLEID, SubtitleId); subtitleAspect.SetAttribute(TempSubtitleAspect.ATTR_LANGUAGE, Language); int idx = 0; foreach (var mediaFile in MediaFiles) { MultipleMediaItemAspect resourceAspect = MediaItemAspect.CreateAspect(aspectData, ProviderResourceAspect.Metadata); resourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_INDEX, idx++); resourceAspect.SetAttribute(ProviderResourceAspect.ATTR_TYPE, ProviderResourceAspect.TYPE_PRIMARY); resourceAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, "subtitle/unknown"); resourceAspect.SetAttribute(ProviderResourceAspect.ATTR_SYSTEM_ID, mediaFile.NativeSystemId); resourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH, mediaFile.NativeResourcePath.Serialize()); } return(true); }
public PlaylistItem(VideoViewModel videoInfo, string resolvedPlaybackUrl) : base(Guid.Empty, new Dictionary <Guid, IList <MediaItemAspect> > { { ProviderResourceAspect.ASPECT_ID, new MediaItemAspect[] { new MultipleMediaItemAspect(ProviderResourceAspect.Metadata) } }, { MediaAspect.ASPECT_ID, new MediaItemAspect[] { new SingleMediaItemAspect(MediaAspect.Metadata) } }, { VideoAspect.ASPECT_ID, new MediaItemAspect[] { new SingleMediaItemAspect(VideoAspect.Metadata) } }, { OnlineVideosAspect.ASPECT_ID, new MediaItemAspect[] { new SingleMediaItemAspect(OnlineVideosAspect.Metadata) } }, }) { SiteName = videoInfo.SiteName; VideoInfo = videoInfo.VideoInfo; Aspects[OnlineVideosAspect.ASPECT_ID].First().SetAttribute(OnlineVideosAspect.ATTR_SITEUTIL, SiteName); ISystemResolver systemResolver = ServiceRegistration.Get <ISystemResolver>(); IList <MultipleMediaItemAspect> providerResourceAspects; MediaItemAspect.TryGetAspects(Aspects, ProviderResourceAspect.Metadata, out providerResourceAspects); MultipleMediaItemAspect providerResourceAspect = providerResourceAspects.First(); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_PRIMARY, true); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_SYSTEM_ID, systemResolver.LocalSystemId); if (videoInfo.SiteUtilName == "DownloadedVideo") { providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH, LocalFsResourceProviderBase.ToResourcePath(resolvedPlaybackUrl).Serialize()); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, "video/unknown"); } else { Uri uri; // Test if the resolved "url" is a real Uri (Sites can provide any content here) var isUriSource = Uri.TryCreate(resolvedPlaybackUrl, UriKind.Absolute, out uri); var value = isUriSource ? RawUrlResourceProvider.ToProviderResourcePath(resolvedPlaybackUrl).Serialize() : RawTokenResourceProvider.ToProviderResourcePath(resolvedPlaybackUrl).Serialize(); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH, value); Aspects[OnlineVideosAspect.ASPECT_ID].First().SetAttribute(OnlineVideosAspect.ATTR_LONGURL, value); var isBrowser = videoInfo.SiteSettings.Player == PlayerType.Browser; providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, isBrowser ? WebBrowserVideoPlayer.ONLINEVIDEOSBROWSER_MIMETYPE : OnlineVideosPlayer.ONLINEVIDEOS_MIMETYPE); } MediaItemAspect.SetAttribute(Aspects, MediaAspect.ATTR_TITLE, videoInfo.Title); // TODO: Restore line after story plot was moved back to VideoAspect! // MediaItemAspect.SetAttribute(aspects, VideoAspect.ATTR_STORYPLOT, videoInfo.Description); DateTime parsedAirDate; if (DateTime.TryParse(videoInfo.VideoInfo.Airdate, out parsedAirDate)) { MediaItemAspect.SetAttribute(Aspects, MediaAspect.ATTR_RECORDINGTIME, parsedAirDate); } }
/// <summary> /// Tries to write metadata into <see cref="GenreAspect.ATTR_GENRE"/> /// </summary> /// <param name="extractedAspectData">Dictionary of <see cref="MediaItemAspect"/>s to write into</param> /// <returns><c>true</c> if any information was written; otherwise <c>false</c></returns> private bool TryWriteAlbumAspectGenres(IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData) { if (_stubs[0].Genres != null && _stubs[0].Genres.Any()) { List <GenreInfo> genres = _stubs[0].Genres.Where(s => !string.IsNullOrEmpty(s?.Trim())).Select(s => new GenreInfo { Name = s.Trim() }).ToList(); IGenreConverter converter = ServiceRegistration.Get <IGenreConverter>(); foreach (var genre in genres) { if (!genre.Id.HasValue && converter.GetGenreId(genre.Name, GenreCategory.Music, null, out int genreId)) { genre.Id = genreId; } } foreach (GenreInfo genre in genres) { MultipleMediaItemAspect genreAspect = MediaItemAspect.CreateAspect(extractedAspectData, GenreAspect.Metadata); genreAspect.SetAttribute(GenreAspect.ATTR_ID, genre.Id); genreAspect.SetAttribute(GenreAspect.ATTR_GENRE, genre.Name); } return(true); } return(false); }
/// <summary> /// Checks if the current MediaItem contains fps information, if not it tries to get it from /// the source filter. /// </summary> protected virtual void UpdateVideoFps() { IList <MultipleMediaItemAspect> videoAspects; // If there are VideoStreamAspects we don't need to fill it. if (_mediaItem == null || MediaItemAspect.TryGetAspects(_mediaItem.Aspects, VideoStreamAspect.Metadata, out videoAspects)) { return; } using (DSFilter d = new DSFilter((IBaseFilter)_tsReader)) { // Would release the filter which causes errors in later access (like stream enumeration) d.ReleaseOnDestroy = false; var videoOutPin = d.Pins.FirstOrDefault(p => p.Direction == PinDirection.Output && p.ConnectionMediaType?.majorType == MediaType.Video); if (videoOutPin != null) { const long nTenMillion = 10000000; long avgTimePerFrameHns = videoOutPin.ConnectionMediaType.GetFrameRate(); if (avgTimePerFrameHns == 0) { return; } float fps = (float)nTenMillion / avgTimePerFrameHns; MultipleMediaItemAspect videoStreamAspects = MediaItemAspect.CreateAspect(_mediaItem.Aspects, VideoStreamAspect.Metadata); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_RESOURCE_INDEX, 0); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_STREAM_INDEX, 0); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_FPS, fps); } } }
private static void SetProviderResourceAspect(string resolvedPlaybackUrl, MediaItem item, string mimeType) { MultipleMediaItemAspect providerResourceAspect = MediaItemAspect.CreateAspect(item.Aspects, ProviderResourceAspect.Metadata); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_SYSTEM_ID, ServiceRegistration.Get <ISystemResolver>().LocalSystemId); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH, RawUrlResourceProvider.ToProviderResourcePath(resolvedPlaybackUrl).Serialize()); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, mimeType); }
public static void StorePersons(IDictionary <Guid, IList <MediaItemAspect> > aspects, List <PersonInfo> infoPersons, bool forAlbum) { foreach (PersonInfo person in infoPersons) { MultipleMediaItemAspect personAspect = MediaItemAspect.CreateAspect(aspects, TempPersonAspect.Metadata); personAspect.SetAttribute(TempPersonAspect.ATTR_MBID, person.MusicBrainzId); personAspect.SetAttribute(TempPersonAspect.ATTR_NAME, person.Name); personAspect.SetAttribute(TempPersonAspect.ATTR_OCCUPATION, person.Occupation); personAspect.SetAttribute(TempPersonAspect.ATTR_FROMALBUM, forAlbum); } }
public static void SetVideoMetaData(this MediaItem item, DmapData metaData) { MediaItemAspect.SetAttribute(item.Aspects, MediaAspect.ATTR_TITLE, metaData.Title); MediaItemAspect.SetCollectionAttribute(item.Aspects, VideoAspect.ATTR_ACTORS, metaData.Actors); foreach (string genre in metaData.Genres) { MultipleMediaItemAspect genreAspect = MediaItemAspect.CreateAspect(item.Aspects, GenreAspect.Metadata); genreAspect.SetAttribute(GenreAspect.ATTR_GENRE, genre); } MediaItemAspect.SetCollectionAttribute(item.Aspects, VideoAspect.ATTR_DIRECTORS, metaData.Directors); }
public static void StoreCharacters(IDictionary <Guid, IList <MediaItemAspect> > aspects, List <CharacterInfo> infoCharacters, bool forSeries) { foreach (CharacterInfo character in infoCharacters) { MultipleMediaItemAspect personAspect = MediaItemAspect.CreateAspect(aspects, TempPersonAspect.Metadata); personAspect.SetAttribute(TempPersonAspect.ATTR_IMDBID, character.ActorImdbId); personAspect.SetAttribute(TempPersonAspect.ATTR_NAME, character.ActorName); personAspect.SetAttribute(TempPersonAspect.ATTR_CHARACTER, character.Name); personAspect.SetAttribute(TempPersonAspect.ATTR_ORDER, character.Order); personAspect.SetAttribute(TempPersonAspect.ATTR_FROMSERIES, forSeries); } }
public static void SetAudioMetaData(this MediaItem item, DmapData metaData) { MediaItemAspect.SetAttribute(item.Aspects, MediaAspect.ATTR_TITLE, metaData.Title); MediaItemAspect.SetAttribute(item.Aspects, AudioAspect.ATTR_ALBUM, metaData.Album); MediaItemAspect.SetCollectionAttribute(item.Aspects, AudioAspect.ATTR_ARTISTS, metaData.Artists); foreach (string genre in metaData.Genres) { MultipleMediaItemAspect genreAspect = MediaItemAspect.CreateAspect(item.Aspects, GenreAspect.Metadata); genreAspect.SetAttribute(GenreAspect.ATTR_GENRE, genre); } MediaItemAspect.SetAttribute(item.Aspects, AudioAspect.ATTR_TRACK, metaData.OriginalTrackNumber); MediaItemAspect.SetAttribute(item.Aspects, AudioAspect.ATTR_NUMDISCS, metaData.OriginalDiscCount); }
public static void StorePersonAndCharacter(IDictionary <Guid, IList <MediaItemAspect> > aspects, PersonStub person, string occupation, bool forSeries) { MultipleMediaItemAspect personAspect = MediaItemAspect.CreateAspect(aspects, TempPersonAspect.Metadata); personAspect.SetAttribute(TempPersonAspect.ATTR_IMDBID, person.ImdbId); personAspect.SetAttribute(TempPersonAspect.ATTR_NAME, person.Name); personAspect.SetAttribute(TempPersonAspect.ATTR_OCCUPATION, occupation); personAspect.SetAttribute(TempPersonAspect.ATTR_CHARACTER, person.Role); personAspect.SetAttribute(TempPersonAspect.ATTR_BIOGRAPHY, !string.IsNullOrEmpty(person.Biography) ? person.Biography : person.MiniBiography); personAspect.SetAttribute(TempPersonAspect.ATTR_DATEOFBIRTH, person.Birthdate); personAspect.SetAttribute(TempPersonAspect.ATTR_DATEOFDEATH, person.Deathdate); personAspect.SetAttribute(TempPersonAspect.ATTR_ORDER, person.Order); personAspect.SetAttribute(TempPersonAspect.ATTR_ORIGIN, person.Birthplace); personAspect.SetAttribute(TempPersonAspect.ATTR_FROMSERIES, forSeries); }
public static void StorePersons(IDictionary <Guid, IList <MediaItemAspect> > aspects, List <PersonInfo> infoPersons, bool forSeries) { foreach (PersonInfo person in infoPersons) { MultipleMediaItemAspect personAspect = MediaItemAspect.CreateAspect(aspects, TempPersonAspect.Metadata); personAspect.SetAttribute(TempPersonAspect.ATTR_IMDBID, person.ImdbId); personAspect.SetAttribute(TempPersonAspect.ATTR_NAME, person.Name); personAspect.SetAttribute(TempPersonAspect.ATTR_OCCUPATION, person.Occupation); personAspect.SetAttribute(TempPersonAspect.ATTR_BIOGRAPHY, person.Biography); personAspect.SetAttribute(TempPersonAspect.ATTR_DATEOFBIRTH, person.DateOfBirth); personAspect.SetAttribute(TempPersonAspect.ATTR_DATEOFDEATH, person.DateOfDeath); personAspect.SetAttribute(TempPersonAspect.ATTR_ORDER, person.Order); personAspect.SetAttribute(TempPersonAspect.ATTR_ORIGIN, person.Orign); personAspect.SetAttribute(TempPersonAspect.ATTR_FROMSERIES, forSeries); } }
private static LiveTvMediaItem.LiveTvMediaItem CreateCommonMediaItem(int slotIndex, string path, bool isTv, string customMimeType = null) { ISystemResolver systemResolver = ServiceRegistration.Get <ISystemResolver>(); IDictionary <Guid, IList <MediaItemAspect> > aspects = new Dictionary <Guid, IList <MediaItemAspect> >(); SlimTvResourceAccessor resourceAccessor = new SlimTvResourceAccessor(slotIndex, path); MultipleMediaItemAspect providerResourceAspect = MediaItemAspect.CreateAspect(aspects, ProviderResourceAspect.Metadata); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_TYPE, ProviderResourceAspect.TYPE_PRIMARY); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_SYSTEM_ID, systemResolver.LocalSystemId); String raPath = resourceAccessor.CanonicalLocalResourcePath.Serialize(); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH, raPath); string title; string mimeType; if (isTv) { // VideoAspect needs to be included to associate VideoPlayer later! MediaItemAspect.GetOrCreateAspect(aspects, VideoAspect.Metadata); title = "Live TV"; mimeType = LiveTvMediaItem.LiveTvMediaItem.MIME_TYPE_TV; } else { // AudioAspect needs to be included to associate an AudioPlayer later! MediaItemAspect.GetOrCreateAspect(aspects, AudioAspect.Metadata); title = "Live Radio"; mimeType = LiveTvMediaItem.LiveTvMediaItem.MIME_TYPE_RADIO; } // Allow overriding from argument if (!string.IsNullOrEmpty(customMimeType)) { mimeType = customMimeType; } MediaItemAspect.SetAttribute(aspects, MediaAspect.ATTR_TITLE, title); MediaItemAspect.SetAttribute(aspects, MediaAspect.ATTR_SORT_TITLE, BaseInfo.GetSortTitle(title)); MediaItemAspect.SetAttribute(aspects, MediaAspect.ATTR_ISVIRTUAL, false); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, mimeType); // Custom mimetype for LiveTv or Radio LiveTvMediaItem.LiveTvMediaItem tvStream = new LiveTvMediaItem.LiveTvMediaItem(new Guid(), aspects); return(tvStream); }
public void TestConvenienceMethod() { IDictionary <Guid, IList <MediaItemAspect> > aspects = new Dictionary <Guid, IList <MediaItemAspect> >(); MultipleMediaItemAspect providerAspect = MediaItemAspect.CreateAspect(aspects, ProviderResourceAspect.Metadata); providerAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_INDEX, 0); providerAspect.SetAttribute(ProviderResourceAspect.ATTR_PRIMARY, true); providerAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, "audio/mp3"); Assert.AreEqual(aspects.Keys.Count, 1, "aspect key count"); IList <MultipleMediaItemAspect> providerAspects2; Assert.IsTrue(MediaItemAspect.TryGetAspects(aspects, ProviderResourceAspect.Metadata, out providerAspects2), "ProviderResource"); Assert.AreEqual("audio/mp3", providerAspects2[0][ProviderResourceAspect.ATTR_MIME_TYPE], "MIME type"); }
public MockedDatabaseMovie(string imdbId, string tmdbId, string title, int year, int playPercentage) { IDictionary <Guid, IList <MediaItemAspect> > movieAspects = new Dictionary <Guid, IList <MediaItemAspect> >(); MultipleMediaItemAspect resourceAspect = new MultipleMediaItemAspect(ProviderResourceAspect.Metadata); resourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH, "c:\\" + title + ".mkv"); MediaItemAspect.AddOrUpdateAspect(movieAspects, resourceAspect); MediaItemAspect.AddOrUpdateExternalIdentifier(movieAspects, ExternalIdentifierAspect.SOURCE_IMDB, ExternalIdentifierAspect.TYPE_MOVIE, imdbId); MediaItemAspect.AddOrUpdateExternalIdentifier(movieAspects, ExternalIdentifierAspect.SOURCE_TMDB, ExternalIdentifierAspect.TYPE_MOVIE, tmdbId); MediaItemAspect.SetAttribute(movieAspects, MovieAspect.ATTR_MOVIE_NAME, title); SingleMediaItemAspect smia = new SingleMediaItemAspect(MediaAspect.Metadata); smia.SetAttribute(MediaAspect.ATTR_RECORDINGTIME, new DateTime(year, 1, 1)); MediaItemAspect.SetAspect(movieAspects, smia); IDictionary <string, string> userData = new Dictionary <string, string>(); userData.Add(UserDataKeysKnown.KEY_PLAY_PERCENTAGE, playPercentage.ToString()); Movie = new MediaItem(Guid.NewGuid(), movieAspects, userData); }
public MockedDatabaseEpisode(string tvDbId, int seasonIndex, List <int> episodeIndex, int playPercentage) { IDictionary <Guid, IList <MediaItemAspect> > episodeAspects = new Dictionary <Guid, IList <MediaItemAspect> >(); MultipleMediaItemAspect resourceAspect = new MultipleMediaItemAspect(ProviderResourceAspect.Metadata); resourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH, "c:\\" + tvDbId + ".mkv"); MediaItemAspect.AddOrUpdateAspect(episodeAspects, resourceAspect); MediaItemAspect.AddOrUpdateExternalIdentifier(episodeAspects, ExternalIdentifierAspect.SOURCE_TVDB, ExternalIdentifierAspect.TYPE_SERIES, tvDbId); MediaItemAspect.SetAttribute(episodeAspects, EpisodeAspect.ATTR_SEASON, seasonIndex); MediaItemAspect.SetCollectionAttribute(episodeAspects, EpisodeAspect.ATTR_EPISODE, episodeIndex); SingleMediaItemAspect smia = new SingleMediaItemAspect(MediaAspect.Metadata); MediaItemAspect.SetAspect(episodeAspects, smia); IDictionary <string, string> userData = new Dictionary <string, string>(); userData.Add(UserDataKeysKnown.KEY_PLAY_PERCENTAGE, playPercentage.ToString()); Episode = new MediaItem(Guid.NewGuid(), episodeAspects, userData); }
/// <summary> /// Constructs a dynamic <see cref="MediaItem"/> that contains the URL for the given <paramref name="stream"/>. /// </summary> /// <param name="stream">Stream.</param> private static MediaItem CreateStreamMediaItem(MyStream stream) { IDictionary <Guid, IList <MediaItemAspect> > aspects = new Dictionary <Guid, IList <MediaItemAspect> >(); MultipleMediaItemAspect providerResourceAspect = MediaItemAspect.CreateAspect(aspects, ProviderResourceAspect.Metadata); SingleMediaItemAspect mediaAspect = MediaItemAspect.GetOrCreateAspect(aspects, MediaAspect.Metadata); SingleMediaItemAspect audioAspect = MediaItemAspect.GetOrCreateAspect(aspects, AudioAspect.Metadata); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_TYPE, ProviderResourceAspect.TYPE_PRIMARY); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH, RawUrlResourceProvider.ToProviderResourcePath(stream.StreamUrls[0].StreamUrl).Serialize()); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_SYSTEM_ID, ServiceRegistration.Get <ISystemResolver>().LocalSystemId); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, WEBRADIO_MIMETYPE); mediaAspect.SetAttribute(MediaAspect.ATTR_TITLE, stream.Title); MediaItemAspect.SetAttribute(aspects, ThumbnailLargeAspect.ATTR_THUMBNAIL, ImageFromLogo(stream.Logo)); var mediaItem = new MediaItem(Guid.Empty, aspects); return(mediaItem); }
/// <summary> /// Constructs a dynamic <see cref="MediaItem"/> that contains the URL for the given <paramref name="trailer"/>. /// </summary> /// <param name="trailer">Trailer.</param> private static MediaItem CreateStreamMediaItem(Trailer trailer) { IDictionary <Guid, IList <MediaItemAspect> > aspects = new Dictionary <Guid, IList <MediaItemAspect> >(); MultipleMediaItemAspect providerResourceAspect = MediaItemAspect.CreateAspect(aspects, ProviderResourceAspect.Metadata); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_PRIMARY, true); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_SYSTEM_ID, ServiceRegistration.Get <ISystemResolver>().LocalSystemId); MediaItemAspect.GetOrCreateAspect(aspects, VideoAspect.Metadata); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH, RawUrlResourceProvider.ToProviderResourcePath(trailer.Url).Serialize()); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_SYSTEM_ID, ServiceRegistration.Get <ISystemResolver>().LocalSystemId); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, CINEMA_MIMETYPE); MediaItemAspect.SetAttribute(aspects, MediaAspect.ATTR_TITLE, trailer.Title); var mediaItem = new MediaItem(Guid.Empty, aspects); return(mediaItem); }
public MediaItem CreateLocalMediaItem(IResourceAccessor mediaItemAccessor, IEnumerable <Guid> metadataExtractorIds) { ISystemResolver systemResolver = ServiceRegistration.Get <ISystemResolver>(); IDictionary <Guid, IList <MediaItemAspect> > aspects = ExtractMetadataAsync(mediaItemAccessor, metadataExtractorIds, true).Result; if (aspects == null) { return(null); } IList <MultipleMediaItemAspect> providerResourceAspects; if (MediaItemAspect.TryGetAspects(aspects, ProviderResourceAspect.Metadata, out providerResourceAspects) && providerResourceAspects.Count > 0) { MultipleMediaItemAspect providerResourceAspect = providerResourceAspects.First(); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_TYPE, ProviderResourceAspect.TYPE_PRIMARY); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_SYSTEM_ID, systemResolver.LocalSystemId); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH, mediaItemAccessor.CanonicalLocalResourcePath.Serialize()); return(new MediaItem(Guid.Empty, aspects)); } return(null); }
public void TestAudioItem() { IList <IDirectoryObject> objects = new List <IDirectoryObject>(); BasicContainer root = new BasicContainer("TEST", new EndPointSettings { PreferredSubtitleLanguages = new string[] { "EN" }, PreferredAudioLanguages = new string[] { "EN" }, Profile = new EndPointProfile() }); Guid id = new Guid("11111111-aaaa-aaaa-aaaa-111111111111"); IDictionary <Guid, IList <MediaItemAspect> > aspects = new Dictionary <Guid, IList <MediaItemAspect> >(); SingleMediaItemAspect aspect1 = new SingleMediaItemAspect(MediaAspect.Metadata); aspect1.SetAttribute(MediaAspect.ATTR_TITLE, "The Track"); MediaItemAspect.SetAspect(aspects, aspect1); MultipleMediaItemAspect aspect2 = new MultipleMediaItemAspect(ProviderResourceAspect.Metadata); aspect2.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH, "c:\\file.mp3"); MediaItemAspect.AddOrUpdateAspect(aspects, aspect2); SingleMediaItemAspect aspect3 = new SingleMediaItemAspect(AudioAspect.Metadata); MediaItemAspect.SetAspect(aspects, aspect3); MediaItem item = new MediaItem(id, aspects); objects.Add(MediaLibraryHelper.InstansiateMediaLibraryObject(item, root, "Test")); GenericDidlMessageBuilder builder = new GenericDidlMessageBuilder(); builder.BuildAll("*", objects); string xml = builder.ToString(); Console.WriteLine("XML: {0}", xml); }
public MockedDatabaseMovie(MediaLibraryMovie movie) { IDictionary <Guid, IList <MediaItemAspect> > movieAspects = new Dictionary <Guid, IList <MediaItemAspect> >(); MultipleMediaItemAspect resourceAspect = new MultipleMediaItemAspect(ProviderResourceAspect.Metadata); resourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH, "c:\\" + movie.Title + ".mkv"); MediaItemAspect.AddOrUpdateAspect(movieAspects, resourceAspect); MediaItemAspect.AddOrUpdateExternalIdentifier(movieAspects, ExternalIdentifierAspect.SOURCE_IMDB, ExternalIdentifierAspect.TYPE_MOVIE, movie.Imdb); MediaItemAspect.SetAttribute(movieAspects, MovieAspect.ATTR_MOVIE_NAME, movie.Title); SingleMediaItemAspect mediaItemAspect = new SingleMediaItemAspect(MediaAspect.Metadata); mediaItemAspect.SetAttribute(MediaAspect.ATTR_PLAYCOUNT, movie.PlayCount); mediaItemAspect.SetAttribute(MediaAspect.ATTR_LASTPLAYED, DateTime.Parse(movie.LastPlayed)); MediaItemAspect.SetAspect(movieAspects, mediaItemAspect); SingleMediaItemAspect importerAspect = new SingleMediaItemAspect(ImporterAspect.Metadata); importerAspect.SetAttribute(ImporterAspect.ATTR_DATEADDED, DateTime.Parse(movie.AddedToDb)); MediaItemAspect.SetAspect(movieAspects, importerAspect); Movie = new MediaItem(Guid.NewGuid(), movieAspects); }
public virtual Task <bool> TryExtractMetadataAsync(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData, bool forceQuickMode) { try { IResourceAccessor metaFileAccessor; if (!CanExtract(mediaItemAccessor, extractedAspectData, out metaFileAccessor)) { return(Task.FromResult(false)); } Argus.Recording recording; using (metaFileAccessor) { using (Stream metaStream = ((IFileSystemResourceAccessor)metaFileAccessor).OpenRead()) recording = (Argus.Recording)GetTagsXmlSerializer().Deserialize(metaStream); } // Force MimeType IList <MultipleMediaItemAspect> providerAspects; MediaItemAspect.TryGetAspects(extractedAspectData, ProviderResourceAspect.Metadata, out providerAspects); foreach (MultipleMediaItemAspect aspect in providerAspects) { aspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, "slimtv/arg"); } MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_ISVIRTUAL, false); MediaItemAspect.SetAttribute(extractedAspectData, VideoAspect.ATTR_ISDVD, false); MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, recording.Title); MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_SORT_TITLE, BaseInfo.GetSortTitle(recording.Title)); if (!string.IsNullOrEmpty(recording.Category?.Trim())) { List <GenreInfo> genreList = new List <GenreInfo>(new GenreInfo[] { new GenreInfo { Name = recording.Category.Trim() } }); IGenreConverter converter = ServiceRegistration.Get <IGenreConverter>(); foreach (var genre in genreList) { if (!genre.Id.HasValue && converter.GetGenreId(genre.Name, GenreCategory.Movie, null, out int genreId)) { genre.Id = genreId; } } if (genreList.Count > 0) { MultipleMediaItemAspect genreAspect = MediaItemAspect.CreateAspect(extractedAspectData, GenreAspect.Metadata); genreAspect.SetAttribute(GenreAspect.ATTR_ID, genreList[0].Id); genreAspect.SetAttribute(GenreAspect.ATTR_GENRE, genreList[0].Name); } } MediaItemAspect.SetAttribute(extractedAspectData, VideoAspect.ATTR_STORYPLOT, recording.Description); Match yearMatch = _yearMatcher.Match(recording.Description); int guessedYear; if (int.TryParse(yearMatch.Value, out guessedYear)) { MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_RECORDINGTIME, new DateTime(guessedYear, 1, 1)); } MediaItemAspect.SetAttribute(extractedAspectData, RecordingAspect.ATTR_CHANNEL, recording.ChannelDisplayName); MediaItemAspect.SetAttribute(extractedAspectData, RecordingAspect.ATTR_STARTTIME, recording.ProgramStartTime); MediaItemAspect.SetAttribute(extractedAspectData, RecordingAspect.ATTR_ENDTIME, recording.ProgramStopTime); RecordingUtils.CheckAndPrepareAspectRefresh(extractedAspectData); if (!string.IsNullOrWhiteSpace(recording.Director)) { MediaItemAspect.SetCollectionAttribute(extractedAspectData, VideoAspect.ATTR_DIRECTORS, recording.Director.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)); } if (!string.IsNullOrWhiteSpace(recording.Actors)) { MediaItemAspect.SetCollectionAttribute(extractedAspectData, VideoAspect.ATTR_ACTORS, recording.Actors.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)); } return(Task.FromResult(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("ArgusRecordingMetadataExtractor: Exception reading resource '{0}' (Text: '{1}')", mediaItemAccessor.CanonicalLocalResourcePath, e.Message); } return(Task.FromResult(false)); }
protected virtual Task <bool> ExtractMetadataAsync(ILocalFsResourceAccessor lfsra, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData, bool forceQuickMode) { if (!CanExtract(lfsra, extractedAspectData)) { return(Task.FromResult(false)); } using (var rec = new MCRecMetadataEditor(lfsra.LocalFileSystemPath)) { // Handle series information IDictionary tags = rec.GetAttributes(); // Force MimeType IList <MultipleMediaItemAspect> providerAspects; MediaItemAspect.TryGetAspects(extractedAspectData, ProviderResourceAspect.Metadata, out providerAspects); foreach (MultipleMediaItemAspect aspect in providerAspects) { aspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, "slimtv/wtv"); } MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_ISVIRTUAL, false); MediaItemAspect.SetAttribute(extractedAspectData, VideoAspect.ATTR_ISDVD, false); string value; if (TryGet(tags, TAG_TITLE, out value) && !string.IsNullOrEmpty(value)) { MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, value); MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_SORT_TITLE, BaseInfo.GetSortTitle(value)); } if (TryGet(tags, TAG_GENRE, out value)) { List <GenreInfo> genreList = new List <GenreInfo>(value.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries).Select(s => new GenreInfo { Name = s.Trim() })); IGenreConverter converter = ServiceRegistration.Get <IGenreConverter>(); foreach (var genre in genreList) { if (!genre.Id.HasValue && converter.GetGenreId(genre.Name, GenreCategory.Movie, null, out int genreId)) { genre.Id = genreId; } } foreach (GenreInfo genre in genreList) { MultipleMediaItemAspect genreAspect = MediaItemAspect.CreateAspect(extractedAspectData, GenreAspect.Metadata); genreAspect.SetAttribute(GenreAspect.ATTR_ID, genre.Id); genreAspect.SetAttribute(GenreAspect.ATTR_GENRE, genre.Name); } } if (TryGet(tags, TAG_PLOT, out value)) { MediaItemAspect.SetAttribute(extractedAspectData, VideoAspect.ATTR_STORYPLOT, value); } if (TryGet(tags, TAG_ORIGINAL_TIME, out value)) { DateTime origTime; if (DateTime.TryParse(value, out origTime)) { MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_RECORDINGTIME, origTime); } } if (TryGet(tags, TAG_CHANNEL, out value)) { MediaItemAspect.SetAttribute(extractedAspectData, RecordingAspect.ATTR_CHANNEL, value); } long lValue; if (TryGet(tags, TAG_STARTTIME, out lValue)) { MediaItemAspect.SetAttribute(extractedAspectData, RecordingAspect.ATTR_STARTTIME, FromMCEFileTime(lValue)); } if (TryGet(tags, TAG_ENDTIME, out lValue)) { MediaItemAspect.SetAttribute(extractedAspectData, RecordingAspect.ATTR_ENDTIME, FromMCEFileTime(lValue)); } } return(Task.FromResult(true)); }
public bool TryExtractMetadata(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData, bool importOnly, bool forceQuickMode) { try { if (!(mediaItemAccessor is IFileSystemResourceAccessor)) { return(false); } if (extractedAspectData.ContainsKey(VideoAspect.ASPECT_ID)) { return(false); } using (LocalFsResourceAccessorHelper rah = new LocalFsResourceAccessorHelper(mediaItemAccessor)) { if (!rah.LocalFsResourceAccessor.IsFile && rah.LocalFsResourceAccessor.ResourceExists("BDMV")) { using (IFileSystemResourceAccessor fsraBDMV = rah.LocalFsResourceAccessor.GetResource("BDMV")) if (fsraBDMV != null && fsraBDMV.ResourceExists("index.bdmv")) { MultipleMediaItemAspect providerResourceAspect = MediaItemAspect.CreateAspect(extractedAspectData, ProviderResourceAspect.Metadata); // Calling EnsureLocalFileSystemAccess not necessary; only string operation providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_INDEX, 0); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_PRIMARY, true); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, "video/bluray"); // BluRay disc providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH, mediaItemAccessor.CanonicalLocalResourcePath.Serialize()); // This line is important to keep in, if no VideoAspect is created here, the MediaItems is not detected as Video! SingleMediaItemAspect videoAspect = MediaItemAspect.GetOrCreateAspect(extractedAspectData, VideoAspect.Metadata); videoAspect.SetAttribute(VideoAspect.ATTR_ISDVD, true); MultipleMediaItemAspect videoStreamAspect = MediaItemAspect.CreateAspect(extractedAspectData, VideoStreamAspect.Metadata); videoStreamAspect.SetAttribute(VideoStreamAspect.ATTR_RESOURCE_INDEX, 0); videoStreamAspect.SetAttribute(VideoStreamAspect.ATTR_STREAM_INDEX, -1); MediaItemAspect mediaAspect = MediaItemAspect.GetOrCreateAspect(extractedAspectData, MediaAspect.Metadata); mediaAspect.SetAttribute(MediaAspect.ATTR_ISVIRTUAL, false); using (rah.LocalFsResourceAccessor.EnsureLocalFileSystemAccess()) { BDInfoExt bdinfo = new BDInfoExt(rah.LocalFsResourceAccessor.LocalFileSystemPath); string title = bdinfo.GetTitle(); mediaAspect.SetAttribute(MediaAspect.ATTR_TITLE, title ?? mediaItemAccessor.ResourceName); // Check for BD disc thumbs FileInfo thumbnail = bdinfo.GetBiggestThumb(); if (thumbnail != null) { try { using (FileStream fileStream = new FileStream(thumbnail.FullName, FileMode.Open, FileAccess.Read)) using (MemoryStream resized = (MemoryStream)ImageUtilities.ResizeImage(fileStream, ImageFormat.Jpeg, MAX_COVER_WIDTH, MAX_COVER_HEIGHT)) { MediaItemAspect.SetAttribute(extractedAspectData, ThumbnailLargeAspect.ATTR_THUMBNAIL, resized.ToArray()); } } // Decoding of invalid image data can fail, but main MediaItem is correct. catch { } } } return(true); } } } return(false); } catch { // Only log at the info level here - And simply return false. This makes the importer know that we // couldn't perform our task here if (mediaItemAccessor != null) { ServiceRegistration.Get <ILogger>().Info("BluRayMetadataExtractor: Exception reading source '{0}'", mediaItemAccessor.ResourcePathName); } return(false); } }
public bool TryExtractMetadata(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData, bool importOnly, bool forceQuickMode) { IFileSystemResourceAccessor fsra = mediaItemAccessor as IFileSystemResourceAccessor; if (fsra == null || !fsra.IsFile) { return(false); } if (extractedAspectData.ContainsKey(AudioAspect.ASPECT_ID)) { return(false); } try { var extension = DosPathHelper.GetExtension(fsra.ResourceName).ToLowerInvariant(); if (extension != ".ts") { return(false); } using (MediaInfoWrapper mediaInfo = ReadMediaInfo(fsra)) { // Before we start evaluating the file, check if it is not a video file ( if (mediaInfo.IsValid && (mediaInfo.GetVideoCount() != 0 || mediaInfo.GetAudioCount() == 0)) { return(false); } string fileName = ProviderPathHelper.GetFileNameWithoutExtension(fsra.Path) ?? string.Empty; MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, fileName); MultipleMediaItemAspect providerResourceAspect = MediaItemAspect.CreateAspect(extractedAspectData, ProviderResourceAspect.Metadata); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_SIZE, fsra.Size); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, "slimtv/radio"); var audioBitrate = mediaInfo.GetAudioBitrate(0); if (audioBitrate.HasValue) { MediaItemAspect.SetAttribute(extractedAspectData, AudioAspect.ATTR_BITRATE, (int)(audioBitrate.Value / 1000)); // We store kbit/s; } var audioChannels = mediaInfo.GetAudioChannels(0); if (audioChannels.HasValue) { MediaItemAspect.SetAttribute(extractedAspectData, AudioAspect.ATTR_CHANNELS, audioChannels.Value); } var audioSampleRate = mediaInfo.GetAudioSampleRate(0); if (audioSampleRate.HasValue) { MediaItemAspect.SetAttribute(extractedAspectData, AudioAspect.ATTR_SAMPLERATE, audioSampleRate.Value); } MediaItemAspect.SetAttribute(extractedAspectData, AudioAspect.ATTR_ENCODING, mediaInfo.GetAudioCodec(0)); // MediaInfo returns milliseconds, we need seconds long?time = mediaInfo.GetPlaytime(0); if (time.HasValue && time > 1000) { MediaItemAspect.SetAttribute(extractedAspectData, AudioAspect.ATTR_DURATION, time.Value / 1000); } } return(true); } catch (Exception e) { // Only log at the info level here - And simply return false. This makes the importer know that we // couldn't perform our task here ServiceRegistration.Get <ILogger>().Info("RadioRecordingMetadataExtractor: Exception reading resource '{0}' (Text: '{1}')", fsra.CanonicalLocalResourcePath, e.Message); return(false); } }
/// <summary> /// Asynchronously tries to extract episode metadata for the given <param name="mediaItemAccessor"></param> /// </summary> /// <param name="mediaItemAccessor">Points to the resource for which we try to extract metadata</param> /// <param name="extractedAspectData">Dictionary of <see cref="MediaItemAspect"/>s with the extracted metadata</param> /// <param name="forceQuickMode">If <c>true</c>, nothing is downloaded from the internet</param> /// <returns><c>true</c> if metadata was found and stored into <param name="extractedAspectData"></param>, else <c>false</c></returns> private async Task <bool> TryExtractEpsiodeMetadataAsync(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData, bool forceQuickMode) { // Get a unique number for this call to TryExtractMetadataAsync. We use this to make reading the debug log easier. // This MetadataExtractor is called in parallel for multiple MediaItems so that the respective debug log entries // for one call are not contained one after another in debug log. We therefore prepend this number before every log entry. var miNumber = Interlocked.Increment(ref _lastMediaItemNumber); bool isStub = extractedAspectData.ContainsKey(StubAspect.ASPECT_ID); try { _debugLogger.Info("[#{0}]: Start extracting metadata for resource '{1}' (forceQuickMode: {2})", miNumber, mediaItemAccessor, forceQuickMode); // This MetadataExtractor only works for MediaItems accessible by an IFileSystemResourceAccessor. // Otherwise it is not possible to find a nfo-file in the MediaItem's directory or parent directory. if (!(mediaItemAccessor is IFileSystemResourceAccessor)) { _debugLogger.Info("[#{0}]: Cannot extract metadata; mediaItemAccessor is not an IFileSystemResourceAccessor", miNumber); return(false); } // We only extract metadata with this MetadataExtractor, if another MetadataExtractor that was applied before // has identified this MediaItem as a video and therefore added a VideoAspect. if (!extractedAspectData.ContainsKey(VideoAspect.ASPECT_ID)) { _debugLogger.Info("[#{0}]: Cannot extract metadata; this resource is not a video", miNumber); return(false); } // Here we try to find an IFileSystemResourceAccessor pointing to the episode nfo-file. // If we don't find one, we cannot extract any metadata. IFileSystemResourceAccessor episodeNfoFsra; NfoSeriesEpisodeReader episodeNfoReader = null; bool episodeDetailsFound = false; if (TryGetEpisodeNfoSResourceAccessor(miNumber, mediaItemAccessor as IFileSystemResourceAccessor, out episodeNfoFsra)) { episodeDetailsFound = true; // Now we (asynchronously) extract the metadata into a stub object. // If no metadata was found, nothing can be stored in the MediaItemAspects. episodeNfoReader = new NfoSeriesEpisodeReader(_debugLogger, miNumber, forceQuickMode, isStub, _httpClient, _settings); using (episodeNfoFsra) { if (!await episodeNfoReader.TryReadMetadataAsync(episodeNfoFsra).ConfigureAwait(false)) { _debugLogger.Warn("[#{0}]: No valid metadata found in episode nfo-file", miNumber); return(false); } } } // Then we try to find an IFileSystemResourceAccessor pointing to the series nfo-file. IFileSystemResourceAccessor seriesNfoFsra; if (TryGetSeriesNfoSResourceAccessor(miNumber, mediaItemAccessor as IFileSystemResourceAccessor, out seriesNfoFsra)) { // If we found one, we (asynchronously) extract the metadata into a stub object and, if metadata was found, // we store it into the episodeNfoReader so that the latter can store metadata from series and episode level into the MediaItemAspects. var seriesNfoReader = new NfoSeriesReader(_debugLogger, miNumber, forceQuickMode, !episodeDetailsFound, isStub, _httpClient, _settings); using (seriesNfoFsra) { if (await seriesNfoReader.TryReadMetadataAsync(seriesNfoFsra).ConfigureAwait(false)) { //Check reimport if (extractedAspectData.ContainsKey(ReimportAspect.ASPECT_ID)) { SeriesInfo reimport = new SeriesInfo(); reimport.FromMetadata(extractedAspectData); if (!VerifySeriesReimport(seriesNfoReader, reimport)) { ServiceRegistration.Get <ILogger>().Info("NfoSeriesMetadataExtractor: Nfo series metadata from resource '{0}' ignored because it does not match reimport {1}", mediaItemAccessor, reimport); return(false); } } Stubs.SeriesStub series = seriesNfoReader.GetSeriesStubs().FirstOrDefault(); // Check if episode should be found if (isStub || !episodeDetailsFound) { if (series != null && series.Episodes?.Count > 0) { List <Stubs.SeriesEpisodeStub> episodeStubs = null; if (extractedAspectData.ContainsKey(EpisodeAspect.ASPECT_ID)) { int? seasonNo = 0; IEnumerable episodes; if (MediaItemAspect.TryGetAttribute(extractedAspectData, EpisodeAspect.ATTR_SEASON, out seasonNo) && MediaItemAspect.TryGetAttribute(extractedAspectData, EpisodeAspect.ATTR_EPISODE, out episodes)) { List <int> episodeNos = new List <int>(); CollectionUtils.AddAll(episodeNos, episodes.Cast <int>()); if (seasonNo.HasValue && episodeNos.Count > 0) { episodeStubs = series.Episodes.Where(e => e.Season == seasonNo.Value && episodeNos.Intersect(e.Episodes).Any()).ToList(); } } } else { string title = null; if (MediaItemAspect.TryGetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, out title)) { Regex regex = new Regex(@"(?<series>[^\\]+).S(?<seasonnum>\d+)[\s|\.|\-|_]{0,1}E((?<episodenum>\d+)_?)+(?<episode>.*)"); Match match = regex.Match(title); if (match.Success && match.Groups["seasonnum"].Length > 0 && match.Groups["episodenum"].Length > 0) { episodeStubs = series.Episodes.Where(e => e.Season == Convert.ToInt32(match.Groups["seasonnum"].Value) && e.Episodes.Contains(Convert.ToInt32(match.Groups["episodenum"].Value))).ToList(); } } } if (episodeStubs != null && episodeStubs.Count > 0) { Stubs.SeriesEpisodeStub mergedEpisode = null; if (isStub) { if (episodeStubs.Count == 1) { mergedEpisode = episodeStubs.First(); } else { Stubs.SeriesEpisodeStub episode = episodeStubs.First(); mergedEpisode = new Stubs.SeriesEpisodeStub(); mergedEpisode.Actors = episode.Actors; mergedEpisode.Aired = episode.Aired; mergedEpisode.Credits = episode.Credits; mergedEpisode.Director = episode.Director; mergedEpisode.DisplayEpisode = episode.DisplayEpisode; mergedEpisode.DisplaySeason = episode.DisplaySeason; mergedEpisode.EpBookmark = episode.EpBookmark; mergedEpisode.FileInfo = episode.FileInfo; mergedEpisode.LastPlayed = episode.LastPlayed; mergedEpisode.Mpaa = episode.Mpaa; mergedEpisode.PlayCount = episode.PlayCount; mergedEpisode.Premiered = episode.Premiered; mergedEpisode.ProductionCodeNumber = episode.ProductionCodeNumber; mergedEpisode.ResumePosition = episode.ResumePosition; mergedEpisode.Season = episode.Season; mergedEpisode.Sets = episode.Sets; mergedEpisode.ShowTitle = episode.ShowTitle; mergedEpisode.Status = episode.Status; mergedEpisode.Studio = episode.Studio; mergedEpisode.Tagline = episode.Tagline; mergedEpisode.Thumb = episode.Thumb; mergedEpisode.Top250 = episode.Top250; mergedEpisode.Trailer = episode.Trailer; mergedEpisode.Watched = episode.Watched; mergedEpisode.Year = episode.Year; mergedEpisode.Id = episode.Id; mergedEpisode.UniqueId = episode.UniqueId; //Merge episodes mergedEpisode.Title = string.Join("; ", episodeStubs.OrderBy(e => e.Episodes.First()).Select(e => e.Title).ToArray()); mergedEpisode.Rating = episodeStubs.Where(e => e.Rating.HasValue).Sum(e => e.Rating.Value) / episodeStubs.Where(e => e.Rating.HasValue).Count(); // Average rating mergedEpisode.Votes = episodeStubs.Where(e => e.Votes.HasValue).Sum(e => e.Votes.Value) / episodeStubs.Where(e => e.Votes.HasValue).Count(); mergedEpisode.Runtime = TimeSpan.FromSeconds(episodeStubs.Where(e => e.Runtime.HasValue).Sum(e => e.Runtime.Value.TotalSeconds)); mergedEpisode.Plot = string.Join("\r\n\r\n", episodeStubs.OrderBy(e => e.Episodes.First()). Select(e => string.Format("{0,02}) {1}", e.Episodes.First(), e.Plot)).ToArray()); mergedEpisode.Outline = string.Join("\r\n\r\n", episodeStubs.OrderBy(e => e.Episodes.First()). Select(e => string.Format("{0,02}) {1}", e.Episodes.First(), e.Outline)).ToArray()); mergedEpisode.Episodes = new HashSet <int>(episodeStubs.SelectMany(x => x.Episodes).ToList()); mergedEpisode.DvdEpisodes = new HashSet <decimal>(episodeStubs.SelectMany(x => x.DvdEpisodes).ToList()); } IList <MultipleMediaItemAspect> providerResourceAspects; if (MediaItemAspect.TryGetAspects(extractedAspectData, ProviderResourceAspect.Metadata, out providerResourceAspects)) { MultipleMediaItemAspect providerResourceAspect = providerResourceAspects.First(pa => pa.GetAttributeValue <int>(ProviderResourceAspect.ATTR_TYPE) == ProviderResourceAspect.TYPE_STUB); string mime = null; if (mergedEpisode.FileInfo != null && mergedEpisode.FileInfo.Count > 0) { mime = MimeTypeDetector.GetMimeTypeFromExtension("file" + mergedEpisode.FileInfo.First().Container); } if (mime != null) { providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, mime); } } MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, string.Format("{0} S{1:00}{2} {3}", series.ShowTitle, mergedEpisode.Season, mergedEpisode.Episodes.Select(e => "E" + e.ToString("00")), mergedEpisode.Title)); MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_SORT_TITLE, BaseInfo.GetSortTitle(mergedEpisode.Title)); MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_RECORDINGTIME, mergedEpisode.Premiered.HasValue ? mergedEpisode.Premiered.Value : mergedEpisode.Year.HasValue ? mergedEpisode.Year.Value : (DateTime?)null); if (mergedEpisode.FileInfo != null && mergedEpisode.FileInfo.Count > 0) { extractedAspectData.Remove(VideoStreamAspect.ASPECT_ID); extractedAspectData.Remove(VideoAudioStreamAspect.ASPECT_ID); extractedAspectData.Remove(SubtitleAspect.ASPECT_ID); StubParser.ParseFileInfo(extractedAspectData, mergedEpisode.FileInfo, mergedEpisode.Title); } } episodeNfoReader = new NfoSeriesEpisodeReader(_debugLogger, miNumber, forceQuickMode, isStub, _httpClient, _settings); episodeNfoReader.SetEpisodeStubs(new List <Stubs.SeriesEpisodeStub> { mergedEpisode }); } } } if (series != null) { if (episodeNfoReader != null) { episodeNfoReader.SetSeriesStubs(new List <Stubs.SeriesStub> { series }); // Then we store the found metadata in the MediaItemAspects. If we only found metadata that is // not (yet) supported by our MediaItemAspects, this MetadataExtractor returns false. if (!episodeNfoReader.TryWriteMetadata(extractedAspectData)) { _debugLogger.Warn("[#{0}]: No metadata was written into MediaItemsAspects", miNumber); return(false); } } else { EpisodeInfo episode = new EpisodeInfo(); if (series.Id.HasValue) { episode.SeriesTvdbId = series.Id.Value; } if (series.Premiered.HasValue) { episode.SeriesFirstAired = series.Premiered.Value; } episode.SeriesName = series.ShowTitle; episode.SetMetadata(extractedAspectData); } } } else { _debugLogger.Warn("[#{0}]: No valid metadata found in series nfo-file", miNumber); } } } else if (episodeNfoReader != null) { //Check reimport if (extractedAspectData.ContainsKey(ReimportAspect.ASPECT_ID)) { EpisodeInfo reimport = new EpisodeInfo(); reimport.FromMetadata(extractedAspectData); if (!VerifyEpisodeReimport(episodeNfoReader, reimport)) { ServiceRegistration.Get <ILogger>().Info("NfoSeriesMetadataExtractor: Nfo episode metadata from resource '{0}' ignored because it does not match reimport {1}", mediaItemAccessor, reimport); return(false); } } // Then we store the found metadata in the MediaItemAspects. If we only found metadata that is // not (yet) supported by our MediaItemAspects, this MetadataExtractor returns false. if (!episodeNfoReader.TryWriteMetadata(extractedAspectData)) { _debugLogger.Warn("[#{0}]: No metadata was written into MediaItemsAspects", miNumber); return(false); } } _debugLogger.Info("[#{0}]: Successfully finished extracting metadata", miNumber); ServiceRegistration.Get <ILogger>().Debug("NfoSeriesMetadataExtractor: Assigned nfo episode metadata for resource '{0}'", mediaItemAccessor); return(true); } catch (Exception e) { ServiceRegistration.Get <ILogger>().Warn("NfoSeriesMetadataExtractor: Exception while extracting metadata for resource '{0}'; enable debug logging for more details.", mediaItemAccessor); _debugLogger.Error("[#{0}]: Exception while extracting metadata", e, miNumber); return(false); } }
public void TestComplexItem() { Guid trackId = new Guid("11111111-aaaa-aaaa-aaaa-100000000000"); Guid albumId = new Guid("11111111-aaaa-aaaa-aaaa-100000000001"); Guid artistId = new Guid("11111111-aaaa-aaaa-aaaa-100000000002"); Guid trackRelationship = new Guid("22222222-bbbb-bbbb-bbbb-200000000001"); Guid albumRelationship = new Guid("33333333-cccc-cccc-cccc-300000000001"); Guid artistRelationship = new Guid("44444444-dddd-dddd-dddd-400000000001"); IDictionary <Guid, IList <MediaItemAspect> > aspects1 = new Dictionary <Guid, IList <MediaItemAspect> >(); MultipleMediaItemAspect resourceAspect1 = new MultipleMediaItemAspect(ProviderResourceAspect.Metadata); resourceAspect1.Deleted = true; resourceAspect1.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH, "c:\\file.mp3"); MediaItemAspect.AddOrUpdateAspect(aspects1, resourceAspect1); MediaItemAspect.AddOrUpdateRelationship(aspects1, trackRelationship, albumRelationship, albumId, 1); MediaItemAspect.AddOrUpdateRelationship(aspects1, trackRelationship, artistRelationship, artistId, 0); MediaItem track1 = new MediaItem(trackId, aspects1); TextWriter writer = new StringWriter(); XmlWriter serialiser = new XmlTextWriter(writer); serialiser.WriteStartElement("Test"); // Wrapper around the tracks // Write the track twice track1.Serialize(serialiser); track1.Serialize(serialiser); serialiser.WriteEndElement(); //Console.WriteLine("XML: {0}", writer.ToString()); //Assert.AreEqual("<MI Id=\"" + trackId + "\"><Relationship ItemType=\"" + AudioAspect.RELATIONSHIP_TRACK + "\" RelationshipType=\"" + AlbumAspect.RELATIONSHIP_ALBUM + "\" RelationshipId=\"" + albumId + "\" /></MI>", trackText.ToString(), "Track XML"); XmlReader reader = XmlReader.Create(new StringReader(writer.ToString())); reader.Read(); // Test //Console.WriteLine("Reader state Test, {0} {1}", reader.NodeType, reader.Name); // Read the track once reader.Read(); // MI //Console.WriteLine("Reader state track2, {0} {1}", reader.NodeType, reader.Name); MediaItem track2 = MediaItem.Deserialize(reader); IList <MultipleMediaItemAspect> resourceAspect2; Assert.IsTrue(MediaItemAspect.TryGetAspects(track2.Aspects, ProviderResourceAspect.Metadata, out resourceAspect2), "Resource aspects"); Assert.AreEqual(true, resourceAspect2[0].Deleted, "Track deleted status"); Assert.AreEqual("c:\\file.mp3", resourceAspect2[0].GetAttributeValue <string>(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH), "Track location"); IList <MediaItemAspect> relationships2 = track2[RelationshipAspect.ASPECT_ID]; Assert.IsTrue(track2[RelationshipAspect.ASPECT_ID] != null, "Relationship aspects"); Assert.AreEqual(relationships2.Count, 2, "Track relationship count"); Assert.AreEqual(trackRelationship, relationships2[0].GetAttributeValue(RelationshipAspect.ATTR_ROLE), "Track -> album item type"); Assert.AreEqual(albumRelationship, relationships2[0].GetAttributeValue(RelationshipAspect.ATTR_LINKED_ROLE), "Track -> album relationship type"); Assert.AreEqual(albumId, relationships2[0].GetAttributeValue(RelationshipAspect.ATTR_LINKED_ID), "Track -> album relationship ID"); Assert.AreEqual(trackRelationship, relationships2[1].GetAttributeValue(RelationshipAspect.ATTR_ROLE), "Track -> album item type"); Assert.AreEqual(artistRelationship, relationships2[1].GetAttributeValue(RelationshipAspect.ATTR_LINKED_ROLE), "Track -> album relationship type"); Assert.AreEqual(artistId, relationships2[1].GetAttributeValue(RelationshipAspect.ATTR_LINKED_ID), "Track -> album relationship ID"); // Read the track a second time ( //Console.WriteLine("Reader state track3, {0} {1}", reader.NodeType, reader.Name); MediaItem track3 = MediaItem.Deserialize(reader); IList <MultipleMediaItemAspect> resourceAspect3; Assert.IsTrue(MediaItemAspect.TryGetAspects(track3.Aspects, ProviderResourceAspect.Metadata, out resourceAspect3), "Resource aspects"); Assert.AreEqual("c:\\file.mp3", resourceAspect3[0].GetAttributeValue <string>(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH), "Track location"); IList <MediaItemAspect> relationships3 = track3[RelationshipAspect.ASPECT_ID]; Assert.IsTrue(track3[RelationshipAspect.ASPECT_ID] != null, "Relationship aspects"); Assert.AreEqual(2, relationships3.Count, "Track relationship count"); Assert.AreEqual(trackRelationship, relationships3[0].GetAttributeValue(RelationshipAspect.ATTR_ROLE), "Track -> album item type"); Assert.AreEqual(albumRelationship, relationships3[0].GetAttributeValue(RelationshipAspect.ATTR_LINKED_ROLE), "Track -> album relationship type"); Assert.AreEqual(albumId, relationships3[0].GetAttributeValue(RelationshipAspect.ATTR_LINKED_ID), "Track -> album relationship ID"); Assert.AreEqual(trackRelationship, relationships3[1].GetAttributeValue(RelationshipAspect.ATTR_ROLE), "Track -> album item type"); Assert.AreEqual(artistRelationship, relationships3[1].GetAttributeValue(RelationshipAspect.ATTR_LINKED_ROLE), "Track -> album relationship type"); Assert.AreEqual(artistId, relationships3[1].GetAttributeValue(RelationshipAspect.ATTR_LINKED_ID), "Track -> album relationship ID"); reader.Read(); // Test }