/// <summary> /// Retrieve a tag with an arbitrary name. /// Returns an empty tag if the value isn't found or if no Xiph tags are present. /// </summary> /// <param name="TagName"> /// A <see cref="System.String"/> containing the name of the tag to find /// </param> /// <returns> /// An <see cref="OggTag"/> containing the returned tag /// </returns> public OggTag GetTag(string TagName) { if (TagName.Length <= 0) { return(OggUtilities.GetEmptyTag()); } // Save some processing time and just exit if we haven't been given a tag name // Based on tasty examples @ "Accessing Hidden Gems": http://developer.novell.com/wiki/index.php/TagLib_Sharp:_Examples TagLib.Ogg.XiphComment XC = (TagLib.Ogg.XiphComment)m_TagLibFile.GetTag(TagTypes.Xiph); if (XC != null) { string[] TagValue = XC.GetField(TagName); if (TagValue.Length == 0) { // Tag doesn't exist, return empty return(OggUtilities.GetEmptyTag()); } else { OggTag tmpTag; tmpTag.Name = TagName; tmpTag.IsArray = (TagValue.Length > 1); tmpTag.IsEmpty = false; tmpTag.Values = TagValue; tmpTag.Value = TagValue[0]; return(tmpTag); } } else { // No valid Xiph tags found return(OggUtilities.GetEmptyTag()); } }
public static void StorePlayCount(int playcount, TagLib.File to_file) { TagLib.Ogg.XiphComment xiphtag = GetTag(to_file); if (xiphtag == null) { return; } ArrayList playcount_fieldnames = new ArrayList(); // Collect list of playcount tags to be updated: foreach (string fieldname in xiphtag) { if (fieldname.ToUpper().StartsWith(playcount_prefix)) { playcount_fieldnames.Add(fieldname); } } // Add "BANSHEE" tags if no playcount tags were found: if (playcount_fieldnames.Count == 0) { playcount_fieldnames.Add(playcount_prefix + ogg_our_creator_name); } string ogg_playcount = playcount.ToString(); foreach (string playcountname in playcount_fieldnames) { xiphtag.SetField(playcountname, ogg_playcount); Hyena.Log.DebugFormat("Exporting Ogg Playcount={0}({1}) to File \"{2}\" as Creator \"{3}\"", playcount, ogg_playcount, to_file.Name, playcountname.Substring(playcount_prefix.Length)); } }
public static void DumpXiphMetadata(File tagFile) { TagLib.Ogg.XiphComment tags = (TagLib.Ogg.XiphComment)tagFile.GetTag(TagTypes.Xiph); foreach (string fieldName in tags.Distinct().OrderBy(t => t)) { string[] fieldValue = tags.GetField(fieldName); if (fieldValue.Length > 1) { Console.WriteLine("{0} ({1}):", fieldName, fieldValue.Length); foreach (string fv in fieldValue) { WriteLineWithIndent(4, fv); } } else if (fieldValue.Length == 1) { Console.WriteLine("{0}:", fieldName); WriteLineWithIndent(4, fieldValue[0]); } else { Console.WriteLine("{0} (No Value)", fieldName); } } }
public void TestAlbumArtists() { var tag = new XiphComment(); TagTestWithSave(ref tag, delegate(XiphComment t, string m) { Assert.IsTrue(t.IsEmpty, "Initial (IsEmpty): " + m); Assert.AreEqual(0, t.AlbumArtists.Length, "Initial (Zero): " + m); }); tag.AlbumArtists = val_mult; TagTestWithSave(ref tag, delegate(XiphComment t, string m) { Assert.IsFalse(t.IsEmpty, "Value Set (!IsEmpty): " + m); Assert.AreEqual(val_mult.Length, t.AlbumArtists.Length, "Value Set: " + m); for (int i = 0; i < val_mult.Length; i++) { Assert.AreEqual(val_mult[i], t.AlbumArtists[i], "Value Set: " + m); } }); tag.AlbumArtists = new string[0]; TagTestWithSave(ref tag, delegate(XiphComment t, string m) { Assert.IsTrue(t.IsEmpty, "Value Cleared (IsEmpty): " + m); Assert.AreEqual(0, t.AlbumArtists.Length, "Value Cleared (Zero): " + m); }); }
// Scans the file for ogg rating/playcount tags as defined by the Quod Libet standard // All applicable tags are overwritten with the new values, regardless of tag author public static void StoreRating(int rating, TagLib.File to_file) { TagLib.Ogg.XiphComment xiphtag = GetTag(to_file); if (xiphtag == null) { return; } ArrayList rating_fieldnames = new ArrayList(); // Collect list of rating tags to be updated: foreach (string fieldname in xiphtag) { if (fieldname.ToUpper().StartsWith(rating_prefix)) { rating_fieldnames.Add(fieldname); } } // Add "BANSHEE" tags if no rating tags were found: if (rating_fieldnames.Count == 0) { rating_fieldnames.Add(rating_prefix + ogg_our_creator_name); } string ogg_rating = BansheeToOgg(rating); foreach (string ratingname in rating_fieldnames) { xiphtag.SetField(ratingname, ogg_rating); Hyena.Log.DebugFormat("Exporting Ogg Rating={0}({1}) to File \"{2}\" as Creator \"{3}\"", rating, ogg_rating, to_file.Name, ratingname.Substring(rating_prefix.Length)); } }
public static bool UpdateTags(TagLib.File fileInfo, NameValueCollection tags, CUEToolsCodecsConfig config, bool useId3v24) { if (fileInfo is TagLib.Riff.File) { return(false); } TagLib.Ogg.XiphComment xiph = (TagLib.Ogg.XiphComment)fileInfo.GetTag(TagLib.TagTypes.Xiph); if (xiph != null) { foreach (string tag in tags.AllKeys) { xiph.SetField(tag, tags.GetValues(tag)); } return(true); } if (fileInfo is TagLib.Mpeg4.File) { var mpeg4 = (TagLib.Mpeg4.AppleTag)fileInfo.GetTag(TagLib.TagTypes.Apple, true); foreach (string tag in tags.AllKeys) { mpeg4.SetDashBox("com.apple.iTunes", tag, string.Join(";", tags.GetValues(tag))); } return(true); } if (fileInfo is TagLib.Mpeg.AudioFile || (fileInfo is TagLib.UserDefined.File && (fileInfo as TagLib.UserDefined.File).Tagger == CUEToolsTagger.ID3v2)) { var id3v2 = (TagLib.Id3v2.Tag)fileInfo.GetTag(TagLib.TagTypes.Id3v2, true); id3v2.Version = (byte)(useId3v24 ? 4 : 3); foreach (string tag in tags.AllKeys) { var frame = TagLib.Id3v2.UserTextInformationFrame.Get(id3v2, tag, true); frame.Text = tags.GetValues(tag); } return(true); } if (fileInfo is TagLib.Asf.File) { var asf = (TagLib.Asf.Tag)fileInfo.GetTag(TagLib.TagTypes.Asf, true); foreach (string tag in tags.AllKeys) { asf.SetDescriptorStrings(tags.GetValues(tag), "foobar2000/" + tag); } return(true); } TagLib.Ape.Tag ape = (TagLib.Ape.Tag)fileInfo.GetTag(TagLib.TagTypes.Ape, true); if (ape != null) { foreach (string tag in tags.AllKeys) { ape.SetValue(tag, tags.GetValues(tag)); } } return(true); }
/// <summary>Function to read the various tags from file, if available /// These will be checked in various get functions /// </summary> private void ReadTags() { //currentFile = TagLib.File.Create(FileInfoView.FocusedItem.SubItems[4].Text); id3v1 = currentFile.GetTag(TagLib.TagTypes.Id3v1) as TagLib.Id3v1.Tag; id3v2 = currentFile.GetTag(TagLib.TagTypes.Id3v2) as TagLib.Id3v2.Tag; apple = currentFile.GetTag(TagLib.TagTypes.Apple) as TagLib.Mpeg4.AppleTag; ape = currentFile.GetTag(TagLib.TagTypes.Ape) as TagLib.Ape.Tag; // asf = currentFile.GetTag(TagLib.TagTypes.Asf) as TagLib.Asf.Tag; ogg = currentFile.GetTag(TagLib.TagTypes.Xiph) as TagLib.Ogg.XiphComment; flac = currentFile.GetTag(TagLib.TagTypes.FlacMetadata) as TagLib.Flac.Metadata; }
public void TestClear() { var tag = new XiphComment { Title = "A", Performers = new[] { "B" }, AlbumArtists = new[] { "C" }, Composers = new[] { "D" }, Album = "E", Comment = "F", Genres = new[] { "Blues" }, Year = 123, Track = 234, TrackCount = 234, Disc = 234, DiscCount = 234, Lyrics = "G", Grouping = "H", BeatsPerMinute = 234, Conductor = "I", Copyright = "J", Pictures = new[] { new Picture(TestPath.Covers + "sample_a.png") }, InitialKey = "K", Publisher = "L", ISRC = "M", RemixedBy = "N" }; Assert.IsFalse(tag.IsEmpty, "Should be full."); tag.Clear(); Assert.IsNull(tag.Title, "Title"); Assert.AreEqual(0, tag.Performers.Length, "Performers"); Assert.AreEqual(0, tag.AlbumArtists.Length, "AlbumArtists"); Assert.AreEqual(0, tag.Composers.Length, "Composers"); Assert.IsNull(tag.Album, "Album"); Assert.IsNull(tag.Comment, "Comment"); Assert.AreEqual(0, tag.Genres.Length, "Genres"); Assert.AreEqual(0, tag.Year, "Year"); Assert.AreEqual(0, tag.Track, "Track"); Assert.AreEqual(0, tag.TrackCount, "TrackCount"); Assert.AreEqual(0, tag.Disc, "Disc"); Assert.AreEqual(0, tag.DiscCount, "DiscCount"); Assert.IsNull(tag.Lyrics, "Lyrics"); Assert.IsNull(tag.Comment, "Comment"); Assert.AreEqual(0, tag.BeatsPerMinute, "BeatsPerMinute"); Assert.IsNull(tag.Conductor, "Conductor"); Assert.IsNull(tag.Copyright, "Copyright"); Assert.AreEqual(0, tag.Pictures.Length, "Pictures"); Assert.IsTrue(tag.IsEmpty, "Should be empty."); Assert.IsNull(tag.InitialKey, "InitialKey"); Assert.IsNull(tag.Publisher, "Publisher"); Assert.IsNull(tag.ISRC, "ISRC"); Assert.IsNull(tag.RemixedBy, "RemixedBy"); }
/// <summary> /// Write a single Xiph tag to the file /// This will overwrite the tag if it already exists, or create it if it doesn't /// It will also create the Xiph tag block within the file if it doesn't already have one /// This function writes to disk. If setting multiple tags consider using SetTags(OggTag[] Tags) to reduce the number of write operations /// If setting an array, Tag.Values must contain at least one item. Tag.Value is ignored in this case /// If setting a single value, Tag.Value must contain at least one character. Tag.Values is ignored in this case /// </summary> /// <param name="Tag"> /// The <see cref="OggTag"/> to write /// </param> /// <returns> /// An <see cref="OggTagWriteCommandReturn"/> indicating the result of the operation /// </returns> public OggTagWriteCommandReturn SetTag(OggTag Tag) { // Validate Tag if (Tag.IsEmpty) { return(OggTagWriteCommandReturn.InvalidValue); } if (Tag.Name.Length <= 0) { return(OggTagWriteCommandReturn.UnknownTag); } if (Tag.IsArray) { if (Tag.Values.Length <= 0) { return(OggTagWriteCommandReturn.InvalidValue); } } else { if (Tag.Value.Length <= 0) { return(OggTagWriteCommandReturn.InvalidValue); } } // Tag valid, try and write it TagLib.Ogg.XiphComment XC = (TagLib.Ogg.XiphComment)m_TagLibFile.GetTag(TagTypes.Xiph, true); if (XC != null) { string[] tmpStrArray; if (Tag.IsArray) { tmpStrArray = Tag.Values; } else { tmpStrArray = new string[1]; tmpStrArray[0] = Tag.Value; } // Set field XC.SetField(Tag.Name, tmpStrArray); // Copy the XC instance into our file (not sure if this is needed) XC.CopyTo(m_TagLibFile.Tag, true); // Commit m_TagLibFile.Save(); return(OggTagWriteCommandReturn.Success); } else { // If we're null something went wrong (we tried to create the XiphComment block and it failed probably) return(OggTagWriteCommandReturn.Error); } }
// Scans the file for ogg rating/playcount tags as defined by the Quod Libet standard // If a Banshee tag is found, it is given priority. // If a Banshee tag is not found, the last rating/playcount tags found are used public static void GetRatingAndPlayCount(TagLib.File from_file, ref int rating, ref int playcount) { TagLib.Ogg.XiphComment xiphtag = GetTag(from_file); if (xiphtag == null) { return; } bool banshee_rating_done = false, banshee_playcount_done = false; string rating_raw = "", playcount_raw = ""; foreach (string fieldname in xiphtag) { if (!banshee_rating_done && fieldname.ToUpper().StartsWith(rating_prefix)) { rating_raw = xiphtag.GetFirstField(fieldname); string rating_creator = fieldname.Substring(rating_prefix.Length); if (rating_creator.ToUpper() == ogg_our_creator_name) { // We made this rating, consider it authoritative. banshee_rating_done = true; // Don't return -- we might not have seen a playcount yet. } } else if (!banshee_playcount_done && fieldname.ToUpper().StartsWith(playcount_prefix)) { playcount_raw = xiphtag.GetFirstField(fieldname); string playcount_creator = fieldname.Substring(playcount_prefix.Length); if (playcount_creator.ToUpper() == ogg_our_creator_name) { // We made this playcount, consider it authoritative. banshee_playcount_done = true; // Don't return -- we might not have seen a rating yet. } } } if (rating_raw != "") { rating = OggToBanshee(rating_raw); } if (playcount_raw != "") { playcount = int.Parse(playcount_raw); } Hyena.Log.DebugFormat("Importing Ogg Rating={0}({1}) and Playcount={2}({3}) from File \"{4}\"", rating, rating_raw, playcount, playcount_raw, from_file.Name); }
/// <summary> /// Retrieve an array of all tag values /// Returns a zero-length array if no Xiph tags are found /// </summary> /// <returns> /// An <see cref="OggTag[]"/> containing the returned values /// </returns> public OggTag[] GetTags() { TagLib.Ogg.XiphComment XC = (TagLib.Ogg.XiphComment)m_TagLibFile.GetTag(TagTypes.Xiph); if (XC != null) { if (XC.FieldCount > 0) { OggTag[] tmpOggTag = new OggTag[XC.FieldCount]; int Index = 0; foreach (string FieldName in XC) { string[] TagValue = XC.GetField(FieldName); if (TagValue.Length == 0) { tmpOggTag[Index] = OggUtilities.GetEmptyTag(); // This should never happen, but I bet if I don't check it it will! } else { // Populate this tag tmpOggTag[Index].Name = FieldName; tmpOggTag[Index].IsArray = (TagValue.Length > 1); tmpOggTag[Index].IsEmpty = false; tmpOggTag[Index].Values = TagValue; tmpOggTag[Index].Value = TagValue[0]; } ++Index; // Increment the index so we know which OggTag we're molesting } // Done! Return the heap of tags return(tmpOggTag); } else { // Xiph tags contain no items return(new OggTag[0]); } } else { // No valid Xiph tags found return(new OggTag[0]); } }
public FlacTagger(string path, bool write = true) { f = Utils.OpenFile(path, write); t = (TagLib.Ogg.XiphComment)f.TagLibFile.GetTag(TagLib.TagTypes.Xiph, true); if (t == null) { SafeClose(); throw new HaException("FLAC file has no Xiph tag"); } foreach (string tagName in t) { valueTags.Add(tagName.ToLower(), t.GetFirstField(tagName).ToLower()); } string data = t.GetFirstField("hatag"); if (data != null) { data.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).ToList().ForEach(x => tags.Add(x)); } }
public static string[] GetMiscTag(TagLib.File file, string name) { //TagLib.Mpeg4.AppleTag apple = (TagLib.Mpeg4.AppleTag)file.GetTag(TagLib.TagTypes.Apple); //TagLib.Id3v2.Tag id3v2 = (TagLib.Id3v2.Tag)file.GetTag(TagLib.TagTypes.Id3v2); TagLib.Ogg.XiphComment xiph = (TagLib.Ogg.XiphComment)file.GetTag(TagLib.TagTypes.Xiph); TagLib.Ape.Tag ape = (TagLib.Ape.Tag)file.GetTag(TagLib.TagTypes.Ape); //if (apple != null) //{ // string[] text = apple.GetText(name); // if (text.Length != 0) // return text; //} //if (id3v2 != null) // foreach (TagLib.Id3v2.Frame f in id3v2.GetFrames()) // if (f is TagLib.Id3v2.TextInformationFrame && ((TagLib.Id3v2.TextInformationFrame)f).Text != null) // return ((TagLib.Id3v2.TextInformationFrame)f).Text; if (xiph != null) { string[] l = xiph.GetField(name); if (l != null && l.Length != 0) { return(l); } } if (ape != null) { TagLib.Ape.Item item = ape.GetItem(name); if (item != null) { return(item.ToStringArray()); } } return(null); }
public void TestBeatsPerMinute() { var tag = new XiphComment(); TagTestWithSave(ref tag, delegate(XiphComment t, string m) { Assert.IsTrue(t.IsEmpty, "Initial (IsEmpty): " + m); Assert.AreEqual(0, tag.BeatsPerMinute, "Initial (Zero): " + m); }); tag.BeatsPerMinute = 199; TagTestWithSave(ref tag, delegate(XiphComment t, string m) { Assert.IsFalse(t.IsEmpty, "Value Set (!IsEmpty): " + m); Assert.AreEqual(199, tag.BeatsPerMinute, "Value Set: " + m); }); tag.BeatsPerMinute = 0; TagTestWithSave(ref tag, delegate(XiphComment t, string m) { Assert.IsTrue(t.IsEmpty, "Value Cleared (IsEmpty): " + m); Assert.AreEqual(0, t.BeatsPerMinute, "Value Cleared (Zero): " + m); }); }
public void TestMusicBrainzReleaseCountry() { var tag = new XiphComment(); TagTestWithSave(ref tag, delegate(XiphComment t, string m) { Assert.IsTrue(t.IsEmpty, "Initial (IsEmpty): " + m); Assert.IsNull(t.MusicBrainzReleaseCountry, "Initial (Null): " + m); }); tag.MusicBrainzReleaseCountry = val_sing; TagTestWithSave(ref tag, delegate(XiphComment t, string m) { Assert.IsFalse(t.IsEmpty, "Value Set (!IsEmpty): " + m); Assert.AreEqual(val_sing, t.MusicBrainzReleaseCountry, "Value Set (!Null): " + m); }); tag.MusicBrainzReleaseCountry = string.Empty; TagTestWithSave(ref tag, delegate(XiphComment t, string m) { Assert.IsTrue(t.IsEmpty, "Value Cleared (IsEmpty): " + m); Assert.IsNull(t.MusicBrainzReleaseCountry, "Value Cleared (Null): " + m); }); }
public void TestIsCompilation() { var tag = new XiphComment(); TagTestWithSave(ref tag, delegate(XiphComment t, string m) { Assert.IsTrue(t.IsEmpty, "Initial (IsEmpty): " + m); Assert.IsFalse(t.IsCompilation, "Initial (False): " + m); }); tag.IsCompilation = true; TagTestWithSave(ref tag, delegate(XiphComment t, string m) { Assert.IsFalse(t.IsEmpty, "Value Set (!IsEmpty): " + m); Assert.IsTrue(t.IsCompilation, "Value Set (True): " + m); }); tag.IsCompilation = false; TagTestWithSave(ref tag, delegate(XiphComment t, string m) { Assert.IsTrue(t.IsEmpty, "Value Cleared (IsEmpty): " + m); Assert.IsFalse(t.IsCompilation, "Value Cleared (False): " + m); }); }
public void TestRemixedBy() { XiphComment tag = new XiphComment(); TagTestWithSave(ref tag, delegate(XiphComment t, string m) { Assert.IsTrue(t.IsEmpty, "Initial (IsEmpty): " + m); Assert.IsNull(t.RemixedBy, "Initial (Null): " + m); }); tag.RemixedBy = val_sing; TagTestWithSave(ref tag, delegate(XiphComment t, string m) { Assert.IsFalse(t.IsEmpty, "Value Set (!IsEmpty): " + m); Assert.AreEqual(val_sing, t.RemixedBy, "Value Set (!Null): " + m); }); tag.RemixedBy = string.Empty; TagTestWithSave(ref tag, delegate(XiphComment t, string m) { Assert.IsTrue(t.IsEmpty, "Value Cleared (IsEmpty): " + m); Assert.IsNull(t.RemixedBy, "Value Cleared (Null): " + m); }); }
/// <summary> /// Remove a tag from the file. /// This command writes to disk. /// </summary> /// <param name="TagName"> /// A <see cref="System.String"/> indicating which tag to remove /// </param> /// <returns> /// An <see cref="OggTagWriteCommandReturn"/> indicating the result of the operation /// </returns> public OggTagWriteCommandReturn RemoveTag(string TagName) { // Check that the tag name contains at least one character if (TagName.Length < 1) { return(OggTagWriteCommandReturn.UnknownTag); } TagLib.Ogg.XiphComment XC = (TagLib.Ogg.XiphComment)m_TagLibFile.GetTag(TagTypes.Xiph, false); if (XC != null) { // Remove the tag XC.RemoveField(TagName); // Copy the XC instance into our file (might need to clear the Xiph block first, but we'll see) XC.CopyTo(m_TagLibFile.Tag, true); // Save m_TagLibFile.Save(); return(OggTagWriteCommandReturn.Success); } else { // Either there isn't a Xiph comment block or something went wrong return(OggTagWriteCommandReturn.Error); } }
/// <summary> /// Write multiple Xiph tags to the file /// This will overwrite any existing tags, and create them if they don't exist /// It will also create the Xiph tag block within the file if it doesn't already have one /// This function writes to disk. If setting only a single tag, consider using SetTag(OggTag Tag) to reduce the array handling overheads /// If setting an array value Tags[i].Values must contain at least one item. Tags[i].Value is ignored in this case /// If setting a single value, Tags[i].Value must contain at least one character. Tags[i].Values is ignored in this case /// If AbortOnError is true, this function will abort (and not write) if any item in the Tags array is invalid. /// If AbortOnError is false, this function will continue (and write) if items in the Tags array are invalid. It will still abort (and not write) if there are other errors. /// </summary> /// <param name="Tags"> /// An <see cref="OggTag[]"/> containing the tags to be written /// </param> /// <param name="AbortOnError"> /// A <see cref="System.bool"/> indicating whether to invalid items in the Tags array. /// <returns> /// An <see cref="OggTagWriteCommandReturn"/> indicating the result of the operation /// </returns> public OggTagWriteCommandReturn SetTags(OggTag[] Tags, bool AbortOnError) { // Check that the Tags array has at least one item in it if (Tags.Length < 1) { return(OggTagWriteCommandReturn.UnknownTag); } TagLib.Ogg.XiphComment XC = (TagLib.Ogg.XiphComment)m_TagLibFile.GetTag(TagTypes.Xiph, true); if (XC != null) { // Write the tags to the 'virtual' file foreach (OggTag Tag in Tags) { // Validate tag if (Tag.IsEmpty) { if (AbortOnError) { return(OggTagWriteCommandReturn.InvalidValue); } else { continue; } } if (Tag.Name.Length <= 0) { if (AbortOnError) { return(OggTagWriteCommandReturn.UnknownTag); } else { continue; } } if (Tag.IsArray) { if (Tag.Values.Length <= 0) { if (AbortOnError) { return(OggTagWriteCommandReturn.InvalidValue); } else { continue; } } } else { if (Tag.Value.Length <= 0) { if (AbortOnError) { return(OggTagWriteCommandReturn.InvalidValue); } else { continue; } } } string[] tmpStrArray; if (Tag.IsArray) { tmpStrArray = Tag.Values; } else { tmpStrArray = new string[1]; tmpStrArray[0] = Tag.Value; } // Write tag XC.SetField(Tag.Name, tmpStrArray); } // Copy the XC instance into our file (not sure if this is needed) XC.CopyTo(m_TagLibFile.Tag, true); // Save to disk m_TagLibFile.Save(); return(OggTagWriteCommandReturn.Success); } else { // If we're null something went wrong (we tried to create the XiphComment block and it failed probably) return(OggTagWriteCommandReturn.Error); } }
void TagTestWithSave(ref XiphComment tag, TagTestFunc testFunc) { testFunc(tag, "Before Save"); tag = new XiphComment(tag.Render(true)); testFunc(tag, "After Save"); }
public void TestPictures() { var tag = new XiphComment(); Picture[] pictures = { new Picture(TestPath.Covers + "sample_a.png"), new Picture(TestPath.Covers + "sample_a.jpg"), new Picture(TestPath.Covers + "sample_b.png"), new Picture(TestPath.Covers + "sample_b.jpg"), new Picture(TestPath.Covers + "sample_c.png"), new Picture(TestPath.Covers + "sample_c.jpg") }; for (int i = 0; i < 6; i++) { pictures[i].Type = (PictureType)(i * 2); } pictures[3].Description = val_sing; TagTestWithSave(ref tag, delegate(XiphComment t, string m) { Assert.IsTrue(t.IsEmpty, "Initial (IsEmpty): " + m); Assert.AreEqual(0, t.Pictures.Length, "Initial (Zero): " + m); }); tag.Pictures = pictures; TagTestWithSave(ref tag, delegate(XiphComment t, string m) { Assert.IsTrue(!t.IsEmpty, "Value Set (IsEmpty): " + m); }); tag.Pictures = new Picture[0]; TagTestWithSave(ref tag, delegate(XiphComment t, string m) { Assert.IsTrue(t.IsEmpty, "Value Cleared (IsEmpty): " + m); Assert.AreEqual(0, t.Pictures.Length, "Value Cleared (Zero): " + m); }); // Test that COVERART fields are parsed in Pictures property string[] pictureStrings = new string[pictures.Length]; for (int i = 0; i < 6; ++i) { pictureStrings[i] = Convert.ToBase64String(pictures[i].Data.Data); } tag.SetField("COVERART", pictureStrings); var parsedPictures = tag.Pictures; Assert.IsTrue(!tag.IsEmpty, "Legacy Value Set (IsEmpty)"); Assert.AreEqual(6, parsedPictures.Length, "Legacy Value Set (Length)"); TagTestWithSave(ref tag, delegate(XiphComment t, string m) { // COVERART should be preserved Assert.AreEqual(6, t.GetField("COVERART").Length, "Legacy Field Set (Length): " + m); }); // Setting the pictures array should replace COVERART with METADATA_BLOCK_PICTURE tag.Pictures = pictures; TagTestWithSave(ref tag, delegate(XiphComment t, string m) { Assert.AreEqual(0, t.GetField("COVERART").Length, "Legacy Field Set (Length): " + m); Assert.AreEqual(6, t.GetField("METADATA_BLOCK_PICTURE").Length, "Current Field Set (Length): " + m); }); // The user should be able to clear the pictures array tag.Pictures = null; TagTestWithSave(ref tag, delegate(XiphComment t, string m) { Assert.AreEqual(0, t.Pictures.Length, "Pictures Length (null): " + m); }); }