#include <tstringlist.h>
#include "commentsframe.h"
+#include "tpropertymap.h"
using namespace TagLib;
using namespace ID3v2;
#include <id3v2tag.h>
#include "textidentificationframe.h"
+#include "tpropertymap.h"
+#include "id3v1genres.h"
using namespace TagLib;
using namespace ID3v2;
TextIdentificationFrame *TextIdentificationFrame::createTIPLFrame(const PropertyMap &properties) // static
{
- TextIdentificationFrame *frame = TextIdentificationFrame("TIPL");
+ TextIdentificationFrame *frame = new TextIdentificationFrame("TIPL");
StringList l;
for(PropertyMap::ConstIterator it = properties.begin(); it != properties.end(); ++it){
l.append(it->first);
TextIdentificationFrame *TextIdentificationFrame::createTMCLFrame(const PropertyMap &properties) // static
{
- TextIdentificationFrame *frame = TextIdentificationFrame("TMCL");
+ TextIdentificationFrame *frame = new TextIdentificationFrame("TMCL");
StringList l;
for(PropertyMap::ConstIterator it = properties.begin(); it != properties.end(); ++it){
if(!it->first.startsWith(instrumentPrefix)) // should not happen
// array of allowed TIPL prefixes and their corresponding key value
static const uint involvedPeopleSize = 5;
-static const char* involvedPeople[2] = {
+static const char* involvedPeople[][2] = {
{"ARRANGER", "ARRANGER"},
{"ENGINEER", "ENGINEER"},
{"PRODUCER", "PRODUCER"},
{"DJ-MIX", "DJMIXER"},
- {"MIX", "MIXER"}
+ {"MIX", "MIXER"},
};
const KeyConversionMap &TextIdentificationFrame::involvedPeopleMap() // static
if(frameID() == "TMCL")
return makeTMCLProperties();
PropertyMap map;
- String tagName = frameIDToTagName(frameID());
+ String tagName = frameIDToKey(frameID());
if(tagName.isNull()) {
map.unsupportedData().append(frameID());
return map;
(*it)[tpos] = ' ';
}
}
- return KeyValuePair(tagName, values);
+ PropertyMap ret;
+ ret.insert(tagName, values);
+ return ret;
}
////////////////////////////////////////////////////////////////////////////////
bool found = false;
for(uint i = 0; i < involvedPeopleSize; ++i)
if(*it == involvedPeople[i][0]) {
- map.insert(involvedPeople[i][1], (++it).split(","));
+ map.insert(involvedPeople[i][1], (++it)->split(","));
found = true;
break;
}
map.unsupportedData().append(frameID());
return map;
}
- map.insert(L"PERFORMER:" + instrument, (++it).split(","));
+ map.insert(L"PERFORMER:" + instrument, (++it)->split(","));
}
return map;
}
#include "unsynchronizedlyricsframe.h"
#include <tbytevectorlist.h>
#include <tdebug.h>
+#include <tpropertymap.h>
using namespace TagLib;
using namespace ID3v2;
#include "urllinkframe.h"
#include <tdebug.h>
#include <tstringlist.h>
+#include <tpropertymap.h>
using namespace TagLib;
using namespace ID3v2;
#include "id3v2frame.h"
#include "id3v2synchdata.h"
#include "tpropertymap.h"
+#include "frames/textidentificationframe.h"
+#include "frames/urllinkframe.h"
+#include "frames/unsynchronizedlyricsframe.h"
+#include "frames/commentsframe.h"
using namespace TagLib;
using namespace ID3v2;
return d;
}
-String TextIdentificationFrame::instrumentPrefix("PERFORMER:");
-String TextIdentificationFrame::commentPrefix("COMMENT:");
-String TextIdentificationFrame::urlPrefix("URL:");
+const String Frame::instrumentPrefix("PERFORMER:");
+const String Frame::commentPrefix("COMMENT:");
+const String Frame::urlPrefix("URL:");
////////////////////////////////////////////////////////////////////////////////
// public members
ByteVector frameID = keyToFrameID(key);
if(!frameID.isNull()) {
if(frameID[0] == 'T'){ // text frame
- TextIdentificationFrame* frame = TextIdentificationFrame(frameID, String::UTF8);
+ TextIdentificationFrame *frame = new TextIdentificationFrame(frameID, String::UTF8);
frame->setText(values);
return frame;
} else if(values.size() == 1){ // URL frame (not WXXX); support only one value
- UrlLinkFrame* frame = UrlLinkFrame(frameID);
+ UrlLinkFrame* frame = new UrlLinkFrame(frameID);
frame->setUrl(values.front());
return frame;
}
// now we check if it's one of the "special" cases:
// -LYRICS: depending on the number of values, use USLT or TXXX (with description=LYRICS)
if(key == "LYRICS" && values.size() == 1){
- UnsynchronizedLyricsFrame *frame = UnsynchronizedLyricsFrame();
+ UnsynchronizedLyricsFrame *frame = new UnsynchronizedLyricsFrame();
frame->setText(values.front());
return frame;
}
// -URL: depending on the number of values, use WXXX or TXXX (with description=URL)
if((key == "URL" || key.startsWith(urlPrefix)) && values.size() == 1){
- UserUrlLinkFrame *frame = UserUrlLinkFrame(String::UTF8);
+ UserUrlLinkFrame *frame = new UserUrlLinkFrame(String::UTF8);
frame->setDescription(key == "URL" ? key : key.substr(urlPrefix.size()));
frame->setUrl(values.front());
return frame;
}
// -COMMENT: depending on the number of values, use COMM or TXXX (with description=COMMENT)
if((key == "COMMENT" || key.startsWith(commentPrefix)) && values.size() == 1){
- CommentsFrame *frame = CommentsFrame(String::UTF8);
+ CommentsFrame *frame = new CommentsFrame(String::UTF8);
frame->setDescription(key == "COMMENT" ? key : key.substr(commentPrefix.size()));
frame->setText(values.front());
return frame;
}
// if non of the above cases apply, we use a TXXX frame with the key as description
- return UserTextIdentificationFrame(key, values, String::UTF8);
+ return new UserTextIdentificationFrame(key, values, String::UTF8);
}
Frame::~Frame()
{"TIME", "TDRC"}, // 2.3 -> 2.4
};
-FrameIDMap &deprecationMap()
+Map<ByteVector,ByteVector> &deprecationMap()
{
- static FrameIDMap depMap;
+ static Map<ByteVector,ByteVector> depMap;
if(depMap.isEmpty())
for(uint i = 0; i < deprecatedFramesSize; ++i)
depMap[deprecatedFrames[i][0]] = deprecatedFrames[i][1];
for(FrameListMap::ConstIterator it = frameListMap().begin(); it != frameListMap().end(); ++it){
for(FrameList::ConstIterator lit = it->second.begin(); lit != it->second.end(); ++lit){
PropertyMap frameProperties = (*lit)->asProperties();
- if(it->first == "TIPL")
+ if(it->first == "TIPL") {
if (tiplProperties != frameProperties)
framesToDelete.append(*lit);
else
tiplProperties.erase(frameProperties);
- else if(it->first == "TMCL")
+ } else if(it->first == "TMCL") {
if (tmclProperties != frameProperties)
framesToDelete.append(*lit);
else
tmclProperties.erase(frameProperties);
- else if(!properties.contains(frameProperties))
+ } else if(!properties.contains(frameProperties))
framesToDelete.append(*lit);
else
properties.erase(frameProperties);
// now create the "one key per frame" frames
for(PropertyMap::ConstIterator it = properties.begin(); it != properties.end(); ++it)
addFrame(Frame::createTextualFrame(it->first, it->second));
- return PropertyMap; // ID3 implements the complete PropertyMap interface, so an empty map is returned
+ return PropertyMap(); // ID3 implements the complete PropertyMap interface, so an empty map is returned
}
ByteVector ID3v2::Tag::render() const
#include <tstring.h>
#include <tdebug.h>
+#include <tpropertymap.h>
#include "vorbisfile.h"
+
using namespace TagLib;
class Vorbis::File::FilePrivate
#include <tdebug.h>
#include <xiphcomment.h>
+#include <tpropertymap.h>
using namespace TagLib;
return d->fieldListMap;
}
-TagDict Ogg::XiphComment::toDict() const
+PropertyMap Ogg::XiphComment::properties() const
{
return d->fieldListMap;
}
-void Ogg::XiphComment::fromDict(const TagDict &tagDict)
+PropertyMap Ogg::XiphComment::setProperties(const PropertyMap &properties)
{
// check which keys are to be deleted
StringList toRemove;
- FieldListMap::ConstIterator it = d->fieldListMap.begin();
- for(; it != d->fieldListMap.end(); ++it) {
- if (!tagDict.contains(it->first))
- toRemove.append(it->first);
- }
+ for(FieldListMap::ConstIterator it = d->fieldListMap.begin(); it != d->fieldListMap.end(); ++it)
+ if (!properties.contains(it->first))
+ toRemove.append(it->first);
- StringList::ConstIterator removeIt = toRemove.begin();
- for (; removeIt != toRemove.end(); ++removeIt)
- removeField(*removeIt);
+ for(StringList::ConstIterator it = toRemove.begin(); it != toRemove.end(); ++it)
+ removeField(*it);
- /* now go through keys in tagDict and check that the values match those in the xiph comment */
- TagDict::ConstIterator tagIt = tagDict.begin();
- for (; tagIt != tagDict.end(); ++tagIt)
+ // now go through keys in \a properties and check that the values match those in the xiph comment */
+ PropertyMap::ConstIterator it = properties.begin();
+ for(; it != properties.end(); ++it)
{
- if (!d->fieldListMap.contains(tagIt->first) || !(tagIt->second == d->fieldListMap[tagIt->first])) {
- const StringList &sl = tagIt->second;
- if(sl.size() == 0) {
+ if(!d->fieldListMap.contains(it->first) || !(it->second == d->fieldListMap[it->first])) {
+ const StringList &sl = it->second;
+ if(sl.size() == 0)
// zero size string list -> remove the tag with all values
- removeField(tagIt->first);
- }
+ removeField(it->first);
else {
// replace all strings in the list for the tag
StringList::ConstIterator valueIterator = sl.begin();
- addField(tagIt->first, *valueIterator, true);
+ addField(it->first, *valueIterator, true);
++valueIterator;
for(; valueIterator != sl.end(); ++valueIterator)
- addField(tagIt->first, *valueIterator, false);
+ addField(it->first, *valueIterator, false);
}
}
}
+ return PropertyMap();
}
String Ogg::XiphComment::vendorID() const
const FieldListMap &fieldListMap() const;
/*!
- * Implements the unified tag dictionary interface -- export function.
+ * Implements the unified property 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
+ * completely compatible with the property interface (in fact, a Xiph
* comment is nothing more than a map from tag names to list of values,
* as is the dict interface).
*/
- TagDict toDict() const;
+ PropertyMap properties() const;
/*!
- * Implements the unified tag dictionary interface -- import function.
- * The tags from the given dict will be stored one-to-one in the file.
+ * Implements the unified property interface -- import function.
+ * The tags from the given map will be stored one-to-one in the file.
*/
- void fromDict(const TagDict &);
+ PropertyMap setProperties(const PropertyMap&);
/*!
* Returns the vendor ID of the Ogg Vorbis encoder. libvorbis 1.0 as the
{
}
-PropertyMap::PropertyMap(const PropertyMap &m) : SimplePropertyMap(m)
+PropertyMap::PropertyMap(const PropertyMap &m) : SimplePropertyMap(m), unsupported(m.unsupported)
{
}
+PropertyMap::PropertyMap(const SimplePropertyMap &m)
+{
+ for(SimplePropertyMap::ConstIterator it = m.begin(); it != m.end(); ++it){
+ String key = prepareKey(it->first);
+ if(!key.isNull())
+ insert(it->first, it->second);
+ else
+ unsupported.append(it->first);
+ }
+}
+
PropertyMap::~PropertyMap()
{
}
PropertyMap(const PropertyMap &m);
+ /*!
+ * Creates a PropertyMap initialized from a SimplePropertyMap. Copies all
+ * entries from \a m that have valid keys.
+ * Invalid keys will be appended to the unsupportedData() list.
+ */
+ PropertyMap(const SimplePropertyMap &m);
+
virtual ~PropertyMap();
/*!
/*!
* Returns true if this map contains all keys of \a other
- * and the values coincide for that keys.
+ * and the values coincide for that keys. Does not take
+ * the unsupportedData list into account.
*/
bool contains(const PropertyMap &other) const;
*/
StringList &operator[](const String &key);
+ /*!
+ * Returns true if and only if \other has the same contents as this map.
+ */
+ bool operator==(const PropertyMap &other) const;
+
+ /*!
+ * Returns false if and only \other has the same contents as this map.
+ */
+ bool operator!=(const PropertyMap &other) const;
+
/*!
* If a PropertyMap is read from a File object using File::properties(),
* the StringList returned from this function will represent metadata