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;
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.
*/
/*!
* 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 &);