diff --git a/src/TaglibSharp.Tests/TaggingFormats/Id3V2Test.cs b/src/TaglibSharp.Tests/TaggingFormats/Id3V2Test.cs index 8b2ea676..1f6fc3a9 100644 --- a/src/TaglibSharp.Tests/TaggingFormats/Id3V2Test.cs +++ b/src/TaglibSharp.Tests/TaggingFormats/Id3V2Test.cs @@ -18,6 +18,8 @@ public class Id3V2Test static readonly string[] val_gnre = {"Rap", "Jazz", "Non-Genre", "Blues"}; + static readonly System.DateTime val_date = new System.DateTime (2022, 10, 20, 16, 45, 23, 0, 0); + [Test] public void TestTitle () { @@ -968,6 +970,35 @@ public void TestPublisher () } } + + [Test] + public void TestEncodedBy () + { + Tag tag = new Tag (); + for (byte version = 2; version <= 4; version++) { + tag.Version = version; + + TagTestWithSave (ref tag, delegate (Tag t, string m) { + Assert.IsTrue (t.IsEmpty, "Initial (IsEmpty): " + m); + Assert.IsNull (t.EncodedBy, "Initial (Null): " + m); + }); + + tag.EncodedBy = val_sing; + + TagTestWithSave (ref tag, delegate (Tag t, string m) { + Assert.IsFalse (t.IsEmpty, "Value Set (!IsEmpty): " + m); + Assert.AreEqual (val_sing, t.EncodedBy, "Value Set (!Null): " + m); + }); + + tag.EncodedBy = string.Empty; + + TagTestWithSave (ref tag, delegate (Tag t, string m) { + Assert.IsTrue (t.IsEmpty, "Value Cleared (IsEmpty): " + m); + Assert.IsNull (t.EncodedBy, "Value Cleared (Null): " + m); + }); + } + } + [Test] public void TestISRC () { @@ -996,6 +1027,34 @@ public void TestISRC () } } + [Test] + public void TestReleaseDate () + { + Tag tag = new Tag (); + for (byte version = 4; version <= 4; version++) { + tag.Version = version; + + TagTestWithSave (ref tag, delegate (Tag t, string m) { + Assert.IsTrue (t.IsEmpty, "Initial (IsEmpty): " + m); + Assert.IsNull (t.ReleaseDate, "Initial (Null): " + m); + }, 4); + + tag.ReleaseDate = val_date; + + TagTestWithSave (ref tag, delegate (Tag t, string m) { + Assert.IsFalse (t.IsEmpty, "Value Set (!IsEmpty): " + m); + Assert.AreEqual (val_date, t.ReleaseDate.Value, "Value Set (!Null): " + m); + }, 4); + + tag.ReleaseDate = null; + + TagTestWithSave (ref tag, delegate (Tag t, string m) { + Assert.IsTrue (t.IsEmpty, "Value Cleared (IsEmpty): " + m); + Assert.IsNull (t.ReleaseDate, "Value Cleared (Null): " + m); + }, 4); + } + } + [Test] public void TestLength () { @@ -1634,10 +1693,10 @@ public void TestInvolvedPersonsFrame () delegate void TagTestFunc (Tag tag, string msg); - void TagTestWithSave (ref Tag tag, TagTestFunc testFunc) + void TagTestWithSave (ref Tag tag, TagTestFunc testFunc, byte minVersion = 2) { testFunc (tag, "Before Save"); - for (byte version = 2; version <= 4; version++) { + for (byte version = minVersion; version <= 4; version++) { tag.Version = version; tag = new Tag (tag.Render ()); testFunc (tag, "After Save, Version: " + version); diff --git a/src/TaglibSharp/Id3v2/FrameTypes.cs b/src/TaglibSharp/Id3v2/FrameTypes.cs index 2fda85de..7cad5ec6 100644 --- a/src/TaglibSharp/Id3v2/FrameTypes.cs +++ b/src/TaglibSharp/Id3v2/FrameTypes.cs @@ -101,5 +101,7 @@ static class FrameType public static readonly ReadOnlyByteVector WPUB = "WPUB"; public static readonly ReadOnlyByteVector WXXX = "WXXX"; public static readonly ReadOnlyByteVector ETCO = "ETCO"; + public static readonly ReadOnlyByteVector TDRL = "TDRL"; // Release Time Frame + public static readonly ReadOnlyByteVector TENC = "TENC"; // Encoded By Frame. } } diff --git a/src/TaglibSharp/Id3v2/Tag.cs b/src/TaglibSharp/Id3v2/Tag.cs index 1c3676ff..da236b4c 100644 --- a/src/TaglibSharp/Id3v2/Tag.cs +++ b/src/TaglibSharp/Id3v2/Tag.cs @@ -2265,6 +2265,20 @@ IEnumerator IEnumerable.GetEnumerator () set { SetTextFrame (FrameType.TPUB, value); } } + /// + /// Gets and sets the TENC (Encoded by) of the song. + /// + /// + /// A object containing the TENC of the song. + /// + /// + /// This property is implemented using the "TENC" field. + /// + public string EncodedBy { + get { return GetTextAsString (FrameType.TENC); } + set { SetTextFrame (FrameType.TENC, value); } + } + /// /// Gets and sets the ISRC (International Standard Recording Code) of the song. /// @@ -2279,6 +2293,48 @@ IEnumerator IEnumerable.GetEnumerator () set { SetTextFrame (FrameType.TSRC, value); } } + /// + /// Gets and sets the date at which the song has been released. + /// + /// + /// A nullable object containing the + /// date at which the song has been released, or if no value present. + /// + /// + /// This property is implemented using the "TDRL" field. + /// This is a ID3v2.4 type tag. + /// + public DateTime? ReleaseDate { + get { + string value = GetTextAsString (FrameType.TDRL); + + if (String.IsNullOrWhiteSpace(value)) { + return null; + } else if (DateTime.TryParseExact (value.Replace ('T', ' '), "yyyy-MM-dd HH:mm:ss", null, DateTimeStyles.None, out DateTime exactDate)) { + return exactDate; + } else if (DateTime.TryParse(value, out DateTime parsedDate)) { + return parsedDate; + } + + return null; + } + set { + string date = null; + + if (value != null) { + date = $"{value:yyyy-MM-dd HH:mm:ss}"; + date = date.Replace (' ', 'T'); + } + + if (date == null) { + RemoveFrames(FrameType.TDRL); + } else { + SetTextFrame(FrameType.TDRL, date); + } + } + } + /// /// Gets and sets the length of the media represented /// by the current instance.