示例#1
0
 public static void SetCustomField(this File tagFile, string key, string value)
 {
     if (tagFile.GetTag(TagTypes.Id3v2) is Tag id3V2Tag)
     {
         UserTextInformationFrame userTextInformationFrame = UserTextInformationFrame.Get(id3V2Tag, key, StringType.UTF8,
                                                                                          true,
                                                                                          true);
         if (string.IsNullOrEmpty(value))
         {
             id3V2Tag.RemoveFrame(userTextInformationFrame);
         }
         else
         {
             userTextInformationFrame.Text = value.Split(';');
         }
     }
     else if (tagFile.GetTag(TagTypes.Xiph) is XiphComment xiphComment)
     {
         xiphComment.SetField(key.ToUpperInvariant(), value);
     }
     else
     {
         throw new ArgumentException(nameof(tagFile));
     }
 }
示例#2
0
        private void WriteId3Tag(TagLib.Id3v2.Tag tag, string id, string value)
        {
            var frame = UserTextInformationFrame.Get(tag, id, true);

            if (value.IsNotNullOrWhiteSpace())
            {
                frame.Text = value.Split(';');
            }
            else
            {
                tag.RemoveFrame(frame);
            }
        }
示例#3
0
 /// <summary>
 /// Attempt to write a private frame
 /// </summary>
 private bool TryWriteUserFrame(string name, string value)
 {
     try
     {
         TagLib.Id3v2.Tag tag = (TagLib.Id3v2.Tag)mp3File.GetTag(TagTypes.Id3v2, true);
         var userFrame        = UserTextInformationFrame.Get(tag, name, true);
         userFrame.Text = value == null ? new string[] { string.Empty } : value.Split(';');
         return(true);
     }
     catch
     {
         return(false);
     }
 }
示例#4
0
 /// <summary>
 /// Attempt to read a user frame
 /// </summary>
 private bool TryReadUserFrame(string name, out string value)
 {
     try
     {
         TagLib.Id3v2.Tag tag = (TagLib.Id3v2.Tag)mp3File.GetTag(TagTypes.Id3v2);
         var userFrame        = UserTextInformationFrame.Get(tag, name, false);
         value = stringArrayToString(userFrame.Text);
         return(true);
     }
     catch
     {
         value = string.Empty;
         return(false);
     }
 }
示例#5
0
        public static string GetCustomField(this File tagFile, string key)
        {
            if (tagFile.GetTag(TagTypes.Id3v2) is Tag id3V2Tag)
            {
                UserTextInformationFrame userTextInformationFrame = UserTextInformationFrame.Get(id3V2Tag, key, StringType.UTF8,
                                                                                                 false,
                                                                                                 true);

                return(userTextInformationFrame != null?string.Join(';', userTextInformationFrame.Text) : null);
            }

            if (tagFile.GetTag(TagTypes.Xiph) is XiphComment xiphComment)
            {
                return(xiphComment.GetFirstField(key.ToUpperInvariant()));
            }

            throw new ArgumentException(nameof(tagFile));
        }
示例#6
0
        public void Read(string path)
        {
            Logger.Debug($"Starting tag read for {path}");

            IsValid = false;
            TagLib.File file = null;
            try
            {
                file = TagLib.File.Create(path);
                var tag = file.Tag;

                Title        = tag.Title ?? tag.TitleSort;
                Performers   = tag.Performers ?? tag.PerformersSort;
                AlbumArtists = tag.AlbumArtists ?? tag.AlbumArtistsSort;
                Track        = tag.Track;
                TrackCount   = tag.TrackCount;
                Album        = tag.Album ?? tag.AlbumSort;
                Disc         = tag.Disc;
                DiscCount    = tag.DiscCount;
                Year         = tag.Year;
                Publisher    = tag.Publisher;
                Duration     = file.Properties.Duration;
                Genres       = tag.Genres;
                ImageSize    = tag.Pictures.FirstOrDefault()?.Data.Count ?? 0;
                MusicBrainzReleaseCountry  = tag.MusicBrainzReleaseCountry;
                MusicBrainzReleaseStatus   = tag.MusicBrainzReleaseStatus;
                MusicBrainzReleaseType     = tag.MusicBrainzReleaseType;
                MusicBrainzReleaseId       = tag.MusicBrainzReleaseId;
                MusicBrainzArtistId        = tag.MusicBrainzArtistId;
                MusicBrainzReleaseArtistId = tag.MusicBrainzReleaseArtistId;
                MusicBrainzReleaseGroupId  = tag.MusicBrainzReleaseGroupId;
                MusicBrainzTrackId         = tag.MusicBrainzTrackId;

                DateTime tempDate;

                // Do the ones that aren't handled by the generic taglib implementation
                if (file.TagTypesOnDisk.HasFlag(TagTypes.Id3v2))
                {
                    var id3tag = (TagLib.Id3v2.Tag)file.GetTag(TagTypes.Id3v2);
                    Media = id3tag.GetTextAsString("TMED");
                    Date  = ReadId3Date(id3tag, "TDRC");
                    OriginalReleaseDate       = ReadId3Date(id3tag, "TDOR");
                    MusicBrainzAlbumComment   = UserTextInformationFrame.Get(id3tag, "MusicBrainz Album Comment", false)?.Text.ExclusiveOrDefault();
                    MusicBrainzReleaseTrackId = UserTextInformationFrame.Get(id3tag, "MusicBrainz Release Track Id", false)?.Text.ExclusiveOrDefault();
                }
                else if (file.TagTypesOnDisk.HasFlag(TagTypes.Xiph))
                {
                    // while publisher is handled by taglib, it seems to be mapped to 'ORGANIZATION' and not 'LABEL' like Picard is
                    // https://picard.musicbrainz.org/docs/mappings/
                    var flactag = (TagLib.Ogg.XiphComment)file.GetTag(TagLib.TagTypes.Xiph);
                    Media = flactag.GetField("MEDIA").ExclusiveOrDefault();
                    Date  = DateTime.TryParse(flactag.GetField("DATE").ExclusiveOrDefault(), out tempDate) ? tempDate : default(DateTime?);
                    OriginalReleaseDate       = DateTime.TryParse(flactag.GetField("ORIGINALDATE").ExclusiveOrDefault(), out tempDate) ? tempDate : default(DateTime?);
                    Publisher                 = flactag.GetField("LABEL").ExclusiveOrDefault();
                    MusicBrainzAlbumComment   = flactag.GetField("MUSICBRAINZ_ALBUMCOMMENT").ExclusiveOrDefault();
                    MusicBrainzReleaseTrackId = flactag.GetField("MUSICBRAINZ_RELEASETRACKID").ExclusiveOrDefault();

                    // If we haven't managed to read status/type, try the alternate mapping
                    if (MusicBrainzReleaseStatus.IsNullOrWhiteSpace())
                    {
                        MusicBrainzReleaseStatus = flactag.GetField("RELEASESTATUS").ExclusiveOrDefault();
                    }

                    if (MusicBrainzReleaseType.IsNullOrWhiteSpace())
                    {
                        MusicBrainzReleaseType = flactag.GetField("RELEASETYPE").ExclusiveOrDefault();
                    }
                }
                else if (file.TagTypesOnDisk.HasFlag(TagTypes.Ape))
                {
                    var apetag = (TagLib.Ape.Tag)file.GetTag(TagTypes.Ape);
                    Media = apetag.GetItem("Media")?.ToString();
                    Date  = DateTime.TryParse(apetag.GetItem("Year")?.ToString(), out tempDate) ? tempDate : default(DateTime?);
                    OriginalReleaseDate       = DateTime.TryParse(apetag.GetItem("Original Date")?.ToString(), out tempDate) ? tempDate : default(DateTime?);
                    Publisher                 = apetag.GetItem("Label")?.ToString();
                    MusicBrainzAlbumComment   = apetag.GetItem("MUSICBRAINZ_ALBUMCOMMENT")?.ToString();
                    MusicBrainzReleaseTrackId = apetag.GetItem("MUSICBRAINZ_RELEASETRACKID")?.ToString();
                }
                else if (file.TagTypesOnDisk.HasFlag(TagTypes.Asf))
                {
                    var asftag = (TagLib.Asf.Tag)file.GetTag(TagTypes.Asf);
                    Media = asftag.GetDescriptorString("WM/Media");
                    Date  = DateTime.TryParse(asftag.GetDescriptorString("WM/Year"), out tempDate) ? tempDate : default(DateTime?);
                    OriginalReleaseDate       = DateTime.TryParse(asftag.GetDescriptorString("WM/OriginalReleaseTime"), out tempDate) ? tempDate : default(DateTime?);
                    Publisher                 = asftag.GetDescriptorString("WM/Publisher");
                    MusicBrainzAlbumComment   = asftag.GetDescriptorString("MusicBrainz/Album Comment");
                    MusicBrainzReleaseTrackId = asftag.GetDescriptorString("MusicBrainz/Release Track Id");
                }
                else if (file.TagTypesOnDisk.HasFlag(TagTypes.Apple))
                {
                    var appletag = (TagLib.Mpeg4.AppleTag)file.GetTag(TagTypes.Apple);
                    Media = appletag.GetDashBox("com.apple.iTunes", "MEDIA");
                    Date  = DateTime.TryParse(appletag.DataBoxes(FixAppleId("day")).FirstOrDefault()?.Text, out tempDate) ? tempDate : default(DateTime?);
                    OriginalReleaseDate       = DateTime.TryParse(appletag.GetDashBox("com.apple.iTunes", "Original Date"), out tempDate) ? tempDate : default(DateTime?);
                    MusicBrainzAlbumComment   = appletag.GetDashBox("com.apple.iTunes", "MusicBrainz Album Comment");
                    MusicBrainzReleaseTrackId = appletag.GetDashBox("com.apple.iTunes", "MusicBrainz Release Track Id");
                }

                OriginalYear = OriginalReleaseDate.HasValue ? (uint)OriginalReleaseDate?.Year : 0;

                foreach (ICodec codec in file.Properties.Codecs)
                {
                    IAudioCodec acodec = codec as IAudioCodec;

                    if (acodec != null && (acodec.MediaTypes & MediaTypes.Audio) != MediaTypes.None)
                    {
                        int bitrate = acodec.AudioBitrate;
                        if (bitrate == 0)
                        {
                            // Taglib can't read bitrate for Opus.
                            bitrate = EstimateBitrate(file, path);
                        }

                        Logger.Debug("Audio Properties: " + acodec.Description + ", Bitrate: " + bitrate + ", Sample Size: " +
                                     file.Properties.BitsPerSample + ", SampleRate: " + acodec.AudioSampleRate + ", Channels: " + acodec.AudioChannels);

                        Quality = QualityParser.ParseQuality(file.Name, acodec.Description, bitrate, file.Properties.BitsPerSample);
                        Logger.Debug($"Quality parsed: {Quality}, Source: {Quality.QualityDetectionSource}");

                        MediaInfo = new MediaInfoModel
                        {
                            AudioFormat     = acodec.Description,
                            AudioBitrate    = bitrate,
                            AudioChannels   = acodec.AudioChannels,
                            AudioBits       = file.Properties.BitsPerSample,
                            AudioSampleRate = acodec.AudioSampleRate
                        };
                    }
                }

                IsValid = true;
            }
            catch (Exception ex)
            {
                if (ex is CorruptFileException)
                {
                    Logger.Warn(ex, $"Tag reading failed for {path}.  File is corrupt");
                }
                else
                {
                    // Log as error so it goes to sentry with correct fingerprint
                    Logger.Error(ex, "Tag reading failed for {0}", path);
                }
            }
            finally
            {
                file?.Dispose();
            }

            // make sure these are initialized to avoid errors later on
            if (Quality == null)
            {
                Quality = QualityParser.ParseQuality(path, null, EstimateBitrate(file, path));
                Logger.Debug($"Unable to parse qulity from tag, Quality parsed from file path: {Quality}, Source: {Quality.QualityDetectionSource}");
            }

            MediaInfo = MediaInfo ?? new MediaInfoModel();
        }