/// <summary> /// Creates a MediaItem that represents a TV stream. The MediaItem also holds information about stream indices to provide PiP /// functions (<paramref name="slotIndex"/>). /// </summary> /// <param name="slotIndex">Index of the slot (0/1)</param> /// <param name="path">Path or URL of the stream</param> /// <param name="channel"></param> /// <returns></returns> public static LiveTvMediaItem CreateMediaItem(int slotIndex, string path, IChannel channel) { if (!String.IsNullOrEmpty(path)) { ISystemResolver systemResolver = ServiceRegistration.Get<ISystemResolver>(); IDictionary<Guid, MediaItemAspect> aspects = new Dictionary<Guid, MediaItemAspect>(); MediaItemAspect providerResourceAspect; MediaItemAspect mediaAspect; SlimTvResourceAccessor resourceAccessor = new SlimTvResourceAccessor(slotIndex, path); aspects[ProviderResourceAspect.ASPECT_ID] = providerResourceAspect = new MediaItemAspect(ProviderResourceAspect.Metadata); aspects[MediaAspect.ASPECT_ID] = mediaAspect = new MediaItemAspect(MediaAspect.Metadata); // VideoAspect needs to be included to associate VideoPlayer later! aspects[VideoAspect.ASPECT_ID] = new MediaItemAspect(VideoAspect.Metadata); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_SYSTEM_ID, systemResolver.LocalSystemId); String raPath = resourceAccessor.CanonicalLocalResourcePath.Serialize(); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH, raPath); mediaAspect.SetAttribute(MediaAspect.ATTR_TITLE, "Live TV"); mediaAspect.SetAttribute(MediaAspect.ATTR_MIME_TYPE, "video/livetv"); // Custom mimetype for LiveTv LiveTvMediaItem tvStream = new LiveTvMediaItem(new Guid(), aspects); tvStream.AdditionalProperties[LiveTvMediaItem.SLOT_INDEX] = slotIndex; tvStream.AdditionalProperties[LiveTvMediaItem.CHANNEL] = channel; tvStream.AdditionalProperties[LiveTvMediaItem.TUNING_TIME] = DateTime.Now; return tvStream; } return null; }
/// <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, MediaItemAspect> aspects = new Dictionary<Guid, MediaItemAspect>(); MediaItemAspect providerResourceAspect; aspects[ProviderResourceAspect.ASPECT_ID] = providerResourceAspect = new MediaItemAspect(ProviderResourceAspect.Metadata); MediaItemAspect mediaAspect; aspects[MediaAspect.ASPECT_ID] = mediaAspect = new MediaItemAspect(MediaAspect.Metadata); aspects[VideoAspect.ASPECT_ID] = new MediaItemAspect(VideoAspect.Metadata); // VideoAspect needs to be contained for player mapping providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH, RawUrlResourceProvider.ToProviderResourcePath(trailer.Url).Serialize()); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_SYSTEM_ID, ServiceRegistration.Get<ISystemResolver>().LocalSystemId); mediaAspect.SetAttribute(MediaAspect.ATTR_MIME_TYPE, CINEMA_MIMETYPE); mediaAspect.SetAttribute(MediaAspect.ATTR_TITLE, trailer.Title); var mediaItem = new MediaItem(Guid.Empty, aspects); return mediaItem; }
private static LiveTvMediaItem.LiveTvMediaItem CreateCommonMediaItem(int slotIndex, string path, bool isTv) { ISystemResolver systemResolver = ServiceRegistration.Get<ISystemResolver>(); IDictionary<Guid, MediaItemAspect> aspects = new Dictionary<Guid, MediaItemAspect>(); MediaItemAspect providerResourceAspect; MediaItemAspect mediaAspect; SlimTvResourceAccessor resourceAccessor = new SlimTvResourceAccessor(slotIndex, path); aspects[ProviderResourceAspect.ASPECT_ID] = providerResourceAspect = new MediaItemAspect(ProviderResourceAspect.Metadata); aspects[MediaAspect.ASPECT_ID] = mediaAspect = new MediaItemAspect(MediaAspect.Metadata); 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! aspects[VideoAspect.ASPECT_ID] = new MediaItemAspect(VideoAspect.Metadata); title = "Live TV"; mimeType = LiveTvMediaItem.LiveTvMediaItem.MIME_TYPE_TV; } else { // AudioAspect needs to be included to associate an AudioPlayer later! aspects[AudioAspect.ASPECT_ID] = new MediaItemAspect(AudioAspect.Metadata); title = "Live Radio"; mimeType = LiveTvMediaItem.LiveTvMediaItem.MIME_TYPE_RADIO; } mediaAspect.SetAttribute(MediaAspect.ATTR_TITLE, title); mediaAspect.SetAttribute(MediaAspect.ATTR_MIME_TYPE, mimeType); // Custom mimetype for LiveTv or Radio LiveTvMediaItem.LiveTvMediaItem tvStream = new LiveTvMediaItem.LiveTvMediaItem(new Guid(), aspects); return tvStream; }
public static void ParseFileInfo(IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData, HashSet <StreamDetailsStub> FileInfo, string title, decimal?fps = null) { int streamId = 0; if (FileInfo != null && FileInfo.Count > 0) { if (FileInfo.First().VideoStreams != null && FileInfo.First().VideoStreams.Count > 0) { foreach (var video in FileInfo.First().VideoStreams) { MultipleMediaItemAspect videoStreamAspects = MediaItemAspect.CreateAspect(extractedAspectData, VideoStreamAspect.Metadata); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_RESOURCE_INDEX, 0); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_STREAM_INDEX, streamId++); string videoType = VideoStreamAspect.GetVideoType(null, video.StereoMode, video.Height, video.Width); if (!string.IsNullOrEmpty(videoType)) { videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_VIDEO_TYPE, videoType); } if (videoType == VideoStreamAspect.TYPE_SBS || videoType == VideoStreamAspect.TYPE_HSBS) { video.Width = video.Width.Value / 2; video.Aspect = (decimal)video.Width.Value / (decimal)video.Height.Value; } else if (videoType == VideoStreamAspect.TYPE_TAB || videoType == VideoStreamAspect.TYPE_HTAB) { video.Height = video.Height.Value / 2; video.Aspect = (decimal)video.Width.Value / (decimal)video.Height.Value; } if (video.Aspect.HasValue) { videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_ASPECTRATIO, Convert.ToSingle(video.Aspect.Value)); } if (fps.HasValue) { videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_FPS, Convert.ToSingle(fps.Value)); } if (video.Width.HasValue) { videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_WIDTH, video.Width.Value); } if (video.Height.HasValue) { videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_HEIGHT, video.Height.Value); } if (video.Duration.HasValue) { videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_DURATION, Convert.ToInt64(video.Duration.Value.TotalSeconds)); } if (video.Bitrate.HasValue) { videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_VIDEOBITRATE, video.Bitrate.Value / 1000); // We store kbit/s } videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_VIDEOENCODING, video.Codec); if (FileInfo.First().AudioStreams != null && FileInfo.First().AudioStreams.Count > 0) { videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_AUDIOSTREAMCOUNT, FileInfo.First().AudioStreams.Count); } videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_VIDEO_PART, -1); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_VIDEO_PART_SET, -1); List <string> suffixes = new List <string>(); if (!string.IsNullOrEmpty(videoType)) { suffixes.Add(videoType); } if (video.Height.HasValue && video.Width.HasValue) { suffixes.Add($"{video.Width.Value}x{video.Height.Value}"); } videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_VIDEO_PART_SET_NAME, title + (suffixes.Count > 0 ? " (" + string.Join(", ", suffixes) + ")" : "")); } } if (FileInfo.First().AudioStreams != null && FileInfo.First().AudioStreams.Count > 0) { foreach (var audio in FileInfo.First().AudioStreams) { MultipleMediaItemAspect audioAspect = MediaItemAspect.CreateAspect(extractedAspectData, VideoAudioStreamAspect.Metadata); audioAspect.SetAttribute(VideoAudioStreamAspect.ATTR_RESOURCE_INDEX, 0); audioAspect.SetAttribute(VideoAudioStreamAspect.ATTR_STREAM_INDEX, streamId++); if (audio.Codec != null) { audioAspect.SetAttribute(VideoAudioStreamAspect.ATTR_AUDIOENCODING, audio.Codec); } if (audio.Bitrate != null) { audioAspect.SetAttribute(VideoAudioStreamAspect.ATTR_AUDIOBITRATE, audio.Bitrate.Value / 1000); // We store kbit/s } if (audio.Channels != null) { audioAspect.SetAttribute(VideoAudioStreamAspect.ATTR_AUDIOCHANNELS, audio.Channels.Value); } if (audio.Language != null) { audioAspect.SetAttribute(VideoAudioStreamAspect.ATTR_AUDIOLANGUAGE, ParseLanguage(audio.Language)); } } } if (FileInfo.First().SubtitleStreams != null && FileInfo.First().SubtitleStreams.Count > 0) { foreach (var subtitle in FileInfo.First().SubtitleStreams) { MultipleMediaItemAspect subtitleAspect = MediaItemAspect.CreateAspect(extractedAspectData, SubtitleAspect.Metadata); subtitleAspect.SetAttribute(SubtitleAspect.ATTR_RESOURCE_INDEX, 0); subtitleAspect.SetAttribute(SubtitleAspect.ATTR_VIDEO_RESOURCE_INDEX, 0); subtitleAspect.SetAttribute(SubtitleAspect.ATTR_STREAM_INDEX, streamId++); subtitleAspect.SetAttribute(SubtitleAspect.ATTR_INTERNAL, true); if (subtitle.Language != null) { subtitleAspect.SetAttribute(SubtitleAspect.ATTR_SUBTITLE_LANGUAGE, ParseLanguage(subtitle.Language)); } } } } }
public override int Compare(MediaItem x, MediaItem y) { SingleMediaItemAspect mediaAspectX; SingleMediaItemAspect mediaAspectY; if (MediaItemAspect.TryGetAspect(x.Aspects, MediaAspect.Metadata, out mediaAspectX) && MediaItemAspect.TryGetAspect(y.Aspects, MediaAspect.Metadata, out mediaAspectY)) { DateTime?recordingTimeX = (DateTime?)mediaAspectX.GetAttributeValue(MediaAspect.ATTR_RECORDINGTIME); DateTime?recordingTimeY = (DateTime?)mediaAspectY.GetAttributeValue(MediaAspect.ATTR_RECORDINGTIME); return(ObjectUtils.Compare(recordingTimeX, recordingTimeY)); } return(base.Compare(x, y)); }
/// <summary> /// Adds a direcotry MediaItem to the MediaLibrary /// </summary> /// <param name="directoryAccessor">ResourceAccessor to the directory to be saved</param> /// <param name="parentDirectoryId">ID of the parent Directory</param> /// <returns></returns> private async Task<Guid> AddDirectory(IFileSystemResourceAccessor directoryAccessor, Guid parentDirectoryId) { var directoryPath = directoryAccessor.CanonicalLocalResourcePath; var mediaAspect = new MediaItemAspect(MediaAspect.Metadata); mediaAspect.SetAttribute(MediaAspect.ATTR_TITLE, directoryAccessor.ResourceName); mediaAspect.SetAttribute(MediaAspect.ATTR_MIME_TYPE, null); mediaAspect.SetAttribute(MediaAspect.ATTR_RECORDINGTIME, DateTime.MinValue); mediaAspect.SetAttribute(MediaAspect.ATTR_RATING, 0); mediaAspect.SetAttribute(MediaAspect.ATTR_COMMENT, null); mediaAspect.SetAttribute(MediaAspect.ATTR_LASTPLAYED, DateTime.MinValue); var directoryAspect = new MediaItemAspect(DirectoryAspect.Metadata); IList<MediaItemAspect> aspects = new List<MediaItemAspect>(new[] { mediaAspect, directoryAspect }); return await UpdateMediaItem(parentDirectoryId, directoryPath, aspects); }
private int GetSeasonIndex(MediaItem currMediaItem) { int value; return(MediaItemAspect.TryGetAttribute(currMediaItem.Aspects, SeriesAspect.ATTR_SEASON, out value) ? value : 0); }
private string GetMovieTitle(MediaItem currMediaItem) { string value; return(MediaItemAspect.TryGetAttribute(currMediaItem.Aspects, MovieAspect.ATTR_MOVIE_NAME, out value) ? value : null); }
/// <summary> /// Creates Scrobble data based on a DBMovieInfo object /// </summary> /// <param name="psc"></param> /// <param name="pc">PlayerContext</param> /// <param name="starting"></param> /// <param name="scrobbleData"></param> /// <param name="state"></param> /// <returns>The Trakt scrobble data to send</returns> private bool TryCreateScrobbleData(IPlayerSlotController psc, IPlayerContext pc, bool starting, out AbstractScrobble scrobbleData, out TraktScrobbleStates state) { scrobbleData = null; state = starting ? TraktScrobbleStates.watching : TraktScrobbleStates.scrobble; if (_settings.Settings.Authentication == null) { return(false); } string username = _settings.Settings.Authentication.Username; string password = _settings.Settings.Authentication.Password; if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password)) { return(false); } // For canceling the watching, it is to have no TraktMovieScrobble. if (pc.CurrentMediaItem == null) { if (starting) { return(false); } state = TraktScrobbleStates.cancelwatching; return(true); } bool isMovie = pc.CurrentMediaItem.Aspects.ContainsKey(MovieAspect.ASPECT_ID); bool isSeries = pc.CurrentMediaItem.Aspects.ContainsKey(SeriesAspect.ASPECT_ID); if (!isMovie && !isSeries) { return(false); } string title = pc.CurrentPlayer != null ? pc.CurrentPlayer.MediaItemTitle : null; IMediaPlaybackControl pmc = pc.CurrentPlayer as IMediaPlaybackControl; TimeSpan currentPosition; if (pmc != null) { _progressUpdateWorks[psc].Duration = pmc.Duration; currentPosition = pmc.CurrentTime; } else { // Player is already removed on stopping, so take the resume position if available currentPosition = _progressUpdateWorks[psc].ResumePosition; } int progress = currentPosition == TimeSpan.Zero ? (starting ? 0 : 100) : Math.Min((int)(currentPosition.TotalSeconds * 100 / _progressUpdateWorks[psc].Duration.TotalSeconds), 100); string value; int iValue; DateTime dtValue; long lValue; if (isMovie) { TraktMovieScrobble movie = new TraktMovieScrobble(); if (MediaItemAspect.TryGetAttribute(pc.CurrentMediaItem.Aspects, MovieAspect.ATTR_IMDB_ID, out value) && !string.IsNullOrWhiteSpace(value)) { movie.IMDBID = value; } if (MediaItemAspect.TryGetAttribute(pc.CurrentMediaItem.Aspects, MovieAspect.ATTR_TMDB_ID, out iValue) && iValue > 0) { movie.TMDBID = iValue.ToString(); } if (MediaItemAspect.TryGetAttribute(pc.CurrentMediaItem.Aspects, MediaAspect.ATTR_RECORDINGTIME, out dtValue)) { movie.Year = dtValue.Year.ToString(); } if (MediaItemAspect.TryGetAttribute(pc.CurrentMediaItem.Aspects, MovieAspect.ATTR_RUNTIME_M, out iValue) && iValue > 0) { movie.Duration = iValue.ToString(); } scrobbleData = movie; } if (isSeries) { TraktEpisodeScrobble series = new TraktEpisodeScrobble(); if (MediaItemAspect.TryGetAttribute(pc.CurrentMediaItem.Aspects, SeriesAspect.ATTR_IMDB_ID, out value) && !string.IsNullOrWhiteSpace(value)) { series.IMDBID = value; } if (MediaItemAspect.TryGetAttribute(pc.CurrentMediaItem.Aspects, SeriesAspect.ATTR_TVDB_ID, out iValue)) { series.SeriesID = iValue.ToString(); } if (MediaItemAspect.TryGetAttribute(pc.CurrentMediaItem.Aspects, SeriesAspect.ATTR_SERIESNAME, out value) && !string.IsNullOrWhiteSpace(value)) { series.Title = value; } if (MediaItemAspect.TryGetAttribute(pc.CurrentMediaItem.Aspects, SeriesAspect.ATTR_FIRSTAIRED, out dtValue)) { series.Year = dtValue.Year.ToString(); } if (MediaItemAspect.TryGetAttribute(pc.CurrentMediaItem.Aspects, SeriesAspect.ATTR_SEASON, out iValue)) { series.Season = iValue.ToString(); } List <int> intList; if (MediaItemAspect.TryGetAttribute(pc.CurrentMediaItem.Aspects, SeriesAspect.ATTR_EPISODE, out intList) && intList.Any()) { series.Episode = intList.First().ToString(); // TODO: multi episode files?! } scrobbleData = series; } // Fallback duration info if (string.IsNullOrWhiteSpace(scrobbleData.Duration) && MediaItemAspect.TryGetAttribute(pc.CurrentMediaItem.Aspects, VideoAspect.ATTR_DURATION, out lValue) && lValue > 0) { scrobbleData.Duration = (lValue / 60).ToString(); } if (string.IsNullOrWhiteSpace(scrobbleData.Title)) { scrobbleData.Title = title; } scrobbleData.Progress = progress.ToString(); if (!starting && progress < WATCHED_PERCENT) { state = TraktScrobbleStates.cancelwatching; } scrobbleData.PluginVersion = TraktSettings.Version; scrobbleData.MediaCenter = "MediaPortal 2"; scrobbleData.MediaCenterVersion = Assembly.GetEntryAssembly().GetName().Version.ToString(); scrobbleData.MediaCenterBuildDate = String.Empty; scrobbleData.Username = username; scrobbleData.Password = password; return(true); }
private string GetSeriesTitle(MediaItem currMediaItem) { string value; return(MediaItemAspect.TryGetAttribute(currMediaItem.Aspects, SeriesAspect.ATTR_SERIESNAME, out value) ? value : null); }
protected Guid GetOrAddDirectory(IFileSystemResourceAccessor directoryAccessor, Guid parentDirectoryId, IMediaBrowsing mediaBrowsing, IImportResultHandler resultHandler) { ResourcePath directoryPath = directoryAccessor.CanonicalLocalResourcePath; MediaItem directoryItem = mediaBrowsing.LoadLocalItem(directoryPath, EMPTY_MIA_ID_ENUMERATION, DIRECTORY_MIA_ID_ENUMERATION); if (directoryItem != null) { MediaItemAspect da; if (!directoryItem.Aspects.TryGetValue(DirectoryAspect.ASPECT_ID, out da)) { // This is the case if the path was formerly imported as a non-directory media item; we cannot reuse it resultHandler.DeleteMediaItem(directoryPath); directoryItem = null; } } if (directoryItem == null) { // Add directory item to ML MediaItemAspect mia = new MediaItemAspect(MediaAspect.Metadata); mia.SetAttribute(MediaAspect.ATTR_TITLE, directoryAccessor.ResourceName); mia.SetAttribute(MediaAspect.ATTR_MIME_TYPE, null); mia.SetAttribute(MediaAspect.ATTR_RECORDINGTIME, DateTime.MinValue); mia.SetAttribute(MediaAspect.ATTR_RATING, 0); mia.SetAttribute(MediaAspect.ATTR_COMMENT, null); mia.SetAttribute(MediaAspect.ATTR_LASTPLAYED, DateTime.MinValue); MediaItemAspect da = new MediaItemAspect(DirectoryAspect.Metadata); IList<MediaItemAspect> aspects = new List<MediaItemAspect>(new[] { mia, da, }); return resultHandler.UpdateMediaItem(parentDirectoryId, directoryPath, aspects); } return directoryItem.MediaItemId; }
public void TestReconcileMediaItem() { //TODO: Update below code to work with ML changes return; MockCore.SetupLibrary(true); ServiceRegistration.Set <IPluginManager>(new MockPluginManager()); MockRelationshipExtractor extractor = new MockRelationshipExtractor(); MockMediaAccessor accessor = new MockMediaAccessor(); accessor.AddRelationshipExtractor(extractor); ServiceRegistration.Set <IMediaAccessor>(accessor); ServiceRegistration.Get <IMediaAccessor>().Initialize(); MockCore.Management.AddMediaItemAspectStorage(EpisodeAspect.Metadata); MockCore.Management.AddMediaItemAspectStorage(ExternalIdentifierAspect.Metadata); MockCore.Management.AddMediaItemAspectStorage(ImporterAspect.Metadata); MockCore.Management.AddMediaItemAspectStorage(MediaAspect.Metadata); MockCore.Management.AddMediaItemAspectStorage(ProviderResourceAspect.Metadata); MockCore.Management.AddMediaItemAspectStorage(RelationshipAspect.Metadata); MockCore.Management.AddMediaItemAspectStorage(SeasonAspect.Metadata); MockCore.Management.AddMediaItemAspectStorage(SeriesAspect.Metadata); Guid episodeItemId = new Guid("aaaaaaaa-1111-1111-1111-aaaaaaaaaaaa"); Guid seasonItemId = new Guid("bbbbbbbb-2222-2222-2222-bbbbbbbbbbbb"); Guid seriesItemId = new Guid("cccccccc-3333-3333-3333-cccccccccccc"); string seriesName = "The Series"; string seriesDescription = "The adventures of some characters"; int episode = 1; string episodeName = "The Episode"; string episodeTitle = seriesName + ": " + episodeName; Guid parentDirectoryId = new Guid("dddddddd-4444-4444-4444-dddddddddddd"); int season = 2; string seriesSeasonName = seriesName + " " + season; string seasonDescription = "Continuing adventures of some characters, several story arcs etc"; string externalSource = "TEST"; string externalSeriesId = "345"; MockCore.Library.AddMediaItemId(episodeItemId); MockCore.Library.AddMediaItemId(seasonItemId); MockCore.Library.AddMediaItemId(seriesItemId); string systemId = "local"; string mimeType = "video/mkv"; string pathStr = @"c:\item.mkv"; ResourcePath path = LocalFsResourceProviderBase.ToResourcePath(pathStr); DateTime importDate; DateTime.TryParse("2014-10-11 12:34:56", out importDate); IDictionary <Guid, IList <MediaItemAspect> > episodeAspects = new Dictionary <Guid, IList <MediaItemAspect> >(); MediaItemAspect.SetAttribute(episodeAspects, MediaAspect.ATTR_TITLE, episodeTitle); MediaItemAspect.SetCollectionAttribute(episodeAspects, EpisodeAspect.ATTR_EPISODE, new[] { episode }); MediaItemAspect.SetAttribute(episodeAspects, EpisodeAspect.ATTR_SEASON, season); MultipleMediaItemAspect providerResourceAspect = MediaItemAspect.CreateAspect(episodeAspects, ProviderResourceAspect.Metadata); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, mimeType); MediaItemAspect.AddOrUpdateExternalIdentifier(episodeAspects, externalSource, ExternalIdentifierAspect.TYPE_SERIES, externalSeriesId); ServiceRegistration.Get <ILogger>().Debug("Episode:"); MockCore.ShowMediaAspects(episodeAspects, MockCore.Library.GetManagedMediaItemAspectMetadata()); IDictionary <Guid, IList <MediaItemAspect> > seasonAspects = new Dictionary <Guid, IList <MediaItemAspect> >(); MediaItemAspect.SetAttribute(seasonAspects, SeasonAspect.ATTR_SERIES_NAME, seriesName); MediaItemAspect.SetAttribute(seasonAspects, SeasonAspect.ATTR_SEASON, season); MediaItemAspect.SetAttribute(seasonAspects, SeasonAspect.ATTR_DESCRIPTION, seasonDescription); MediaItemAspect.AddOrUpdateExternalIdentifier(seasonAspects, externalSource, ExternalIdentifierAspect.TYPE_SERIES, externalSeriesId); ServiceRegistration.Get <ILogger>().Debug("Season:"); MockCore.ShowMediaAspects(seasonAspects, MockCore.Library.GetManagedMediaItemAspectMetadata()); Guid[] matchAspects = new[] { SeasonAspect.ASPECT_ID, ExternalIdentifierAspect.ASPECT_ID, MediaAspect.ASPECT_ID }; extractor.AddRelationship(EpisodeAspect.ROLE_EPISODE, new[] { EpisodeAspect.ASPECT_ID }, SeasonAspect.ROLE_SEASON, new[] { SeasonAspect.ASPECT_ID }, matchAspects, externalSource, ExternalIdentifierAspect.TYPE_SERIES, externalSeriesId, new List <IDictionary <Guid, IList <MediaItemAspect> > >() { seasonAspects }, EpisodeSeasonMatcher, episode); IDictionary <Guid, IList <MediaItemAspect> > seriesAspects = new Dictionary <Guid, IList <MediaItemAspect> >(); MediaItemAspect.SetAttribute(seriesAspects, SeasonAspect.ATTR_SERIES_NAME, seriesName); MediaItemAspect.SetAttribute(seriesAspects, SeasonAspect.ATTR_DESCRIPTION, seriesDescription); MediaItemAspect.AddOrUpdateExternalIdentifier(seriesAspects, externalSource, ExternalIdentifierAspect.TYPE_SERIES, externalSeriesId); ServiceRegistration.Get <ILogger>().Debug("Series:"); MockCore.ShowMediaAspects(seriesAspects, MockCore.Library.GetManagedMediaItemAspectMetadata()); matchAspects = new[] { SeriesAspect.ASPECT_ID, ExternalIdentifierAspect.ASPECT_ID, MediaAspect.ASPECT_ID }; extractor.AddRelationship(SeasonAspect.ROLE_SEASON, new[] { SeasonAspect.ASPECT_ID }, SeriesAspect.ROLE_SERIES, new[] { SeriesAspect.ASPECT_ID }, matchAspects, externalSource, ExternalIdentifierAspect.TYPE_SERIES, externalSeriesId, new List <IDictionary <Guid, IList <MediaItemAspect> > >() { seriesAspects }, null, season); MockDBUtils.AddReader(1, "SELECT MEDIA_ITEM_ID FROM M_PROVIDERRESOURCE WHERE SYSTEM_ID = @SYSTEM_ID AND PATH = @PATH", "MEDIA_ITEM_ID"); MockDBUtils.AddReader(2, "SELECT MEDIA_ITEM_ID FROM M_PROVIDERRESOURCE WHERE MEDIA_ITEM_ID = @MEDIA_ITEM_ID", "MEDIA_ITEM_ID"); // Readers used by UpdateRelationships to find episode item MockReader reader2 = MockDBUtils.AddReader(3, "SELECT T6.MEDIA_ITEM_ID A30, T0.MEDIA_ITEM_ID A31, T1.MEDIA_ITEM_ID A32, T2.MEDIA_ITEM_ID A33, T3.MEDIA_ITEM_ID A34, T4.MEDIA_ITEM_ID A35, T5.MEDIA_ITEM_ID A36, " + "T0.SERIESNAME A0, T0.SEASON A1, T0.SERIESSEASONNAME A2, T0.EPISODENAME A3, T0.FIRSTAIRED A4, T0.TOTALRATING A5, T0.RATINGCOUNT A6, " + "T1.LASTIMPORTDATE A7, T1.DIRTY A8, T1.DATEADDED A9, " + "T2.TITLE A10, T2.RECORDINGTIME A11, T2.RATING A12, T2.COMMENT A13, T2.PLAYCOUNT A14, T2.LASTPLAYED A15, " + "T3.SYSTEM_ID A16, T3.MIMETYPE A17, T3.SIZE A18, T3.PATH A19, T3.PARENTDIRECTORY A20, " + "T4.SERIESNAME_0 A21, T4.SEASON_0 A22, T4.SERIESSEASONNAME_0 A23, T4.DESCRIPTION A24, T4.FIRSTAIRED_0 A25, T4.TOTALRATING_0 A26, T4.RATINGCOUNT_0 A27, " + "T5.SERIESNAME_1 A28, T5.DESCRIPTION_0 A29 " + "FROM MEDIA_ITEMS T6 " + "LEFT OUTER JOIN M_EPISODEITEM T0 ON T0.MEDIA_ITEM_ID = T6.MEDIA_ITEM_ID " + "LEFT OUTER JOIN M_IMPORTEDITEM T1 ON T1.MEDIA_ITEM_ID = T6.MEDIA_ITEM_ID " + "LEFT OUTER JOIN M_MEDIAITEM T2 ON T2.MEDIA_ITEM_ID = T6.MEDIA_ITEM_ID " + "LEFT OUTER JOIN M_PROVIDERRESOURCE T3 ON T3.MEDIA_ITEM_ID = T6.MEDIA_ITEM_ID " + "LEFT OUTER JOIN M_SEASONITEM T4 ON T4.MEDIA_ITEM_ID = T6.MEDIA_ITEM_ID " + "LEFT OUTER JOIN M_SERIESITEM T5 ON T5.MEDIA_ITEM_ID = T6.MEDIA_ITEM_ID " + "WHERE T6.MEDIA_ITEM_ID = @V0", CreateAttributeIdList(30, 36)); reader2.AddResult( episodeItemId, episodeItemId, episodeItemId, episodeItemId, episodeItemId, null, null, null, season, null, null, null, null, null, importDate, false, importDate, episodeTitle, null, null, null, null, null, systemId, mimeType, 100, @"c:\", parentDirectoryId, null, null, null, null, null, null, null, null, null ); MockReader reader3 = MockDBUtils.AddReader(4, "SELECT T0.MEDIA_ITEM_ID A0, " + "T1.VALUE A1 " + "FROM NM_EPISODE T0 " + "INNER JOIN V_EPISODE T1 ON T0.VALUE_ID = T1.VALUE_ID " + "WHERE T0.MEDIA_ITEM_ID = @V0", "A0", "A1"); reader3.AddResult( episodeItemId, episode); MockDBUtils.AddReader(5, "SELECT T0.MEDIA_ITEM_ID A0, T1.VALUE A1 FROM NM_DVDEPISODE T0 INNER JOIN V_DVDEPISODE T1 ON T0.VALUE_ID = T1.VALUE_ID WHERE T0.MEDIA_ITEM_ID = @V0", "A0", "A1"); MockReader reader5 = MockDBUtils.AddReader(6, "SELECT T0.MEDIA_ITEM_ID A3, T0.MEDIA_ITEM_ID A4, " + "T0.SOURCE A0, T0.TYPE A1, T0.ID A2 " + "FROM M_EXTERNALIDENTIFIER T0 " + "WHERE T0.MEDIA_ITEM_ID = @V0", CreateAttributeIdList(3, 4)); reader5.AddResult( episodeItemId, episodeItemId, externalSource, ExternalIdentifierAspect.TYPE_SERIES, externalSeriesId); MockDBUtils.AddReader(7, "SELECT T0.MEDIA_ITEM_ID A4, T0.MEDIA_ITEM_ID A5, " + "T0.ROLE A0, T0.LINKEDROLE A1, T0.LINKEDID A2, T0.RELATIONSHIPINDEX A3 " + "FROM M_RELATIONSHIP T0 " + "WHERE T0.MEDIA_ITEM_ID = @V0", CreateAttributeIdList(3, 4)); MockDBUtils.AddReader(8, "SELECT T0.MEDIA_ITEM_ID A4, T0.MEDIA_ITEM_ID A5, T0.ROLE A0, T0.LINKEDROLE A1, T0.LINKEDID A2, T0.RELATIONSHIPINDEX A3 FROM M_RELATIONSHIP T0 WHERE T0.LINKEDID IN (@V0)"); // Readers used by UpdateRelationships to find season item MockDBUtils.AddReader(9, "SELECT T0.MEDIA_ITEM_ID A30, T0.MEDIA_ITEM_ID A31, T1.MEDIA_ITEM_ID A32, T2.MEDIA_ITEM_ID A33, T3.MEDIA_ITEM_ID A34, T4.MEDIA_ITEM_ID A35, T5.MEDIA_ITEM_ID A36, " + "T0.SERIESNAME_0 A0, T0.SEASON_0 A1, T0.SERIESSEASONNAME_0 A2, T0.DESCRIPTION A3, T0.FIRSTAIRED_0 A4, T0.TOTALRATING_0 A5, T0.RATINGCOUNT_0 A6, " + "T1.TITLE A7, T1.RECORDINGTIME A8, T1.RATING A9, T1.COMMENT A10, T1.PLAYCOUNT A11, T1.LASTPLAYED A12, " + "T2.SERIESNAME A13, T2.SEASON A14, T2.SERIESSEASONNAME A15, T2.EPISODENAME A16, T2.FIRSTAIRED A17, T2.TOTALRATING A18, T2.RATINGCOUNT A19, " + "T3.LASTIMPORTDATE A20, T3.DIRTY A21, T3.DATEADDED A22, " + "T4.SYSTEM_ID A23, T4.MIMETYPE A24, T4.SIZE A25, T4.PATH A26, T4.PARENTDIRECTORY A27, " + "T5.SERIESNAME_1 A28, T5.DESCRIPTION_0 A29 " + "FROM M_SEASONITEM T0 " + "INNER JOIN M_MEDIAITEM T1 ON T1.MEDIA_ITEM_ID = T0.MEDIA_ITEM_ID " + "LEFT OUTER JOIN M_EPISODEITEM T2 ON T2.MEDIA_ITEM_ID = T0.MEDIA_ITEM_ID " + "LEFT OUTER JOIN M_IMPORTEDITEM T3 ON T3.MEDIA_ITEM_ID = T0.MEDIA_ITEM_ID " + "LEFT OUTER JOIN M_PROVIDERRESOURCE T4 ON T4.MEDIA_ITEM_ID = T0.MEDIA_ITEM_ID " + "LEFT OUTER JOIN M_SERIESITEM T5 ON T5.MEDIA_ITEM_ID = T0.MEDIA_ITEM_ID " + "WHERE T0.MEDIA_ITEM_ID IN(SELECT MEDIA_ITEM_ID FROM M_EXTERNALIDENTIFIER WHERE SOURCE = @V0 AND TYPE = @V1 AND ID = @V2)", CreateAttributeIdList(30, 36)); MockDBUtils.AddReader(10, "SELECT MEDIA_ITEM_ID FROM M_PROVIDERRESOURCE WHERE SYSTEM_ID = @SYSTEM_ID AND PATH = @PATH", "MEDIA_ITEM_ID"); MockReader reader10 = MockDBUtils.AddReader(11, "SELECT T6.MEDIA_ITEM_ID A30, T0.MEDIA_ITEM_ID A31, T1.MEDIA_ITEM_ID A32, T2.MEDIA_ITEM_ID A33, T3.MEDIA_ITEM_ID A34, T4.MEDIA_ITEM_ID A35, T5.MEDIA_ITEM_ID A36, " + "T0.SERIESNAME A0, T0.SEASON A1, T0.SERIESSEASONNAME A2, T0.EPISODENAME A3, T0.FIRSTAIRED A4, T0.TOTALRATING A5, T0.RATINGCOUNT A6, " + "T1.LASTIMPORTDATE A7, T1.DIRTY A8, T1.DATEADDED A9, " + "T2.TITLE A10, T2.RECORDINGTIME A11, T2.RATING A12, T2.COMMENT A13, T2.PLAYCOUNT A14, T2.LASTPLAYED A15, " + "T3.SYSTEM_ID A16, T3.MIMETYPE A17, T3.SIZE A18, T3.PATH A19, T3.PARENTDIRECTORY A20, " + "T4.SERIESNAME_0 A21, T4.SEASON_0 A22, T4.SERIESSEASONNAME_0 A23, T4.DESCRIPTION A24, T4.FIRSTAIRED_0 A25, T4.TOTALRATING_0 A26, T4.RATINGCOUNT_0 A27, " + "T5.SERIESNAME_1 A28, T5.DESCRIPTION_0 A29 " + "FROM MEDIA_ITEMS T6 " + "LEFT OUTER JOIN M_EPISODEITEM T0 ON T0.MEDIA_ITEM_ID = T6.MEDIA_ITEM_ID " + "LEFT OUTER JOIN M_IMPORTEDITEM T1 ON T1.MEDIA_ITEM_ID = T6.MEDIA_ITEM_ID " + "LEFT OUTER JOIN M_MEDIAITEM T2 ON T2.MEDIA_ITEM_ID = T6.MEDIA_ITEM_ID " + "LEFT OUTER JOIN M_PROVIDERRESOURCE T3 ON T3.MEDIA_ITEM_ID = T6.MEDIA_ITEM_ID " + "LEFT OUTER JOIN M_SEASONITEM T4 ON T4.MEDIA_ITEM_ID = T6.MEDIA_ITEM_ID " + "LEFT OUTER JOIN M_SERIESITEM T5 ON T5.MEDIA_ITEM_ID = T6.MEDIA_ITEM_ID " + "WHERE T6.MEDIA_ITEM_ID = @V0", CreateAttributeIdList(30, 36)); reader10.AddResult( seasonItemId, null, seasonItemId, seasonItemId, seasonItemId, seasonItemId, null, null, null, null, null, null, null, null, importDate, false, importDate, seriesSeasonName, null, null, null, null, null, null, null, 0, null, Guid.Empty, seriesName, season, seriesSeasonName, seasonDescription, null, null, null, null, null ); MockReader reader11 = MockDBUtils.AddReader(12, "SELECT T0.MEDIA_ITEM_ID A3, T0.MEDIA_ITEM_ID A4, " + "T0.SOURCE A0, T0.TYPE A1, T0.ID A2 " + "FROM M_EXTERNALIDENTIFIER T0 " + "WHERE T0.MEDIA_ITEM_ID = @V0", CreateAttributeIdList(3, 4)); reader11.AddResult( seasonItemId, seasonItemId, externalSource, ExternalIdentifierAspect.TYPE_SERIES, externalSeriesId); MockDBUtils.AddReader(13, "SELECT T0.MEDIA_ITEM_ID A4, T0.MEDIA_ITEM_ID A5, " + "T0.ROLE A0, T0.LINKEDROLE A1, T0.LINKEDID A2, T0.RELATIONSHIPINDEX A3 " + "FROM M_RELATIONSHIP T0 " + "WHERE T0.MEDIA_ITEM_ID = @V0", CreateAttributeIdList(3, 4)); MockDBUtils.AddReader(14, "SELECT T0.MEDIA_ITEM_ID A4, T0.MEDIA_ITEM_ID A5, T0.ROLE A0, T0.LINKEDROLE A1, T0.LINKEDID A2, T0.RELATIONSHIPINDEX A3 FROM M_RELATIONSHIP T0 WHERE T0.LINKEDID IN (@V0)"); MockDBUtils.AddReader(15, "SELECT T0.MEDIA_ITEM_ID A30, T0.MEDIA_ITEM_ID A31, T1.MEDIA_ITEM_ID A32, T2.MEDIA_ITEM_ID A33, T3.MEDIA_ITEM_ID A34, T4.MEDIA_ITEM_ID A35, T5.MEDIA_ITEM_ID A36, " + "T0.SERIESNAME_1 A0, T0.DESCRIPTION_0 A1, " + "T1.TITLE A2, T1.RECORDINGTIME A3, T1.RATING A4, T1.COMMENT A5, T1.PLAYCOUNT A6, T1.LASTPLAYED A7, " + "T2.SERIESNAME A8, T2.SEASON A9, T2.SERIESSEASONNAME A10, T2.EPISODENAME A11, T2.FIRSTAIRED A12, T2.TOTALRATING A13, T2.RATINGCOUNT A14, " + "T3.LASTIMPORTDATE A15, T3.DIRTY A16, T3.DATEADDED A17, " + "T4.SYSTEM_ID A18, T4.MIMETYPE A19, T4.SIZE A20, T4.PATH A21, T4.PARENTDIRECTORY A22, " + "T5.SERIESNAME_0 A23, T5.SEASON_0 A24, T5.SERIESSEASONNAME_0 A25, T5.DESCRIPTION A26, T5.FIRSTAIRED_0 A27, T5.TOTALRATING_0 A28, T5.RATINGCOUNT_0 A29 " + "FROM M_SERIESITEM T0 " + "INNER JOIN M_MEDIAITEM T1 ON T1.MEDIA_ITEM_ID = T0.MEDIA_ITEM_ID " + "LEFT OUTER JOIN M_EPISODEITEM T2 ON T2.MEDIA_ITEM_ID = T0.MEDIA_ITEM_ID " + "LEFT OUTER JOIN M_IMPORTEDITEM T3 ON T3.MEDIA_ITEM_ID = T0.MEDIA_ITEM_ID " + "LEFT OUTER JOIN M_PROVIDERRESOURCE T4 ON T4.MEDIA_ITEM_ID = T0.MEDIA_ITEM_ID " + "LEFT OUTER JOIN M_SEASONITEM T5 ON T5.MEDIA_ITEM_ID = T0.MEDIA_ITEM_ID " + "WHERE T0.MEDIA_ITEM_ID IN(SELECT MEDIA_ITEM_ID FROM M_EXTERNALIDENTIFIER WHERE SOURCE = @V0 AND TYPE = @V1 AND ID = @V2)", CreateAttributeIdList(30, 36)); MockDBUtils.AddReader(16, "SELECT MEDIA_ITEM_ID FROM M_PROVIDERRESOURCE WHERE SYSTEM_ID = @SYSTEM_ID AND PATH = @PATH", "MEDIA_ITEM_ID"); // Readers used by UpdateRelationships to find series item MockReader reader16 = MockDBUtils.AddReader(17, "SELECT T6.MEDIA_ITEM_ID A30, T0.MEDIA_ITEM_ID A31, T1.MEDIA_ITEM_ID A32, T2.MEDIA_ITEM_ID A33, T3.MEDIA_ITEM_ID A34, T4.MEDIA_ITEM_ID A35, T5.MEDIA_ITEM_ID A36, " + "T0.SERIESNAME A0, T0.SEASON A1, T0.SERIESSEASONNAME A2, T0.EPISODENAME A3, T0.FIRSTAIRED A4, T0.TOTALRATING A5, T0.RATINGCOUNT A6, " + "T1.LASTIMPORTDATE A7, T1.DIRTY A8, T1.DATEADDED A9, " + "T2.TITLE A10, T2.RECORDINGTIME A11, T2.RATING A12, T2.COMMENT A13, T2.PLAYCOUNT A14, T2.LASTPLAYED A15, " + "T3.SYSTEM_ID A16, T3.MIMETYPE A17, T3.SIZE A18, T3.PATH A19, T3.PARENTDIRECTORY A20, " + "T4.SERIESNAME_0 A21, T4.SEASON_0 A22, T4.SERIESSEASONNAME_0 A23, T4.DESCRIPTION A24, T4.FIRSTAIRED_0 A25, T4.TOTALRATING_0 A26, T4.RATINGCOUNT_0 A27, " + "T5.SERIESNAME_1 A28, T5.DESCRIPTION_0 A29 " + "FROM MEDIA_ITEMS T6 " + "LEFT OUTER JOIN M_EPISODEITEM T0 ON T0.MEDIA_ITEM_ID = T6.MEDIA_ITEM_ID " + "LEFT OUTER JOIN M_IMPORTEDITEM T1 ON T1.MEDIA_ITEM_ID = T6.MEDIA_ITEM_ID " + "LEFT OUTER JOIN M_MEDIAITEM T2 ON T2.MEDIA_ITEM_ID = T6.MEDIA_ITEM_ID " + "LEFT OUTER JOIN M_PROVIDERRESOURCE T3 ON T3.MEDIA_ITEM_ID = T6.MEDIA_ITEM_ID " + "LEFT OUTER JOIN M_SEASONITEM T4 ON T4.MEDIA_ITEM_ID = T6.MEDIA_ITEM_ID " + "LEFT OUTER JOIN M_SERIESITEM T5 ON T5.MEDIA_ITEM_ID = T6.MEDIA_ITEM_ID " + "WHERE T6.MEDIA_ITEM_ID = @V0", CreateAttributeIdList(30, 36)); reader16.AddResult( seriesItemId, null, seasonItemId, seasonItemId, seasonItemId, null, seriesItemId, null, null, null, null, null, null, null, importDate, false, importDate, seriesName, null, null, null, null, null, null, null, 0, null, Guid.Empty, null, null, null, null, null, null, null, seriesName, seriesDescription ); MockReader reader17 = MockDBUtils.AddReader(18, "SELECT T0.MEDIA_ITEM_ID A3, T0.MEDIA_ITEM_ID A4, " + "T0.SOURCE A0, T0.TYPE A1, T0.ID A2 " + "FROM M_EXTERNALIDENTIFIER T0 " + "WHERE T0.MEDIA_ITEM_ID = @V0", CreateAttributeIdList(3, 4)); reader17.AddResult( seriesItemId, seriesItemId, externalSource, ExternalIdentifierAspect.TYPE_SERIES, externalSeriesId); MockDBUtils.AddReader(19, "SELECT T0.MEDIA_ITEM_ID A4, T0.MEDIA_ITEM_ID A5, " + "T0.ROLE A0, T0.LINKEDROLE A1, T0.LINKEDID A2, T0.RELATIONSHIPINDEX A3 " + "FROM M_RELATIONSHIP T0 " + "WHERE T0.MEDIA_ITEM_ID = @V0", CreateAttributeIdList(4, 5)); MockDBUtils.AddReader(20, "SELECT T0.MEDIA_ITEM_ID A4, T0.MEDIA_ITEM_ID A5, T0.ROLE A0, T0.LINKEDROLE A1, T0.LINKEDID A2, T0.RELATIONSHIPINDEX A3 FROM M_RELATIONSHIP T0 WHERE T0.LINKEDID IN (@V0)"); MockReader reader20 = MockDBUtils.AddReader(21, "SELECT MEDIA_ITEM_ID " + "FROM M_EXTERNALIDENTIFIER " + "WHERE MEDIA_ITEM_ID = @MEDIA_ITEM_ID AND SOURCE = @SOURCE AND TYPE = @TYPE", "MEDIA_ITEM_ID"); reader20.AddResult( seasonItemId, externalSource, ExternalIdentifierAspect.TYPE_SERIES, externalSeriesId); MockDBUtils.AddReader(22, "SELECT MEDIA_ITEM_ID " + "FROM M_RELATIONSHIP " + "WHERE MEDIA_ITEM_ID = @MEDIA_ITEM_ID AND ROLE = @ROLE AND LINKEDROLE = @LINKEDROLE AND LINKEDID = @LINKEDID", "MEDIA_ITEM_ID"); MockReader reader22 = MockDBUtils.AddReader(23, "SELECT MEDIA_ITEM_ID " + "FROM M_EXTERNALIDENTIFIER " + "WHERE MEDIA_ITEM_ID = @MEDIA_ITEM_ID AND SOURCE = @SOURCE AND TYPE = @TYPE", "MEDIA_ITEM_ID"); reader22.AddResult( seasonItemId, externalSource, ExternalIdentifierAspect.TYPE_SERIES, externalSeriesId); MockDBUtils.AddReader(24, "SELECT MEDIA_ITEM_ID " + "FROM M_RELATIONSHIP " + "WHERE MEDIA_ITEM_ID = @MEDIA_ITEM_ID AND ROLE = @ROLE AND LINKEDROLE = @LINKEDROLE AND LINKEDID = @LINKEDID", "MEDIA_ITEM_ID"); MockCore.Library.AddOrUpdateMediaItem(parentDirectoryId, systemId, path, episodeAspects.Values.SelectMany(x => x), true); MockCore.ShutdownLibrary(); }
public override bool FromMetadata(IDictionary <Guid, IList <MediaItemAspect> > aspectData) { if (!aspectData.ContainsKey(AudioAspect.ASPECT_ID)) { return(false); } GetMetadataChanged(aspectData); MediaItemAspect.TryGetAttribute(aspectData, AudioAspect.ATTR_TRACKNAME, out TrackName); MediaItemAspect.TryGetAttribute(aspectData, MediaAspect.ATTR_SORT_TITLE, out TrackNameSort); MediaItemAspect.TryGetAttribute(aspectData, AudioAspect.ATTR_LYRICS, out TrackLyrics); MediaItemAspect.TryGetAttribute(aspectData, MediaAspect.ATTR_RECORDINGTIME, out ReleaseDate); MediaItemAspect.TryGetAttribute(aspectData, AudioAspect.ATTR_TRACK, out TrackNum); MediaItemAspect.TryGetAttribute(aspectData, AudioAspect.ATTR_NUMTRACKS, out TotalTracks); MediaItemAspect.TryGetAttribute(aspectData, AudioAspect.ATTR_COMPILATION, out Compilation); MediaItemAspect.TryGetAttribute(aspectData, AudioAspect.ATTR_BITRATE, out BitRate); MediaItemAspect.TryGetAttribute(aspectData, AudioAspect.ATTR_SAMPLERATE, out SampleRate); MediaItemAspect.TryGetAttribute(aspectData, AudioAspect.ATTR_CHANNELS, out Channels); MediaItemAspect.TryGetAttribute(aspectData, AudioAspect.ATTR_ALBUM, out Album); MediaItemAspect.TryGetAttribute(aspectData, AudioAspect.ATTR_DISCID, out DiscNum); MediaItemAspect.TryGetAttribute(aspectData, AudioAspect.ATTR_NUMDISCS, out TotalDiscs); MediaItemAspect.TryGetAttribute(aspectData, AudioAspect.ATTR_DURATION, out Duration); MediaItemAspect.TryGetAttribute(aspectData, AudioAspect.ATTR_ENCODING, out Encoding); MediaItemAspect.TryGetAttribute(aspectData, AudioAspect.ATTR_CONTENT_GROUP, out ContentGroup); double?rating; MediaItemAspect.TryGetAttribute(aspectData, AudioAspect.ATTR_TOTAL_RATING, out rating); int?voteCount; MediaItemAspect.TryGetAttribute(aspectData, AudioAspect.ATTR_RATING_COUNT, out voteCount); Rating = new SimpleRating(rating, voteCount); CustomIds.Clear(); CustomAlbumIds.Clear(); IList <MultipleMediaItemAspect> externalIdAspects; if (MediaItemAspect.TryGetAspects(aspectData, ExternalIdentifierAspect.Metadata, out externalIdAspects)) { foreach (MultipleMediaItemAspect externalId in externalIdAspects) { string source = externalId.GetAttributeValue <string>(ExternalIdentifierAspect.ATTR_SOURCE); string id = externalId.GetAttributeValue <string>(ExternalIdentifierAspect.ATTR_ID); string type = externalId.GetAttributeValue <string>(ExternalIdentifierAspect.ATTR_TYPE); if (type == ExternalIdentifierAspect.TYPE_TRACK) { if (source == ExternalIdentifierAspect.SOURCE_AUDIODB) { AudioDbId = Convert.ToInt32(id); } else if (source == ExternalIdentifierAspect.SOURCE_LYRIC) { LyricId = Convert.ToInt32(id); } else if (source == ExternalIdentifierAspect.SOURCE_MVDB) { MvDbId = Convert.ToInt32(id); } else if (source == ExternalIdentifierAspect.SOURCE_MUSICBRAINZ) { MusicBrainzId = id; } else if (source == ExternalIdentifierAspect.SOURCE_ISRC) { IsrcId = id; } else if (source == ExternalIdentifierAspect.SOURCE_MUSIC_IP) { MusicIpId = id; } else if (source == ExternalIdentifierAspect.SOURCE_NAME) { NameId = id; } else { CustomIds.Add(source, id); } } else if (type == ExternalIdentifierAspect.TYPE_ALBUM) { if (source == ExternalIdentifierAspect.SOURCE_AUDIODB) { AlbumAudioDbId = Convert.ToInt32(id); } else if (source == ExternalIdentifierAspect.SOURCE_MUSICBRAINZ) { AlbumMusicBrainzId = id; } else if (source == ExternalIdentifierAspect.SOURCE_MUSICBRAINZ_GROUP) { AlbumMusicBrainzGroupId = id; } else if (source == ExternalIdentifierAspect.SOURCE_CDDB) { AlbumCdDdId = id; } else if (source == ExternalIdentifierAspect.SOURCE_UPCEAN) { AlbumUpcEanId = id; } else if (source == ExternalIdentifierAspect.SOURCE_AMAZON) { AlbumAmazonId = id; } else if (source == ExternalIdentifierAspect.SOURCE_ITUNES) { AlbumItunesId = id; } else if (source == ExternalIdentifierAspect.SOURCE_NAME) { AlbumNameId = id; } else { CustomAlbumIds.Add(source, id); } } } } //Brownard 17.06.2016 //The returned type of the collection differs on the server and client. //On the server it's an object collection but on the client it's a string collection due to [de]serialization. //Use the non generic Ienumerable to allow for both types. IEnumerable collection; Artists.Clear(); if (MediaItemAspect.TryGetAttribute(aspectData, AudioAspect.ATTR_ARTISTS, out collection)) { Artists.AddRange(collection.Cast <string>().Select(s => new PersonInfo { Name = s, Occupation = PersonAspect.OCCUPATION_ARTIST, MediaName = TrackName, ParentMediaName = Album })); } foreach (PersonInfo artist in Artists) { artist.AssignNameId(); } AlbumArtists.Clear(); if (MediaItemAspect.TryGetAttribute(aspectData, AudioAspect.ATTR_ALBUMARTISTS, out collection)) { AlbumArtists.AddRange(collection.Cast <string>().Select(s => new PersonInfo { Name = s, Occupation = PersonAspect.OCCUPATION_ARTIST, MediaName = TrackName, ParentMediaName = Album })); } foreach (PersonInfo artist in AlbumArtists) { artist.AssignNameId(); } Composers.Clear(); if (MediaItemAspect.TryGetAttribute(aspectData, AudioAspect.ATTR_COMPOSERS, out collection)) { Composers.AddRange(collection.Cast <string>().Select(s => new PersonInfo { Name = s, Occupation = PersonAspect.OCCUPATION_COMPOSER, MediaName = TrackName, ParentMediaName = Album })); } foreach (PersonInfo composer in Composers) { composer.AssignNameId(); } Conductors.Clear(); if (MediaItemAspect.TryGetAttribute(aspectData, AudioAspect.ATTR_CONDUCTERS, out collection)) { Conductors.AddRange(collection.Cast <string>().Select(s => new PersonInfo { Name = s, Occupation = PersonAspect.OCCUPATION_CONDUCTOR, MediaName = TrackName, ParentMediaName = Album })); } foreach (PersonInfo conductor in Conductors) { conductor.AssignNameId(); } Genres.Clear(); IList <MultipleMediaItemAspect> genreAspects; if (MediaItemAspect.TryGetAspects(aspectData, GenreAspect.Metadata, out genreAspects)) { foreach (MultipleMediaItemAspect genre in genreAspects) { Genres.Add(new GenreInfo { Id = genre.GetAttributeValue <int?>(GenreAspect.ATTR_ID), Name = genre.GetAttributeValue <string>(GenreAspect.ATTR_GENRE) }); } } byte[] data; if (MediaItemAspect.TryGetAttribute(aspectData, ThumbnailLargeAspect.ATTR_THUMBNAIL, out data)) { HasThumbnail = true; } return(true); }
/// <summary> /// Copies the contained track 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); } AssignNameId(); SetMetadataChanged(aspectData); MediaItemAspect.SetAttribute(aspectData, MediaAspect.ATTR_TITLE, ToString()); if (!string.IsNullOrEmpty(TrackNameSort)) { MediaItemAspect.SetAttribute(aspectData, MediaAspect.ATTR_SORT_TITLE, TrackNameSort); } MediaItemAspect.SetAttribute(aspectData, MediaAspect.ATTR_ISVIRTUAL, IsVirtualResource(aspectData)); MediaItemAspect.SetAttribute(aspectData, AudioAspect.ATTR_TRACKNAME, TrackName); MediaItemAspect.SetAttribute(aspectData, AudioAspect.ATTR_COMPILATION, Compilation); if (!string.IsNullOrEmpty(TrackLyrics)) { MediaItemAspect.SetAttribute(aspectData, AudioAspect.ATTR_LYRICS, TrackLyrics); } if (ReleaseDate.HasValue) { MediaItemAspect.SetAttribute(aspectData, MediaAspect.ATTR_RECORDINGTIME, ReleaseDate.Value); } if (TrackNum > 0) { MediaItemAspect.SetAttribute(aspectData, AudioAspect.ATTR_TRACK, TrackNum); } if (TotalTracks > 0) { MediaItemAspect.SetAttribute(aspectData, AudioAspect.ATTR_NUMTRACKS, TotalTracks); } if (Duration > 0) { MediaItemAspect.SetAttribute(aspectData, AudioAspect.ATTR_DURATION, Duration); } bool?isCd; if (!MediaItemAspect.TryGetAttribute(aspectData, AudioAspect.ATTR_ISCD, out isCd) || !isCd.HasValue) { MediaItemAspect.SetAttribute(aspectData, AudioAspect.ATTR_ISCD, false); } if (!string.IsNullOrEmpty(MusicBrainzId)) { MediaItemAspect.AddOrUpdateExternalIdentifier(aspectData, ExternalIdentifierAspect.SOURCE_MUSICBRAINZ, ExternalIdentifierAspect.TYPE_TRACK, MusicBrainzId); } if (!string.IsNullOrEmpty(IsrcId)) { MediaItemAspect.AddOrUpdateExternalIdentifier(aspectData, ExternalIdentifierAspect.SOURCE_ISRC, ExternalIdentifierAspect.TYPE_TRACK, IsrcId); } if (!string.IsNullOrEmpty(MusicIpId)) { MediaItemAspect.AddOrUpdateExternalIdentifier(aspectData, ExternalIdentifierAspect.SOURCE_MUSIC_IP, ExternalIdentifierAspect.TYPE_TRACK, MusicIpId); } if (AudioDbId > 0) { MediaItemAspect.AddOrUpdateExternalIdentifier(aspectData, ExternalIdentifierAspect.SOURCE_AUDIODB, ExternalIdentifierAspect.TYPE_TRACK, AudioDbId.ToString()); } if (LyricId > 0) { MediaItemAspect.AddOrUpdateExternalIdentifier(aspectData, ExternalIdentifierAspect.SOURCE_LYRIC, ExternalIdentifierAspect.TYPE_TRACK, LyricId.ToString()); } if (MvDbId > 0) { MediaItemAspect.AddOrUpdateExternalIdentifier(aspectData, ExternalIdentifierAspect.SOURCE_MVDB, ExternalIdentifierAspect.TYPE_TRACK, MvDbId.ToString()); } if (!string.IsNullOrEmpty(NameId)) { MediaItemAspect.AddOrUpdateExternalIdentifier(aspectData, ExternalIdentifierAspect.SOURCE_NAME, ExternalIdentifierAspect.TYPE_TRACK, NameId); } foreach (var customId in CustomIds) { MediaItemAspect.AddOrUpdateExternalIdentifier(aspectData, customId.Key, ExternalIdentifierAspect.TYPE_TRACK, customId.Value); } if (!string.IsNullOrEmpty(Album)) { MediaItemAspect.SetAttribute(aspectData, AudioAspect.ATTR_ALBUM, Album); } if (DiscNum > 0) { MediaItemAspect.SetAttribute(aspectData, AudioAspect.ATTR_DISCID, DiscNum); } if (TotalDiscs > 0) { MediaItemAspect.SetAttribute(aspectData, AudioAspect.ATTR_NUMDISCS, TotalDiscs); } if (BitRate > 0) { MediaItemAspect.SetAttribute(aspectData, AudioAspect.ATTR_BITRATE, BitRate); } if (Channels > 0) { MediaItemAspect.SetAttribute(aspectData, AudioAspect.ATTR_CHANNELS, Channels); } if (SampleRate > 0) { MediaItemAspect.SetAttribute(aspectData, AudioAspect.ATTR_SAMPLERATE, SampleRate); } if (!string.IsNullOrEmpty(Encoding)) { MediaItemAspect.SetAttribute(aspectData, AudioAspect.ATTR_ENCODING, Encoding); } if (!string.IsNullOrEmpty(ContentGroup)) { MediaItemAspect.SetAttribute(aspectData, AudioAspect.ATTR_CONTENT_GROUP, ContentGroup); } if (!Rating.IsEmpty) { MediaItemAspect.SetAttribute(aspectData, AudioAspect.ATTR_TOTAL_RATING, Rating.RatingValue.Value); if (Rating.VoteCount.HasValue) { MediaItemAspect.SetAttribute(aspectData, AudioAspect.ATTR_RATING_COUNT, Rating.VoteCount.Value); } } if (!string.IsNullOrEmpty(AlbumUpcEanId)) { MediaItemAspect.AddOrUpdateExternalIdentifier(aspectData, ExternalIdentifierAspect.SOURCE_UPCEAN, ExternalIdentifierAspect.TYPE_ALBUM, AlbumUpcEanId); } if (!string.IsNullOrEmpty(AlbumCdDdId)) { MediaItemAspect.AddOrUpdateExternalIdentifier(aspectData, ExternalIdentifierAspect.SOURCE_CDDB, ExternalIdentifierAspect.TYPE_ALBUM, AlbumCdDdId); } if (!string.IsNullOrEmpty(AlbumMusicBrainzId)) { MediaItemAspect.AddOrUpdateExternalIdentifier(aspectData, ExternalIdentifierAspect.SOURCE_MUSICBRAINZ, ExternalIdentifierAspect.TYPE_ALBUM, AlbumMusicBrainzId); } if (!string.IsNullOrEmpty(AlbumMusicBrainzGroupId)) { MediaItemAspect.AddOrUpdateExternalIdentifier(aspectData, ExternalIdentifierAspect.SOURCE_MUSICBRAINZ_GROUP, ExternalIdentifierAspect.TYPE_ALBUM, AlbumMusicBrainzGroupId); } if (AlbumAudioDbId > 0) { MediaItemAspect.AddOrUpdateExternalIdentifier(aspectData, ExternalIdentifierAspect.SOURCE_AUDIODB, ExternalIdentifierAspect.TYPE_ALBUM, AlbumAudioDbId.ToString()); } if (!string.IsNullOrEmpty(AlbumAmazonId)) { MediaItemAspect.AddOrUpdateExternalIdentifier(aspectData, ExternalIdentifierAspect.SOURCE_AMAZON, ExternalIdentifierAspect.TYPE_ALBUM, AlbumAmazonId); } if (!string.IsNullOrEmpty(AlbumItunesId)) { MediaItemAspect.AddOrUpdateExternalIdentifier(aspectData, ExternalIdentifierAspect.SOURCE_ITUNES, ExternalIdentifierAspect.TYPE_ALBUM, AlbumItunesId); } if (!string.IsNullOrEmpty(AlbumNameId)) { MediaItemAspect.AddOrUpdateExternalIdentifier(aspectData, ExternalIdentifierAspect.SOURCE_NAME, ExternalIdentifierAspect.TYPE_ALBUM, AlbumNameId); } foreach (var customId in CustomAlbumIds) { MediaItemAspect.AddOrUpdateExternalIdentifier(aspectData, customId.Key, ExternalIdentifierAspect.TYPE_ALBUM, customId.Value); } if (Artists.Count > 0) { MediaItemAspect.SetCollectionAttribute(aspectData, AudioAspect.ATTR_ARTISTS, Artists.Where(p => !string.IsNullOrEmpty(p.Name)).Select(p => p.Name).Distinct().ToList()); } if (AlbumArtists.Count > 0) { MediaItemAspect.SetCollectionAttribute(aspectData, AudioAspect.ATTR_ALBUMARTISTS, AlbumArtists.Where(p => !string.IsNullOrEmpty(p.Name)).Select(p => p.Name).Distinct().ToList()); } if (Composers.Count > 0) { MediaItemAspect.SetCollectionAttribute(aspectData, AudioAspect.ATTR_COMPOSERS, Composers.Where(p => !string.IsNullOrEmpty(p.Name)).Select(p => p.Name).Distinct().ToList()); } if (Conductors.Count > 0) { MediaItemAspect.SetCollectionAttribute(aspectData, AudioAspect.ATTR_CONDUCTERS, Conductors.Where(p => !string.IsNullOrEmpty(p.Name)).Select(p => p.Name).Distinct().ToList()); } aspectData.Remove(GenreAspect.ASPECT_ID); foreach (GenreInfo genre in Genres.Distinct()) { MultipleMediaItemAspect genreAspect = MediaItemAspect.CreateAspect(aspectData, GenreAspect.Metadata); genreAspect.SetAttribute(GenreAspect.ATTR_ID, genre.Id); genreAspect.SetAttribute(GenreAspect.ATTR_GENRE, genre.Name); } SetThumbnailMetadata(aspectData); return(true); }
public void TestMediaItemsLoader_SingleAndMultipleMIAs_BooleanLikeFilter() { MockDBUtils.Reset(); SingleTestMIA mia1 = TestBackendUtils.CreateSingleMIA("SINGLE1", Cardinality.Inline, true, true); MultipleTestMIA mia2 = TestBackendUtils.CreateMultipleMIA("MULTIPLE2", Cardinality.Inline, true, false); MultipleTestMIA mia3 = TestBackendUtils.CreateMultipleMIA("MULTIPLE3", Cardinality.Inline, false, true); Guid itemId0 = new Guid("aaaaaaaa-1111-1111-1111-aaaaaaaaaaaa"); Guid itemId1 = new Guid("bbbbbbbb-2222-2222-2222-bbbbbbbbbbbb"); IFilter filter = new BooleanCombinationFilter(BooleanOperator.And, new List <IFilter> { new LikeFilter(mia1.ATTR_STRING, "%", null), new LikeFilter(mia2.ATTR_STRING, "%", null) }); MockReader reader = MockDBUtils.AddReader(1, "SELECT T0.MEDIA_ITEM_ID A2, T0.MEDIA_ITEM_ID A3, T1.MEDIA_ITEM_ID A4, T0.ATTR_STRING A0, T0.ATTR_INTEGER A1 " + "FROM M_SINGLE1 T0 INNER JOIN M_MULTIPLE2 T1 ON T1.MEDIA_ITEM_ID = T0.MEDIA_ITEM_ID " + " WHERE T0.MEDIA_ITEM_ID IN(SELECT MEDIA_ITEM_ID FROM M_MULTIPLE2 WHERE ATTR_STRING LIKE @V0) AND T0.ATTR_STRING LIKE @V1", "A2", "A3", "A4", "A0", "A1"); reader.AddResult(itemId0, itemId0, itemId0, "zero", 0, "0_0"); reader.AddResult(itemId1, itemId1, itemId1, "one", 1, "1_1"); MockReader multipleReader2 = MockDBUtils.AddReader(2, "SELECT T0.MEDIA_ITEM_ID A2, T0.MEDIA_ITEM_ID A3, T0.ATTR_ID A0, T0.ATTR_STRING A1 FROM M_MULTIPLE2 T0 WHERE T0.MEDIA_ITEM_ID IN (@V0, @V1)", "A2", "A3", "A0", "A1"); multipleReader2.AddResult(itemId0, itemId0, "0_0", "zerozero"); multipleReader2.AddResult(itemId0, itemId0, "0_1", "zeroone"); multipleReader2.AddResult(itemId1, itemId1, "1_0", "onezero"); MockReader multipleReader3 = MockDBUtils.AddReader(3, "SELECT T0.MEDIA_ITEM_ID A2, T0.MEDIA_ITEM_ID A3, T0.ATTR_ID A0, T0.ATTR_INTEGER A1 FROM M_MULTIPLE3 T0 WHERE T0.MEDIA_ITEM_ID IN (@V0, @V1)", "A2", "A3", "A0", "A1"); multipleReader3.AddResult(itemId0, itemId0, "1_0", 10); multipleReader3.AddResult(itemId0, itemId0, "1_1", 11); multipleReader3.AddResult(itemId0, itemId0, "1_2", 12); multipleReader3.AddResult(itemId0, itemId0, "1_3", 13); multipleReader3.AddResult(itemId0, itemId0, "1_4", 14); multipleReader3.AddResult(itemId1, itemId1, "1_0", 20); Guid[] requiredAspects = { mia1.ASPECT_ID, mia2.ASPECT_ID }; Guid[] optionalAspects = { mia3.ASPECT_ID }; MediaItemQuery query = new MediaItemQuery(requiredAspects, optionalAspects, filter); CompiledMediaItemQuery compiledQuery = CompiledMediaItemQuery.Compile(MockCore.Management, query); IList <MediaItem> results = compiledQuery.QueryList(); /* * foreach (MediaItem result in results) * //Console.WriteLine("Query result " + result.MediaItemId + ": " + string.Join(",", result.Aspects.Values) + ": " + result); */ SingleMediaItemAspect value; IList <MultipleMediaItemAspect> values; Assert.AreEqual(2, results.Count, "Results count"); Assert.AreEqual(itemId0, results[0].MediaItemId, "MediaItem ID #0"); Assert.IsTrue(MediaItemAspect.TryGetAspect(results[0].Aspects, mia1.Metadata, out value), "MIA1 #0"); Assert.AreEqual("zero", value.GetAttributeValue(mia1.ATTR_STRING), "MIA1 string attibute #0"); Assert.AreEqual(0, value.GetAttributeValue(mia1.ATTR_INTEGER), "MIA1 integer attibute #0"); Assert.IsTrue(MediaItemAspect.TryGetAspects(results[0].Aspects, mia2.Metadata, out values), "MIA2 #0"); Assert.AreEqual(2, values.Count, "MIA2 count #0"); Assert.AreEqual("zerozero", values[0].GetAttributeValue(mia2.ATTR_STRING), "MIA2 string attibute 0 #0"); Assert.AreEqual("zeroone", values[1].GetAttributeValue(mia2.ATTR_STRING), "MIA2 string attibute 1 #0"); Assert.IsTrue(MediaItemAspect.TryGetAspects(results[0].Aspects, mia3.Metadata, out values), "MIA3 #0"); Assert.AreEqual(5, values.Count, "MIA3 count #0"); Assert.AreEqual(10, values[0].GetAttributeValue(mia3.ATTR_INTEGER), "MIA3 integer attibute 0 #0"); Assert.AreEqual(11, values[1].GetAttributeValue(mia3.ATTR_INTEGER), "MIA3 integer attibute 1 #0"); Assert.AreEqual(12, values[2].GetAttributeValue(mia3.ATTR_INTEGER), "MIA3 integer attibute 2 #0"); Assert.AreEqual(13, values[3].GetAttributeValue(mia3.ATTR_INTEGER), "MIA3 integer attibute 3 #0"); Assert.AreEqual(14, values[4].GetAttributeValue(mia3.ATTR_INTEGER), "MIA3 integer attibute 4 #0"); Assert.AreEqual(itemId1, results[1].MediaItemId, "MediaItem ID #1"); Assert.IsTrue(MediaItemAspect.TryGetAspect(results[1].Aspects, mia1.Metadata, out value), "MIA1 #0"); Assert.AreEqual("one", value.GetAttributeValue(mia1.ATTR_STRING), "MIA1 string attibute #1"); Assert.AreEqual(1, value.GetAttributeValue(mia1.ATTR_INTEGER), "MIA1 integer attibute #1"); Assert.IsTrue(MediaItemAspect.TryGetAspects(results[1].Aspects, mia2.Metadata, out values), "MIA2 #1"); Assert.AreEqual(1, values.Count, "MIA2 count #1"); Assert.AreEqual("onezero", values[0].GetAttributeValue(mia2.ATTR_STRING), "MIA2 string attibute 0 #1"); Assert.IsTrue(MediaItemAspect.TryGetAspects(results[1].Aspects, mia3.Metadata, out values), "MIA3 #0"); Assert.AreEqual(1, values.Count, "MIA3 count #1"); Assert.AreEqual(20, values[0].GetAttributeValue(mia3.ATTR_INTEGER), "MIA3 integer attibute 0 #1"); }
/// <summary> /// Imports or refreshes the directory with the specified <paramref name="directoryAccessor"/>. Sub directories will not /// be processed in this method. /// </summary> /// <param name="importJob">The import job being processed.</param> /// <param name="parentDirectoryId">Media item id of the parent directory, if present, else <see cref="Guid.Empty"/>.</param> /// <param name="directoryAccessor">Resource accessor for the directory to import.</param> /// <param name="metadataExtractors">Metadata extractors to apply on the resources.</param> /// <param name="mediaBrowsing">Callback interface to the media library for the refresh import type.</param> /// <param name="resultHandler">Callback to notify the import result.</param> /// <param name="mediaAccessor">Convenience reference to the media accessor.</param> /// <returns>Id of the directory's media item or <c>null</c>, if the given <paramref name="directoryAccessor"/> /// was imported as a media item or if an error occured. If <c>null</c> is returned, the directory import should be /// considered to be finished.</returns> protected Guid?ImportDirectory(ImportJob importJob, Guid parentDirectoryId, IFileSystemResourceAccessor directoryAccessor, ICollection <IMetadataExtractor> metadataExtractors, IMediaBrowsing mediaBrowsing, IImportResultHandler resultHandler, IMediaAccessor mediaAccessor) { ResourcePath currentDirectoryPath = directoryAccessor.CanonicalLocalResourcePath; try { ImporterWorkerMessaging.SendImportMessage(ImporterWorkerMessaging.MessageType.ImportStatus, currentDirectoryPath); if (ImportResource(importJob, directoryAccessor, parentDirectoryId, metadataExtractors, resultHandler, mediaAccessor)) { // The directory could be imported as a media item. // If the directory itself was identified as a normal media item, don't import its children. // Necessary for DVD directories, for example. return(null); } Guid directoryId = GetOrAddDirectory(importJob, directoryAccessor, parentDirectoryId, mediaBrowsing, resultHandler); IDictionary <string, MediaItem> path2Item = new Dictionary <string, MediaItem>(); if (importJob.JobType == ImportJobType.Refresh) { foreach (MediaItem mediaItem in mediaBrowsing.BrowseAsync(directoryId, IMPORTER_PROVIDER_MIA_ID_ENUMERATION, EMPTY_MIA_ID_ENUMERATION, null, false).Result) { IList <MultipleMediaItemAspect> providerResourceAspects; if (MediaItemAspect.TryGetAspects(mediaItem.Aspects, ProviderResourceAspect.Metadata, out providerResourceAspects)) { path2Item[providerResourceAspects[0].GetAttributeValue <string>(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH)] = mediaItem; } } } CheckImportStillRunning(importJob.State); ICollection <IFileSystemResourceAccessor> files = FileSystemResourceNavigator.GetFiles(directoryAccessor, false); if (files != null) { foreach (IFileSystemResourceAccessor fileAccessor in files) { using (fileAccessor) { // Add & update files ResourcePath currentFilePath = fileAccessor.CanonicalLocalResourcePath; string serializedFilePath = currentFilePath.Serialize(); try { SingleMediaItemAspect importerAspect; MediaItem mediaItem; if (importJob.JobType == ImportJobType.Refresh && path2Item.TryGetValue(serializedFilePath, out mediaItem) && MediaItemAspect.TryGetAspect(mediaItem.Aspects, ImporterAspect.Metadata, out importerAspect) && importerAspect.GetAttributeValue <DateTime>(ImporterAspect.ATTR_LAST_IMPORT_DATE) > fileAccessor.LastChanged) { // We can skip this file; it was imported after the last change time of the item path2Item.Remove(serializedFilePath); continue; } if (ImportResource(importJob, fileAccessor, directoryId, metadataExtractors, resultHandler, mediaAccessor)) { path2Item.Remove(serializedFilePath); } } catch (Exception e) { CheckSuspended(e); // Throw ImportAbortException if suspended - will skip warning and tagging job as erroneous ServiceRegistration.Get <ILogger>().Warn("ImporterWorker: Problem while importing resource '{0}'", e, serializedFilePath); importJob.State = ImportJobState.Erroneous; } CheckImportStillRunning(importJob.State); } } } if (importJob.JobType == ImportJobType.Refresh) { // Remove remaining (= non-present) files foreach (string pathStr in path2Item.Keys) { ResourcePath path = ResourcePath.Deserialize(pathStr); try { IResourceAccessor ra; if (!path.TryCreateLocalResourceAccessor(out ra)) { throw new IllegalCallException("Unable to access resource path '{0}'", importJob.BasePath); } using (ra) { IFileSystemResourceAccessor fsra = ra as IFileSystemResourceAccessor; if (fsra == null || !fsra.IsFile) { // Don't touch directories because they will be imported in a different call of ImportDirectory continue; } } } catch (IllegalCallException) { // This happens if the resource doesn't exist any more - we also catch missing directories here } // Delete all remaining items resultHandler.DeleteMediaItemAsync(path); CheckImportStillRunning(importJob.State); } } return(directoryId); } catch (ImportSuspendedException) { throw; } catch (ImportAbortException) { throw; } catch (UnauthorizedAccessException e) { // If the access to the file or folder was denied, simply continue with the others ServiceRegistration.Get <ILogger>().Warn("ImporterWorker: Problem accessing resource '{0}', continueing with one", e, currentDirectoryPath); } catch (Exception e) { CheckSuspended(e); // Throw ImportAbortException if suspended - will skip warning and tagging job as erroneous ServiceRegistration.Get <ILogger>().Warn("ImporterWorker: Problem while importing directory '{0}'", e, currentDirectoryPath); importJob.State = ImportJobState.Erroneous; } return(null); }
protected bool GetPattern(FanArtConstants.FanArtMediaType mediaType, FanArtConstants.FanArtType fanArtType, Guid mediaItemId, string name, out string[] patterns) { patterns = null; string basePath = null; if (mediaItemId != Guid.Empty) { 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); if (items == null || items.Count == 0) { return(false); } MediaItem mediaItem = items.First(); int movieDbId; if (MediaItemAspect.TryGetAttribute(mediaItem.Aspects, MovieAspect.ATTR_TMDB_ID, out movieDbId)) { switch (mediaType) { case FanArtConstants.FanArtMediaType.Undefined: case FanArtConstants.FanArtMediaType.Movie: basePath = Path.Combine(MovieTheMovieDbMatcher.CACHE_PATH, movieDbId.ToString()); break; } } } else { switch (mediaType) { case FanArtConstants.FanArtMediaType.Undefined: case FanArtConstants.FanArtMediaType.Movie: int movieDbId; basePath = !MovieTheMovieDbMatcher.Instance.TryGetMovieDbId(name, out movieDbId) ? null : Path.Combine(MovieTheMovieDbMatcher.CACHE_PATH, movieDbId.ToString()); break; case FanArtConstants.FanArtMediaType.MovieCollection: int collectionId; basePath = !MovieTheMovieDbMatcher.Instance.TryGetCollectionId(name, out collectionId) ? null : Path.Combine(MovieTheMovieDbMatcher.CACHE_PATH, "COLL_" + collectionId); break; } } if (string.IsNullOrWhiteSpace(basePath)) { return(false); } switch (fanArtType) { case FanArtConstants.FanArtType.Thumbnail: case FanArtConstants.FanArtType.Poster: patterns = new[] { Path.Combine(basePath, "Posters\\*.jpg") }; return(true); case FanArtConstants.FanArtType.FanArt: patterns = new[] { Path.Combine(basePath, "Backdrops\\*.jpg") }; return(true); } return(false); }
public void AddOrUpdateMIA(ITransaction transaction, Guid mediaItemId, MediaItemAspect mia, bool add) { MediaItemAspectMetadata miaType; if (!_managedMIATypes.TryGetValue(mia.Metadata.AspectId, out miaType) || miaType == null) throw new ArgumentException(string.Format("MIA_Management: Requested media item aspect type with id '{0}' doesn't exist", mia.Metadata.AspectId)); IList<string> terms1 = new List<string>(); IList<string> terms2 = new List<string>(); IList<BindVar> bindVars = new List<BindVar>(); int ct = 0; string miaTableName = GetMIATableName(miaType); // Attributes: First run foreach (MediaItemAspectMetadata.AttributeSpecification spec in miaType.AttributeSpecifications.Values) { if (mia.IsIgnore(spec)) continue; string attrColName; object attributeValue; string bindVarName = "V" + ct++; switch (spec.Cardinality) { case Cardinality.Inline: attrColName = GetMIAAttributeColumnName(spec); if (add) { terms1.Add(attrColName); terms2.Add("@" + bindVarName); } else terms1.Add(attrColName + " = @" + bindVarName); attributeValue = mia.GetAttributeValue(spec); attributeValue = TruncateBigValue(attributeValue, spec); bindVars.Add(new BindVar(bindVarName, AttributeIsEmpty(attributeValue) ? null : attributeValue, spec.AttributeType)); break; case Cardinality.OneToMany: // After main query break; case Cardinality.ManyToOne: attrColName = GetMIAAttributeColumnName(spec); attributeValue = mia.GetAttributeValue(spec); Guid? insertValue; if (AttributeIsEmpty(attributeValue)) insertValue = null; else { Guid valuePk; GetOrCreateManyToOneMIAAttributeValue(transaction, spec, mia.GetAttributeValue(spec), add, out valuePk); insertValue = valuePk; } if (add) { terms1.Add(attrColName); terms2.Add("@" + bindVarName); } else terms1.Add(attrColName + " = @" + bindVarName); bindVars.Add(new BindVar(bindVarName, insertValue.HasValue ? (Guid?) insertValue.Value : null, typeof(Guid))); break; case Cardinality.ManyToMany: // After main query break; default: throw new NotImplementedException(string.Format("Cardinality '{0}' for attribute '{1}.{2}' is not implemented", spec.Cardinality, miaType.AspectId, spec.AttributeName)); } } // terms = all inline attributes // sqlValues = all inline attribute values if (add || terms1.Count > 0) { // Main query StringBuilder mainQueryBuilder = new StringBuilder(); if (add) { mainQueryBuilder.Append("INSERT INTO "); mainQueryBuilder.Append(miaTableName); mainQueryBuilder.Append(" ("); } else { mainQueryBuilder.Append("UPDATE "); mainQueryBuilder.Append(miaTableName); mainQueryBuilder.Append(" SET "); } mainQueryBuilder.Append(StringUtils.Join(", ", terms1)); bindVars.Add(new BindVar("MEDIA_ITEM_ID", mediaItemId, typeof(Guid))); // values = all inline attribute values plus media item ID if (add) { if (terms1.Count > 0) mainQueryBuilder.Append(", "); mainQueryBuilder.Append(MIA_MEDIA_ITEM_ID_COL_NAME); // Append the ID column as a normal attribute mainQueryBuilder.Append(") VALUES ("); terms2.Add("@MEDIA_ITEM_ID"); mainQueryBuilder.Append(StringUtils.Join(", ", terms2)); mainQueryBuilder.Append(")"); } else { mainQueryBuilder.Append(" WHERE "); mainQueryBuilder.Append(MIA_MEDIA_ITEM_ID_COL_NAME); // Use the ID column in WHERE condition mainQueryBuilder.Append(" = @MEDIA_ITEM_ID"); } ISQLDatabase database = transaction.Database; using (IDbCommand command = transaction.CreateCommand()) { command.CommandText = mainQueryBuilder.ToString(); foreach (BindVar bindVar in bindVars) database.AddParameter(command, bindVar.Name, bindVar.Value, bindVar.VariableType); command.ExecuteNonQuery(); } } // Attributes: Second run foreach (MediaItemAspectMetadata.AttributeSpecification spec in miaType.AttributeSpecifications.Values) { if (mia.IsIgnore(spec)) continue; switch (spec.Cardinality) { case Cardinality.Inline: break; case Cardinality.OneToMany: InsertOrUpdateOneToManyMIAAttributeValues(transaction, spec, mediaItemId, mia.GetCollectionAttribute(spec), add); break; case Cardinality.ManyToOne: break; case Cardinality.ManyToMany: InsertOrUpdateManyToManyMIAAttributeValues(transaction, spec, mediaItemId, mia.GetCollectionAttribute(spec), add); break; default: throw new NotImplementedException(string.Format("Cardinality '{0}' for attribute '{1}.{2}' is not implemented", spec.Cardinality, miaType.AspectId, spec.AttributeName)); } } CleanupAllManyToOneOrphanedAttributeValues(transaction, miaType); }
public override bool TryExtractMetadata(IResourceAccessor mediaItemAccessor, IDictionary <Guid, MediaItemAspect> extractedAspectData, bool forceQuickMode) { // If the base AudioMDE already extracted metadata, don't try here again to avoid conflicts. if (extractedAspectData.ContainsKey(AudioAspect.ASPECT_ID)) { return(false); } ILocalFsResourceAccessor fsra = mediaItemAccessor as ILocalFsResourceAccessor; if (fsra == null) { return(false); } if (!fsra.IsFile) { return(false); } string filePath = fsra.LocalFileSystemPath; string fileName = fsra.ResourceName; if (!HasAudioExtension(fileName)) { return(false); } try { var tags = BassTags.BASS_TAG_GetFromFile(filePath); if (tags == null) { return(false); } fileName = ProviderPathHelper.GetFileNameWithoutExtension(fileName) ?? string.Empty; string title; string artist; uint? trackNo; GuessMetadataFromFileName(fileName, out title, out artist, out trackNo); if (!string.IsNullOrWhiteSpace(tags.title)) { title = tags.title; } IEnumerable <string> artists; if (!string.IsNullOrWhiteSpace(tags.artist)) { artists = SplitTagEnum(tags.artist); artists = PatchID3v23Enumeration(artists); } else { artists = artist == null ? null : new string[] { artist } }; if (!string.IsNullOrWhiteSpace(tags.track) && tags.track != "0") { int iTrackNo; if (int.TryParse(tags.track, out iTrackNo)) { trackNo = (uint?)iTrackNo; } else { trackNo = null; } } MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, title); MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_SIZE, fsra.Size); MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_MIME_TYPE, "audio/" + Path.GetExtension(filePath).Substring(1)); MediaItemAspect.SetCollectionAttribute(extractedAspectData, AudioAspect.ATTR_ARTISTS, ApplyAdditionalSeparator(artists)); MediaItemAspect.SetAttribute(extractedAspectData, AudioAspect.ATTR_ALBUM, StringUtils.TrimToNull(tags.album)); IEnumerable <string> albumArtists = SplitTagEnum(tags.albumartist); albumArtists = PatchID3v23Enumeration(albumArtists); MediaItemAspect.SetCollectionAttribute(extractedAspectData, AudioAspect.ATTR_ALBUMARTISTS, ApplyAdditionalSeparator(albumArtists)); MediaItemAspect.SetAttribute(extractedAspectData, AudioAspect.ATTR_BITRATE, tags.bitrate); MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_COMMENT, StringUtils.TrimToNull(tags.comment)); IEnumerable <string> composers = SplitTagEnum(tags.composer); composers = PatchID3v23Enumeration(composers); MediaItemAspect.SetCollectionAttribute(extractedAspectData, AudioAspect.ATTR_COMPOSERS, ApplyAdditionalSeparator(composers)); MediaItemAspect.SetAttribute(extractedAspectData, AudioAspect.ATTR_DURATION, (long)tags.duration); IEnumerable <string> genres = SplitTagEnum(tags.genre); genres = PatchID3v23Enumeration(genres); MediaItemAspect.SetCollectionAttribute(extractedAspectData, AudioAspect.ATTR_GENRES, ApplyAdditionalSeparator(genres)); if (trackNo.HasValue) { MediaItemAspect.SetAttribute(extractedAspectData, AudioAspect.ATTR_TRACK, (int)trackNo.Value); } int year; if (int.TryParse(tags.year, out year)) { if (year >= 30 && year <= 99) { year += 1900; } if (year >= 1930 && year <= 2030) { MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_RECORDINGTIME, new DateTime(year, 1, 1)); } } // The following code gets cover art images from file (embedded) or from windows explorer cache (supports folder.jpg). if (tags.PictureCount > 0) { try { using (Image cover = tags.PictureGetImage(0)) using (Image resized = ImageUtilities.ResizeImage(cover, MAX_COVER_WIDTH, MAX_COVER_HEIGHT)) using (MemoryStream result = new MemoryStream()) { resized.Save(result, ImageFormat.Jpeg); MediaItemAspect.SetAttribute(extractedAspectData, ThumbnailLargeAspect.ATTR_THUMBNAIL, result.ToArray()); } } // Decoding of invalid image data can fail, but main MediaItem is correct. catch { } } else { // In quick mode only allow thumbs taken from cache. bool cachedOnly = forceQuickMode; // Thumbnail extraction fileName = mediaItemAccessor.ResourcePathName; IThumbnailGenerator generator = ServiceRegistration.Get <IThumbnailGenerator>(); byte[] thumbData; ImageType imageType; if (generator.GetThumbnail(fileName, 256, 256, cachedOnly, out thumbData, out imageType)) { MediaItemAspect.SetAttribute(extractedAspectData, ThumbnailLargeAspect.ATTR_THUMBNAIL, thumbData); } } return(true); } catch (Exception e) { // Only log at the info level here - And simply return false. This makes the importer know that we // couldn't perform our task here ServiceRegistration.Get <ILogger>().Info("BassAudioMetadataExtractor: Exception reading resource '{0}' (Text: '{1}')", fsra.CanonicalLocalResourcePath, e.Message); } return(false); }
public MediaItem QueryMediaItem() { ISQLDatabase database = ServiceRegistration.Get<ISQLDatabase>(); ITransaction transaction = database.BeginTransaction(); try { MediaItem result = null; // 1. Main query MainQueryBuilder mainQueryBuilder = new MainQueryBuilder(_miaManagement, _mainSelectAttributes.Values, null, _necessaryRequestedMIAs, _optionalRequestedMIAs, _filter, _sortInformation); using (IDbCommand mainQueryCommand = transaction.CreateCommand()) { string mediaItemIdAlias2; IDictionary<MediaItemAspectMetadata, string> miamAliases; // Maps (selected and filtered) QueryAttributes to CompiledQueryAttributes in the SQL query IDictionary<QueryAttribute, string> qa2a; string statementStr; IList<BindVar> bindVars; mainQueryBuilder.GenerateSqlStatement(out mediaItemIdAlias2, out miamAliases, out qa2a, out statementStr, out bindVars); mainQueryCommand.CommandText = statementStr; foreach (BindVar bindVar in bindVars) database.AddParameter(mainQueryCommand, bindVar.Name, bindVar.Value, bindVar.VariableType); IEnumerable<MediaItemAspectMetadata> selectedMIAs = _necessaryRequestedMIAs.Union(_optionalRequestedMIAs); using (IDataReader mainReader = mainQueryCommand.ExecuteReader()) { if (mainReader.Read()) { Guid mediaItemId = database.ReadDBValue<Guid>(mainReader, mainReader.GetOrdinal(mediaItemIdAlias2)); result = new MediaItem(mediaItemId); // Request complex attributes using media item ID IFilter modifiedFilter = BooleanCombinationFilter.CombineFilters(BooleanOperator.And, _filter, new MediaItemIdFilter(mediaItemId)); IDictionary<MediaItemAspectMetadata.AttributeSpecification, ICollection<object>> complexAttributeValues = new Dictionary<MediaItemAspectMetadata.AttributeSpecification, ICollection<object>>(); foreach (MediaItemAspectMetadata.AttributeSpecification attr in _explicitSelectAttributes) { ComplexAttributeQueryBuilder complexAttributeQueryBuilder = new ComplexAttributeQueryBuilder( _miaManagement, attr, null, null, modifiedFilter); using (IDbCommand complexQueryCommand = transaction.CreateCommand()) { string mediaItemIdAlias; string valueAlias; complexAttributeQueryBuilder.GenerateSqlStatement(out mediaItemIdAlias, out valueAlias, out statementStr, out bindVars); complexQueryCommand.CommandText = statementStr; foreach (BindVar bindVar in bindVars) database.AddParameter(complexQueryCommand, bindVar.Name, bindVar.Value, bindVar.VariableType); Type valueType = attr.AttributeType; using (IDataReader reader = complexQueryCommand.ExecuteReader()) { if (reader.Read()) { object value = database.ReadDBValue(valueType, reader, reader.GetOrdinal(valueAlias)); ICollection<object> attrValues; if (!complexAttributeValues.TryGetValue(attr, out attrValues)) attrValues = complexAttributeValues[attr] = new List<object>(); attrValues.Add(value); } } } } // Put together all attributes foreach (MediaItemAspectMetadata miam in selectedMIAs) { if (mainReader.IsDBNull(mainReader.GetOrdinal(miamAliases[miam]))) // MIAM is not available for current media item continue; MediaItemAspect mia = new MediaItemAspect(miam); foreach (MediaItemAspectMetadata.AttributeSpecification attr in miam.AttributeSpecifications.Values) if (attr.Cardinality == Cardinality.Inline) { QueryAttribute qa = _mainSelectAttributes[attr]; string alias = qa2a[qa]; mia.SetAttribute(attr, database.ReadDBValue(attr.AttributeType, mainReader, mainReader.GetOrdinal(alias))); } else { ICollection<object> attrValues; if (complexAttributeValues.TryGetValue(attr, out attrValues)) mia.SetCollectionAttribute(attr, attrValues); } result.Aspects[miam.AspectId] = mia; } } return result; } } } finally { transaction.Dispose(); } }
private bool ExtractThumbnail(ILocalFsResourceAccessor lfsra, IDictionary <Guid, MediaItemAspect> extractedAspectData) { // We can only work on files and make sure this file was detected by a lower MDE before (title is set then). // VideoAspect must be present to be sure it is actually a video resource. if (!lfsra.IsFile || !extractedAspectData.ContainsKey(VideoAspect.ASPECT_ID)) { return(false); } byte[] thumb; // We only want to create missing thumbnails here, so check for existing ones first if (MediaItemAspect.TryGetAttribute(extractedAspectData, ThumbnailLargeAspect.ATTR_THUMBNAIL, out thumb) && thumb != null) { return(true); } // Check for a reasonable time offset long defaultVideoOffset = 720; long videoDuration; if (MediaItemAspect.TryGetAttribute(extractedAspectData, VideoAspect.ATTR_DURATION, out videoDuration)) { if (defaultVideoOffset > videoDuration * 1 / 3) { defaultVideoOffset = videoDuration * 1 / 3; } } // ToDo: Move creation of temp file names to FileUtils class string tempFileName = Path.GetTempPath() + Guid.NewGuid() + ".jpg"; string executable = FileUtils.BuildAssemblyRelativePath("ffmpeg.exe"); string arguments = string.Format("-ss {0} -i \"{1}\" -vframes 1 -an -dn -vf \"yadif='mode=send_frame:parity=auto:deint=all',scale=iw*sar:ih,setsar=1/1,scale=iw/2:-1\" -y \"{2}\"", defaultVideoOffset, // Calling EnsureLocalFileSystemAccess not necessary; access for external process ensured by ExecuteWithResourceAccess lfsra.LocalFileSystemPath, tempFileName); try { bool success; lock (FFMPEG_THROTTLE_LOCK) success = lfsra.ExecuteWithResourceAccessAsync(executable, arguments, ProcessPriorityClass.Idle, PROCESS_TIMEOUT_MS).Result.Success; if (success && File.Exists(tempFileName)) { var binary = FileUtils.ReadFile(tempFileName); MediaItemAspect.SetAttribute(extractedAspectData, ThumbnailLargeAspect.ATTR_THUMBNAIL, binary); // Calling EnsureLocalFileSystemAccess not necessary; only string operation ServiceRegistration.Get <ILogger>().Info("VideoThumbnailer: Successfully created thumbnail for resource '{0}'", lfsra.LocalFileSystemPath); } else { // Calling EnsureLocalFileSystemAccess not necessary; only string operation ServiceRegistration.Get <ILogger>().Warn("VideoThumbnailer: Failed to create thumbnail for resource '{0}'", lfsra.LocalFileSystemPath); } } catch (AggregateException ae) { ae.Handle(e => { if (e is TaskCanceledException) { ServiceRegistration.Get <ILogger>().Warn("VideoThumbnailer.ExtractThumbnail: External process aborted due to timeout: Executable='{0}', Arguments='{1}', Timeout='{2}'", executable, arguments, PROCESS_TIMEOUT_MS); return(true); } return(false); }); } finally { if (File.Exists(tempFileName)) { File.Delete(tempFileName); } } return(true); }
private int GetMovieTmdb(MediaItem currMediaItem) { int iValue; return(MediaItemAspect.TryGetAttribute(currMediaItem.Aspects, MovieAspect.ATTR_TMDB_ID, out iValue) ? iValue : 0); }
private static bool IsWatched(MediaItem mediaItem) { int playCount; return(MediaItemAspect.TryGetAttribute(mediaItem.Aspects, MediaAspect.ATTR_PLAYCOUNT, 0, out playCount) && playCount > 0); }
private int GetSeriesTvdbId(MediaItem currMediaItem) { int value; return(MediaItemAspect.TryGetAttribute(currMediaItem.Aspects, SeriesAspect.ATTR_TVDB_ID, out value) ? value : 0); }
public override int Compare(MediaItem x, MediaItem y) { SingleMediaItemAspect audioAspectX; SingleMediaItemAspect audioAspectY; if (MediaItemAspect.TryGetAspect(x.Aspects, AudioAspect.Metadata, out audioAspectX) && MediaItemAspect.TryGetAspect(y.Aspects, AudioAspect.Metadata, out audioAspectY)) { string albumX = (string)audioAspectX.GetAttributeValue(AudioAspect.ATTR_ALBUM); string albumY = (string)audioAspectY.GetAttributeValue(AudioAspect.ATTR_ALBUM); int res = string.Compare(albumX, albumY); if (res != 0) { return(res); } } // Fallback if album comparison is equal: Compare by track return(base.Compare(x, y)); }
private string GetSeriesImdbId(MediaItem currMediaItem) { string value; return(MediaItemAspect.TryGetAttribute(currMediaItem.Aspects, SeriesAspect.ATTR_IMDB_ID, out value) ? value : null); }
public bool TryMerge(IDictionary <Guid, IList <MediaItemAspect> > extractedAspects, IDictionary <Guid, IList <MediaItemAspect> > existingAspects) { try { EpisodeInfo existing = new EpisodeInfo(); EpisodeInfo extracted = new EpisodeInfo(); //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()) { 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("EpisodeMergeHandler: Exception merging resources (Text: '{0}')", e.Message); return(false); } }
public override int Compare(MediaItem item1, MediaItem item2) { SingleMediaItemAspect audioAspectX; SingleMediaItemAspect audioAspectY; if (MediaItemAspect.TryGetAspect(item1.Aspects, AudioAspect.Metadata, out audioAspectX) && MediaItemAspect.TryGetAspect(item2.Aspects, AudioAspect.Metadata, out audioAspectY)) { bool compilationX = (bool)(audioAspectX.GetAttributeValue(AudioAspect.ATTR_COMPILATION) ?? false); bool compilationY = (bool)(audioAspectY.GetAttributeValue(AudioAspect.ATTR_COMPILATION) ?? false); return(compilationX.CompareTo(compilationY)); } return(base.Compare(item1, item2)); }
internal static WebTVShowBasic TVShowBasic(IOwinContext context, MediaItem item) { ISet <Guid> necessaryMIATypespisodes = new HashSet <Guid>(); necessaryMIATypespisodes.Add(MediaAspect.ASPECT_ID); necessaryMIATypespisodes.Add(EpisodeAspect.ASPECT_ID); IFilter unwatchedEpisodeFilter = BooleanCombinationFilter.CombineFilters(BooleanOperator.And, new RelationshipFilter(EpisodeAspect.ROLE_EPISODE, SeriesAspect.ROLE_SERIES, item.MediaItemId), new RelationalUserDataFilter(Guid.Empty, UserDataKeysKnown.KEY_PLAY_PERCENTAGE, RelationalOperator.LT, UserDataKeysKnown.GetSortablePlayPercentageString(100), true)); int unwatchedCount = MediaLibraryAccess.CountMediaItems(context, necessaryMIATypespisodes, unwatchedEpisodeFilter); var mediaAspect = item.GetAspect(MediaAspect.Metadata); var seriesAspect = item.GetAspect(SeriesAspect.Metadata); var importerAspect = item.GetAspect(ImporterAspect.Metadata); DateTime? firstAired = mediaAspect.GetAttributeValue <DateTime?>(MediaAspect.ATTR_RECORDINGTIME); IList <WebActor> actors = seriesAspect.GetCollectionAttribute <string>(SeriesAspect.ATTR_ACTORS)?.Distinct().Select(a => new WebActor(a)).ToList() ?? new List <WebActor>(); WebArtwork aw = new WebArtwork(); var show = new WebTVShowBasic() { Id = item.MediaItemId.ToString(), Title = seriesAspect.GetAttributeValue <string>(SeriesAspect.ATTR_SERIES_NAME), DateAdded = importerAspect.GetAttributeValue <DateTime>(ImporterAspect.ATTR_DATEADDED), EpisodeCount = seriesAspect.GetAttributeValue <int>(SeriesAspect.ATTR_AVAILABLE_EPISODES), SeasonCount = seriesAspect.GetAttributeValue <int>(SeriesAspect.ATTR_AVAILABLE_SEASONS), Rating = Convert.ToSingle(seriesAspect.GetAttributeValue <double>(SeriesAspect.ATTR_TOTAL_RATING)), ContentRating = seriesAspect.GetAttributeValue <string>(SeriesAspect.ATTR_CERTIFICATION), Actors = actors, UnwatchedEpisodeCount = unwatchedCount, Year = firstAired.HasValue ? firstAired.Value.Year : 0, }; IList <MediaItemAspect> genres; if (item.Aspects.TryGetValue(GenreAspect.ASPECT_ID, out genres)) { show.Genres = genres.Select(g => g.GetAttributeValue <string>(GenreAspect.ATTR_GENRE)).ToList(); } string tvDbId; MediaItemAspect.TryGetExternalAttribute(item.Aspects, ExternalIdentifierAspect.SOURCE_TVDB, ExternalIdentifierAspect.TYPE_SERIES, out tvDbId); if (tvDbId != null) { show.ExternalId.Add(new WebExternalId { Site = "TVDB", Id = tvDbId }); } string imdbId; MediaItemAspect.TryGetExternalAttribute(item.Aspects, ExternalIdentifierAspect.SOURCE_IMDB, ExternalIdentifierAspect.TYPE_SERIES, out imdbId); if (imdbId != null) { show.ExternalId.Add(new WebExternalId { Site = "IMDB", Id = imdbId }); } return(show); }
public bool TryExtractMetadata(IResourceAccessor mediaItemAccessor, IDictionary <Guid, MediaItemAspect> extractedAspectData, bool forceQuickMode) { try { IFileSystemResourceAccessor fsra = mediaItemAccessor as IFileSystemResourceAccessor; if (fsra == null || !fsra.IsFile) { return(false); } string title; if (!MediaItemAspect.TryGetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, out title) || string.IsNullOrEmpty(title)) { return(false); } string filePath = mediaItemAccessor.CanonicalLocalResourcePath.ToString(); string lowerExtension = StringUtils.TrimToEmpty(ProviderPathHelper.GetExtension(filePath)).ToLowerInvariant(); if (lowerExtension != ".ts") { return(false); } string metaFilePath = ProviderPathHelper.ChangeExtension(filePath, ".xml"); IResourceAccessor metaFileAccessor; if (!ResourcePath.Deserialize(metaFilePath).TryCreateLocalResourceAccessor(out metaFileAccessor)) { return(false); } Tags tags; using (metaFileAccessor) { using (Stream metaStream = ((IFileSystemResourceAccessor)metaFileAccessor).OpenRead()) tags = (Tags)GetTagsXmlSerializer().Deserialize(metaStream); } // Handle series information SeriesInfo seriesInfo = GetSeriesFromTags(tags); if (seriesInfo.IsCompleteMatch) { if (!forceQuickMode) { SeriesTvDbMatcher.Instance.FindAndUpdateSeries(seriesInfo); } seriesInfo.SetMetadata(extractedAspectData); } string value; if (TryGet(tags, TAG_TITLE, out value) && !string.IsNullOrEmpty(value)) { MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, value); } if (TryGet(tags, TAG_GENRE, out value)) { MediaItemAspect.SetCollectionAttribute(extractedAspectData, VideoAspect.ATTR_GENRES, new List <String> { value }); } 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_CHANNEL, out value)) { MediaItemAspect.SetAttribute(extractedAspectData, RecordingAspect.ATTR_CHANNEL, value); } // Recording date formatted: 2011-11-04 20:55 DateTime recordingStart; DateTime recordingEnd; if (TryGet(tags, TAG_STARTTIME, out value) && DateTime.TryParse(value, out recordingStart)) { MediaItemAspect.SetAttribute(extractedAspectData, RecordingAspect.ATTR_STARTTIME, recordingStart); } if (TryGet(tags, TAG_ENDTIME, out value) && DateTime.TryParse(value, out recordingEnd)) { MediaItemAspect.SetAttribute(extractedAspectData, RecordingAspect.ATTR_ENDTIME, recordingEnd); } 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("Tve3RecordingMetadataExtractor: Exception reading resource '{0}' (Text: '{1}')", mediaItemAccessor.CanonicalLocalResourcePath, e.Message); } return(false); }
/// <summary> /// Gets a list of <see cref="FanArtImage"/>s for a requested <paramref name="mediaType"/>, <paramref name="fanArtType"/> and <paramref name="name"/>. /// The name can be: Series name, Actor name, Artist name depending on the <paramref name="mediaType"/>. /// </summary> /// <param name="mediaType">Requested FanArtMediaType</param> /// <param name="fanArtType">Requested FanArtType</param> /// <param name="name">Requested name of Series, Actor, Artist...</param> /// <param name="maxWidth">Maximum width for image. <c>0</c> returns image in original size.</param> /// <param name="maxHeight">Maximum height for image. <c>0</c> returns image in original size.</param> /// <param name="singleRandom">If <c>true</c> only one random image URI will be returned</param> /// <param name="result">Result if return code is <c>true</c>.</param> /// <returns><c>true</c> if at least one match was found.</returns> public bool TryGetFanArt(string mediaType, string fanArtType, string name, int maxWidth, int maxHeight, bool singleRandom, out IList <IResourceLocator> result) { result = null; if (!VALID_MEDIA_TYPES.Contains(mediaType) || !VALID_FANART_TYPES.Contains(fanArtType)) { return(false); } if (string.IsNullOrWhiteSpace(name)) { return(false); } Guid mediaItemId; if (Guid.TryParse(name, out mediaItemId) == false) { return(false); } IFanArtCache fanArtCache = ServiceRegistration.Get <IFanArtCache>(); List <string> fanArtFiles = new List <string>(); fanArtFiles.AddRange(fanArtCache.GetFanArtFiles(mediaItemId, fanArtType)); // Try fallback if (fanArtFiles.Count == 0 && (mediaType == FanArtMediaTypes.MovieCollection || mediaType == FanArtMediaTypes.Character)) { 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, OPTIONAL_MIAS, filter), false, null, true); if (items == null || items.Count == 0) { return(false); } MediaItem mediaItem = items.First(); if (mediaType == FanArtMediaTypes.MovieCollection) { if (mediaItem.Aspects.ContainsKey(MovieCollectionAspect.ASPECT_ID)) { IList <MultipleMediaItemAspect> relationAspects; if (MediaItemAspect.TryGetAspects(mediaItem.Aspects, RelationshipAspect.Metadata, out relationAspects)) { foreach (MultipleMediaItemAspect relation in relationAspects) { if ((Guid?)relation[RelationshipAspect.ATTR_LINKED_ROLE] == MovieAspect.ROLE_MOVIE) { fanArtFiles.AddRange(fanArtCache.GetFanArtFiles((Guid)relation[RelationshipAspect.ATTR_LINKED_ID], fanArtType)); if (fanArtFiles.Count > 0) { break; } } } } } } else if (mediaType == FanArtMediaTypes.Character) { if (mediaItem.Aspects.ContainsKey(CharacterAspect.ASPECT_ID)) { IList <MultipleMediaItemAspect> relationAspects; if (MediaItemAspect.TryGetAspects(mediaItem.Aspects, RelationshipAspect.Metadata, out relationAspects)) { foreach (MultipleMediaItemAspect relation in relationAspects) { if ((Guid?)relation[RelationshipAspect.ATTR_LINKED_ROLE] == PersonAspect.ROLE_ACTOR) { fanArtFiles.AddRange(fanArtCache.GetFanArtFiles((Guid)relation[RelationshipAspect.ATTR_LINKED_ID], fanArtType)); if (fanArtFiles.Count > 0) { break; } } } } } } } List <IResourceLocator> files = new List <IResourceLocator>(); try { files.AddRange(fanArtFiles .Select(fileName => new ResourceLocator(ResourcePath.BuildBaseProviderPath(LocalFsResourceProviderBase.LOCAL_FS_RESOURCE_PROVIDER_ID, fileName))) ); result = files; return(result.Count > 0); } catch (Exception) { } return(false); }
public Guid AddOrUpdateMediaItem(Guid parentDirectoryId, string systemId, ResourcePath path, IEnumerable<MediaItemAspect> mediaItemAspects) { // TODO: Avoid multiple write operations to the same media item ISQLDatabase database = ServiceRegistration.Get<ISQLDatabase>(); ITransaction transaction = database.BeginTransaction(); try { Guid? mediaItemId = GetMediaItemId(transaction, systemId, path); DateTime now = DateTime.Now; MediaItemAspect importerAspect; bool wasCreated = !mediaItemId.HasValue; if (wasCreated) { mediaItemId = AddMediaItem(database, transaction); MediaItemAspect pra = new MediaItemAspect(ProviderResourceAspect.Metadata); pra.SetAttribute(ProviderResourceAspect.ATTR_SYSTEM_ID, systemId); pra.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH, path.Serialize()); pra.SetAttribute(ProviderResourceAspect.ATTR_PARENT_DIRECTORY_ID, parentDirectoryId); _miaManagement.AddOrUpdateMIA(transaction, mediaItemId.Value, pra, true); importerAspect = new MediaItemAspect(ImporterAspect.Metadata); importerAspect.SetAttribute(ImporterAspect.ATTR_DATEADDED, now); } else importerAspect = _miaManagement.GetMediaItemAspect(transaction, mediaItemId.Value, ImporterAspect.ASPECT_ID); importerAspect.SetAttribute(ImporterAspect.ATTR_DIRTY, false); importerAspect.SetAttribute(ImporterAspect.ATTR_LAST_IMPORT_DATE, now); _miaManagement.AddOrUpdateMIA(transaction, mediaItemId.Value, importerAspect, wasCreated); // Update foreach (MediaItemAspect mia in mediaItemAspects) { if (!_miaManagement.ManagedMediaItemAspectTypes.ContainsKey(mia.Metadata.AspectId)) // Simply skip unknown MIA types. All types should have been added before import. continue; if (mia.Metadata.AspectId == ImporterAspect.ASPECT_ID || mia.Metadata.AspectId == ProviderResourceAspect.ASPECT_ID) { // Those aspects are managed by the MediaLibrary ServiceRegistration.Get<ILogger>().Warn("MediaLibrary.AddOrUpdateMediaItem: Client tried to update either ImporterAspect or ProviderResourceAspect"); continue; } if (wasCreated) _miaManagement.AddOrUpdateMIA(transaction, mediaItemId.Value, mia, true); else _miaManagement.AddOrUpdateMIA(transaction, mediaItemId.Value, mia); } transaction.Commit(); return mediaItemId.Value; } catch (Exception e) { ServiceRegistration.Get<ILogger>().Error("MediaLibrary: Error adding or updating media item(s) in path '{0}'", e, path.Serialize()); transaction.Rollback(); throw; } }
protected override void Update() { if (_updating) { return; } _updating = true; try { IPlayerContextManager playerContextManager = ServiceRegistration.Get <IPlayerContextManager>(); IPlayerContext playerContext = playerContextManager.GetPlayerContext(_playerContext); _currentMediaItem = playerContext == null ? null : playerContext.CurrentMediaItem; SingleMediaItemAspect imageAspect; if (_currentMediaItem == null || !MediaItemAspect.TryGetAspect(_currentMediaItem.Aspects, ImageAspect.Metadata, out imageAspect)) { imageAspect = null; } if (imageAspect == null) { ImageDimensions = string.Empty; CameraMake = string.Empty; CameraModel = string.Empty; ImageISOSpeed = string.Empty; ImageExposureTime = string.Empty; ImageFNumber = string.Empty; ImageFlashMode = string.Empty; ImageMeteringMode = string.Empty; Country = string.Empty; State = string.Empty; City = string.Empty; } else { var mpc = playerContext != null ?playerContext.CurrentPlayer as IMediaPlaybackControl : null; if (mpc != null) { TransitionDuration = mpc.IsPaused ? 0.1d : 2.0d; } ImageDimensions = String.Format("{0} x {1}", imageAspect[ImageAspect.ATTR_WIDTH], imageAspect[ImageAspect.ATTR_HEIGHT]); CameraMake = (string)imageAspect[ImageAspect.ATTR_MAKE]; CameraModel = (string)imageAspect[ImageAspect.ATTR_MODEL]; ImageISOSpeed = (string)imageAspect[ImageAspect.ATTR_ISO_SPEED]; ImageExposureTime = (string)imageAspect[ImageAspect.ATTR_EXPOSURE_TIME]; ImageFNumber = (string)imageAspect[ImageAspect.ATTR_FNUMBER]; ImageFlashMode = (string)imageAspect[ImageAspect.ATTR_FLASH_MODE]; ImageMeteringMode = (string)imageAspect[ImageAspect.ATTR_METERING_MODE]; Country = (string)imageAspect[ImageAspect.ATTR_COUNTRY]; State = (string)imageAspect[ImageAspect.ATTR_STATE]; City = (string)imageAspect[ImageAspect.ATTR_CITY]; } } catch (Exception e) { ServiceRegistration.Get <ILogger>().Warn("ImagePlayerUIContributor: Error updating properties", e); } finally { _updating = false; } }
protected int CompareDifferentTypes(MediaItemAspect aspectX, MediaItemAspect aspectY) { return aspectX != null ? 1 : -1; }
/// <summary> /// Gets a list of <see cref="FanArtImage"/>s for a requested <paramref name="mediaType"/>, <paramref name="fanArtType"/> and <paramref name="name"/>. /// The name can be: Series name, Actor name, Artist name depending on the <paramref name="mediaType"/>. /// </summary> /// <param name="mediaType">Requested FanArtMediaType</param> /// <param name="fanArtType">Requested FanArtType</param> /// <param name="name">Requested name of Series, Actor, Artist...</param> /// <param name="maxWidth">Maximum width for image. <c>0</c> returns image in original size.</param> /// <param name="maxHeight">Maximum height for image. <c>0</c> returns image in original size.</param> /// <param name="singleRandom">If <c>true</c> only one random image URI will be returned</param> /// <param name="result">Result if return code is <c>true</c>.</param> /// <returns><c>true</c> if at least one match was found.</returns> public bool TryGetFanArt(string mediaType, string fanArtType, string name, int maxWidth, int maxHeight, bool singleRandom, out IList <IResourceLocator> result) { result = null; Guid mediaItemId; if (mediaType != FanArtMediaTypes.Actor || (fanArtType != FanArtTypes.Undefined && fanArtType != FanArtTypes.Thumbnail)) { return(false); } // Don't try to load "fanart" for images if (!Guid.TryParse(name, out mediaItemId)) { return(false); } IMediaLibrary mediaLibrary = ServiceRegistration.Get <IMediaLibrary>(false); if (mediaLibrary == null) { return(false); } IFilter filter = new RelationshipFilter(MovieAspect.ROLE_MOVIE, PersonAspect.ROLE_ACTOR, mediaItemId); IList <MediaItem> items = null; List <Guid> necessaryMias = new List <Guid>(NECESSARY_MIAS); MediaItemQuery mediaQuery = new MediaItemQuery(necessaryMias, filter); mediaQuery.Limit = 1; items = mediaLibrary.Search(mediaQuery, false, null, false); 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 mediaIteamLocator = mediaItem.GetResourceLocator(); var fanArtPaths = new List <ResourcePath>(); var files = new List <IResourceLocator>(); string actorName = null; SingleMediaItemAspect videoAspect; List <string> actors = new List <string>(); if (MediaItemAspect.TryGetAspect(mediaItem.Aspects, VideoAspect.Metadata, out videoAspect)) { IEnumerable <object> actorObjects = videoAspect.GetCollectionAttribute <object>(VideoAspect.ATTR_ACTORS); if (actorObjects != null) { actors.AddRange(actorObjects.Cast <string>()); } } IList <MultipleMediaItemAspect> relationAspects; if (MediaItemAspect.TryGetAspects(mediaItem.Aspects, RelationshipAspect.Metadata, out relationAspects)) { foreach (MultipleMediaItemAspect relation in relationAspects) { if ((Guid?)relation[RelationshipAspect.ATTR_LINKED_ROLE] == PersonAspect.ROLE_ACTOR && (Guid?)relation[RelationshipAspect.ATTR_LINKED_ID] == mediaItemId) { int?index = (int?)relation[RelationshipAspect.ATTR_RELATIONSHIP_INDEX]; if (index.HasValue && actors.Count > index.Value && index.Value >= 0) { actorName = actors[index.Value]; } break; } } } // File based access try { var mediaItemPath = mediaIteamLocator.NativeResourcePath; var mediaItemDirectoryPath = ResourcePathHelper.Combine(mediaItemPath, "../"); if (!string.IsNullOrEmpty(actorName)) { using (var directoryRa = new ResourceLocator(mediaIteamLocator.NativeSystemId, mediaItemDirectoryPath).CreateAccessor()) { var directoryFsra = directoryRa as IFileSystemResourceAccessor; if (directoryFsra != null) { //Get Artists thumbs IFileSystemResourceAccessor actorMediaItemDirectory = directoryFsra.GetResource(".actors"); if (actorMediaItemDirectory != null) { var potentialArtistFanArtFiles = LocalFanartHelper.GetPotentialFanArtFiles(actorMediaItemDirectory); foreach (ResourcePath thumbPath in from potentialFanArtFile in potentialArtistFanArtFiles let potentialFanArtFileNameWithoutExtension = ResourcePathHelper.GetFileNameWithoutExtension(potentialFanArtFile.ToString()) where potentialFanArtFileNameWithoutExtension.StartsWith(actorName.Replace(" ", "_"), StringComparison.InvariantCultureIgnoreCase) select potentialFanArtFile) { files.Add(new ResourceLocator(mediaIteamLocator.NativeSystemId, thumbPath)); } } } } //Find central actor information folder ResourcePath centralActorFolderPath = LocalFanartHelper.GetCentralPersonFolder(mediaItemDirectoryPath, CentralPersonFolderType.MovieActors); if (centralActorFolderPath != null) { // First get the ResourcePath of the central directory var actorFolderPath = ResourcePathHelper.Combine(centralActorFolderPath, $"{LocalFanartHelper.GetSafePersonFolderName(actorName)}/"); // Then try to create an IFileSystemResourceAccessor for this directory actorFolderPath.TryCreateLocalResourceAccessor(out var artistNfoDirectoryRa); var directoryFsra = artistNfoDirectoryRa as IFileSystemResourceAccessor; if (directoryFsra != null) { var potentialFanArtFiles = LocalFanartHelper.GetPotentialFanArtFiles(directoryFsra); if (fanArtType == FanArtTypes.Poster || fanArtType == FanArtTypes.Thumbnail) { fanArtPaths.AddRange(LocalFanartHelper.FilterPotentialFanArtFilesByPrefix(potentialFanArtFiles, LocalFanartHelper.ARTIST_FILENAMES)); fanArtPaths.AddRange(LocalFanartHelper.FilterPotentialFanArtFilesByPrefix(potentialFanArtFiles, LocalFanartHelper.POSTER_FILENAMES)); fanArtPaths.AddRange(LocalFanartHelper.FilterPotentialFanArtFilesByPrefix(potentialFanArtFiles, LocalFanartHelper.THUMB_FILENAMES)); } if (fanArtType == FanArtTypes.Banner) { fanArtPaths.AddRange(LocalFanartHelper.FilterPotentialFanArtFilesByPrefix(potentialFanArtFiles, LocalFanartHelper.BANNER_FILENAMES)); } if (fanArtType == FanArtTypes.Logo) { fanArtPaths.AddRange(LocalFanartHelper.FilterPotentialFanArtFilesByPrefix(potentialFanArtFiles, LocalFanartHelper.LOGO_FILENAMES)); } if (fanArtType == FanArtTypes.ClearArt) { fanArtPaths.AddRange(LocalFanartHelper.FilterPotentialFanArtFilesByPrefix(potentialFanArtFiles, LocalFanartHelper.CLEARART_FILENAMES)); } if (fanArtType == FanArtTypes.FanArt) { fanArtPaths.AddRange(LocalFanartHelper.FilterPotentialFanArtFilesByPrefix(potentialFanArtFiles, LocalFanartHelper.BACKDROP_FILENAMES)); if (directoryFsra.ResourceExists("ExtraFanArt/")) { using (var extraFanArtDirectoryFsra = directoryFsra.GetResource("ExtraFanArt/")) fanArtPaths.AddRange(LocalFanartHelper.GetPotentialFanArtFiles(extraFanArtDirectoryFsra)); } } files.AddRange(fanArtPaths.Select(path => new ResourceLocator(mediaIteamLocator.NativeSystemId, path))); } } } } catch (Exception ex) { #if DEBUG ServiceRegistration.Get <ILogger>().Warn("LocalMovieActorFanArtProvider: Error while searching fanart of type '{0}' for '{1}'", ex, fanArtType, mediaIteamLocator); #endif } result = files; return(files.Count > 0); }
public MediaItemAspect GetMediaItemAspect(ITransaction transaction, Guid mediaItemId, Guid aspectId) { MediaItemAspectMetadata miaType; if (!_managedMIATypes.TryGetValue(aspectId, out miaType) || miaType == null) throw new ArgumentException(string.Format("MIA_Management: Requested media item aspect type with id '{0}' doesn't exist", aspectId)); MediaItemAspect result = new MediaItemAspect(miaType); Namespace ns = new Namespace(); string miaTableName = GetMIATableName(miaType); IList<string> terms = new List<string>(); foreach (MediaItemAspectMetadata.AttributeSpecification spec in miaType.AttributeSpecifications.Values) { switch (spec.Cardinality) { case Cardinality.Inline: string attrName = GetMIAAttributeColumnName(spec); terms.Add(attrName + " " + ns.GetOrCreate(spec, "A")); break; case Cardinality.OneToMany: result.SetCollectionAttribute(spec, GetOneToManyMIAAttributeValues(transaction, mediaItemId, spec)); break; case Cardinality.ManyToOne: object value = GetManyToOneMIAAttributeValue(transaction, mediaItemId, spec, miaTableName); if (!AttributeIsEmpty(value)) result.SetAttribute(spec, value); break; case Cardinality.ManyToMany: result.SetCollectionAttribute(spec, GetManyToManyMIAAttributeValues(transaction, mediaItemId, spec)); break; default: throw new NotImplementedException(string.Format("Cardinality '{0}' for attribute '{1}.{2}' is not implemented", spec.Cardinality, miaType.AspectId, spec.AttributeName)); } } StringBuilder mainQueryBuilder = new StringBuilder("SELECT "); mainQueryBuilder.Append(StringUtils.Join(", ", terms)); mainQueryBuilder.Append(" FROM "); mainQueryBuilder.Append(miaTableName); mainQueryBuilder.Append(" WHERE "); mainQueryBuilder.Append(MIA_MEDIA_ITEM_ID_COL_NAME); mainQueryBuilder.Append(" = @MEDIA_ITEM_ID"); ISQLDatabase database = transaction.Database; using (IDbCommand command = transaction.CreateCommand()) { command.CommandText = mainQueryBuilder.ToString(); database.AddParameter(command, "MEDIA_ITEM_ID", mediaItemId, typeof(Guid)); using (IDataReader reader = command.ExecuteReader(CommandBehavior.SingleRow)) { int i = 0; if (reader.Read()) foreach (MediaItemAspectMetadata.AttributeSpecification spec in miaType.AttributeSpecifications.Values) { if (spec.Cardinality == Cardinality.Inline) { object value = ReadObject(database, reader, i, spec); if (!AttributeIsEmpty(value)) result.SetAttribute(spec, value); } i++; } } } return result; }
public static MediaItemAspectMetadata.AttributeSpecification GetAttributeSpecification(MediaItem mediaItem, IEnumerable <MediaItemAspectMetadata.SingleAttributeSpecification> attributes, out MediaItemAspect aspect) { SingleMediaItemAspect singleAspect = null; MediaItemAspectMetadata.SingleAttributeSpecification attr = attributes.FirstOrDefault(a => MediaItemAspect.TryGetAspect(mediaItem.Aspects, a.ParentMIAM, out singleAspect)); aspect = singleAspect; return(attr); }
/// <summary> /// Adds or updates the given media item aspect on the media item with the given id. /// </summary> /// <param name="transaction">Database transaction to use.</param> /// <param name="mediaItemId">Id of the media item to be added or updated.</param> /// <param name="mia">Media item aspect to write to DB.</param> public void AddOrUpdateMIA(ITransaction transaction, Guid mediaItemId, MediaItemAspect mia) { AddOrUpdateMIA(transaction, mediaItemId, mia, !MIAExists(transaction, mediaItemId, mia.Metadata.AspectId)); }
public static MediaItemAspectMetadata.AttributeSpecification GetAttributeSpecification(MediaItem mediaItem, IEnumerable <MediaItemAspectMetadata.MultipleAttributeSpecification> attributes, out MediaItemAspect aspect) { IList <MultipleMediaItemAspect> multipleAspects = null; MediaItemAspectMetadata.MultipleAttributeSpecification attr = attributes.FirstOrDefault(a => MediaItemAspect.TryGetAspects(mediaItem.Aspects, a.ParentMIAM, out multipleAspects)); aspect = attr != null ? multipleAspects[0] : null; return(attr); }
public IList<MediaItem> QueryList() { ISQLDatabase database = ServiceRegistration.Get<ISQLDatabase>(); ITransaction transaction = database.BeginTransaction(); try { string statementStr; IList<BindVar> bindVars; // 1. Request all complex attributes IDictionary<Guid, IDictionary<MediaItemAspectMetadata.AttributeSpecification, ICollection<object>>> complexAttributeValues = new Dictionary<Guid, IDictionary<MediaItemAspectMetadata.AttributeSpecification, ICollection<object>>>(); foreach (MediaItemAspectMetadata.AttributeSpecification attr in _explicitSelectAttributes) { ComplexAttributeQueryBuilder complexAttributeQueryBuilder = new ComplexAttributeQueryBuilder( _miaManagement, attr, null, _necessaryRequestedMIAs, _filter); using (IDbCommand command = transaction.CreateCommand()) { string mediaItemIdAlias; string valueAlias; complexAttributeQueryBuilder.GenerateSqlStatement(out mediaItemIdAlias, out valueAlias, out statementStr, out bindVars); command.CommandText = statementStr; foreach (BindVar bindVar in bindVars) database.AddParameter(command, bindVar.Name, bindVar.Value, bindVar.VariableType); Type valueType = attr.AttributeType; using (IDataReader reader = command.ExecuteReader()) { while (reader.Read()) { Guid mediaItemId = database.ReadDBValue<Guid>(reader, reader.GetOrdinal(mediaItemIdAlias)); object value = database.ReadDBValue(valueType, reader, reader.GetOrdinal(valueAlias)); IDictionary<MediaItemAspectMetadata.AttributeSpecification, ICollection<object>> attributeValues; if (!complexAttributeValues.TryGetValue(mediaItemId, out attributeValues)) attributeValues = complexAttributeValues[mediaItemId] = new Dictionary<MediaItemAspectMetadata.AttributeSpecification, ICollection<object>>(); ICollection<object> attrValues; if (!attributeValues.TryGetValue(attr, out attrValues)) attrValues = attributeValues[attr] = new List<object>(); attrValues.Add(value); } } } } // 2. Main query MainQueryBuilder mainQueryBuilder = new MainQueryBuilder(_miaManagement, _mainSelectAttributes.Values, null, _necessaryRequestedMIAs, _optionalRequestedMIAs, _filter, _sortInformation); using (IDbCommand command = transaction.CreateCommand()) { string mediaItemIdAlias2; IDictionary<MediaItemAspectMetadata, string> miamAliases; // Maps (selected and filtered) QueryAttributes to CompiledQueryAttributes in the SQL query IDictionary<QueryAttribute, string> qa2a; mainQueryBuilder.GenerateSqlStatement(out mediaItemIdAlias2, out miamAliases, out qa2a, out statementStr, out bindVars); command.CommandText = statementStr; foreach (BindVar bindVar in bindVars) database.AddParameter(command, bindVar.Name, bindVar.Value, bindVar.VariableType); IEnumerable<MediaItemAspectMetadata> selectedMIAs = _necessaryRequestedMIAs.Union(_optionalRequestedMIAs); ICollection<Guid> mediaItems = new HashSet<Guid>(); using (IDataReader reader = command.ExecuteReader()) { IList<MediaItem> result = new List<MediaItem>(); while (reader.Read()) { Guid mediaItemId = database.ReadDBValue<Guid>(reader, reader.GetOrdinal(mediaItemIdAlias2)); if (mediaItems.Contains(mediaItemId)) // Media item was already added to result - query results are not always unique because of JOINs used for filtering continue; mediaItems.Add(mediaItemId); IDictionary<MediaItemAspectMetadata.AttributeSpecification, ICollection<object>> attributeValues; if (!complexAttributeValues.TryGetValue(mediaItemId, out attributeValues)) attributeValues = null; MediaItem mediaItem = new MediaItem(mediaItemId); foreach (MediaItemAspectMetadata miam in selectedMIAs) { if (reader.IsDBNull(reader.GetOrdinal(miamAliases[miam]))) // MIAM is not available for current media item continue; MediaItemAspect mia = new MediaItemAspect(miam); foreach (MediaItemAspectMetadata.AttributeSpecification attr in miam.AttributeSpecifications.Values) if (attr.Cardinality == Cardinality.Inline) { QueryAttribute qa = _mainSelectAttributes[attr]; string alias = qa2a[qa]; mia.SetAttribute(attr, database.ReadDBValue(attr.AttributeType, reader, reader.GetOrdinal(alias))); } else { ICollection<object> attrValues; if (attributeValues != null && attributeValues.TryGetValue(attr, out attrValues)) mia.SetCollectionAttribute(attr, attrValues); } mediaItem.Aspects[miam.AspectId] = mia; } result.Add(mediaItem); } return result; } } } finally { transaction.Dispose(); } }
private string GetMovieImdb(MediaItem currMediaItem) { string value; return(MediaItemAspect.TryGetAttribute(currMediaItem.Aspects, MovieAspect.ATTR_IMDB_ID, out value) ? value : null); }
public bool TryExtractMetadata(IResourceAccessor mediaItemAccessor, IDictionary<Guid, MediaItemAspect> extractedAspectData, bool forceQuickMode) { try { IResourceAccessor ra = mediaItemAccessor.Clone(); try { using (ILocalFsResourceAccessor fsra = StreamedResourceToLocalFsAccessBridge.GetLocalFsResourceAccessor(ra)) if (fsra != null && fsra.IsDirectory && fsra.ResourceExists("BDMV")) { IFileSystemResourceAccessor fsraBDMV = fsra.GetResource("BDMV"); if (fsraBDMV != null && fsraBDMV.ResourceExists("index.bdmv")) { // BluRay MediaItemAspect mediaAspect; if (!extractedAspectData.TryGetValue(MediaAspect.ASPECT_ID, out mediaAspect)) extractedAspectData[MediaAspect.ASPECT_ID] = mediaAspect = new MediaItemAspect(MediaAspect.Metadata); MediaItemAspect videoAspect; if (!extractedAspectData.TryGetValue(VideoAspect.ASPECT_ID, out videoAspect)) extractedAspectData[VideoAspect.ASPECT_ID] = new MediaItemAspect(VideoAspect.Metadata); mediaAspect.SetAttribute(MediaAspect.ATTR_MIME_TYPE, "video/bluray"); // BluRay disc string bdmvDirectory = fsra.LocalFileSystemPath; BDInfoExt bdinfo = new BDInfoExt(bdmvDirectory); mediaAspect.SetAttribute(MediaAspect.ATTR_TITLE, bdinfo.GetTitle() ?? mediaItemAccessor.ResourceName); return true; } } } catch { ra.Dispose(); throw; } 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; } }
private async Task <bool> TryExtractStubItemsAsync(IResourceAccessor mediaItemAccessor, ICollection <IDictionary <Guid, IList <MediaItemAspect> > > extractedStubAspectData) { // 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); try { _debugLogger.Info("[#{0}]: Start extracting stubs for resource '{1}'", miNumber, mediaItemAccessor); if (!IsStubResource(mediaItemAccessor)) { _debugLogger.Info("[#{0}]: Cannot extract stubs; file does not have a supported extension", miNumber); return(false); } // This MetadataExtractor only works for MediaItems accessible by an IFileSystemResourceAccessor. // Otherwise it is not possible to find a stub-file in the MediaItem's directory. if (!(mediaItemAccessor is IFileSystemResourceAccessor)) { _debugLogger.Info("[#{0}]: Cannot extract stubs; mediaItemAccessor is not an IFileSystemResourceAccessor", miNumber); return(false); } var fsra = mediaItemAccessor as IFileSystemResourceAccessor; var movieStubReader = new StubMovieReader(_debugLogger, miNumber, true, _settings); if (fsra != null && await movieStubReader.TryReadMetadataAsync(fsra).ConfigureAwait(false)) { MovieStub movie = movieStubReader.GetMovieStubs().FirstOrDefault(); if (movie != null) { Dictionary <Guid, IList <MediaItemAspect> > extractedAspectData = new Dictionary <Guid, IList <MediaItemAspect> >(); MultipleMediaItemAspect providerResourceAspect = MediaItemAspect.CreateAspect(extractedAspectData, ProviderResourceAspect.Metadata); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_INDEX, 0); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_TYPE, ProviderResourceAspect.TYPE_STUB); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH, fsra.CanonicalLocalResourcePath.Serialize()); if (IsVhs(mediaItemAccessor)) { providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, "video/unknown"); MultipleMediaItemAspect videoStreamAspects = MediaItemAspect.CreateAspect(extractedAspectData, VideoStreamAspect.Metadata); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_RESOURCE_INDEX, 0); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_STREAM_INDEX, 0); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_VIDEO_TYPE, VideoStreamAspect.TYPE_SD); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_ASPECTRATIO, Convert.ToSingle(4.0 / 3.0)); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_FPS, 25F); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_WIDTH, 720); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_HEIGHT, 576); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_AUDIOSTREAMCOUNT, 1); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_VIDEO_PART, 1); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_VIDEO_PART_SET_NAME, "VHS Stub"); MultipleMediaItemAspect audioAspect = MediaItemAspect.CreateAspect(extractedAspectData, VideoAudioStreamAspect.Metadata); audioAspect.SetAttribute(VideoAudioStreamAspect.ATTR_RESOURCE_INDEX, 0); audioAspect.SetAttribute(VideoAudioStreamAspect.ATTR_STREAM_INDEX, 1); audioAspect.SetAttribute(VideoAudioStreamAspect.ATTR_AUDIOCHANNELS, 2); } else if (IsTv(mediaItemAccessor)) { providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, "video/unknown"); MultipleMediaItemAspect videoStreamAspects = MediaItemAspect.CreateAspect(extractedAspectData, VideoStreamAspect.Metadata); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_RESOURCE_INDEX, 0); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_STREAM_INDEX, 0); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_VIDEO_TYPE, VideoStreamAspect.TYPE_HD); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_ASPECTRATIO, Convert.ToSingle(16.0 / 9.0)); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_FPS, 25F); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_WIDTH, 1920); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_HEIGHT, 1080); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_AUDIOSTREAMCOUNT, 1); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_VIDEO_PART, 1); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_VIDEO_PART_SET_NAME, "TV Stub"); MultipleMediaItemAspect audioAspect = MediaItemAspect.CreateAspect(extractedAspectData, VideoAudioStreamAspect.Metadata); audioAspect.SetAttribute(VideoAudioStreamAspect.ATTR_RESOURCE_INDEX, 0); audioAspect.SetAttribute(VideoAudioStreamAspect.ATTR_STREAM_INDEX, 1); audioAspect.SetAttribute(VideoAudioStreamAspect.ATTR_AUDIOCHANNELS, 2); } else if (IsDvd(mediaItemAccessor)) { providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, "video/mp2t"); MultipleMediaItemAspect videoStreamAspects = MediaItemAspect.CreateAspect(extractedAspectData, VideoStreamAspect.Metadata); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_RESOURCE_INDEX, 0); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_STREAM_INDEX, 0); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_VIDEO_TYPE, VideoStreamAspect.TYPE_SD); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_ASPECTRATIO, Convert.ToSingle(16.0 / 9.0)); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_FPS, 25F); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_WIDTH, 720); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_HEIGHT, 576); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_VIDEOENCODING, "MPEG-2 Video"); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_AUDIOSTREAMCOUNT, 1); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_VIDEO_PART, 1); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_VIDEO_PART_SET_NAME, "DVD Stub"); MultipleMediaItemAspect audioAspect = MediaItemAspect.CreateAspect(extractedAspectData, VideoAudioStreamAspect.Metadata); audioAspect.SetAttribute(VideoAudioStreamAspect.ATTR_RESOURCE_INDEX, 0); audioAspect.SetAttribute(VideoAudioStreamAspect.ATTR_STREAM_INDEX, 1); audioAspect.SetAttribute(VideoAudioStreamAspect.ATTR_AUDIOENCODING, "AC3"); audioAspect.SetAttribute(VideoAudioStreamAspect.ATTR_AUDIOCHANNELS, 6); audioAspect.SetAttribute(VideoAudioStreamAspect.ATTR_AUDIOSAMPLERATE, 48000L); } else if (IsBluray(mediaItemAccessor)) { providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, "video/mp4"); MultipleMediaItemAspect videoStreamAspects = MediaItemAspect.CreateAspect(extractedAspectData, VideoStreamAspect.Metadata); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_RESOURCE_INDEX, 0); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_STREAM_INDEX, 0); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_VIDEO_TYPE, VideoStreamAspect.TYPE_HD); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_ASPECTRATIO, Convert.ToSingle(16.0 / 9.0)); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_FPS, 24F); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_WIDTH, 1920); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_HEIGHT, 1080); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_VIDEOENCODING, "AVC"); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_AUDIOSTREAMCOUNT, 1); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_VIDEO_PART, 1); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_VIDEO_PART_SET_NAME, "Bluray Stub"); MultipleMediaItemAspect audioAspect = MediaItemAspect.CreateAspect(extractedAspectData, VideoAudioStreamAspect.Metadata); audioAspect.SetAttribute(VideoAudioStreamAspect.ATTR_RESOURCE_INDEX, 0); audioAspect.SetAttribute(VideoAudioStreamAspect.ATTR_STREAM_INDEX, 1); audioAspect.SetAttribute(VideoAudioStreamAspect.ATTR_AUDIOENCODING, "AC3"); audioAspect.SetAttribute(VideoAudioStreamAspect.ATTR_AUDIOCHANNELS, 6); audioAspect.SetAttribute(VideoAudioStreamAspect.ATTR_AUDIOSAMPLERATE, 48000L); } else if (IsHdDvd(mediaItemAccessor)) { providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, "video/wvc1"); MultipleMediaItemAspect videoStreamAspects = MediaItemAspect.CreateAspect(extractedAspectData, VideoStreamAspect.Metadata); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_RESOURCE_INDEX, 0); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_STREAM_INDEX, 0); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_VIDEO_TYPE, VideoStreamAspect.TYPE_HD); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_ASPECTRATIO, Convert.ToSingle(16.0 / 9.0)); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_FPS, 24F); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_WIDTH, 1920); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_HEIGHT, 1080); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_VIDEOENCODING, "VC1"); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_AUDIOSTREAMCOUNT, 1); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_VIDEO_PART, 1); videoStreamAspects.SetAttribute(VideoStreamAspect.ATTR_VIDEO_PART_SET_NAME, "HDDVD Stub"); MultipleMediaItemAspect audioAspect = MediaItemAspect.CreateAspect(extractedAspectData, VideoAudioStreamAspect.Metadata); audioAspect.SetAttribute(VideoAudioStreamAspect.ATTR_RESOURCE_INDEX, 0); audioAspect.SetAttribute(VideoAudioStreamAspect.ATTR_STREAM_INDEX, 1); audioAspect.SetAttribute(VideoAudioStreamAspect.ATTR_AUDIOENCODING, "AC3"); audioAspect.SetAttribute(VideoAudioStreamAspect.ATTR_AUDIOCHANNELS, 6); audioAspect.SetAttribute(VideoAudioStreamAspect.ATTR_AUDIOSAMPLERATE, 48000L); } SingleMediaItemAspect videoAspect = MediaItemAspect.GetOrCreateAspect(extractedAspectData, VideoAspect.Metadata); videoAspect.SetAttribute(VideoAspect.ATTR_ISDVD, true); SingleMediaItemAspect movieAspect = MediaItemAspect.GetOrCreateAspect(extractedAspectData, MovieAspect.Metadata); movieAspect.SetAttribute(MovieAspect.ATTR_MOVIE_NAME, movie.Title); SingleMediaItemAspect stubAspect = MediaItemAspect.GetOrCreateAspect(extractedAspectData, StubAspect.Metadata); stubAspect.SetAttribute(StubAspect.ATTR_DISC_NAME, movie.DiscName); stubAspect.SetAttribute(StubAspect.ATTR_MESSAGE, movie.Message); MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, movie.Title); MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_SORT_TITLE, BaseInfo.GetSortTitle(movie.Title)); MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_ISVIRTUAL, false); MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_ISSTUB, true); MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_RECORDINGTIME, fsra.LastChanged); extractedStubAspectData.Add(extractedAspectData); } } else { _debugLogger.Warn("[#{0}]: No valid metadata found in movie stub file", miNumber); } _debugLogger.Info("[#{0}]: Successfully finished extracting stubs", miNumber); return(true); } catch (Exception e) { ServiceRegistration.Get <ILogger>().Warn("StubMovieMetadataExtractor: Exception while extracting stubs for resource '{0}'; enable debug logging for more details.", mediaItemAccessor); _debugLogger.Error("[#{0}]: Exception while extracting stubs", e, miNumber); return(false); } }