Added toDict and fromDict methods for APE tags.

This commit is contained in:
Michael Helmling 2011-08-27 22:30:20 +02:00
parent 58db919e43
commit fa8159a9d0
4 changed files with 91 additions and 0 deletions

View 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;

View 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.
*/

View 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 &);

View 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 &);