]> granicus.if.org Git - taglib/commitdiff
Added toDict and fromDict methods for APE tags.
authorMichael Helmling <helmling@mathematik.uni-kl.de>
Sat, 27 Aug 2011 20:30:20 +0000 (22:30 +0200)
committerMichael Helmling <helmling@mathematik.uni-kl.de>
Sat, 27 Aug 2011 20:30:20 +0000 (22:30 +0200)
taglib/ape/apetag.cpp
taglib/ape/apetag.h
taglib/mpeg/id3v2/id3v2tag.h
taglib/ogg/xiphcomment.h

index 082fd038bc8f0d2d91c2a10fba58428b873374df..1f3f84a26a57b40979c0e1d2e9f1c955d827a97a 100644 (file)
@@ -174,6 +174,70 @@ void APE::Tag::setTrack(uint i)
     addValue("TRACK", String::number(i), true);
 }
 
+TagDict APE::Tag::toDict() const
+{
+  TagDict dict;
+  ItemListMap::ConstIterator it = itemListMap().begin();
+  for (; it != itemListMap().end(); ++it) {
+    String tagName = it->first.upper();
+    // These two tags need to be handled specially; in APE tags the track number is usually
+    // named TRACK instead of TRACKNUMBER, the date tag is YEAR instead of DATE
+    //
+    if (tagName == "TRACK")
+      tagName = "TRACKNUMBER";
+    else if (tagName == "YEAR")
+      tagName = "DATE";
+    if (it->second.type() == Item::Text)
+      dict[tagName].append(it->second.toStringList());
+  }
+  return dict;
+}
+
+void APE::Tag::fromDict(const TagDict &orig_dict)
+{
+  TagDict dict(orig_dict); // make a local copy that can be modified
+
+  if (dict.contains("TRACKNUMBER")) {
+    dict.insert("TRACK", dict["TRACKNUMBER"]);
+    dict.erase("TRACKNUMBER");
+  }
+  if (dict.contains("DATE")) {
+    dict.insert("YEAR", dict["DATE"]);
+    dict.erase("DATE");
+  }
+
+  // first check if tags need to be removed completely
+  StringList toRemove;
+  ItemListMap::ConstIterator remIt = itemListMap().begin();
+  for (; remIt != itemListMap().end(); ++remIt) {
+    if (remIt->second.type() != APE::Item::Text)
+      // ignore binary and locator APE items
+      continue;
+    if (!dict.contains(remIt->first.upper()))
+      toRemove.append(remIt->first);
+  }
+
+  for (StringList::Iterator removeIt = toRemove.begin(); removeIt != toRemove.end(); removeIt++)
+    removeItem(*removeIt);
+
+  // now sync in the "forward direction
+  TagDict::ConstIterator it = dict.begin();
+  for (; it != dict.end(); ++it) {
+    const String &tagName = it->first;
+    if (!(itemListMap().contains(tagName)) || !(itemListMap()[tagName].values() == it->second)) {
+      if (it->second.size() == 0)
+        removeItem(tagName);
+      else {
+        StringList::ConstIterator valueIt = it->second.begin();
+        addValue(tagName, *valueIt, true);
+        ++valueIt;
+        for(; valueIt != it->second.end(); ++valueIt)
+          addValue(tagName, *valueIt, false);
+      }
+    }
+  }
+}
+
 APE::Footer *APE::Tag::footer() const
 {
   return &d->footer;
index 13efd5e0a98a73ac63d6f849b48819d58e524bf4..b48d9291aeead0e761f0e00e98849245c2d4b9fb 100644 (file)
@@ -103,6 +103,25 @@ namespace TagLib {
       virtual void setYear(uint i);
       virtual void setTrack(uint i);
 
+      /*!
+       * Implements the unified tag dictionary interface -- export function.
+       * APE tags are perfectly compatible with the dictionary interface because they
+       * support both arbitrary tag names and multiple values. Currently only
+       * APE items of type *Text* are handled by the dictionary interface, while
+       * *Binary* and *Locator* items are simply ignored.
+       *
+       * The only conversion done by this export function is to rename the APE tags
+       * TRACK to TRACKNUMBER and YEAR to DATE, respectively, in order to be compliant
+       * with the names used in other formats.
+       */
+      virtual TagDict toDict() const;
+
+      /*!
+       * Implements the unified tag dictionary interface -- import function. The same
+       * comments as for the export function apply.
+       */
+      virtual void fromDict(const TagDict &);
+
       /*!
        * Returns a pointer to the tag's footer.
        */
index 715daf04f79873f66ec976244d20999a1c427bfa..f67a71e7e34cad6f81bd0dab4c6274cf8bcd3cd9 100644 (file)
@@ -262,11 +262,14 @@ namespace TagLib {
 
       /*!
        * Implements the unified tag dictionary interface -- export function.
+       * This function does some work to translate the hard-specified ID3v2
+       * frame types into a free-form string-to-stringlist dictionary.
        */
       virtual TagDict toDict() const;
 
       /*!
        * Implements the unified tag dictionary interface -- import function.
+       * See the comments in toDict().
        */
       virtual void fromDict(const TagDict &);
 
index 988f616ddcecee9916d85a53bd41fd92771fc93c..6ad23c6ac02702812fc6d9844a50ac20ab06974e 100644 (file)
@@ -142,11 +142,16 @@ namespace TagLib {
 
       /*!
        * Implements the unified tag dictionary interface -- export function.
+       * The result is a one-to-one match of the Xiph comment, since it is
+       * completely compatible with the dictionary interface (in fact, a Xiph
+       * comment is nothing more than a map from tag names to list of values,
+       * as is the dict interface).
        */
       virtual TagDict toDict() const;
 
       /*!
        * Implements the unified tag dictionary interface -- import function.
+       * The tags from the given dict will be stored one-to-one in the file.
        */
       virtual void fromDict(const TagDict &);