]> granicus.if.org Git - taglib/commitdiff
Implemented dict interface for more formats.
authorMichael Helmling <helmling@mathematik.uni-kl.de>
Wed, 2 Nov 2011 20:02:35 +0000 (21:02 +0100)
committerMichael Helmling <helmling@mathematik.uni-kl.de>
Wed, 2 Nov 2011 20:02:35 +0000 (21:02 +0100)
Now supported: MOD files (IT, MOD, S3M, XM), RIFF files
(AIFF, WAV), TrueAudio, WavPack.

20 files changed:
taglib/it/itfile.cpp
taglib/it/itfile.h
taglib/mod/modfile.cpp
taglib/mod/modfile.h
taglib/mod/modtag.cpp
taglib/mod/modtag.h
taglib/riff/aiff/aifffile.cpp
taglib/riff/aiff/aifffile.h
taglib/riff/wav/wavfile.cpp
taglib/riff/wav/wavfile.h
taglib/s3m/s3mfile.cpp
taglib/s3m/s3mfile.h
taglib/tag.cpp
taglib/toolkit/tfile.cpp
taglib/trueaudio/trueaudiofile.cpp
taglib/trueaudio/trueaudiofile.h
taglib/wavpack/wavpackfile.cpp
taglib/wavpack/wavpackfile.h
taglib/xm/xmfile.cpp
taglib/xm/xmfile.h

index 5f72d3d9993ba5d7bc69e8be0f7a3e03487b3b2e..5815b98adad304867b33f45e06ea75219fc730e2 100644 (file)
@@ -65,6 +65,16 @@ Mod::Tag *IT::File::tag() const
   return &d->tag;
 }
 
+TagDict IT::File::toDict() const
+{
+  return d->tag.toDict();
+}
+
+void IT::File::fromDict(const TagDict &tagDict)
+{
+  d->tag.fromDict(tagDict);
+}
+
 IT::Properties *IT::File::audioProperties() const
 {
   return &d->properties;
index 73256d326bb32156a99ffc034238adf95a375544..e4a744e964985d28ce1c0f9ddadacc4aeb908c59 100644 (file)
@@ -60,6 +60,18 @@ namespace TagLib {
 
         Mod::Tag *tag() const;
 
+        /*!
+         * Implements the unified tag dictionary interface -- export function.
+         * Forwards to Mod::Tag::toDict().
+         */
+        TagDict toDict() const;
+
+        /*!
+         * Implements the unified tag dictionary interface -- import function.
+         * Forwards to Mod::Tag::fromDict().
+         */
+        void fromDict(const TagDict &);
+
         /*!
          * Returns the IT::Properties for this file. If no audio properties
          * were read then this will return a null pointer.
@@ -74,6 +86,7 @@ namespace TagLib {
          */
         bool save();
 
+
       private:
         File(const File &);
         File &operator=(const File &);
index f242ea51dec9f57423272606a8c1e6e25108c6bb..d25ecf27cb3b42e0b4027dc8186c2a47ba394bd1 100644 (file)
@@ -70,6 +70,16 @@ Mod::Properties *Mod::File::audioProperties() const
   return &d->properties;
 }
 
+TagDict Mod::File::toDict() const
+{
+  return d->tag.toDict();
+}
+
+void Mod::File::fromDict(const TagDict &tagDict)
+{
+  d->tag.fromDict(tagDict);
+}
+
 bool Mod::File::save()
 {
   if(readOnly()) {
index f66a0ef3fff6a5115b4df69e821e7d1aba7c7450..7b1119c6329ae7cf2a9fa264516a85cd1ecf3cba 100644 (file)
@@ -61,6 +61,17 @@ namespace TagLib {
 
       Mod::Tag *tag() const;
 
+      /*!
+       * Implements the unified tag dictionary interface -- export function.
+       * Forwards to Mod::Tag::toDict().
+       */
+      TagDict toDict() const;
+
+      /*!
+       * Implements the unified tag dictionary interface -- import function.
+       * Forwards to Mod::Tag::fromDict().
+       */
+      void fromDict(const TagDict &);
       /*!
        * Returns the Mod::Properties for this file. If no audio properties
        * were read then this will return a null pointer.
index 1dabe30e022f0520063859e429db84e61e3c2051..89c21f09bc882b51fe7c5fa8ba9c5e72db47fa4f 100644 (file)
@@ -20,7 +20,7 @@
  ***************************************************************************/
 
 #include "modtag.h"
-
+#include "tstringlist.h"
 using namespace TagLib;
 using namespace Mod;
 
@@ -120,3 +120,31 @@ void Mod::Tag::setTrackerName(const String &trackerName)
 {
   d->trackerName = trackerName;
 }
+
+TagDict Mod::Tag::toDict() const
+{
+  TagDict dict;
+  dict["TITLE"] = d->title;
+  dict["COMMENT"] = d->comment;
+  if (!(d->trackerName == String::null))
+    dict["TRACKERNAME"] = d->trackerName;
+  return dict;
+}
+
+void Mod::Tag::fromDict(const TagDict &tagDict)
+{
+  if (tagDict.contains("TITLE") && !tagDict["TITILE"].isEmpty())
+    d->title = tagDict["TITLE"][0];
+  else
+    d->title = String::null;
+
+  if (tagDict.contains("COMMENT") && !tagDict["COMMENT"].isEmpty())
+    d->comment = tagDict["COMMENT"][0];
+  else
+    d->comment = String::null;
+
+  if (tagDict.contains("TRACKERNAME") && !tagDict["TRACKERNAME"].isEmpty())
+    d->trackerName = tagDict["TRACKERNAME"][0];
+  else
+    d->trackerName = String::null;
+}
index 253a46664871d02c820c0f8e24d692c79ba1c644..70f6bfc1725d6de23a57bd28a8de14ee68d48914 100644 (file)
@@ -159,6 +159,21 @@ namespace TagLib {
        */
       void setTrackerName(const String &trackerName);
 
+      /*!
+       * Implements the unified tag dictionary interface -- export function.
+       * Since the module tag is very limited, the exported dict is as well.
+       */
+      TagDict toDict() const;
+
+      /*!
+       * Implements the unified tag dictionary interface -- import function.
+       * Because of the limitations of the module file tag, any tags besides
+       * COMMENT, TITLE and, if it is an XM file, TRACKERNAME, will be
+       * ignored. Additionally, if the dict contains tags with multiple values,
+       * all but the first will be ignored.
+       */
+      void fromDict(const TagDict &);
+
     private:
       Tag(const Tag &);
       Tag &operator=(const Tag &);
index b868ada46f1d466bc386f5b529e27f221424ce8b..5a00b807dcccbe684dd112d9b7353e3947e77d14 100644 (file)
@@ -26,6 +26,7 @@
 #include <tbytevector.h>
 #include <tdebug.h>
 #include <id3v2tag.h>
+#include <tstringlist.h>
 
 #include "aifffile.h"
 
@@ -83,6 +84,18 @@ ID3v2::Tag *RIFF::AIFF::File::tag() const
   return d->tag;
 }
 
+TagLib::TagDict RIFF::AIFF::File::toDict(void) const
+{
+  return d->tag->toDict();
+
+}
+
+void RIFF::AIFF::File::fromDict(const TagDict &dict)
+{
+  d->tag->fromDict(dict);
+}
+
+
 RIFF::AIFF::Properties *RIFF::AIFF::File::audioProperties() const
 {
   return d->properties;
index cac429341cee0608bcdccafdd37ce54a84159f38..af7d7b7a2362703834765bad1d2e122b0ec737f5 100644 (file)
@@ -83,6 +83,18 @@ namespace TagLib {
          */
         virtual ID3v2::Tag *tag() const;
 
+        /*!
+         * Implements the unified tag dictionary interface -- export function.
+         * This method forwards to ID3v2::Tag::toDict.
+         */
+        TagDict toDict() const;
+
+        /*!
+         * Implements the unified tag dictionary interface -- import function.
+         * This method forwards to ID3v2::Tag::fromDict.
+         */
+        void fromDict(const TagDict &);
+
         /*!
          * Returns the AIFF::Properties for this file.  If no audio properties
          * were read then this will return a null pointer.
index 107d2b45f50a87866ccd81b3d9d8fa63ff592ce6..cb274dd104c0ed55bce2867018772bb385f73438 100644 (file)
@@ -26,6 +26,7 @@
 #include <tbytevector.h>
 #include <tdebug.h>
 #include <id3v2tag.h>
+#include <tstringlist.h>
 
 #include "wavfile.h"
 
@@ -83,6 +84,17 @@ ID3v2::Tag *RIFF::WAV::File::tag() const
   return d->tag;
 }
 
+TagLib::TagDict RIFF::WAV::File::toDict(void) const
+{
+  return d->tag->toDict();
+}
+
+void RIFF::WAV::File::fromDict(const TagDict &dict)
+{
+  d->tag->fromDict(dict);
+}
+
+
 RIFF::WAV::Properties *RIFF::WAV::File::audioProperties() const
 {
   return d->properties;
index 341932b940b4406ea3ee55997c3c6a3c46a98369..8e75afdb9377a3280a5689c56035f31be2f930bb 100644 (file)
@@ -83,6 +83,18 @@ namespace TagLib {
          */
         virtual ID3v2::Tag *tag() const;
 
+        /*!
+         * Implements the unified tag dictionary interface -- export function.
+         * This method forwards to ID3v2::Tag::toDict.
+         */
+        TagDict toDict() const;
+
+        /*!
+         * Implements the unified tag dictionary interface -- import function.
+         * This method forwards to ID3v2::Tag::fromDict.
+         */
+        void fromDict(const TagDict &);
+
         /*!
          * Returns the WAV::Properties for this file.  If no audio properties
          * were read then this will return a null pointer.
index 0c8a712d8511530ef7ea201041d466900edf713e..bf487aef915cf3bf0b89886baf80801a572806e0 100644 (file)
@@ -67,6 +67,16 @@ Mod::Tag *S3M::File::tag() const
   return &d->tag;
 }
 
+TagDict S3M::File::toDict() const
+{
+  return d->tag.toDict();
+}
+
+void S3M::File::fromDict(const TagDict &tagDict)
+{
+  d->tag.fromDict(tagDict);
+}
+
 S3M::Properties *S3M::File::audioProperties() const
 {
   return &d->properties;
index 6eb938a3c62a727fb85fe74cb9ff5c2913d5bce8..99c0402b537c877f143081329d9873e316f1b541 100644 (file)
@@ -60,6 +60,18 @@ namespace TagLib {
 
         Mod::Tag *tag() const;
 
+        /*!
+         * Implements the unified tag dictionary interface -- export function.
+         * Forwards to Mod::Tag::toDict().
+         */
+        TagDict toDict() const;
+
+        /*!
+         * Implements the unified tag dictionary interface -- import function.
+         * Forwards to Mod::Tag::fromDict().
+         */
+        void fromDict(const TagDict &);
+
         /*!
          * Returns the S3M::Properties for this file. If no audio properties
          * were read then this will return a null pointer.
index 9e0ea25862d8af1999f855e51e341a94375bcb89..04d0c461787e82e2fea5999d1f7c6590ec691168 100644 (file)
@@ -75,32 +75,32 @@ TagDict Tag::toDict() const
 
 void Tag::fromDict(const TagDict &dict)
 {
-  if (dict.contains("TITLE") and dict["TITLE"].size() >= 1)
+  if (dict.contains("TITLE") && dict["TITLE"].size() >= 1)
     setTitle(dict["TITLE"].front());
   else
     setTitle(String::null);
 
-  if (dict.contains("ARTIST") and dict["ARTIST"].size() >= 1)
+  if (dict.contains("ARTIST") && !dict["ARTIST"].isEmpty())
     setArtist(dict["ARTIST"].front());
   else
     setArtist(String::null);
 
-  if (dict.contains("ALBUM") and dict["ALBUM"].size() >= 1)
+  if (dict.contains("ALBUM") && !dict["ALBUM"].isEmpty())
       setAlbum(dict["ALBUM"].front());
     else
       setAlbum(String::null);
 
-  if (dict.contains("COMMENT") and dict["COMMENT"].size() >= 1)
+  if (dict.contains("COMMENT") && !dict["COMMENT"].isEmpty())
     setComment(dict["COMMENT"].front());
   else
     setComment(String::null);
 
-  if (dict.contains("GENRE") and dict["GENRE"].size() >=1)
+  if (dict.contains("GENRE") && !dict["GENRE"].isEmpty())
     setGenre(dict["GENRE"].front());
   else
     setGenre(String::null);
 
-  if (dict.contains("DATE") and dict["DATE"].size() >= 1) {
+  if (dict.contains("DATE") && !dict["DATE"].isEmpty()) {
     bool ok;
     int date = dict["DATE"].front().toInt(&ok);
     if (ok)
@@ -111,7 +111,7 @@ void Tag::fromDict(const TagDict &dict)
   else
     setYear(0);
 
-  if (dict.contains("TRACKNUMBER") and dict["TRACKNUMBER"].size() >= 1) {
+  if (dict.contains("TRACKNUMBER") && !dict["TRACKNUMBER"].isEmpty()) {
     bool ok;
     int track = dict["TRACKNUMBER"].front().toInt(&ok);
     if (ok)
index 9ac5f9bb9b637fb213c693cefa58c417d9e4ecd5..b08efbecab4e69ebe208a356f1e420691040249d 100644 (file)
@@ -66,7 +66,7 @@
 #include "modfile.h"
 #include "s3mfile.h"
 #include "itfile.h"
-#include "xmfile.h"                                   \
+#include "xmfile.h"
 
 using namespace TagLib;
 
@@ -117,39 +117,76 @@ TagDict File::toDict() const
 {
   // ugly workaround until this method is virtual
   if (dynamic_cast<const APE::File* >(this))
-      return dynamic_cast<const APE::File* >(this)->toDict();
+    return dynamic_cast<const APE::File* >(this)->toDict();
   if (dynamic_cast<const FLAC::File* >(this))
-        return dynamic_cast<const FLAC::File* >(this)->toDict();
+    return dynamic_cast<const FLAC::File* >(this)->toDict();
+  if (dynamic_cast<const IT::File* >(this))
+    return dynamic_cast<const IT::File* >(this)->toDict();
+  if (dynamic_cast<const Mod::File* >(this))
+    return dynamic_cast<const Mod::File* >(this)->toDict();
   if (dynamic_cast<const MPC::File* >(this))
-        return dynamic_cast<const MPC::File* >(this)->toDict();
+    return dynamic_cast<const MPC::File* >(this)->toDict();
   if (dynamic_cast<const MPEG::File* >(this))
-        return dynamic_cast<const MPEG::File* >(this)->toDict();
+    return dynamic_cast<const MPEG::File* >(this)->toDict();
   if (dynamic_cast<const Ogg::FLAC::File* >(this))
     return dynamic_cast<const Ogg::FLAC::File* >(this)->toDict();
   if (dynamic_cast<const Ogg::Speex::File* >(this))
-      return dynamic_cast<const Ogg::Speex::File* >(this)->toDict();
+    return dynamic_cast<const Ogg::Speex::File* >(this)->toDict();
   if (dynamic_cast<const Ogg::Vorbis::File* >(this))
-      return dynamic_cast<const Ogg::Vorbis::File* >(this)->toDict();
+    return dynamic_cast<const Ogg::Vorbis::File* >(this)->toDict();
+  if (dynamic_cast<const RIFF::AIFF::File* >(this))
+    return dynamic_cast<const RIFF::AIFF::File* >(this)->toDict();
+  if (dynamic_cast<const RIFF::WAV::File* >(this))
+    return dynamic_cast<const RIFF::WAV::File* >(this)->toDict();
+  if (dynamic_cast<const S3M::File* >(this))
+    return dynamic_cast<const S3M::File* >(this)->toDict();
+  if (dynamic_cast<const TrueAudio::File* >(this))
+    return dynamic_cast<const TrueAudio::File* >(this)->toDict();
+  if (dynamic_cast<const WavPack::File* >(this))
+    return dynamic_cast<const WavPack::File* >(this)->toDict();
+  if (dynamic_cast<const XM::File* >(this))
+    return dynamic_cast<const XM::File* >(this)->toDict();
   // no specialized implementation available -> use generic one
+  // - ASF: ugly format, largely undocumented, not worth implementing
+  //   dict interface ...
+  // - MP4: taglib's MP4::Tag does not really support anything beyond
+  //   the basic implementation, therefor we use just the default Tag
+  //   interface
   return tag()->toDict();
 }
 
 void File::fromDict(const TagDict &dict)
 {
-  if (dynamic_cast<const APE::File* >(this))
-    dynamic_cast< APE::File* >(this)->fromDict(dict);
-  else if (dynamic_cast<const FLAC::File* >(this))
-    dynamic_cast< FLAC::File* >(this)->fromDict(dict);
-  else if (dynamic_cast<const MPC::File* >(this))
-      dynamic_cast< MPC::File* >(this)->fromDict(dict);
-  else if (dynamic_cast<const MPEG::File* >(this))
-      dynamic_cast< MPEG::File* >(this)->fromDict(dict);
-  else if (dynamic_cast<const Ogg::FLAC::File* >(this))
-      dynamic_cast< Ogg::FLAC::File* >(this)->fromDict(dict);
-  else if (dynamic_cast<const Ogg::Speex::File* >(this))
-        dynamic_cast< Ogg::Speex::File* >(this)->fromDict(dict);
-  else if (dynamic_cast<const Ogg::Vorbis::File* >(this))
-        dynamic_cast< Ogg::Vorbis::File* >(this)->fromDict(dict);
+  if (dynamic_cast<APE::File* >(this))
+    dynamic_cast<APE::File* >(this)->fromDict(dict);
+  else if (dynamic_cast<FLAC::File* >(this))
+    dynamic_cast<FLAC::File* >(this)->fromDict(dict);
+  else if (dynamic_cast<IT::File* >(this))
+    dynamic_cast<IT::File* >(this)->fromDict(dict);
+  else if (dynamic_cast<Mod::File* >(this))
+    dynamic_cast<Mod::File* >(this)->fromDict(dict);
+  else if (dynamic_cast<MPC::File* >(this))
+    dynamic_cast<MPC::File* >(this)->fromDict(dict);
+  else if (dynamic_cast<MPEG::File* >(this))
+    dynamic_cast<MPEG::File* >(this)->fromDict(dict);
+  else if (dynamic_cast<Ogg::FLAC::File* >(this))
+    dynamic_cast<Ogg::FLAC::File* >(this)->fromDict(dict);
+  else if (dynamic_cast<Ogg::Speex::File* >(this))
+    dynamic_cast<Ogg::Speex::File* >(this)->fromDict(dict);
+  else if (dynamic_cast<Ogg::Vorbis::File* >(this))
+    dynamic_cast<Ogg::Vorbis::File* >(this)->fromDict(dict);
+  else if (dynamic_cast<RIFF::AIFF::File* >(this))
+    dynamic_cast<RIFF::AIFF::File* >(this)->fromDict(dict);
+  else if (dynamic_cast<RIFF::WAV::File* >(this))
+    dynamic_cast<RIFF::WAV::File* >(this)->fromDict(dict);
+  else if (dynamic_cast<S3M::File* >(this))
+    dynamic_cast<S3M::File* >(this)->fromDict(dict);
+  else if (dynamic_cast<TrueAudio::File* >(this))
+    dynamic_cast<TrueAudio::File* >(this)->fromDict(dict);
+  else if (dynamic_cast<WavPack::File* >(this))
+    dynamic_cast<WavPack::File* >(this)->fromDict(dict);
+  else if (dynamic_cast<XM::File* >(this))
+    dynamic_cast<XM::File* >(this)->fromDict(dict);
   else
     tag()->fromDict(dict);
 
index b584b7fdedfe160525c10f869c4cbd6554fe68bf..6875dda77cb76fdd2e94c35f7479727807a30571 100644 (file)
@@ -31,6 +31,7 @@
 #include <tstring.h>
 #include <tdebug.h>
 #include <tagunion.h>
+#include <tstringlist.h>
 
 #include "trueaudiofile.h"
 #include "id3v1tag.h"
@@ -126,6 +127,27 @@ TagLib::Tag *TrueAudio::File::tag() const
   return &d->tag;
 }
 
+TagLib::TagDict TrueAudio::File::toDict(void) const
+{
+  // once Tag::toDict() is virtual, this case distinction could actually be done
+  // within TagUnion.
+  if (d->hasID3v2)
+    return d->tag.access<ID3v2::Tag>(ID3v2Index, false)->toDict();
+  if (d->hasID3v1)
+    return d->tag.access<ID3v1::Tag>(ID3v1Index, false)->toDict();
+  return TagLib::TagDict();
+}
+
+void TrueAudio::File::fromDict(const TagDict &dict)
+{
+  if (d->hasID3v2)
+    d->tag.access<ID3v2::Tag>(ID3v2Index, false)->fromDict(dict);
+  else if (d->hasID3v1)
+    d->tag.access<ID3v1::Tag>(ID3v1Index, false)->fromDict(dict);
+  else
+    d->tag.access<ID3v2::Tag>(ID3v2Index, true)->fromDict(dict);
+}
+
 TrueAudio::Properties *TrueAudio::File::audioProperties() const
 {
   return d->properties;
index 9c8662333eaf2154afd80fc67db95c2f6dc81fb8..2489c7c4fddfd7a1e72fcd4b85ca3c6910a42954 100644 (file)
@@ -124,6 +124,20 @@ namespace TagLib {
        */
       virtual TagLib::Tag *tag() const;
 
+      /*!
+       * Implements the unified tag dictionary interface -- export function.
+       * If the file contains both ID3v1 and v2 tags, only ID3v2 will be
+       * converted to the TagDict.
+       */
+      TagDict toDict() const;
+
+      /*!
+       * Implements the unified tag dictionary interface -- import function.
+       * As with the export, only one tag is taken into account. If the file
+       * has no tag at all, ID3v2 will be created.
+       */
+      void fromDict(const TagDict &);
+
       /*!
        * Returns the TrueAudio::Properties for this file.  If no audio properties
        * were read then this will return a null pointer.
index 19e4c77d7a3c6b0378cd9219ca8f86b21ed9edc4..6afa188dc909de55c6f98d5196601a84e9b3e020 100644 (file)
@@ -105,6 +105,25 @@ TagLib::Tag *WavPack::File::tag() const
   return &d->tag;
 }
 
+TagLib::TagDict WavPack::File::toDict(void) const
+{
+  if (d->hasAPE)
+    return d->tag.access<APE::Tag>(APEIndex, false)->toDict();
+  if (d->hasID3v1)
+    return d->tag.access<ID3v1::Tag>(ID3v1Index, false)->toDict();
+  return TagLib::TagDict();
+}
+
+void WavPack::File::fromDict(const TagDict &dict)
+{
+  if (d->hasAPE)
+    d->tag.access<APE::Tag>(APEIndex, false)->fromDict(dict);
+  else if (d->hasID3v1)
+    d->tag.access<ID3v1::Tag>(ID3v1Index, false)->fromDict(dict);
+  else
+    d->tag.access<APE::Tag>(APE, true)->fromDict(dict);
+}
+
 WavPack::Properties *WavPack::File::audioProperties() const
 {
   return d->properties;
index 5173c136e25797f95e73176fbc0d0bde00be2119..dcc571077aba4213608684ff62c55abb5bb8e5d1 100644 (file)
@@ -106,6 +106,20 @@ namespace TagLib {
        */
       virtual TagLib::Tag *tag() const;
 
+      /*!
+       * Implements the unified tag dictionary interface -- export function.
+       * If the file contains both an APE and an ID3v1 tag, only APE
+       * will be converted to the TagDict.
+       */
+      TagDict toDict() const;
+
+      /*!
+       * Implements the unified tag dictionary interface -- import function.
+       * As for the export, only one tag is taken into account. If the file
+       * has no tag at all, APE will be created.
+       */
+      void fromDict(const TagDict &);
+
       /*!
        * Returns the MPC::Properties for this file.  If no audio properties
        * were read then this will return a null pointer.
index 17aeab0a9a13541a984b298d5e636e26b8e48d32..bd450c85b043eecfa9f3c17cd704ae7554113935 100644 (file)
@@ -379,6 +379,16 @@ Mod::Tag *XM::File::tag() const
   return &d->tag;
 }
 
+TagDict XM::File::toDict() const
+{
+  return d->tag.toDict();
+}
+
+void XM::File::fromDict(const TagDict &tagDict)
+{
+  d->tag.fromDict(tagDict);
+}
+
 XM::Properties *XM::File::audioProperties() const
 {
   return &d->properties;
index a4ae7244785ba8ecde991e27ef14fd4da55e4e41..27257fca5e4f704144a11eea700512822de48180 100644 (file)
@@ -60,6 +60,18 @@ namespace TagLib {
 
         Mod::Tag *tag() const;
 
+        /*!
+         * Implements the unified tag dictionary interface -- export function.
+         * Forwards to Mod::Tag::toDict().
+         */
+        TagDict toDict() const;
+
+        /*!
+         * Implements the unified tag dictionary interface -- import function.
+         * Forwards to Mod::Tag::fromDict().
+         */
+        void fromDict(const TagDict &);
+
         /*!
          * Returns the XM::Properties for this file. If no audio properties
          * were read then this will return a null pointer.