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)); }
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)); } Tags tags; using (metaFileAccessor) { using (Stream metaStream = ((IFileSystemResourceAccessor)metaFileAccessor).OpenRead()) tags = (Tags)GetTagsXmlSerializer().Deserialize(metaStream); } //Assign all tags to the aspects for both tv and radio recordings string value; MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_ISVIRTUAL, false); if (TryGet(tags, TAG_TITLE, out value) && !string.IsNullOrEmpty(value)) { if (value.Equals("manual", StringComparison.InvariantCultureIgnoreCase)) { value = ResourcePathHelper.GetFileNameWithoutExtension(metaFileAccessor.Path); } MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, value); MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_SORT_TITLE, BaseInfo.GetSortTitle(value)); } if (TryGet(tags, TAG_CHANNEL, out value)) { MediaItemAspect.SetAttribute(extractedAspectData, RecordingAspect.ATTR_CHANNEL, value); } // Recording date formatted: 2011-11-04 20:55 DateTime tmpValue; DateTime?recordingStart = null; DateTime?recordingEnd = null; DateTime?programStart = null; DateTime?programEnd = null; // First try to read program start and end times, they will be preferred. if (TryGet(tags, TAG_PROGRAMSTARTTIME, out value) && DateTime.TryParse(value, out tmpValue)) { programStart = tmpValue; } if (TryGet(tags, TAG_PROGRAMENDTIME, out value) && DateTime.TryParse(value, out tmpValue)) { programEnd = tmpValue; } if (TryGet(tags, TAG_STARTTIME, out value) && DateTime.TryParse(value, out tmpValue)) { recordingStart = tmpValue; } if (TryGet(tags, TAG_ENDTIME, out value) && DateTime.TryParse(value, out tmpValue)) { recordingEnd = tmpValue; } // Correct start time if recording started before the program (skip pre-recording offset) if (programStart.HasValue && recordingStart.HasValue && programStart > recordingStart) { recordingStart = programStart; } // Correct end time if recording ended after the program (skip the post-recording offset) if (programEnd.HasValue && recordingEnd.HasValue && programEnd < recordingEnd) { recordingEnd = programEnd; } if (recordingStart.HasValue) { MediaItemAspect.SetAttribute(extractedAspectData, RecordingAspect.ATTR_STARTTIME, recordingStart.Value); } if (recordingEnd.HasValue) { MediaItemAspect.SetAttribute(extractedAspectData, RecordingAspect.ATTR_ENDTIME, recordingEnd.Value); RecordingUtils.CheckAndPrepareAspectRefresh(extractedAspectData); } if (extractedAspectData.ContainsKey(VideoAspect.ASPECT_ID)) //Only add video information for actual video recordings { // Force MimeType IList <MultipleMediaItemAspect> providerAspects; MediaItemAspect.TryGetAspects(extractedAspectData, ProviderResourceAspect.Metadata, out providerAspects); foreach (MultipleMediaItemAspect aspect in providerAspects) { aspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, "slimtv/video"); } MediaItemAspect.SetAttribute(extractedAspectData, VideoAspect.ATTR_ISDVD, false); if (TryGet(tags, TAG_PLOT, out value)) { MediaItemAspect.SetAttribute(extractedAspectData, VideoAspect.ATTR_STORYPLOT, value); Match yearMatch = _yearMatcher.Match(value); int guessedYear; if (int.TryParse(yearMatch.Value, out guessedYear)) { MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_RECORDINGTIME, new DateTime(guessedYear, 1, 1)); } } if (TryGet(tags, TAG_GENRE, out value) && !string.IsNullOrEmpty(value?.Trim())) { List <GenreInfo> genreList = new List <GenreInfo>(new GenreInfo[] { new GenreInfo { Name = value.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; } } MultipleMediaItemAspect genreAspect = MediaItemAspect.CreateAspect(extractedAspectData, GenreAspect.Metadata); genreAspect.SetAttribute(GenreAspect.ATTR_ID, genreList[0].Id); genreAspect.SetAttribute(GenreAspect.ATTR_GENRE, genreList[0].Name); } } else //Add comment for radio recordings { if (TryGet(tags, TAG_PLOT, out value)) { MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_COMMENT, value); } if (TryGet(tags, TAG_GENRE, out value) && !string.IsNullOrEmpty(value?.Trim())) { List <GenreInfo> genreList = new List <GenreInfo>(new GenreInfo[] { new GenreInfo { Name = value.Trim() } }); IGenreConverter converter = ServiceRegistration.Get <IGenreConverter>(); foreach (var genre in genreList) { if (!genre.Id.HasValue && converter.GetGenreId(genre.Name, GenreCategory.Music, null, out int genreId)) { genre.Id = genreId; } } MultipleMediaItemAspect genreAspect = MediaItemAspect.CreateAspect(extractedAspectData, GenreAspect.Metadata); genreAspect.SetAttribute(GenreAspect.ATTR_ID, genreList[0].Id); genreAspect.SetAttribute(GenreAspect.ATTR_GENRE, genreList[0].Name); } } 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("Tve3RecordingMetadataExtractor: Exception reading resource '{0}' (Text: '{1}')", mediaItemAccessor.CanonicalLocalResourcePath, e.Message); } return(Task.FromResult(false)); }