diff options
Diffstat (limited to 'MediaBrowser.Providers/MediaInfo/AudioFileProber.cs')
| -rw-r--r-- | MediaBrowser.Providers/MediaInfo/AudioFileProber.cs | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/MediaBrowser.Providers/MediaInfo/AudioFileProber.cs b/MediaBrowser.Providers/MediaInfo/AudioFileProber.cs new file mode 100644 index 000000000..3699e8f49 --- /dev/null +++ b/MediaBrowser.Providers/MediaInfo/AudioFileProber.cs @@ -0,0 +1,215 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.MediaEncoding; +using MediaBrowser.Controller.Persistence; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Dlna; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.MediaInfo; +using TagLib; + +namespace MediaBrowser.Providers.MediaInfo +{ + /// <summary> + /// Probes audio files for metadata. + /// </summary> + public class AudioFileProber + { + private readonly IMediaEncoder _mediaEncoder; + private readonly IItemRepository _itemRepo; + private readonly ILibraryManager _libraryManager; + private readonly IMediaSourceManager _mediaSourceManager; + + /// <summary> + /// Initializes a new instance of the <see cref="AudioFileProber"/> class. + /// </summary> + /// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param> + /// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param> + /// <param name="itemRepo">Instance of the <see cref="IItemRepository"/> interface.</param> + /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> + public AudioFileProber( + IMediaSourceManager mediaSourceManager, + IMediaEncoder mediaEncoder, + IItemRepository itemRepo, + ILibraryManager libraryManager) + { + _mediaEncoder = mediaEncoder; + _itemRepo = itemRepo; + _libraryManager = libraryManager; + _mediaSourceManager = mediaSourceManager; + } + + /// <summary> + /// Probes the specified item for metadata. + /// </summary> + /// <param name="item">The item to probe.</param> + /// <param name="options">The <see cref="MetadataRefreshOptions"/>.</param> + /// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param> + /// <typeparam name="T">The type of item to resolve.</typeparam> + /// <returns>A <see cref="Task"/> probing the item for metadata.</returns> + public async Task<ItemUpdateType> Probe<T>( + T item, + MetadataRefreshOptions options, + CancellationToken cancellationToken) + where T : Audio + { + var path = item.Path; + var protocol = item.PathProtocol ?? MediaProtocol.File; + + if (!item.IsShortcut || options.EnableRemoteContentProbe) + { + if (item.IsShortcut) + { + path = item.ShortcutPath; + protocol = _mediaSourceManager.GetPathProtocol(path); + } + + var result = await _mediaEncoder.GetMediaInfo( + new MediaInfoRequest + { + MediaType = DlnaProfileType.Audio, + MediaSource = new MediaSourceInfo + { + Path = path, + Protocol = protocol + } + }, + cancellationToken).ConfigureAwait(false); + + cancellationToken.ThrowIfCancellationRequested(); + + Fetch(item, result, cancellationToken); + } + + return ItemUpdateType.MetadataImport; + } + + /// <summary> + /// Fetches the specified audio. + /// </summary> + /// <param name="audio">The <see cref="Audio"/>.</param> + /// <param name="mediaInfo">The <see cref="Model.MediaInfo.MediaInfo"/>.</param> + /// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param> + protected void Fetch(Audio audio, Model.MediaInfo.MediaInfo mediaInfo, CancellationToken cancellationToken) + { + audio.Container = mediaInfo.Container; + audio.TotalBitrate = mediaInfo.Bitrate; + + audio.RunTimeTicks = mediaInfo.RunTimeTicks; + audio.Size = mediaInfo.Size; + + FetchDataFromTags(audio); + + _itemRepo.SaveMediaStreams(audio.Id, mediaInfo.MediaStreams, cancellationToken); + } + + /// <summary> + /// Fetches data from the tags. + /// </summary> + /// <param name="audio">The <see cref="Audio"/>.</param> + private void FetchDataFromTags(Audio audio) + { + var file = TagLib.File.Create(audio.Path); + var tagTypes = file.TagTypesOnDisk; + Tag? tags = null; + + if (tagTypes.HasFlag(TagTypes.Id3v2)) + { + tags = file.GetTag(TagTypes.Id3v2); + } + else if (tagTypes.HasFlag(TagTypes.Ape)) + { + tags = file.GetTag(TagTypes.Ape); + } + else if (tagTypes.HasFlag(TagTypes.FlacMetadata)) + { + tags = file.GetTag(TagTypes.FlacMetadata); + } + else if (tagTypes.HasFlag(TagTypes.Apple)) + { + tags = file.GetTag(TagTypes.Apple); + } + else if (tagTypes.HasFlag(TagTypes.Xiph)) + { + tags = file.GetTag(TagTypes.Xiph); + } + else if (tagTypes.HasFlag(TagTypes.AudibleMetadata)) + { + tags = file.GetTag(TagTypes.AudibleMetadata); + } + else if (tagTypes.HasFlag(TagTypes.Id3v1)) + { + tags = file.GetTag(TagTypes.Id3v1); + } + + if (tags != null) + { + if (audio.SupportsPeople && !audio.LockedFields.Contains(MetadataField.Cast)) + { + var people = new List<PersonInfo>(); + var albumArtists = tags.AlbumArtists; + foreach (var albumArtist in albumArtists) + { + PeopleHelper.AddPerson(people, new PersonInfo + { + Name = albumArtist, + Type = "AlbumArtist" + }); + } + + var performers = tags.Performers; + foreach (var performer in performers) + { + PeopleHelper.AddPerson(people, new PersonInfo + { + Name = performer, + Type = "Artist" + }); + } + + foreach (var composer in tags.Composers) + { + PeopleHelper.AddPerson(people, new PersonInfo + { + Name = composer, + Type = "Composer" + }); + } + + _libraryManager.UpdatePeople(audio, people); + audio.Artists = performers; + audio.AlbumArtists = albumArtists; + } + + audio.Name = tags.Title; + audio.Album = tags.Album; + audio.IndexNumber = Convert.ToInt32(tags.Track); + audio.ParentIndexNumber = Convert.ToInt32(tags.Disc); + if (tags.Year != 0) + { + var year = Convert.ToInt32(tags.Year); + audio.ProductionYear = year; + audio.PremiereDate = new DateTime(year, 01, 01); + } + + if (!audio.LockedFields.Contains(MetadataField.Genres)) + { + audio.Genres = tags.Genres.Distinct(StringComparer.OrdinalIgnoreCase).ToArray(); + } + + audio.SetProviderId(MetadataProvider.MusicBrainzArtist, tags.MusicBrainzArtistId); + audio.SetProviderId(MetadataProvider.MusicBrainzAlbumArtist, tags.MusicBrainzReleaseArtistId); + audio.SetProviderId(MetadataProvider.MusicBrainzAlbum, tags.MusicBrainzReleaseId); + audio.SetProviderId(MetadataProvider.MusicBrainzReleaseGroup, tags.MusicBrainzReleaseGroupId); + audio.SetProviderId(MetadataProvider.MusicBrainzTrack, tags.MusicBrainzTrackId); + } + } + } +} |
