diff options
Diffstat (limited to 'MediaBrowser.Providers/MediaInfo/AudioFileProber.cs')
| -rw-r--r-- | MediaBrowser.Providers/MediaInfo/AudioFileProber.cs | 93 |
1 files changed, 61 insertions, 32 deletions
diff --git a/MediaBrowser.Providers/MediaInfo/AudioFileProber.cs b/MediaBrowser.Providers/MediaInfo/AudioFileProber.cs index 916e2625b..cbbb7e83e 100644 --- a/MediaBrowser.Providers/MediaInfo/AudioFileProber.cs +++ b/MediaBrowser.Providers/MediaInfo/AudioFileProber.cs @@ -32,7 +32,6 @@ namespace MediaBrowser.Providers.MediaInfo private const char InternalValueSeparator = '\u001F'; private readonly IMediaEncoder _mediaEncoder; - private readonly IItemRepository _itemRepo; private readonly ILibraryManager _libraryManager; private readonly ILogger<AudioFileProber> _logger; private readonly IMediaSourceManager _mediaSourceManager; @@ -46,7 +45,6 @@ namespace MediaBrowser.Providers.MediaInfo /// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param> /// <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> /// <param name="lyricResolver">Instance of the <see cref="LyricResolver"/> interface.</param> /// <param name="lyricManager">Instance of the <see cref="ILyricManager"/> interface.</param> @@ -55,14 +53,12 @@ namespace MediaBrowser.Providers.MediaInfo ILogger<AudioFileProber> logger, IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder, - IItemRepository itemRepo, ILibraryManager libraryManager, LyricResolver lyricResolver, ILyricManager lyricManager, IMediaStreamRepository mediaStreamRepository) { _mediaEncoder = mediaEncoder; - _itemRepo = itemRepo; _libraryManager = libraryManager; _logger = logger; _mediaSourceManager = mediaSourceManager; @@ -137,7 +133,6 @@ namespace MediaBrowser.Providers.MediaInfo audio.TotalBitrate = mediaInfo.Bitrate; audio.RunTimeTicks = mediaInfo.RunTimeTicks; - audio.Size = mediaInfo.Size; // Add external lyrics first to prevent the lrc file get overwritten on first scan var mediaStreams = new List<MediaStream>(mediaInfo.MediaStreams); @@ -180,16 +175,24 @@ namespace MediaBrowser.Providers.MediaInfo // That setter is meant for its own tag parser and external editor usage and will have unwanted side effects // For example, setting the Year property will also set the Date property, which is not what we want here. // To properly handle fallback values, we make a clone of those fields when valid. - var trackTitle = (string.IsNullOrEmpty(track.Title) ? mediaInfo.Name : track.Title).Trim(); - var trackAlbum = (string.IsNullOrEmpty(track.Album) ? mediaInfo.Album : track.Album).Trim(); + var trackTitle = (string.IsNullOrEmpty(track.Title) ? mediaInfo.Name : track.Title)?.Trim(); + var trackAlbum = (string.IsNullOrEmpty(track.Album) ? mediaInfo.Album : track.Album)?.Trim(); var trackYear = track.Year is null or 0 ? mediaInfo.ProductionYear : track.Year; var trackTrackNumber = track.TrackNumber is null or 0 ? mediaInfo.IndexNumber : track.TrackNumber; var trackDiscNumber = track.DiscNumber is null or 0 ? mediaInfo.ParentIndexNumber : track.DiscNumber; + // Some users may use a misbehaved tag editor that writes a null character in the tag when not allowed by the standard. + trackTitle = GetSanitizedStringTag(trackTitle, audio.Path); + trackAlbum = GetSanitizedStringTag(trackAlbum, audio.Path); + var trackAlbumArtist = GetSanitizedStringTag(track.AlbumArtist, audio.Path); + var trackArist = GetSanitizedStringTag(track.Artist, audio.Path); + var trackComposer = GetSanitizedStringTag(track.Composer, audio.Path); + var trackGenre = GetSanitizedStringTag(track.Genre, audio.Path); + if (audio.SupportsPeople && !audio.LockedFields.Contains(MetadataField.Cast)) { var people = new List<PersonInfo>(); - var albumArtists = string.IsNullOrEmpty(track.AlbumArtist) ? [] : track.AlbumArtist.Split(InternalValueSeparator); + var albumArtists = string.IsNullOrEmpty(trackAlbumArtist) ? [] : trackAlbumArtist.Split(InternalValueSeparator); if (libraryOptions.UseCustomTagDelimiters) { @@ -211,7 +214,7 @@ namespace MediaBrowser.Providers.MediaInfo string[]? performers = null; if (libraryOptions.PreferNonstandardArtistsTag) { - track.AdditionalFields.TryGetValue("ARTISTS", out var artistsTagString); + TryGetSanitizedAdditionalFields(track, "ARTISTS", out var artistsTagString); if (artistsTagString is not null) { performers = artistsTagString.Split(InternalValueSeparator); @@ -220,7 +223,7 @@ namespace MediaBrowser.Providers.MediaInfo if (performers is null || performers.Length == 0) { - performers = string.IsNullOrEmpty(track.Artist) ? [] : track.Artist.Split(InternalValueSeparator); + performers = string.IsNullOrEmpty(trackArist) ? [] : trackArist.Split(InternalValueSeparator); } if (libraryOptions.UseCustomTagDelimiters) @@ -240,15 +243,18 @@ namespace MediaBrowser.Providers.MediaInfo } } - foreach (var composer in track.Composer.Split(InternalValueSeparator)) + if (!string.IsNullOrWhiteSpace(trackComposer)) { - if (!string.IsNullOrWhiteSpace(composer)) + foreach (var composer in trackComposer.Split(InternalValueSeparator)) { - PeopleHelper.AddPerson(people, new PersonInfo + if (!string.IsNullOrWhiteSpace(composer)) { - Name = composer.Trim(), - Type = PersonKind.Composer - }); + PeopleHelper.AddPerson(people, new PersonInfo + { + Name = composer.Trim(), + Type = PersonKind.Composer + }); + } } } @@ -325,7 +331,7 @@ namespace MediaBrowser.Providers.MediaInfo if (!audio.LockedFields.Contains(MetadataField.Genres)) { - var genres = string.IsNullOrEmpty(track.Genre) ? [] : track.Genre.Split(InternalValueSeparator).Distinct(StringComparer.OrdinalIgnoreCase).ToArray(); + var genres = string.IsNullOrEmpty(trackGenre) ? [] : trackGenre.Split(InternalValueSeparator).Distinct(StringComparer.OrdinalIgnoreCase).ToArray(); if (libraryOptions.UseCustomTagDelimiters) { @@ -339,7 +345,7 @@ namespace MediaBrowser.Providers.MediaInfo : audio.Genres; } - track.AdditionalFields.TryGetValue("REPLAYGAIN_TRACK_GAIN", out var trackGainTag); + TryGetSanitizedAdditionalFields(track, "REPLAYGAIN_TRACK_GAIN", out var trackGainTag); if (trackGainTag is not null) { @@ -348,7 +354,7 @@ namespace MediaBrowser.Providers.MediaInfo trackGainTag = trackGainTag[..^2].Trim(); } - if (float.TryParse(trackGainTag, NumberStyles.Float, CultureInfo.InvariantCulture, out var value)) + if (float.TryParse(trackGainTag, NumberStyles.Float, CultureInfo.InvariantCulture, out var value) && float.IsFinite(value)) { audio.NormalizationGain = value; } @@ -356,8 +362,8 @@ namespace MediaBrowser.Providers.MediaInfo if (options.ReplaceAllMetadata || !audio.TryGetProviderId(MetadataProvider.MusicBrainzArtist, out _)) { - if ((track.AdditionalFields.TryGetValue("MUSICBRAINZ_ARTISTID", out var musicBrainzArtistTag) - || track.AdditionalFields.TryGetValue("MusicBrainz Artist Id", out musicBrainzArtistTag)) + if ((TryGetSanitizedAdditionalFields(track, "MUSICBRAINZ_ARTISTID", out var musicBrainzArtistTag) + || TryGetSanitizedAdditionalFields(track, "MusicBrainz Artist Id", out musicBrainzArtistTag)) && !string.IsNullOrEmpty(musicBrainzArtistTag)) { var id = GetFirstMusicBrainzId(musicBrainzArtistTag, libraryOptions.UseCustomTagDelimiters, libraryOptions.GetCustomTagDelimiters(), libraryOptions.DelimiterWhitelist); @@ -367,8 +373,8 @@ namespace MediaBrowser.Providers.MediaInfo if (options.ReplaceAllMetadata || !audio.TryGetProviderId(MetadataProvider.MusicBrainzAlbumArtist, out _)) { - if ((track.AdditionalFields.TryGetValue("MUSICBRAINZ_ALBUMARTISTID", out var musicBrainzReleaseArtistIdTag) - || track.AdditionalFields.TryGetValue("MusicBrainz Album Artist Id", out musicBrainzReleaseArtistIdTag)) + if ((TryGetSanitizedAdditionalFields(track, "MUSICBRAINZ_ALBUMARTISTID", out var musicBrainzReleaseArtistIdTag) + || TryGetSanitizedAdditionalFields(track, "MusicBrainz Album Artist Id", out musicBrainzReleaseArtistIdTag)) && !string.IsNullOrEmpty(musicBrainzReleaseArtistIdTag)) { var id = GetFirstMusicBrainzId(musicBrainzReleaseArtistIdTag, libraryOptions.UseCustomTagDelimiters, libraryOptions.GetCustomTagDelimiters(), libraryOptions.DelimiterWhitelist); @@ -378,8 +384,8 @@ namespace MediaBrowser.Providers.MediaInfo if (options.ReplaceAllMetadata || !audio.TryGetProviderId(MetadataProvider.MusicBrainzAlbum, out _)) { - if ((track.AdditionalFields.TryGetValue("MUSICBRAINZ_ALBUMID", out var musicBrainzReleaseIdTag) - || track.AdditionalFields.TryGetValue("MusicBrainz Album Id", out musicBrainzReleaseIdTag)) + if ((TryGetSanitizedAdditionalFields(track, "MUSICBRAINZ_ALBUMID", out var musicBrainzReleaseIdTag) + || TryGetSanitizedAdditionalFields(track, "MusicBrainz Album Id", out musicBrainzReleaseIdTag)) && !string.IsNullOrEmpty(musicBrainzReleaseIdTag)) { var id = GetFirstMusicBrainzId(musicBrainzReleaseIdTag, libraryOptions.UseCustomTagDelimiters, libraryOptions.GetCustomTagDelimiters(), libraryOptions.DelimiterWhitelist); @@ -389,8 +395,8 @@ namespace MediaBrowser.Providers.MediaInfo if (options.ReplaceAllMetadata || !audio.TryGetProviderId(MetadataProvider.MusicBrainzReleaseGroup, out _)) { - if ((track.AdditionalFields.TryGetValue("MUSICBRAINZ_RELEASEGROUPID", out var musicBrainzReleaseGroupIdTag) - || track.AdditionalFields.TryGetValue("MusicBrainz Release Group Id", out musicBrainzReleaseGroupIdTag)) + if ((TryGetSanitizedAdditionalFields(track, "MUSICBRAINZ_RELEASEGROUPID", out var musicBrainzReleaseGroupIdTag) + || TryGetSanitizedAdditionalFields(track, "MusicBrainz Release Group Id", out musicBrainzReleaseGroupIdTag)) && !string.IsNullOrEmpty(musicBrainzReleaseGroupIdTag)) { var id = GetFirstMusicBrainzId(musicBrainzReleaseGroupIdTag, libraryOptions.UseCustomTagDelimiters, libraryOptions.GetCustomTagDelimiters(), libraryOptions.DelimiterWhitelist); @@ -400,8 +406,8 @@ namespace MediaBrowser.Providers.MediaInfo if (options.ReplaceAllMetadata || !audio.TryGetProviderId(MetadataProvider.MusicBrainzTrack, out _)) { - if ((track.AdditionalFields.TryGetValue("MUSICBRAINZ_RELEASETRACKID", out var trackMbId) - || track.AdditionalFields.TryGetValue("MusicBrainz Release Track Id", out trackMbId)) + if ((TryGetSanitizedAdditionalFields(track, "MUSICBRAINZ_RELEASETRACKID", out var trackMbId) + || TryGetSanitizedAdditionalFields(track, "MusicBrainz Release Track Id", out trackMbId)) && !string.IsNullOrEmpty(trackMbId)) { var id = GetFirstMusicBrainzId(trackMbId, libraryOptions.UseCustomTagDelimiters, libraryOptions.GetCustomTagDelimiters(), libraryOptions.DelimiterWhitelist); @@ -411,13 +417,13 @@ namespace MediaBrowser.Providers.MediaInfo if (options.ReplaceAllMetadata || !audio.TryGetProviderId(MetadataProvider.MusicBrainzRecording, out _)) { - if ((track.AdditionalFields.TryGetValue("MUSICBRAINZ_TRACKID", out var recordingMbId) - || track.AdditionalFields.TryGetValue("MusicBrainz Track Id", out recordingMbId)) + if ((TryGetSanitizedAdditionalFields(track, "MUSICBRAINZ_TRACKID", out var recordingMbId) + || TryGetSanitizedAdditionalFields(track, "MusicBrainz Track Id", out recordingMbId)) && !string.IsNullOrEmpty(recordingMbId)) { audio.TrySetProviderId(MetadataProvider.MusicBrainzRecording, recordingMbId); } - else if (track.AdditionalFields.TryGetValue("UFID", out var ufIdValue) && !string.IsNullOrEmpty(ufIdValue)) + else if (TryGetSanitizedAdditionalFields(track, "UFID", out var ufIdValue) && !string.IsNullOrEmpty(ufIdValue)) { // If tagged with MB Picard, the format is 'http://musicbrainz.org\0<recording MBID>' if (ufIdValue.Contains("musicbrainz.org", StringComparison.OrdinalIgnoreCase)) @@ -490,5 +496,28 @@ namespace MediaBrowser.Providers.MediaInfo return val; } + + private string? GetSanitizedStringTag(string? tag, string filePath) + { + if (string.IsNullOrEmpty(tag)) + { + return null; + } + + var result = tag.TruncateAtNull(); + if (result.Length != tag.Length) + { + _logger.LogWarning("Audio file {File} contains a null character in its tag, but this is not allowed by its tagging standard. All characters after the null char will be discarded. Please fix your file", filePath); + } + + return result; + } + + private bool TryGetSanitizedAdditionalFields(Track track, string field, out string? value) + { + var hasField = track.AdditionalFields.TryGetValue(field, out value); + value = GetSanitizedStringTag(value, track.Path); + return hasField; + } } } |
