]> granicus.if.org Git - taglib/commitdiff
ID3 interface complete; vorbis done; wav done
authorMichael Helmling <helmling@mathematik.uni-kl.de>
Tue, 14 Feb 2012 20:27:14 +0000 (21:27 +0100)
committerMichael Helmling <helmling@mathematik.uni-kl.de>
Tue, 14 Feb 2012 20:27:14 +0000 (21:27 +0100)
21 files changed:
taglib/mpeg/id3v2/frames/commentsframe.cpp
taglib/mpeg/id3v2/frames/commentsframe.h
taglib/mpeg/id3v2/frames/textidentificationframe.cpp
taglib/mpeg/id3v2/frames/textidentificationframe.h
taglib/mpeg/id3v2/frames/unsynchronizedlyricsframe.cpp
taglib/mpeg/id3v2/frames/unsynchronizedlyricsframe.h
taglib/mpeg/id3v2/frames/urllinkframe.cpp
taglib/mpeg/id3v2/id3v2frame.cpp
taglib/mpeg/id3v2/id3v2frame.h
taglib/mpeg/id3v2/id3v2tag.cpp
taglib/ogg/flac/oggflacfile.cpp
taglib/ogg/flac/oggflacfile.h
taglib/ogg/speex/speexfile.cpp
taglib/ogg/speex/speexfile.h
taglib/ogg/vorbis/vorbisfile.cpp
taglib/ogg/vorbis/vorbisfile.h
taglib/riff/aiff/aifffile.cpp
taglib/riff/aiff/aifffile.h
taglib/riff/wav/wavfile.cpp
taglib/riff/wav/wavfile.h
taglib/toolkit/tpropertymap.h

index 5730b7531115e1771a03f22b83c5e3d2f9937d8b..adc773ea68d3914f1abbec7ac5a99a197eff4367 100644 (file)
@@ -109,7 +109,7 @@ void CommentsFrame::setTextEncoding(String::Type encoding)
   d->textEncoding = encoding;
 }
 
-PropertyMap CommentsFrame::asDescription() const
+PropertyMap CommentsFrame::asProperties() const
 {
   String key = PropertyMap::prepareKey(description());
   PropertyMap map;
@@ -118,7 +118,7 @@ PropertyMap CommentsFrame::asDescription() const
   if(key.isNull())
     map.unsupportedData().append(L"COMM/" + description());
   else
-    map.insert(key, text());
+    map.insert("COMMENT:" + key, text());
   return map;
 }
 
index 30d21ca1effafc342f52ac0f6b778bed0009d2ef..f65f6f01c26130134182fd7181054e01f7829d3e 100644 (file)
@@ -137,15 +137,15 @@ namespace TagLib {
       void setTextEncoding(String::Type encoding);
 
       /*!
-       * Parses this frame as PropertyMap.
-       * - description() will be used as key
-       * - if description() is empty, the key will be "COMMENT"
+       * Parses this frame as PropertyMap with a single key.
+       * - if description() is empty or "COMMENT", the key will be "COMMENT"
        * - if description() is not a valid PropertyMap key, the frame will be
        *   marked unsupported by an entry "COMM/<description>" in the unsupportedData()
        *   attribute of the returned map.
+       * - otherwise, the key will be "COMMENT:<description>"
        * - The single value will be the frame's text().
        */
-      PropertyMap asDescription() const;
+      PropertyMap asProperties() const;
 
       /*!
        * Comments each have a unique description.  This searches for a comment
index f3aeb083903b88f5d9c98079d0c9fbed141dfd5a..29943c964a5bb31dec3a9a39d6f63489da83b3ab 100644 (file)
@@ -59,7 +59,7 @@ TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data) :
 
 TextIdentificationFrame *TextIdentificationFrame::createTIPLFrame(const PropertyMap &properties) // static
 {
-  TextIdentificationFrameframe = TextIdentificationFrame("TIPL");
+  TextIdentificationFrame *frame = TextIdentificationFrame("TIPL");
   StringList l;
   for(PropertyMap::ConstIterator it = properties.begin(); it != properties.end(); ++it){
     l.append(it->first);
@@ -68,6 +68,21 @@ TextIdentificationFrame *TextIdentificationFrame::createTIPLFrame(const Property
   frame->setText(l);
   return frame;
 }
+
+TextIdentificationFrame *TextIdentificationFrame::createTMCLFrame(const PropertyMap &properties) // static
+{
+  TextIdentificationFrame *frame = TextIdentificationFrame("TMCL");
+  StringList l;
+  for(PropertyMap::ConstIterator it = properties.begin(); it != properties.end(); ++it){
+    if(!it->first.startsWith(instrumentPrefix)) // should not happen
+      continue;
+    l.append(it->first.substr(instrumentPrefix.size()));
+    l.append(it->second.toString(","));
+  }
+  frame->setText(l);
+  return frame;
+}
+
 TextIdentificationFrame::~TextIdentificationFrame()
 {
   delete d;
index fc48a99f2825b7b95dcf73f1edd593992f969554..b82e7d3a6d47b414e6bfcc97458f21ade2053016 100644 (file)
@@ -131,6 +131,13 @@ namespace TagLib {
        */
       static TextIdentificationFrame *createTIPLFrame(const PropertyMap &properties);
 
+      /*!
+       * This is a special factory method to create a TMCL (musician credits list)
+       * frame from the given \a properties. Will parse key=[list of values] data
+       * into the TMCL format as specified in the ID3 standard, where key should be
+       * of the form instrumentPrefix:instrument.
+       */
+      static TextIdentificationFrame *createTMCLFrame(const PropertyMap &properties);
       /*!
        * Destroys this TextIdentificationFrame instance.
        */
@@ -186,6 +193,7 @@ namespace TagLib {
        * to the corresponding key used in a TIPL ID3 frame to describe that role.
        */
       static const KeyConversionMap &involvedPeopleMap();
+
       PropertyMap asProperties() const;
 
     protected:
@@ -243,6 +251,12 @@ namespace TagLib {
        */
       explicit UserTextIdentificationFrame(const ByteVector &data);
 
+      /*!
+       * Creates a user defined text identification frame with the given \a description
+       * and \a text.
+       */
+      UserTextIdentificationFrame(const String &description, const StringList &values, String::Type encoding = String::Latin1);
+
       virtual String toString() const;
 
       /*!
index b3a9b3daf1bfa9a3532709d4ce9ec2d3f7b6da68..e5142566434a3dc64d199ea9f229f7f71567b49c 100644 (file)
@@ -113,8 +113,14 @@ void UnsynchronizedLyricsFrame::setTextEncoding(String::Type encoding)
 
 PropertyMap UnsynchronizedLyricsFrame::asProperties() const
 {
+  String key = PropertyMap::prepareKey(description());
   PropertyMap map;
-  map.insert("LYRICS", text());
+  if(key.isEmpty())
+    key = "LYRICS";
+  if(key.isNull())
+    map.unsupportedData().append(L"USLT/" + description());
+  else
+    map.insert("LYRICS:" + key, text());
   return map;
 }
 
index f13134c4b2e43355f8006d48d0e5261230374b71..03648ee47920352a92768d8a526ca028c2fcf625 100644 (file)
@@ -139,6 +139,17 @@ namespace TagLib {
        * Parses this frame as PropertyMap. The returned map will contain a single key
        * "LYRICS" with the text() as single value.
        */
+      /*!
+       * Parses this frame as PropertyMap with a single key.
+       * - if description() is empty or "LYRICS", the key will be "LYRICS"
+       * - if description() is not a valid PropertyMap key, the frame will be
+       *   marked unsupported by an entry "USLT/<description>" in the unsupportedData()
+       *   attribute of the returned map.
+       * - otherwise, the key will be "LYRICS:<description>"
+       * - The single value will be the frame's text().
+       * Note that currently the language() field is not supported by the PropertyMap
+       * interface.
+       */
       PropertyMap asProperties() const;
 
     protected:
index b1800697e097284fb3a50e3f67df12256d676476..c0a771e14b72fb3a1d68edf0ff84fb0307df40c7 100644 (file)
@@ -162,7 +162,7 @@ PropertyMap UserUrlLinkFrame::asProperties() const
   if(key.isNull())
     map.unsupportedData().append(L"WXXX/" + description());
   else
-    map.insert(key, url());
+    map.insert("URL:" + key, url());
   return map;
 }
 
index bf33fa8e8040d716877f0e66410f65ed578cbfaa..25e599aa96dd18d6bf2f7cada6e2300f352c41de 100644 (file)
@@ -96,10 +96,54 @@ ByteVector Frame::textDelimiter(String::Type t)
   return d;
 }
 
+String TextIdentificationFrame::instrumentPrefix("PERFORMER:");
+String TextIdentificationFrame::commentPrefix("COMMENT:");
+String TextIdentificationFrame::urlPrefix("URL:");
+
 ////////////////////////////////////////////////////////////////////////////////
 // public members
 ////////////////////////////////////////////////////////////////////////////////
 
+Frame *Frame::createTextualFrame(const String &key, const StringList &values) //static
+{
+  // check if the key is contained in the key<=>frameID mapping
+  ByteVector frameID = keyToFrameID(key);
+  if(!frameID.isNull()) {
+    if(frameID[0] == 'T'){ // text frame
+      TextIdentificationFrame* frame = 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);
+        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();
+    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);
+    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);
+    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);
+}
+
 Frame::~Frame()
 {
   delete d;
@@ -263,7 +307,7 @@ String::Type Frame::checkTextEncoding(const StringList &fields, String::Type enc
   return checkEncoding(fields, encoding, header()->version());
 }
 
-static const uint frameTranslationSize = 50;
+static const uint frameTranslationSize = 51;
 static const char *frameTranslation[][2] = {
   // Text information frames
   { "TALB", "ALBUM"},
@@ -325,7 +369,7 @@ static const char *frameTranslation[][2] = {
   { "WPUB", "PUBLISHERWEBPAGE" },
   //{ "WXXX", "URL"}, handled specially
   // Other frames
-  //{ "COMM", "COMMENT" }, handled specially
+  { "COMM", "COMMENT" },
   //{ "USLT", "LYRICS" }, handled specially
 };
 
@@ -399,6 +443,24 @@ PropertyMap Frame::asProperties() const
     return m;
   }
 }
+
+void Frame::splitProperties(const PropertyMap &original, PropertyMap &singleFrameProperties,
+          PropertyMap &tiplProperties, PropertyMap &tmclProperties)
+{
+
+  singleFrameProperties.clear();
+  tiplProperties.clear();
+  tmclProperties.clear();
+  for(PropertyMap::ConstIterator it = original.begin(); it != original.end(); ++it) {
+    if(TextIdentificationFrame::involvedPeopleMap().contains(it->first))
+      tiplProperties.insert(it->first, it->second);
+    else if(it->first.startsWith(TextIdentificationFrame::instrumentPrefix))
+      tmclProperties.insert(it->first, it->second);
+    else
+      singleFrameProperties.insert(it->first, it->second);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Frame::Header class
 ////////////////////////////////////////////////////////////////////////////////
index 8efe68708b0ed0fab6c2756763ef06765cb7c9a5..3a9ade267f2e9ead63984ca69a770253fef206dd 100644 (file)
@@ -57,6 +57,14 @@ namespace TagLib {
       friend class FrameFactory;
 
     public:
+
+      /*!
+       * Creates a textual frame which corresponds to a single key in the PropertyMap
+       * interface. These are all (User)TextIdentificationFrames except TIPL and TMCL,
+       * all (User)URLLinkFrames, CommentsFrames, and UnsynchronizedLyricsFrame.
+       */
+      static Frame *createTextualFrame(const String &key, const StringList &values);
+
       /*!
        * Destroys this Frame instance.
        */
@@ -127,6 +135,23 @@ namespace TagLib {
        */
       static ByteVector textDelimiter(String::Type t);
 
+      /*!
+       * The string with which an instrument name is prefixed to build a key in a PropertyMap;
+       * used to translate PropertyMaps to TMCL frames. In the current implementation, this
+       * is "PERFORMER:".
+       */
+      static const String instrumentPrefix;
+      /*!
+       * The PropertyMap key prefix which triggers the use of a COMM frame instead of a TXXX
+       * frame for a non-standard key. In the current implementation, this is "COMMENT:".
+       */
+      static const String commentPrefix;
+      /*!
+       * The PropertyMap key prefix which triggers the use of a WXXX frame instead of a TXX
+       * frame for a non-standard key. In the current implementation, this is "URL:".
+       */
+      static const String urlPrefix;
+
     protected:
       class Header;
 
@@ -244,6 +269,23 @@ namespace TagLib {
        */
       static String frameIDToKey(const ByteVector &);
 
+
+      /*!
+       * This helper function splits the PropertyMap \a original into three ProperytMaps
+       * \a singleFrameProperties, \a tiplProperties, and \a tmclProperties, such that:
+       * - \a singleFrameProperties contains only of keys which can be represented with
+       *   exactly one ID3 frame per key. In the current implementation
+       *   this is everything except for the fixed "involved people" keys and keys of the
+       *   form "TextIdentificationFrame::instrumentPrefix" + "instrument", which are
+       *   mapped to a TMCL frame.
+       * - \a tiplProperties will consist of those keys that are present in
+       *   TextIdentificationFrame::involvedPeopleMap()
+       * - \a tmclProperties contains the "musician credits" keys which should be mapped
+       *   to a TMCL frame
+       */
+      static void splitProperties(const PropertyMap &original, PropertyMap &singleFrameProperties,
+          PropertyMap &tiplProperties, PropertyMap &tmclProperties);
+
     private:
       Frame(const Frame &);
       Frame &operator=(const Frame &);
index f9b5dfa860daac4461f0410b8269df8b3d9dd69a..f6d7e77286f3bbc5a056449985fa5dcc67a86e78 100644 (file)
@@ -344,160 +344,46 @@ PropertyMap ID3v2::Tag::properties() const
 
 PropertyMap ID3v2::Tag::setProperties(const PropertyMap &origProps)
 {
-  FrameList toRemove;
-  PropertyMap properties = origProps;
-  // first find out what frames to remove; we do not remove in-place
-  // because that would invalidate FrameListMap iterators.
-  // At the moment, we remove _all_ frames that don't contain unsupported data,
-  // and create new ones in the next step; this is to avoid clumsy technicalities
-  // arising when trying to do this more efficient. For example, if the current tag
-  // contains one URL attribute stored in an WXXX frame, but the given \a properties
-  // contain two URL values, we would need to remove the WXXX frame (which supports
-  // only one value), and create a TXXX frame with description=URL.
-  // The same may happen with COMM and USLT. Additionally, handling of TIPL and TMCL is
-  // complicated.
-  // In the future, someone might come up with a more clever sync algorithm. :-)
-  for(FrameListMap::ConstIterator it = frameListMap().begin(); it != frameListMap().end(); ++it) {
-    String key = Frame::frameIDToKey(it->first);
-    // for unsupported (binary) frame types, as well as frames that need special treatment
-    // (TXXX, WXXX, COMM, TMCL, TIPL, USLT), key will be String::null
-    if(key.isNull())
-      continue;
-    // else: non-user text or url frame -> there should be only one frame of this type,
-    // and it's asProperties() method should return a PropertyMap with exactly one key
-    // and empty unsupportedData().
-    if(it->second.size() != 1)
-      debug("invalid ID3 tag: found more than one " + it->first + " frame");
-    PropertyMap frameMap = it->second[0]->asProperties();
-    if(properties.contains(key) && frameMap[key] == properties[key])
-      properties.erase(key);
-    else
-      toRemove.append(it->second[0]);
-  }
-
-  // now handle the special cases
-  // first: TXXX frames
-  FrameList &userTextFrames = frameList("TXXX");
-  for(FrameList::ConstIterator it = userTextFrames.begin(); it != userTextFrames.end(); ++it) {
-    PropertyMap frameMap = (*it)->asProperties();
-    if(!frameMap.unsupportedData().isEmpty())
-      // don't touch unsupported frames
-      continue;
-    // TXXX frames yield only one key, so it must be begin()->first
-    String &key = frameMap.begin()->first;
-    if(!Frame::keyToFrameID(key).isNull())
-      // TXXX frame which a description (=key) for which there is a dedicated frame.
-      // We don't want this, so remove the frame, the appropriate T*** or W*** frame
-      // will be created later on.
-      toRemove.append(*it);
-    if(key.find(":") > 0)
-      // colon-separated key: this should be inside a TMCL frame.
-      toRemove.append(*it);
-    // More (ugly) exceptions: If the user provides more than one COMMENT, LYRICS, or URL
-    // tag, we store all of these in a TXXX, because COMM, USLT and WXXX. Otherwise there
-    // should not be such a TXXX frame.
-    if(key == "COMMENT") {
-      if(properties.contains("COMMENT")
-          && properties["COMMENT"].size() >= 2
-          && properties["COMMENT"] == frameMap.begin()->second)
-        properties.erase("COMMENT");
-      else
-        toRemove.append(*it);
-    }else if(key == "LYRICS") {
-      if(properties.contains("LYRICS")
-          && properties["LYRICS"].size() >= 2
-          && properties["LYRICS"] == frameMap.begin()->second)
-        properties.erase("LYRICS");
+  FrameList framesToDelete;
+  // we split up the PropertyMap into the "normal" keys and the "complicated" ones,
+  // which are those according to TIPL or TMCL frames.
+  PropertyMap properties;
+  PropertyMap tiplProperties;
+  PropertyMap tmclProperties;
+  Frame::splitProperties(origProps, properties, tiplProperties, tmclProperties);
+  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 (tiplProperties != frameProperties)
+          framesToDelete.append(*lit);
+        else
+          tiplProperties.erase(frameProperties);
+      else if(it->first == "TMCL")
+        if (tmclProperties != frameProperties)
+          framesToDelete.append(*lit);
+        else
+          tmclProperties.erase(frameProperties);
+      else if(!properties.contains(frameProperties))
+        framesToDelete.append(*lit);
       else
-        toRemove.append(*it);
-    }else if(key == "URL") {
-       if(properties.contains("URL")
-           && properties["URL"].size() >= 2
-           && properties["URL"] == frameMap.begin()->second)
-         properties.erase("URL");
-       else
-         toRemove.append(*it);
+        properties.erase(frameProperties);
     }
   }
-
-  // next: WXXX frames
-  FrameList &userUrlFrames = frameList("WXXX");
-  for(FrameList::ConstIterator it = userUrlFrames.begin(); it != userUrlFrames.end(); ++it) {
-    PropertyMap frameMap = (*it)->asProperties();
-    if(!frameMap.unsupportedData().isEmpty())
-      // don't touch unsupported frames
-      continue;
-    // WXXX frames yield only one key, so it must be begin()->first
-    String &key = frameMap.begin()->first;
-    if(!Frame::keyToFrameID(key).isNull())
-      // WXXX frame which a description (=key) for which there is a dedicated frame.
-      // We don't want this, so remove the frame, the appropriate T*** or W*** frame
-      // will be created later on.
-      toRemove.append(*it);
-    else if(key.find(":") > 0)
-      // colon-separated key: this should be inside a TMCL frame.
-      toRemove.append(*it);
-    // More exceptions: we don't allow COMMENT and LYRICS in WXXX; they should be in COMM and USLT
-    // (or TXXX, see above).
-    else if(key == "COMMENT" || key == "LYRICS")
-      toRemove.append(*it);
-    // now, the key is either URL or some other string that neither has a dedicated text frame, nor
-    // a colon. We accept the frame if it's contents match the values in properties. However, if
-    // key != URL and the values are changed, they will be stored inside a TXXX frame instead, since
-    // we can't distinguish free-form text from free-form URL keys (possible fix: use URL:REASON like
-    // in TMCL / TIPL?).
-    else if(properties.contains(key) && properties[key] == frameMap.begin()->second)
-      properties.erase(key);
-    else
-      toRemove.append(*it);
-  }
-  for(FrameList::ConstIterator it = toRemove.begin(); it != toRemove.end(); ++it)
+  for(FrameList::ConstIterator it = framesToDelete.begin(); it != framesToDelete.end(); ++it)
     removeFrame(*it);
 
-  // next: TIPL
-  PropertyMap existingTipl;
-  if(!frameList("TIPL").isEmpty())
-    existingTipl = frameList("TIPL").front()->asProperties();
-  PropertyMap requestedTipl;
-  KeyConversionMap::ConstIterator it = TextIdentificationFrame::involvedPeopleMap().begin();
-  bool rebuildTipl = false;
-  for(; it != TextIdentificationFrame::involvedPeopleMap().end(); ++it) {
-    if(properties.contains(it->first)){
-      requestedTipl.insert(it->first, properties[it->first]);
-      properties.erase(it->first); // it's ensured now that this key gets handled correctly
-      if(!existingTipl.contains(it->first) || existingTipl[it->first] != requestedTipl[it->first])
-        rebuildTipl = true;
-    } else if(existingTipl.contains(it->first))
-      rebuildTipl = true;
-  }
-  if(rebuildTipl){
-    removeFrames("TIPL");
-    addFrame(TextIdentificationFrame::createTIPLFrame(requestedTipl));
-  }
-
-  // next: create frames for everything still in properties except for TMCL ("PERFORMER:<instrument>")
-  // keys, which are collected in a dedicated map
-  PropertyMap requestedTmcl;
-  for(PropertyMap::ConstIterator it = properties.begin(); it != properties.end(); ++it){
-    if(it->first.find(":") != -1)
-      requestedTmcl.insert(it->first, it->second);
-    else{
-      // phew. Now we are in the simple case that our key=<value list> pair can be represented by a
-      // single frame, either a T*** (not TIPL, TMCL) or W*** frame.
-      ByteVector id = Frame::keyToFrameID(it->first);
-    }
-  }
-
-    // next: TMCL
-  PropertyMap existingTmcl;
-  if(!frameList("TMCL").isEmpty())
-    existingTmcl = frameList("TMCL").front()->asProperties();
-  bool rebuildTmcl = false;
-  // search for TMCL keys ("PERFORMER:<instrument>") in properties
-  for(PropertyMap::ConstIterator it = properties.begin(); it != properties.end(); ++it){
-    if(it->first.find(":") != -1)
-      requestedTmcl.insert(it->first, it->second);
-  }
+  // now create remaining frames:
+  // start with the involved people list (TIPL)
+  if(!tiplProperties.isEmpty())
+      addFrame(TextIdentificationFrame::createTIPLFrame(tiplProperties));
+  // proceed with the musician credit list (TMCL)
+  if(!tmclProperties.isEmpty())
+      addFrame(TextIdentificationFrame::createTMCLFrame(tmclProperties));
+  // 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
 }
 
 ByteVector ID3v2::Tag::render() const
index 437dabf09690dca09bee881a803e7c632dece89b..3addbffaa9b19760f7cd9a2df6c7954a8db0306b 100644 (file)
@@ -92,16 +92,6 @@ Ogg::XiphComment *Ogg::FLAC::File::tag() const
   return d->comment;
 }
 
-TagLib::TagDict Ogg::FLAC::File::toDict(void) const
-{
-  return d->comment->toDict();
-}
-
-void Ogg::FLAC::File::fromDict(const TagDict &dict)
-{
-  d->comment->fromDict(dict);
-}
-
 Properties *Ogg::FLAC::File::audioProperties() const
 {
   return d->properties;
index e39ac2cc4ed9ed133d7fda89611a42fbc0dfa31f..d4373795f1d2e398240cc619db020b9309c61178 100644 (file)
@@ -89,18 +89,6 @@ namespace TagLib {
        */
       virtual XiphComment *tag() const;
 
-      /*!
-       * Implements the unified tag dictionary interface -- export function.
-       * Returns the contents of the Ogg::XiphComment as TagDict.
-       */
-      TagDict toDict() const;
-
-      /*!
-       * Implements the unified tag dictionary interface -- import function.
-       * Matches the TagDict's contents to the XiphComment of the file.
-       */
-      void fromDict(const TagDict &);
-
       /*!
        * Returns the FLAC::Properties for this file.  If no audio properties
        * were read then this will return a null pointer.
index d602bcc827f186df085ca52df5424be25e3a74fb..3a4940a26a3e40c3dd92a0960d1eda67164a1edc 100644 (file)
@@ -82,16 +82,6 @@ Ogg::XiphComment *Speex::File::tag() const
   return d->comment;
 }
 
-TagLib::TagDict Ogg::Speex::File::toDict(void) const
-{
-  return d->comment->toDict();
-}
-
-void Ogg::Speex::File::fromDict(const TagDict &dict)
-{
-  d->comment->fromDict(dict);
-}
-
 Speex::Properties *Speex::File::audioProperties() const
 {
   return d->properties;
index 2af6cd828202aa6ced26a183911d0aad61e78e6b..c14cf2aa60d61d87d915716c175630a41f35e079 100644 (file)
@@ -82,17 +82,6 @@ namespace TagLib {
          * TagLib::File::tag().
          */
         virtual Ogg::XiphComment *tag() const;
-        /*!
-         * Implements the unified tag dictionary interface -- export function.
-         * Returns the contents of the Ogg::XiphComment as TagDict.
-         */
-        TagDict toDict() const;
-
-        /*!
-         * Implements the unified tag dictionary interface -- import function.
-         * Matches the TagDict's contents to the XiphComment of the file.
-         */
-        void fromDict(const TagDict &);
 
         /*!
          * Returns the Speex::Properties for this file.  If no audio properties
index fe50d6d09c4c9e7be63d9ec481b7b9ff226d758c..9b12f4963d9d14588d1a752710ac0b5cc93eb7a0 100644 (file)
@@ -85,14 +85,14 @@ Ogg::XiphComment *Vorbis::File::tag() const
   return d->comment;
 }
 
-TagLib::TagDict Ogg::Vorbis::File::toDict(void) const
+PropertyMap Vorbis::File::properties() const
 {
-  return d->comment->toDict();
+  return d->comment->properties();
 }
 
-void Ogg::Vorbis::File::fromDict(const TagDict &dict)
+PropertyMap Vorbis::File::setProperties(const PropertyMap &properties)
 {
-  d->comment->fromDict(dict);
+  return d->comment->setProperties(properties);
 }
 
 Vorbis::Properties *Vorbis::File::audioProperties() const
index 989eac3dc370ec2943cfb6d71dedf806d1a86f62..15c29d99caaa785fdbfcf9cc51e08668663d321a 100644 (file)
@@ -90,17 +90,19 @@ namespace TagLib {
        */
       virtual Ogg::XiphComment *tag() const;
 
+
       /*!
-       * Implements the unified tag dictionary interface -- export function.
-       * Returns the contents of the Ogg::XiphComment as TagDict.
+       * Implements the unified property interface -- export function.
+       * This forwards directly to XiphComment::properties().
        */
-      TagDict toDict() const;
+      PropertyMap properties() const;
 
       /*!
        * Implements the unified tag dictionary interface -- import function.
-       * Matches the TagDict's contents to the XiphComment of the file.
+       * Like properties(), this is a forwarder to the file's XiphComment.
        */
-      void fromDict(const TagDict &);
+      PropertyMap setProperties(const PropertyMap &);
+
       /*!
        * Returns the Vorbis::Properties for this file.  If no audio properties
        * were read then this will return a null pointer.
index 5a00b807dcccbe684dd112d9b7353e3947e77d14..bc2a8569c9a0a1a24a740c3f7b02c2c0b052cd5b 100644 (file)
@@ -84,15 +84,14 @@ ID3v2::Tag *RIFF::AIFF::File::tag() const
   return d->tag;
 }
 
-TagLib::TagDict RIFF::AIFF::File::toDict(void) const
+PropertyMap RIFF::AIFF::File::properties() const
 {
-  return d->tag->toDict();
-
+  return d->tag->properties();
 }
 
-void RIFF::AIFF::File::fromDict(const TagDict &dict)
+PropertyMap RIFF::AIFF::File::setProperties(const PropertyMap &properties)
 {
-  d->tag->fromDict(dict);
+  return d->tag->setProperties(properties);
 }
 
 
index af7d7b7a2362703834765bad1d2e122b0ec737f5..a50c8ecba6b36c4f255b420be2beec944405adad 100644 (file)
@@ -84,16 +84,16 @@ namespace TagLib {
         virtual ID3v2::Tag *tag() const;
 
         /*!
-         * Implements the unified tag dictionary interface -- export function.
-         * This method forwards to ID3v2::Tag::toDict.
+         * Implements the unified property interface -- export function.
+         * This method forwards to ID3v2::Tag::properties().
          */
-        TagDict toDict() const;
+        PropertyMap properties() const;
 
         /*!
-         * Implements the unified tag dictionary interface -- import function.
-         * This method forwards to ID3v2::Tag::fromDict.
+         * Implements the unified property interface -- import function.
+         * This method forwards to ID3v2::Tag::setProperties().
          */
-        void fromDict(const TagDict &);
+        PropertyMap setProperties(const PropertyMap &);
 
         /*!
          * Returns the AIFF::Properties for this file.  If no audio properties
index cb274dd104c0ed55bce2867018772bb385f73438..afc307d834adabcb17f9fa8fe601ffd7c91f0244 100644 (file)
@@ -84,14 +84,14 @@ ID3v2::Tag *RIFF::WAV::File::tag() const
   return d->tag;
 }
 
-TagLib::TagDict RIFF::WAV::File::toDict(void) const
+PropertyMap RIFF::WAV::File::properties() const
 {
-  return d->tag->toDict();
+  return d->tag->properties();
 }
 
-void RIFF::WAV::File::fromDict(const TagDict &dict)
+PropertyMap RIFF::WAV::File::setProperties(const PropertyMap &properties)
 {
-  d->tag->fromDict(dict);
+  return d->tag->setProperties(properties);
 }
 
 
index 8e75afdb9377a3280a5689c56035f31be2f930bb..861f3f77e1e9354b2373f2bd22023cc9fa0c50e2 100644 (file)
@@ -84,16 +84,16 @@ namespace TagLib {
         virtual ID3v2::Tag *tag() const;
 
         /*!
-         * Implements the unified tag dictionary interface -- export function.
-         * This method forwards to ID3v2::Tag::toDict.
+         * Implements the unified property interface -- export function.
+         * This method forwards to ID3v2::Tag::properties().
          */
-        TagDict toDict() const;
+        PropertyMap properties() const;
 
         /*!
-         * Implements the unified tag dictionary interface -- import function.
-         * This method forwards to ID3v2::Tag::fromDict.
+         * Implements the unified property interface -- import function.
+         * This method forwards to ID3v2::Tag::setProperties().
          */
-        void fromDict(const TagDict &);
+        PropertyMap setProperties(const PropertyMap &);
 
         /*!
          * Returns the WAV::Properties for this file.  If no audio properties
index 1fbcb5845e86641428d7a953895c39da566dfd2f..071c3e9baf5f54b4a0718a469aa402bf221c218a 100644 (file)
@@ -91,11 +91,22 @@ namespace TagLib {
      */
     bool contains(const String &key) const;
 
+    /*!
+     * Returns true if this map contains all keys of \a other
+     * and the values coincide for that keys.
+     */
+    bool contains(const PropertyMap &other) const;
+
     /*!
      * Erase the \a key and its values from the map.
      */
     PropertyMap &erase(const String &key);
 
+    /*!
+     * Erases from this map all keys that appear in \a other.
+     */
+    PropertyMap &erase(const PropertyMap &other);
+
     /*!
      * Merge the contents of \a other into this PropertyMap.
      * If a key is contained in both maps, the values of the second