예제 #1
0
 public static void Write(TagLibMetaDataSource source, MetaDataItem metaDataItem, File file)
 {
     if (file.TagTypes.HasFlag(TagTypes.Id3v2))
     {
         var tag    = GetTag <global::TagLib.Id3v2.Tag>(file, TagTypes.Id3v2);
         var frames = tag.GetFrames <global::TagLib.Id3v2.PopularimeterFrame>();
         if (frames != null && frames.Any())
         {
             foreach (var frame in frames)
             {
                 WritePopularimeterFrame(source, metaDataItem, file, frame);
             }
         }
         else
         {
             var frame = new global::TagLib.Id3v2.PopularimeterFrame(string.Empty);
             WritePopularimeterFrame(source, metaDataItem, file, frame);
             tag.AddFrame(frame);
         }
     }
     else
     {
         WriteCustomTag(metaDataItem.Name, metaDataItem.Value, file);
     }
 }
예제 #2
0
 public static void Read(TagLibMetaDataSource source, IList <MetaDataItem> metaData, File file)
 {
     if (file.TagTypes.HasFlag(TagTypes.Id3v2))
     {
         var tag = GetTag <global::TagLib.Id3v2.Tag>(file, TagTypes.Id3v2);
         if (tag == null)
         {
             return;
         }
         foreach (var frame in tag.GetFrames <global::TagLib.Id3v2.PopularimeterFrame>())
         {
             ReadPopularimeterFrame(source, metaData, file, frame);
         }
     }
     else
     {
         var rating = ReadCustomTag(CommonMetaData.Rating, file);
         if (!string.IsNullOrEmpty(rating))
         {
             source.AddTag(metaData, CommonMetaData.Rating, rating);
         }
         var playCount = ReadCustomTag(CommonMetaData.PlayCount, file);
         if (!string.IsNullOrEmpty(playCount))
         {
             source.AddTag(metaData, CommonMetaData.Rating, playCount);
         }
     }
 }
예제 #3
0
        public static async Task <bool> Read(TagLibMetaDataSource source, IList <MetaDataItem> metaDatas, File file)
        {
            var embedded = source.EmbeddedImages.Value;
            var loose    = source.LooseImages.Value;

            if (embedded && loose)
            {
                switch (MetaDataBehaviourConfiguration.GetImagesPreference(source.ImagesPreference.Value))
                {
                default:
                case ImagePreference.Embedded:
                    return(await ReadEmbedded(source, metaDatas, file).ConfigureAwait(false) || await ReadLoose(source, metaDatas, file).ConfigureAwait(false));

                case ImagePreference.Loose:
                    return(await ReadLoose(source, metaDatas, file).ConfigureAwait(false) || await ReadEmbedded(source, metaDatas, file).ConfigureAwait(false));
                }
            }
            else if (embedded)
            {
                return(await ReadEmbedded(source, metaDatas, file).ConfigureAwait(false));
            }
            else if (loose)
            {
                return(await ReadLoose(source, metaDatas, file).ConfigureAwait(false));
            }
            return(false);
        }
예제 #4
0
        public override IMetaDataSource Create()
        {
            var source = new TagLibMetaDataSource();

            source.InitializeComponent(this.Core);
            return(source);
        }
예제 #5
0
 public static void Write(TagLibMetaDataSource source, MetaDataItem metaDataItem, File file)
 {
     if (file.TagTypes.HasFlag(TagTypes.Id3v2) && (new[] { CommonStatistics.Rating, CommonStatistics.PlayCount }).Contains(metaDataItem.Name, StringComparer.OrdinalIgnoreCase))
     {
         var tag    = TagManager.GetTag <global::TagLib.Id3v2.Tag>(file, TagTypes.Id3v2);
         var frames = tag.GetFrames <global::TagLib.Id3v2.PopularimeterFrame>();
         if (frames != null && frames.Any())
         {
             foreach (var frame in frames)
             {
                 WritePopularimeterFrame(frame, metaDataItem);
             }
         }
         else
         {
             var frame = new global::TagLib.Id3v2.PopularimeterFrame(string.Empty);
             WritePopularimeterFrame(frame, metaDataItem);
             tag.AddFrame(frame);
         }
     }
     else if (string.Equals(metaDataItem.Name, CommonStatistics.Rating, StringComparison.OrdinalIgnoreCase))
     {
         TagManager.WriteCustomTag(metaDataItem.Name, Convert.ToString(GetRatingMask(metaDataItem.Value)), file);
     }
     else
     {
         TagManager.WriteCustomTag(metaDataItem.Name, metaDataItem.Value, file);
     }
 }
예제 #6
0
        public static async Task Write(TagLibMetaDataSource source, MetaDataItem metaDataItem, File file)
        {
            var embedded = source.EmbeddedImages.Value;
            var loose    = source.LooseImages.Value;

            if (embedded && loose)
            {
                switch (MetaDataBehaviourConfiguration.GetImagesPreference(source.ImagesPreference.Value))
                {
                default:
                case ImagePreference.Embedded:
                    await WriteEmbedded(source, metaDataItem, file).ConfigureAwait(false);

                    break;

                case ImagePreference.Loose:
                    WriteLoose(source, metaDataItem, file);
                    break;
                }
            }
            else if (embedded)
            {
                await WriteEmbedded(source, metaDataItem, file).ConfigureAwait(false);
            }
            else if (loose)
            {
                WriteLoose(source, metaDataItem, file);
            }
        }
예제 #7
0
        public static void Write(TagLibMetaDataSource source, MetaDataItem metaDataItem, File file)
        {
            var tag   = file.Tag;
            var value = default(double);

            if (string.IsNullOrEmpty(metaDataItem.Value))
            {
                value = double.NaN;
            }
            else if (!double.TryParse(metaDataItem.Value, out value))
            {
                value = double.NaN;
            }
            if (string.Equals(metaDataItem.Name, CommonMetaData.ReplayGainAlbumGain, StringComparison.OrdinalIgnoreCase))
            {
                tag.ReplayGainAlbumGain = value;
            }
            else if (string.Equals(metaDataItem.Name, CommonMetaData.ReplayGainAlbumPeak, StringComparison.OrdinalIgnoreCase))
            {
                tag.ReplayGainAlbumPeak = value;
            }
            else if (string.Equals(metaDataItem.Name, CommonMetaData.ReplayGainTrackGain, StringComparison.OrdinalIgnoreCase))
            {
                tag.ReplayGainTrackGain = value;
            }
            else if (string.Equals(metaDataItem.Name, CommonMetaData.ReplayGainTrackPeak, StringComparison.OrdinalIgnoreCase))
            {
                tag.ReplayGainTrackPeak = value;
            }
        }
예제 #8
0
        public static void Write(TagLibMetaDataSource source, MetaDataItem metaDataItem, File file)
        {
            if (string.Equals(metaDataItem.Name, CommonMetaData.IsCompilation, StringComparison.OrdinalIgnoreCase))
            {
                var isCompilation = string.Equals(metaDataItem.Value, bool.TrueString, StringComparison.OrdinalIgnoreCase);

                if (TagManager.HasTag(file, TagTypes.Id3v2))
                {
                    var tag = TagManager.GetTag <global::TagLib.Id3v2.Tag>(file, TagTypes.Id3v2);
                    if (tag != null)
                    {
                        tag.IsCompilation = isCompilation;
                    }
                }
                else if (TagManager.HasTag(file, TagTypes.Apple))
                {
                    var tag = TagManager.GetTag <global::TagLib.Mpeg4.AppleTag>(file, TagTypes.Apple);
                    if (tag != null)
                    {
                        tag.IsCompilation = isCompilation;
                    }
                }
                else if (TagManager.HasTag(file, TagTypes.Xiph))
                {
                    var tag = TagManager.GetTag <global::TagLib.Ogg.XiphComment>(file, TagTypes.Xiph);
                    if (tag != null)
                    {
                        tag.IsCompilation = isCompilation;
                    }
                }

                if (source.MusicBrainz.Value)
                {
                    if (isCompilation)
                    {
                        file.Tag.MusicBrainzReleaseType = MusicBrainzReleaseType.Compilation;
                    }
                    else if (string.Equals(file.Tag.MusicBrainzReleaseType, MusicBrainzReleaseType.Compilation, StringComparison.OrdinalIgnoreCase))
                    {
                        //TODO: MusicBrainzReleaseType could be anything...
                    }
                }
            }
        }
예제 #9
0
        public static void Read(TagLibMetaDataSource source, IList <MetaDataItem> metaData, File file)
        {
            var isCompilation = default(bool);

            if (TagManager.HasTag(file, TagTypes.Id3v2))
            {
                var tag = TagManager.GetTag <global::TagLib.Id3v2.Tag>(file, TagTypes.Id3v2);
                if (tag != null)
                {
                    isCompilation = tag.IsCompilation;
                }
            }
            else if (TagManager.HasTag(file, TagTypes.Apple))
            {
                var tag = TagManager.GetTag <global::TagLib.Mpeg4.AppleTag>(file, TagTypes.Apple);
                if (tag != null)
                {
                    isCompilation = tag.IsCompilation;
                }
            }
            else if (TagManager.HasTag(file, TagTypes.Xiph))
            {
                var tag = TagManager.GetTag <global::TagLib.Ogg.XiphComment>(file, TagTypes.Xiph);
                if (tag != null)
                {
                    isCompilation = tag.IsCompilation;
                }
            }

            //Check MB release type, it's innocuous so don't bother respecting READ_MUSICBRAINZ_TAGS.
            if (string.Equals(file.Tag.MusicBrainzReleaseType, MusicBrainzReleaseType.Compilation, StringComparison.OrdinalIgnoreCase))
            {
                isCompilation = true;
            }

            if (isCompilation)
            {
                source.AddTag(metaData, CommonMetaData.IsCompilation, bool.TrueString);
                //TODO: CustomMetaData.VariousArtists should go away but scripts use it, let's keep it updated for now.
                source.AddTag(metaData, CustomMetaData.VariousArtists, bool.TrueString);
            }
        }
예제 #10
0
        private static void WriteLoose(TagLibMetaDataSource source, MetaDataItem metaDataItem, File file)
        {
            var fileName = default(string);

            if (HasImage(metaDataItem.Name, file, out fileName))
            {
                if (!string.IsNullOrEmpty(metaDataItem.Value))
                {
                    ReplaceImage(metaDataItem, fileName);
                }
                else
                {
                    RemoveImage(metaDataItem, fileName);
                }
            }
            else if (!string.IsNullOrEmpty(metaDataItem.Value))
            {
                AddImage(metaDataItem, file);
            }
        }
예제 #11
0
        public static void Read(TagLibMetaDataSource source, IList <MetaDataItem> metaDatas, File file)
        {
            try
            {
                if (file.InvariantStartPosition > TagLibMetaDataSource.MAX_TAG_SIZE)
                {
                    Logger.Write(typeof(ImageManager), LogLevel.Warn, "Not importing documents from file \"{0}\" due to size: {1} > {2}", file.Name, file.InvariantStartPosition, TagLibMetaDataSource.MAX_TAG_SIZE);
                    return;
                }

                var pictures = file.Tag.Pictures;
                foreach (var picture in pictures)
                {
                    if (string.IsNullOrEmpty(picture.Description))
                    {
                        //We need the desciption for the meta data name.
                        continue;
                    }
                    try
                    {
                        if (string.Equals(picture.MimeType, MIME_TYPE_JSON, StringComparison.OrdinalIgnoreCase))
                        {
                            var name  = string.Concat(PREFIX, ":", picture.Description);
                            var value = string.Concat(MIME_TYPE_JSON, ":", ReadJsonDocument(picture.Data.Data));
                            metaDatas.Add(new MetaDataItem(name, MetaDataItemType.Document)
                            {
                                Value = value
                            });
                        }
                    }
                    catch (Exception e)
                    {
                        Logger.Write(typeof(DocumentManager), LogLevel.Warn, "Failed to read document: {0} => {1} => {2}", file.Name, picture.Description, e.Message);
                    }
                }
            }
            catch (Exception e)
            {
                Logger.Write(typeof(DocumentManager), LogLevel.Warn, "Failed to read documents: {0} => {1}", file.Name, e.Message);
            }
        }
예제 #12
0
        public static void Read(TagLibMetaDataSource source, IList <MetaDataItem> metaData, File file)
        {
            var tag = file.Tag;

            if (tag.ReplayGainAlbumPeak != 0 && !double.IsNaN(tag.ReplayGainAlbumPeak) && !double.IsInfinity(tag.ReplayGainAlbumPeak))
            {
                source.AddTag(metaData, CommonMetaData.ReplayGainAlbumPeak, tag.ReplayGainAlbumPeak.ToString());
            }
            if (tag.ReplayGainAlbumGain != 0 && !double.IsNaN(tag.ReplayGainAlbumGain) && !double.IsInfinity(tag.ReplayGainAlbumGain))
            {
                source.AddTag(metaData, CommonMetaData.ReplayGainAlbumGain, tag.ReplayGainAlbumGain.ToString());
            }
            if (tag.ReplayGainTrackPeak != 0 && !double.IsNaN(tag.ReplayGainTrackPeak) && !double.IsInfinity(tag.ReplayGainTrackPeak))
            {
                source.AddTag(metaData, CommonMetaData.ReplayGainTrackPeak, tag.ReplayGainTrackPeak.ToString());
            }
            if (tag.ReplayGainTrackGain != 0 && !double.IsNaN(tag.ReplayGainTrackGain) && !double.IsInfinity(tag.ReplayGainTrackGain))
            {
                source.AddTag(metaData, CommonMetaData.ReplayGainTrackGain, tag.ReplayGainTrackGain.ToString());
            }
        }
예제 #13
0
            private static void ReadPopularimeterFrame(TagLibMetaDataSource source, IList <MetaDataItem> metaData, File file, global::TagLib.Id3v2.PopularimeterFrame frame)
            {
                const byte RATING_1 = 1;
                const byte RATING_2 = 64;
                const byte RATING_3 = 128;
                const byte RATING_4 = 196;
                const byte RATING_5 = 255;

                if (frame.Rating != 0)
                {
                    var rating = 0;
                    switch (frame.Rating)
                    {
                    case RATING_1:
                        rating = 1;
                        break;

                    case RATING_2:
                        rating = 2;
                        break;

                    case RATING_3:
                        rating = 3;
                        break;

                    case RATING_4:
                        rating = 4;
                        break;

                    case RATING_5:
                        rating = 5;
                        break;
                    }
                    source.AddTag(metaData, CommonMetaData.Rating, Convert.ToString(rating));
                }
                if (frame.PlayCount != 0)
                {
                    source.AddTag(metaData, CommonMetaData.PlayCount, Convert.ToString(frame.PlayCount));
                }
            }
예제 #14
0
            private static void WritePopularimeterFrame(TagLibMetaDataSource source, MetaDataItem metaDataItem, File file, global::TagLib.Id3v2.PopularimeterFrame frame)
            {
                const byte RATING_1 = 1;
                const byte RATING_2 = 64;
                const byte RATING_3 = 128;
                const byte RATING_4 = 196;
                const byte RATING_5 = 255;

                switch (metaDataItem.Name)
                {
                case CommonMetaData.Rating:
                    switch (Convert.ToByte(metaDataItem.Value))
                    {
                    case 1:
                        frame.Rating = RATING_1;
                        break;

                    case 2:
                        frame.Rating = RATING_2;
                        break;

                    case 3:
                        frame.Rating = RATING_3;
                        break;

                    case 4:
                        frame.Rating = RATING_4;
                        break;

                    case 5:
                        frame.Rating = RATING_5;
                        break;
                    }
                    break;

                case CommonMetaData.PlayCount:
                    frame.PlayCount = Convert.ToUInt64(metaDataItem.Value);
                    break;
                }
            }
예제 #15
0
        private static async Task WriteEmbedded(TagLibMetaDataSource source, MetaDataItem metaDataItem, File file)
        {
            var index    = default(int);
            var pictures = new List <IPicture>(file.Tag.Pictures);

            if (HasImage(metaDataItem.Name, file.Tag, pictures, out index))
            {
                if (!string.IsNullOrEmpty(metaDataItem.Value))
                {
                    await ReplaceImage(metaDataItem, file, pictures, index).ConfigureAwait(false);
                }
                else
                {
                    RemoveImage(metaDataItem, file.Tag, pictures, index);
                }
            }
            else if (!string.IsNullOrEmpty(metaDataItem.Value))
            {
                await AddImage(metaDataItem, file, pictures).ConfigureAwait(false);
            }
            file.Tag.Pictures = pictures.ToArray();
        }
예제 #16
0
        private static async Task <bool> ReadLoose(TagLibMetaDataSource source, IList <MetaDataItem> metaDatas, File file)
        {
            var types = ArtworkType.None;

            try
            {
                foreach (var type in new[] { ArtworkType.FrontCover, ArtworkType.BackCover })
                {
                    if (!ArtworkTypes.HasFlag(type))
                    {
                        continue;
                    }
                    var value = ArtworkProvider.Find(file.Name, type);
                    if (!string.IsNullOrEmpty(value) && global::System.IO.File.Exists(value))
                    {
                        if (source.CopyImages.Value)
                        {
                            value = await ImportImage(value, value, false).ConfigureAwait(false);
                        }
                        metaDatas.Add(new MetaDataItem()
                        {
                            Name  = Enum.GetName(typeof(ArtworkType), type),
                            Value = value,
                            Type  = MetaDataItemType.Image
                        });
                        if (ArtworkTypes.HasFlag(types |= type))
                        {
                            //We have everything we need.
                            return(true);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Logger.Write(typeof(ImageManager), LogLevel.Warn, "Failed to read pictures: {0} => {1}", file.Name, e.Message);
            }
            return(types != ArtworkType.None);
        }
예제 #17
0
        public static void Write(TagLibMetaDataSource source, MetaDataItem metaDataItem, File file)
        {
            var index    = default(int);
            var pictures = new List <IPicture>(file.Tag.Pictures);

            if (HasDocument(metaDataItem.Name, file.Tag, pictures, out index))
            {
                if (!string.IsNullOrEmpty(metaDataItem.Value))
                {
                    ReplaceDocument(metaDataItem, file, pictures, index);
                }
                else
                {
                    RemoveDocument(metaDataItem, file.Tag, pictures, index);
                }
            }
            else if (!string.IsNullOrEmpty(metaDataItem.Value))
            {
                AddDocument(metaDataItem, file, pictures);
            }
            file.Tag.Pictures = pictures.ToArray();
        }
예제 #18
0
        public static void Read(TagLibMetaDataSource source, IList <MetaDataItem> metaData, File file)
        {
            var result = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);

            //If it's an Id3v2 tag then try to read the popularimeter frame.
            //It can contain a rating and a play counter.
            if (file.TagTypes.HasFlag(TagTypes.Id3v2))
            {
                var tag = TagManager.GetTag <global::TagLib.Id3v2.Tag>(file, TagTypes.Id3v2);
                if (tag == null)
                {
                    return;
                }
                foreach (var frame in tag.GetFrames <global::TagLib.Id3v2.PopularimeterFrame>())
                {
                    ReadPopularimeterFrame(frame, result);
                }
            }
            //If we didn't find a popularimeter frame then attempt to read the rating from a custom tag.
            if (!result.ContainsKey(CommonStatistics.Rating))
            {
                var rating = TagManager.ReadCustomTag(CommonStatistics.Rating, file);
                if (!string.IsNullOrEmpty(rating))
                {
                    result.Add(CommonStatistics.Rating, Convert.ToString(GetRatingStars(rating)));
                }
                else
                {
                    result.Add(CommonStatistics.Rating, string.Empty);
                }
            }
            //If we didn't find a popularimeter frame then attempt to read the play count from a custom tag.
            if (!result.ContainsKey(CommonStatistics.PlayCount))
            {
                var playCount = TagManager.ReadCustomTag(CommonStatistics.PlayCount, file);
                if (!string.IsNullOrEmpty(playCount))
                {
                    result.Add(CommonStatistics.PlayCount, playCount);
                }
                else
                {
                    result.Add(CommonStatistics.PlayCount, "0");
                }
            }
            //Popularimeter frame does not support last played, attempt to read the play count from a custom tag.
            //if (!result.ContainsKey(CommonMetaData.LastPlayed))
            {
                var lastPlayed = TagManager.ReadCustomTag(CommonStatistics.LastPlayed, file);
                if (!string.IsNullOrEmpty(lastPlayed))
                {
                    result.Add(CommonStatistics.LastPlayed, lastPlayed);
                }
                else
                {
                    result.Add(CommonStatistics.LastPlayed, DateTimeHelper.NEVER);
                }
            }
            //Copy our informations back to the meta data collection.
            foreach (var key in result.Keys)
            {
                var value = result[key];
                source.AddTag(metaData, key, value);
            }
        }
예제 #19
0
        private static async Task <bool> ReadEmbedded(TagLibMetaDataSource source, IList <MetaDataItem> metaDatas, File file)
        {
            var types = ArtworkType.None;

            try
            {
                if (file.InvariantStartPosition > TagLibMetaDataSource.MAX_TAG_SIZE)
                {
                    Logger.Write(typeof(ImageManager), LogLevel.Warn, "Not importing images from file \"{0}\" due to size: {1} > {2}", file.Name, file.InvariantStartPosition, TagLibMetaDataSource.MAX_TAG_SIZE);
                    return(false);
                }

                var pictures = file.Tag.Pictures;
                if (pictures != null)
                {
                    foreach (var fallback in new[] { false, true })
                    {
                        foreach (var picture in pictures.OrderBy(picture => GetPicturePriority(picture)))
                        {
                            var type = GetArtworkType(picture.Type, fallback);
                            if (!ArtworkTypes.HasFlag(type) || types.HasFlag(type))
                            {
                                continue;
                            }

                            if (fallback)
                            {
                                if (!string.IsNullOrEmpty(picture.Description))
                                {
                                    //If we're in fallback (i.e the picture type isn't right) then ignore "pictures" with a description as it likely means the data has a specific purpose.
                                    Logger.Write(typeof(ImageManager), LogLevel.Warn, "Not importing image from file \"{0}\" due to description: {1}", file.Name, picture.Description);
                                    continue;
                                }
                                Logger.Write(typeof(ImageManager), LogLevel.Warn, "Importing image from file \"{0}\" with bad type: {1}.", file.Name, Enum.GetName(typeof(PictureType), picture.Type));
                                source.AddWarning(file.Name, string.Format("Image has bad type: {0}.", Enum.GetName(typeof(PictureType), picture.Type)));
                            }

                            if (string.IsNullOrEmpty(picture.MimeType))
                            {
                                Logger.Write(typeof(ImageManager), LogLevel.Warn, "Importing image from file \"{0}\" with empty mime type.", file.Name);
                                source.AddWarning(file.Name, "Image has empty mime type.");
                            }
                            else if (!MimeMapping.Instance.IsImage(picture.MimeType))
                            {
                                Logger.Write(typeof(ImageManager), LogLevel.Warn, "Importing image from file \"{0}\" with bad mime type: {1}", file.Name, picture.MimeType);
                                source.AddWarning(file.Name, string.Format("Image has bad mime type: {0}", picture.MimeType));
                            }

                            if (picture.Data.Count > source.MaxImageSize.Value * 1024000)
                            {
                                Logger.Write(typeof(ImageManager), LogLevel.Warn, "Not importing image from file \"{0}\" due to size: {1} > {2}", file.Name, picture.Data.Count, source.MaxImageSize.Value * 1024000);
                                source.AddWarning(file.Name, string.Format("Image was not imported due to size: {0} > {1}", picture.Data.Count, source.MaxImageSize.Value * 1024000));
                                continue;
                            }

                            metaDatas.Add(new MetaDataItem(Enum.GetName(typeof(ArtworkType), type), MetaDataItemType.Image)
                            {
                                Value = await ImportImage(file, picture, type, false).ConfigureAwait(false)
                            });
                            if (ArtworkTypes.HasFlag(types |= type))
                            {
                                //We have everything we need.
                                return(true);
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Logger.Write(typeof(ImageManager), LogLevel.Warn, "Failed to read pictures: {0} => {1}", file.Name, e.Message);
            }
            return(types != ArtworkType.None);
        }