From bcc5c2a4b4355a8ca13c750a9466e39625ea775a Mon Sep 17 00:00:00 2001 From: Mike DePouw Date: Tue, 26 Nov 2019 11:18:09 -0500 Subject: [PATCH 1/5] Fix Recording Date Serialzation --- src/Id3.Net/Frames/DateTime/RecordingDateFrame.cs | 2 +- test/Id3.Net.Tests/SerializationTests.cs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Id3.Net/Frames/DateTime/RecordingDateFrame.cs b/src/Id3.Net/Frames/DateTime/RecordingDateFrame.cs index 9c5d372..5621604 100644 --- a/src/Id3.Net/Frames/DateTime/RecordingDateFrame.cs +++ b/src/Id3.Net/Frames/DateTime/RecordingDateFrame.cs @@ -31,7 +31,7 @@ public RecordingDateFrame(DateTime value) : base(value) { } - protected override string DateTimeFormat => "ddMM"; + protected override string DateTimeFormat => "yyyy-MM-dd"; public static implicit operator RecordingDateFrame(DateTime value) => new RecordingDateFrame(value); } diff --git a/test/Id3.Net.Tests/SerializationTests.cs b/test/Id3.Net.Tests/SerializationTests.cs index 2cfea26..b4b2509 100644 --- a/test/Id3.Net.Tests/SerializationTests.cs +++ b/test/Id3.Net.Tests/SerializationTests.cs @@ -17,12 +17,11 @@ limitations under the License. */ #endregion +using Id3.Frames; +using Id3.Serialization; using System; using System.IO; using System.Runtime.Serialization.Formatters.Binary; -using Id3.Frames; -using Id3.Serialization; - using Xunit; namespace Id3.Net.Tests @@ -32,7 +31,8 @@ public sealed class SerializationTests [Fact] public void Serialize_deserialize_test() { - var tag = new Id3Tag { + var tag = new Id3Tag + { Title = "There Will Never Be Another Tonight", Album = "Waking up the neighbors", Track = new TrackFrame(9, 15), From 4a2ce61bba16a53e44a7480bde7a842738bf81cd Mon Sep 17 00:00:00 2001 From: Mike DePouw Date: Tue, 3 Dec 2019 16:06:58 -0500 Subject: [PATCH 2/5] Read/Write Popularimeter (Rating) --- .../SerializationExtensions.cs | 5 +- .../Surrogates/PopularimeterFrameSurrogate.cs | 45 ++++ .../Frames/Others/PopularimeterFrame.cs | 38 +++ src/Id3.Net/Id3/Id3Tag.cs | 13 +- src/Id3.Net/Id3/v2/Id3v23Handler.Frames.cs | 132 ++++++++-- src/Id3.Net/Id3/v2/Id3v23Handler.cs | 4 +- test/Id3.Net.Tests/PopularimeterTests.cs | 248 ++++++++++++++++++ test/Id3.Net.Tests/SerializationTests.cs | 4 +- 8 files changed, 460 insertions(+), 29 deletions(-) create mode 100644 src/Id3.Net.Serialization/Surrogates/PopularimeterFrameSurrogate.cs create mode 100644 src/Id3.Net/Frames/Others/PopularimeterFrame.cs create mode 100644 test/Id3.Net.Tests/PopularimeterTests.cs diff --git a/src/Id3.Net.Serialization/SerializationExtensions.cs b/src/Id3.Net.Serialization/SerializationExtensions.cs index 64cb9f3..ebfc0e4 100644 --- a/src/Id3.Net.Serialization/SerializationExtensions.cs +++ b/src/Id3.Net.Serialization/SerializationExtensions.cs @@ -17,10 +17,10 @@ limitations under the License. */ #endregion -using System; -using System.Runtime.Serialization; using Id3.Frames; using Id3.Serialization.Surrogates; +using System; +using System.Runtime.Serialization; namespace Id3.Serialization { @@ -101,6 +101,7 @@ public static TFormatter IncludeId3SerializationSupport(this TFormat selector.AddFrameSurrogate(); selector.AddFrameSurrogate(); selector.AddFrameSurrogate(); + selector.AddFrameSurrogate(); formatter.SurrogateSelector = selector; return formatter; diff --git a/src/Id3.Net.Serialization/Surrogates/PopularimeterFrameSurrogate.cs b/src/Id3.Net.Serialization/Surrogates/PopularimeterFrameSurrogate.cs new file mode 100644 index 0000000..efe32d1 --- /dev/null +++ b/src/Id3.Net.Serialization/Surrogates/PopularimeterFrameSurrogate.cs @@ -0,0 +1,45 @@ +#region --- License & Copyright Notice --- +/* +Copyright (c) 2005-2018 Jeevan James +All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +#endregion + +using Id3.Frames; +using System.Runtime.Serialization; + +namespace Id3.Serialization.Surrogates +{ + internal sealed class PopularimeterFrameSurrogate : Id3FrameSurrogate + { + protected override void GetFrameData(PopularimeterFrame frame, SerializationInfo info, StreamingContext context) + { + //info.AddValue("EncodingType", frame.EncodingType); + info.AddValue(nameof(PopularimeterFrame.RatingRaw), frame.RatingRaw); + info.AddValue(nameof(PopularimeterFrame.Email), "ID3.NET"); //todo revisit + info.AddValue(nameof(PopularimeterFrame.PlayCounter), frame.PlayCounter); + } + + protected override PopularimeterFrame SetObjectData(PopularimeterFrame frame, SerializationInfo info, StreamingContext context, + ISurrogateSelector selector) + { + //frame.EncodingType = (Id3TextEncoding)info.GetByte("EncodingType"); + frame.Rating = (Rating)info.GetByte(nameof(PopularimeterFrame.RatingRaw)); + frame.PlayCounter = info.GetInt32(nameof(PopularimeterFrame.PlayCounter)); + frame.Email = info.GetString(nameof(PopularimeterFrame.Email)); + return frame; + } + } +} \ No newline at end of file diff --git a/src/Id3.Net/Frames/Others/PopularimeterFrame.cs b/src/Id3.Net/Frames/Others/PopularimeterFrame.cs new file mode 100644 index 0000000..8fa22e4 --- /dev/null +++ b/src/Id3.Net/Frames/Others/PopularimeterFrame.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Id3.Frames +{ + public sealed class PopularimeterFrame : Id3Frame + { + public override bool IsAssigned => RatingRaw != 0; + + public byte RatingRaw => (byte)Rating; + + public Rating Rating { get; set; } + + public string Email { get; set; } + + public long PlayCounter { get; set; } + + public PopularimeterFrame() { } + + public PopularimeterFrame(Rating rating) + { + Rating = rating; + } + } + + public enum Rating + { + NotRated = 0, + OneStar = 1, + TwoStars = 64, + ThreeStars = 128, + FourStars = 196, + FiveStars = 255 + } +} diff --git a/src/Id3.Net/Id3/Id3Tag.cs b/src/Id3.Net/Id3/Id3Tag.cs index 7095ab4..6f2d2a6 100644 --- a/src/Id3.Net/Id3/Id3Tag.cs +++ b/src/Id3.Net/Id3/Id3Tag.cs @@ -17,6 +17,7 @@ limitations under the License. */ #endregion +using Id3.Frames; using System; using System.Collections; using System.Collections.Generic; @@ -25,7 +26,6 @@ limitations under the License. using System.Reflection; using System.Runtime.Serialization; using System.Threading.Tasks; -using Id3.Frames; namespace Id3 { @@ -419,6 +419,17 @@ public YearFrame Year get => GetSingleFrame(); set => SetSingleFrame(value); } + + public PopularimeterFrame Popularimeter + { + //todo revisit + //http://id3.org/id3v2.4.0-frames + //4.17. Popularimeter + //There may be more than one "POPM" frame in each tag, but only one with the same + //email address. + get => GetSingleFrame(); + set => SetSingleFrame(value); + } #endregion #region Frame internals diff --git a/src/Id3.Net/Id3/v2/Id3v23Handler.Frames.cs b/src/Id3.Net/Id3/v2/Id3v23Handler.Frames.cs index f3f6df3..f3c1925 100644 --- a/src/Id3.Net/Id3/v2/Id3v23Handler.Frames.cs +++ b/src/Id3.Net/Id3/v2/Id3v23Handler.Frames.cs @@ -17,10 +17,10 @@ limitations under the License. */ #endregion +using Id3.Frames; using System; using System.Collections.Generic; using System.Text; -using Id3.Frames; namespace Id3.v2 { @@ -35,13 +35,14 @@ private static TFrame DecodeText(byte[] data) string value; if (encodingByte == 0 || encodingByte == 1) { - frame.EncodingType = (Id3TextEncoding) encodingByte; + frame.EncodingType = (Id3TextEncoding)encodingByte; Encoding encoding = TextEncodingHelper.GetEncoding(frame.EncodingType); value = encoding.GetString(data, 1, data.Length - 1); if (value.Length > 0 && frame.EncodingType == Id3TextEncoding.Unicode && (value[0] == '\xFFFE' || value[0] == '\xFEFF')) value = value.Remove(0, 1); - } else + } + else { frame.EncodingType = Id3TextEncoding.Iso8859_1; Encoding encoding = TextEncodingHelper.GetEncoding(frame.EncodingType); @@ -56,12 +57,12 @@ private static TFrame DecodeText(byte[] data) private static byte[] EncodeText(Id3Frame id3Frame) where TFrame : TextFrameBase { - var frame = (TFrame) id3Frame; + var frame = (TFrame)id3Frame; Encoding encoding = TextEncodingHelper.GetEncoding(frame.EncodingType); byte[] preamble = encoding.GetPreamble(); byte[] textBytes = encoding.GetBytes(frame.TextValue); var data = new byte[1 + preamble.Length + textBytes.Length]; - data[0] = (byte) frame.EncodingType; + data[0] = (byte)frame.EncodingType; preamble.CopyTo(data, 1); textBytes.CopyTo(data, preamble.Length + 1); return data; @@ -70,33 +71,34 @@ private static byte[] EncodeText(Id3Frame id3Frame) private static TFrame DecodeUrlLink(byte[] data) where TFrame : UrlLinkFrame, new() { - var frame = new TFrame {Url = TextEncodingHelper.GetDefaultString(data, 0, data.Length)}; + var frame = new TFrame { Url = TextEncodingHelper.GetDefaultString(data, 0, data.Length) }; return frame; } private static byte[] EncodeUrlLink(Id3Frame id3Frame) where TFrame : UrlLinkFrame { - var frame = (TFrame) id3Frame; + var frame = (TFrame)id3Frame; return frame.Url != null ? TextEncodingHelper.GetDefaultEncoding().GetBytes(frame.Url) : new byte[0]; } private static Id3Frame DecodeComment(byte[] data) { - var frame = new CommentFrame {EncodingType = (Id3TextEncoding) data[0]}; + var frame = new CommentFrame { EncodingType = (Id3TextEncoding)data[0] }; string language = TextEncodingHelper.GetDefaultEncoding().GetString(data, 1, 3).ToLowerInvariant(); if (!Enum.IsDefined(typeof(Id3Language), language)) frame.Language = Id3Language.eng; else - frame.Language = (Id3Language) Enum.Parse(typeof(Id3Language), language, true); + frame.Language = (Id3Language)Enum.Parse(typeof(Id3Language), language, true); string[] splitStrings = TextEncodingHelper.GetSplitStrings(data, 4, data.Length - 4, frame.EncodingType); if (splitStrings.Length > 1) { frame.Description = splitStrings[0]; frame.Comment = splitStrings[1]; - } else if (splitStrings.Length == 1) + } + else if (splitStrings.Length == 1) frame.Comment = splitStrings[0]; return frame; @@ -104,7 +106,7 @@ private static Id3Frame DecodeComment(byte[] data) private static byte[] EncodeComment(Id3Frame id3Frame) { - var frame = (CommentFrame) id3Frame; + var frame = (CommentFrame)id3Frame; var bytes = new List { (byte) frame.EncodingType @@ -126,7 +128,7 @@ private static byte[] EncodeComment(Id3Frame id3Frame) private static Id3Frame DecodeCustomUrlLink(byte[] data) { - var frame = new CustomUrlLinkFrame {EncodingType = (Id3TextEncoding) data[0]}; + var frame = new CustomUrlLinkFrame { EncodingType = (Id3TextEncoding)data[0] }; byte[][] splitBytes = ByteArrayHelper.SplitBySequence(data, 1, data.Length - 1, TextEncodingHelper.GetSplitterBytes(frame.EncodingType)); @@ -136,7 +138,8 @@ private static Id3Frame DecodeCustomUrlLink(byte[] data) frame.Description = TextEncodingHelper.GetString(splitBytes[0], 0, splitBytes[0].Length, frame.EncodingType); url = TextEncodingHelper.GetDefaultString(splitBytes[1], 0, splitBytes[1].Length); - } else if (splitBytes.Length == 1) + } + else if (splitBytes.Length == 1) url = TextEncodingHelper.GetDefaultString(splitBytes[0], 0, splitBytes[0].Length); frame.Url = url; @@ -146,7 +149,7 @@ private static Id3Frame DecodeCustomUrlLink(byte[] data) private static byte[] EncodeCustomUrlLink(Id3Frame id3Frame) { - var frame = (CustomUrlLinkFrame) id3Frame; + var frame = (CustomUrlLinkFrame)id3Frame; var bytes = new List { (byte) frame.EncodingType @@ -165,20 +168,21 @@ private static byte[] EncodeCustomUrlLink(Id3Frame id3Frame) private static Id3Frame DecodeLyrics(byte[] data) { - var frame = new LyricsFrame {EncodingType = (Id3TextEncoding) data[0]}; + var frame = new LyricsFrame { EncodingType = (Id3TextEncoding)data[0] }; string language = TextEncodingHelper.GetDefaultEncoding().GetString(data, 1, 3).ToLowerInvariant(); if (!Enum.IsDefined(typeof(Id3Language), language)) frame.Language = Id3Language.eng; else - frame.Language = (Id3Language) Enum.Parse(typeof(Id3Language), language, true); + frame.Language = (Id3Language)Enum.Parse(typeof(Id3Language), language, true); string[] splitStrings = TextEncodingHelper.GetSplitStrings(data, 4, data.Length - 4, frame.EncodingType); if (splitStrings.Length > 1) { frame.Description = splitStrings[0]; frame.Lyrics = splitStrings[1]; - } else if (splitStrings.Length == 1) + } + else if (splitStrings.Length == 1) frame.Lyrics = splitStrings[0]; return frame; @@ -191,9 +195,9 @@ private static byte[] EncodeLyrics(Id3Frame id3Frame) private static Id3Frame DecodePicture(byte[] data) { - var frame = new PictureFrame {EncodingType = (Id3TextEncoding) data[0]}; + var frame = new PictureFrame { EncodingType = (Id3TextEncoding)data[0] }; - byte[] mimeType = ByteArrayHelper.GetBytesUptoSequence(data, 1, new byte[] {0x00}); + byte[] mimeType = ByteArrayHelper.GetBytesUptoSequence(data, 1, new byte[] { 0x00 }); if (mimeType == null) { frame.MimeType = "image/"; @@ -203,7 +207,7 @@ private static Id3Frame DecodePicture(byte[] data) frame.MimeType = TextEncodingHelper.GetDefaultString(mimeType, 0, mimeType.Length); int currentPos = mimeType.Length + 2; - frame.PictureType = (PictureType) data[currentPos]; + frame.PictureType = (PictureType)data[currentPos]; currentPos++; byte[] description = ByteArrayHelper.GetBytesUptoSequence(data, currentPos, @@ -221,7 +225,7 @@ private static Id3Frame DecodePicture(byte[] data) private static byte[] EncodePicture(Id3Frame id3Frame) { - var frame = (PictureFrame) id3Frame; + var frame = (PictureFrame)id3Frame; var bytes = new List { (byte) frame.EncodingType @@ -233,7 +237,7 @@ private static byte[] EncodePicture(Id3Frame id3Frame) : defaultEncoding.GetBytes("image/")); bytes.Add(0); - bytes.Add((byte) frame.PictureType); + bytes.Add((byte)frame.PictureType); Encoding descriptionEncoding = TextEncodingHelper.GetEncoding(frame.EncodingType); bytes.AddRange(descriptionEncoding.GetPreamble()); @@ -261,7 +265,7 @@ private static Id3Frame DecodePrivate(byte[] data) private static byte[] EncodePrivate(Id3Frame id3Frame) { - var frame = (PrivateFrame) id3Frame; + var frame = (PrivateFrame)id3Frame; var bytes = new List(); bytes.AddRange(TextEncodingHelper.GetEncoding(Id3TextEncoding.Iso8859_1).GetBytes(frame.OwnerId)); @@ -269,5 +273,87 @@ private static byte[] EncodePrivate(Id3Frame id3Frame) bytes.AddRange(frame.Data ?? new byte[0]); return bytes.ToArray(); } + + //todo shouldn't these methods be in their own class?? + private static Id3Frame DecodePopularimeter(byte[] data) + { + //todo review/revisit + //seems like there's no way to encode the type in this frame + //var frame = new PopularimeterFrame { EncodingType = (Id3TextEncoding)data[0] }; + + //going to hard code the encoding type until I know more + var frame = new PopularimeterFrame();// { EncodingType = Id3TextEncoding.Iso8859_1 }; + + //todo what's the "right" want to do this??? + //read until we read the delimiter byte, 0, right? + var startIndex = 1; //was 1 when using first byte for encoding type + startIndex = 0; + + //optional email + var emailBytes = ByteArrayHelper.GetBytesUptoSequence(data, startIndex, new byte[] { 0x00 }); + if (emailBytes.Length > 0) + frame.Email = TextEncodingHelper.GetDefaultEncoding() + .GetString(emailBytes); + + //rating index + var ratingIndex = startIndex + emailBytes.Length + 1; //+1 is for the field 'delimiter' + frame.Rating = (Rating)data[ratingIndex]; + + //optional player count + if (data.Length > (ratingIndex + 1)) + { + var bytesRemaining = data.Length - ratingIndex - 1; + if (bytesRemaining == 4) + frame.PlayCounter = BitConverter.ToInt32(data, ratingIndex + 1); + else if (bytesRemaining == 8) + frame.PlayCounter = BitConverter.ToInt64(data, ratingIndex + 1); + else + throw new Exception($"unknown number of bytes to process: {bytesRemaining}"); + } + + return frame; + } + + private static byte[] EncodePopularimeter(Id3Frame id3Frame) + { + var frame = (PopularimeterFrame)id3Frame; + + var bytes = new List(); + //{ + // (byte) frame.EncodingType + //}; + + //Encoding encoding = TextEncodingHelper.GetEncoding(frame.EncodingType) + // ?? throw new Exception($"Unknown encoding type: {frame.EncodingType}"); + var encoding = TextEncodingHelper.GetEncoding(Id3TextEncoding.Iso8859_1); + + if (!string.IsNullOrEmpty(frame.Email)) + bytes.AddRange(encoding.GetBytes(frame.Email)); + + //todo what is the point of preambles??? + //var debug = encoding.GetPreamble(); + //bytes.AddRange(encoding.GetPreamble()); + bytes.Add(0); + + bytes.Add(frame.RatingRaw); + + //advanced play counter + //When the counter reaches all one's, one byte is + //inserted in front of the counter thus making the counter eight bits + //bigger in the same away as the play counter("PCNT") + + //4.16. Play counter PCNT + // When the counter reaches all one's, one byte is inserted in front of the + //counter thus making the counter eight bits bigger. The counter must + //be at least 32 - bits long to begin with. + if(frame.PlayCounter <= int.MaxValue) + //todo is this the "standard" way to convert from int -> bytes in this project??? + bytes.AddRange(BitConverter.GetBytes((int)frame.PlayCounter)); + else + //todo is this the "standard" way to convert from long -> bytes in this project??? + bytes.AddRange(BitConverter.GetBytes(frame.PlayCounter)); + + return bytes.ToArray(); + } } } diff --git a/src/Id3.Net/Id3/v2/Id3v23Handler.cs b/src/Id3.Net/Id3/v2/Id3v23Handler.cs index 40ecc24..102e06b 100644 --- a/src/Id3.Net/Id3/v2/Id3v23Handler.cs +++ b/src/Id3.Net/Id3/v2/Id3v23Handler.cs @@ -17,11 +17,11 @@ limitations under the License. */ #endregion +using Id3.Frames; using System; using System.Collections.Generic; using System.IO; using System.Text; -using Id3.Frames; namespace Id3.v2 { @@ -229,7 +229,7 @@ protected override void BuildFrameHandlers(FrameHandlers mappings) mappings.Add("APIC", EncodePicture, DecodePicture); //mappings.Add("PCNT", null, null); //mappings.Add("TDLY", null, null); - //mappings.Add("POPM", null, null); + mappings.Add("POPM", EncodePopularimeter, DecodePopularimeter); //mappings.Add("POSS", null, null); mappings.Add("PRIV", EncodePrivate, DecodePrivate); mappings.Add("TPUB", EncodeText, DecodeText); diff --git a/test/Id3.Net.Tests/PopularimeterTests.cs b/test/Id3.Net.Tests/PopularimeterTests.cs new file mode 100644 index 0000000..bcf9ac6 --- /dev/null +++ b/test/Id3.Net.Tests/PopularimeterTests.cs @@ -0,0 +1,248 @@ +#region --- License & Copyright Notice --- +/* +Copyright (c) 2005-2018 Jeevan James +All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +#endregion + +using Id3.Frames; +using System; +using System.IO; +using Xunit; +using Xunit.Abstractions; + +namespace Id3.Net.Tests +{ + public sealed class PopularimeterTests : IDisposable + { + private readonly Mp3 mp3; + private readonly ITestOutputHelper output; + + public PopularimeterTests(ITestOutputHelper output) + { + var stream = new MemoryStream(); + mp3 = new Mp3(stream, Mp3Permissions.ReadWrite); + this.output = output; + } + + void IDisposable.Dispose() + { + mp3.Dispose(); + } + + [Fact] + public void RatingTest() + { + //arrange + var tag = new Id3Tag + { + Popularimeter = new PopularimeterFrame(Rating.ThreeStars) + //Album = new AlbumFrame("temp for debugging") + }; + + //act + mp3.WriteTag(tag, Id3Version.V23); + + //assert + var actualTag = mp3.GetTag(Id3TagFamily.Version2X); + Assert.Equal(Rating.ThreeStars, actualTag.Popularimeter.Rating); + } + + [Fact] + public void EmailTest() + { + //arrange + var tag = new Id3Tag + { + Popularimeter = new PopularimeterFrame(Rating.ThreeStars) + { + Email = "Hello World" + } + }; + + //act + mp3.WriteTag(tag, Id3Version.V23); + + //assert + var actualTag = mp3.GetTag(Id3TagFamily.Version2X); + Assert.Equal("Hello World", actualTag.Popularimeter.Email); + } + + [Fact] + public void PlayCounterTest() + { + //arrange + var tag = new Id3Tag + { + Popularimeter = new PopularimeterFrame(Rating.ThreeStars) + { + PlayCounter = 2325 + } + }; + + //act + mp3.WriteTag(tag, Id3Version.V23); + + //assert + var actualTag = mp3.GetTag(Id3TagFamily.Version2X); + Assert.Equal(2325, actualTag.Popularimeter.PlayCounter); + } + + [Fact] + public void FullPopularimeterTest() + { + //arrange + var tag = new Id3Tag + { + Popularimeter = new PopularimeterFrame(Rating.ThreeStars) + { + PlayCounter = 23223, + Email = "unit-testing@fakedomain.com", + Rating = Rating.TwoStars + } + }; + + //act + mp3.WriteTag(tag, Id3Version.V23); + + //assert + var actualTag = mp3.GetTag(Id3TagFamily.Version2X); + Assert.Equal(23223, actualTag.Popularimeter.PlayCounter); + Assert.Equal("unit-testing@fakedomain.com", actualTag.Popularimeter.Email); + Assert.Equal(Rating.TwoStars, actualTag.Popularimeter.Rating); + } + + [Fact] + public void OverIntMaxPlayCounterTest() + { + //arrange + var tag = new Id3Tag + { + Popularimeter = new PopularimeterFrame(Rating.ThreeStars) + { + PlayCounter = (long)int.MaxValue + 1 + } + }; + + //act + mp3.WriteTag(tag, Id3Version.V23); + + //assert + var actualTag = mp3.GetTag(Id3TagFamily.Version2X); + Assert.Equal((long)int.MaxValue + 1, actualTag.Popularimeter.PlayCounter); + } + + //todo temp integrtion test + [Fact] + public void TodoTempVerifyActualFile() + { + //arrange + var path = @"C:\_Temp\rating test\01~K.A.N. - Rating.mp3"; + var mp3 = new Mp3(path, Mp3Permissions.ReadWrite); + var tag = mp3.GetTag(Id3TagFamily.Version2X); + + //act + var email = tag.Popularimeter.Email; + var playCount = tag.Popularimeter.PlayCounter; + tag.Popularimeter.Rating = Rating.FiveStars; + mp3.WriteTag(tag, Id3Version.V23); + mp3.Dispose(); + + //assert + var mp3Actual = new Mp3(path, Mp3Permissions.Read); + var tagActual = mp3Actual.GetTag(Id3TagFamily.Version2X); + Assert.Equal(Rating.FiveStars, tagActual.Popularimeter.Rating); + Assert.Equal(playCount, tagActual.Popularimeter.PlayCounter); + Assert.Equal(email, tag.Popularimeter.Email); + } + + //[Fact] + //public void ReadABunchOfMp3sAndSeeIfItFails() + //{ + // //arrange + // var start = @"C:\Users\mdepouw\OneDrive\Music\DJ Freckles\DJ Freckles\DJ Freckles 2pac's GH"; + // start = @"C:\Users\mdepouw\OneDrive\Music\_me music attempt 2\DMX\_..And Then There Was X"; + // start = @"C:\Users\mdepouw\OneDrive\Music\_me music attempt 2\"; + + // string[] musicFiles = Directory.GetFiles(start, "*.mp3", SearchOption.AllDirectories); + // foreach (string musicFile in musicFiles) + // { + // try + // { + // //act + // using (var mp3 = new Mp3(musicFile, Mp3Permissions.Read)) + // { + // var tag = mp3.GetTag(Id3TagFamily.Version2X); + // if (tag == null) + // continue; + + // Func starRating = (rating) => + // { + // var map = new Dictionary() + // { + // { Rating.OneStar, "⭐" }, + // { Rating.TwoStars, "⭐⭐" }, + // { Rating.ThreeStars, "⭐⭐⭐" }, + // { Rating.FourStars, "⭐⭐⭐⭐" }, + // { Rating.FiveStars, "⭐⭐⭐⭐⭐" }, + // }; + // return map.TryGetValue(rating, out var stars) ? stars : "Not Rated"; + // }; + // //output.WriteLine($"Rating: {starRating(tag.Popularimeter.Rating)}"); + // } + // } + // catch (Exception ex) + // { + // output.WriteLine($"Error processing: {musicFile} - error: {ex.Message}"); + // } + // } + + // //assert + // Assert.True(true); + //} + ////todo temp integrtion test + //[Fact] + //public void TodoTempFreshStart() + //{ + // //arrange + // var path = @"C:\_Temp\rating test\01~K.A.N. - Rating - Copy.mp3"; + // var mp3 = new Mp3(path, Mp3Permissions.ReadWrite); + // var tag = mp3.GetTag(Id3TagFamily.Version2X); + + // //act + // tag.Popularimeter = new PopularimeterFrame(Rating.FiveStars); + // mp3.WriteTag(tag, Id3Version.V23); + + // //assert + // Assert.True(false); + //} + + //[Fact] + //public void TodoTempAfterFreshStart() + //{ + // //arrange + // var path = @"C:\_Temp\rating test\01~K.A.N. - Rating - Copy - Copy.mp3"; + // var mp3 = new Mp3(path, Mp3Permissions.ReadWrite); + // var tag = mp3.GetTag(Id3TagFamily.Version2X); + + // //act + // tag.Popularimeter.Rating = Rating.FiveStars; + // mp3.WriteTag(tag, Id3Version.V23); + + // //assert + // Assert.True(false); + //} + } +} diff --git a/test/Id3.Net.Tests/SerializationTests.cs b/test/Id3.Net.Tests/SerializationTests.cs index b4b2509..c97186a 100644 --- a/test/Id3.Net.Tests/SerializationTests.cs +++ b/test/Id3.Net.Tests/SerializationTests.cs @@ -39,7 +39,8 @@ public void Serialize_deserialize_test() Year = 1991, Genre = "Hard Rock", Publisher = "A&M", - RecordingDate = new DateTime(1991, 03, 01) + RecordingDate = new DateTime(1991, 03, 01), + Popularimeter = new PopularimeterFrame(Rating.FourStars) }; tag.Artists.Value.Add("Bryan Adams"); tag.Composers.Value.Add("Bryan Adams"); @@ -67,6 +68,7 @@ public void Serialize_deserialize_test() Assert.Equal(tag.Genre.Value, clonedTag.Genre.Value); Assert.Equal(tag.Publisher.Value, clonedTag.Publisher.Value); Assert.Equal(tag.RecordingDate.Value, clonedTag.RecordingDate.Value); + Assert.Equal(tag.Popularimeter.Rating, clonedTag.Popularimeter.Rating); Assert.Equal(tag.Artists.Value.Count, clonedTag.Artists.Value.Count); for (var i = 0; i < tag.Artists.Value.Count; i++) From 9471a020f74233fad297b7621bc012c95fcbc29a Mon Sep 17 00:00:00 2001 From: Mike DePouw Date: Tue, 3 Dec 2019 17:44:46 -0500 Subject: [PATCH 3/5] comment out temp integration test --- test/Id3.Net.Tests/PopularimeterTests.cs | 42 ++++++++++++------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/test/Id3.Net.Tests/PopularimeterTests.cs b/test/Id3.Net.Tests/PopularimeterTests.cs index bcf9ac6..d81de79 100644 --- a/test/Id3.Net.Tests/PopularimeterTests.cs +++ b/test/Id3.Net.Tests/PopularimeterTests.cs @@ -144,29 +144,29 @@ public void OverIntMaxPlayCounterTest() Assert.Equal((long)int.MaxValue + 1, actualTag.Popularimeter.PlayCounter); } - //todo temp integrtion test - [Fact] - public void TodoTempVerifyActualFile() - { - //arrange - var path = @"C:\_Temp\rating test\01~K.A.N. - Rating.mp3"; - var mp3 = new Mp3(path, Mp3Permissions.ReadWrite); - var tag = mp3.GetTag(Id3TagFamily.Version2X); + ////todo temp integrtion test + //[Fact] + //public void TodoTempVerifyActualFile() + //{ + // //arrange + // var path = @"C:\_Temp\rating test\01~K.A.N. - Rating.mp3"; + // var mp3 = new Mp3(path, Mp3Permissions.ReadWrite); + // var tag = mp3.GetTag(Id3TagFamily.Version2X); - //act - var email = tag.Popularimeter.Email; - var playCount = tag.Popularimeter.PlayCounter; - tag.Popularimeter.Rating = Rating.FiveStars; - mp3.WriteTag(tag, Id3Version.V23); - mp3.Dispose(); + // //act + // var email = tag.Popularimeter.Email; + // var playCount = tag.Popularimeter.PlayCounter; + // tag.Popularimeter.Rating = Rating.FiveStars; + // mp3.WriteTag(tag, Id3Version.V23); + // mp3.Dispose(); - //assert - var mp3Actual = new Mp3(path, Mp3Permissions.Read); - var tagActual = mp3Actual.GetTag(Id3TagFamily.Version2X); - Assert.Equal(Rating.FiveStars, tagActual.Popularimeter.Rating); - Assert.Equal(playCount, tagActual.Popularimeter.PlayCounter); - Assert.Equal(email, tag.Popularimeter.Email); - } + // //assert + // var mp3Actual = new Mp3(path, Mp3Permissions.Read); + // var tagActual = mp3Actual.GetTag(Id3TagFamily.Version2X); + // Assert.Equal(Rating.FiveStars, tagActual.Popularimeter.Rating); + // Assert.Equal(playCount, tagActual.Popularimeter.PlayCounter); + // Assert.Equal(email, tag.Popularimeter.Email); + //} //[Fact] //public void ReadABunchOfMp3sAndSeeIfItFails() From c0f21b742520fda7b94d795efcc47ead05e5c598 Mon Sep 17 00:00:00 2001 From: Mike DePouw Date: Tue, 3 Dec 2019 17:49:17 -0500 Subject: [PATCH 4/5] remove integration tests --- test/Id3.Net.Tests/PopularimeterTests.cs | 101 ----------------------- 1 file changed, 101 deletions(-) diff --git a/test/Id3.Net.Tests/PopularimeterTests.cs b/test/Id3.Net.Tests/PopularimeterTests.cs index d81de79..a0e999a 100644 --- a/test/Id3.Net.Tests/PopularimeterTests.cs +++ b/test/Id3.Net.Tests/PopularimeterTests.cs @@ -143,106 +143,5 @@ public void OverIntMaxPlayCounterTest() var actualTag = mp3.GetTag(Id3TagFamily.Version2X); Assert.Equal((long)int.MaxValue + 1, actualTag.Popularimeter.PlayCounter); } - - ////todo temp integrtion test - //[Fact] - //public void TodoTempVerifyActualFile() - //{ - // //arrange - // var path = @"C:\_Temp\rating test\01~K.A.N. - Rating.mp3"; - // var mp3 = new Mp3(path, Mp3Permissions.ReadWrite); - // var tag = mp3.GetTag(Id3TagFamily.Version2X); - - // //act - // var email = tag.Popularimeter.Email; - // var playCount = tag.Popularimeter.PlayCounter; - // tag.Popularimeter.Rating = Rating.FiveStars; - // mp3.WriteTag(tag, Id3Version.V23); - // mp3.Dispose(); - - // //assert - // var mp3Actual = new Mp3(path, Mp3Permissions.Read); - // var tagActual = mp3Actual.GetTag(Id3TagFamily.Version2X); - // Assert.Equal(Rating.FiveStars, tagActual.Popularimeter.Rating); - // Assert.Equal(playCount, tagActual.Popularimeter.PlayCounter); - // Assert.Equal(email, tag.Popularimeter.Email); - //} - - //[Fact] - //public void ReadABunchOfMp3sAndSeeIfItFails() - //{ - // //arrange - // var start = @"C:\Users\mdepouw\OneDrive\Music\DJ Freckles\DJ Freckles\DJ Freckles 2pac's GH"; - // start = @"C:\Users\mdepouw\OneDrive\Music\_me music attempt 2\DMX\_..And Then There Was X"; - // start = @"C:\Users\mdepouw\OneDrive\Music\_me music attempt 2\"; - - // string[] musicFiles = Directory.GetFiles(start, "*.mp3", SearchOption.AllDirectories); - // foreach (string musicFile in musicFiles) - // { - // try - // { - // //act - // using (var mp3 = new Mp3(musicFile, Mp3Permissions.Read)) - // { - // var tag = mp3.GetTag(Id3TagFamily.Version2X); - // if (tag == null) - // continue; - - // Func starRating = (rating) => - // { - // var map = new Dictionary() - // { - // { Rating.OneStar, "⭐" }, - // { Rating.TwoStars, "⭐⭐" }, - // { Rating.ThreeStars, "⭐⭐⭐" }, - // { Rating.FourStars, "⭐⭐⭐⭐" }, - // { Rating.FiveStars, "⭐⭐⭐⭐⭐" }, - // }; - // return map.TryGetValue(rating, out var stars) ? stars : "Not Rated"; - // }; - // //output.WriteLine($"Rating: {starRating(tag.Popularimeter.Rating)}"); - // } - // } - // catch (Exception ex) - // { - // output.WriteLine($"Error processing: {musicFile} - error: {ex.Message}"); - // } - // } - - // //assert - // Assert.True(true); - //} - ////todo temp integrtion test - //[Fact] - //public void TodoTempFreshStart() - //{ - // //arrange - // var path = @"C:\_Temp\rating test\01~K.A.N. - Rating - Copy.mp3"; - // var mp3 = new Mp3(path, Mp3Permissions.ReadWrite); - // var tag = mp3.GetTag(Id3TagFamily.Version2X); - - // //act - // tag.Popularimeter = new PopularimeterFrame(Rating.FiveStars); - // mp3.WriteTag(tag, Id3Version.V23); - - // //assert - // Assert.True(false); - //} - - //[Fact] - //public void TodoTempAfterFreshStart() - //{ - // //arrange - // var path = @"C:\_Temp\rating test\01~K.A.N. - Rating - Copy - Copy.mp3"; - // var mp3 = new Mp3(path, Mp3Permissions.ReadWrite); - // var tag = mp3.GetTag(Id3TagFamily.Version2X); - - // //act - // tag.Popularimeter.Rating = Rating.FiveStars; - // mp3.WriteTag(tag, Id3Version.V23); - - // //assert - // Assert.True(false); - //} } } From 75e02158e1747181c7dc41f6978bda812a5df450 Mon Sep 17 00:00:00 2001 From: spottedmahn Date: Mon, 16 Dec 2019 11:10:44 -0500 Subject: [PATCH 5/5] Fix Serialization Test --- src/Id3.Net/Frames/DateTime/RecordingDateFrame.cs | 2 +- test/Id3.Net.Tests/SerializationTests.cs | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Id3.Net/Frames/DateTime/RecordingDateFrame.cs b/src/Id3.Net/Frames/DateTime/RecordingDateFrame.cs index 5621604..9c5d372 100644 --- a/src/Id3.Net/Frames/DateTime/RecordingDateFrame.cs +++ b/src/Id3.Net/Frames/DateTime/RecordingDateFrame.cs @@ -31,7 +31,7 @@ public RecordingDateFrame(DateTime value) : base(value) { } - protected override string DateTimeFormat => "yyyy-MM-dd"; + protected override string DateTimeFormat => "ddMM"; public static implicit operator RecordingDateFrame(DateTime value) => new RecordingDateFrame(value); } diff --git a/test/Id3.Net.Tests/SerializationTests.cs b/test/Id3.Net.Tests/SerializationTests.cs index b4b2509..5f3f197 100644 --- a/test/Id3.Net.Tests/SerializationTests.cs +++ b/test/Id3.Net.Tests/SerializationTests.cs @@ -66,7 +66,11 @@ public void Serialize_deserialize_test() Assert.Equal(tag.Year.Value, clonedTag.Year.Value); Assert.Equal(tag.Genre.Value, clonedTag.Genre.Value); Assert.Equal(tag.Publisher.Value, clonedTag.Publisher.Value); - Assert.Equal(tag.RecordingDate.Value, clonedTag.RecordingDate.Value); + + //https://github.com/JeevanJames/Id3/pull/27#issuecomment-565815805 + //TDAT is only day and month + Assert.Equal(tag.RecordingDate.Value.Value.Month, clonedTag.RecordingDate.Value.Value.Month); + Assert.Equal(tag.RecordingDate.Value.Value.Day, clonedTag.RecordingDate.Value.Value.Day); Assert.Equal(tag.Artists.Value.Count, clonedTag.Artists.Value.Count); for (var i = 0; i < tag.Artists.Value.Count; i++)