diff --git a/taglib/it/itfile.cpp b/taglib/it/itfile.cpp index 5f72d3d9..5815b98a 100644 --- a/taglib/it/itfile.cpp +++ b/taglib/it/itfile.cpp @@ -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; diff --git a/taglib/it/itfile.h b/taglib/it/itfile.h index 73256d32..e4a744e9 100644 --- a/taglib/it/itfile.h +++ b/taglib/it/itfile.h @@ -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 &); diff --git a/taglib/mod/modfile.cpp b/taglib/mod/modfile.cpp index f242ea51..d25ecf27 100644 --- a/taglib/mod/modfile.cpp +++ b/taglib/mod/modfile.cpp @@ -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()) { diff --git a/taglib/mod/modfile.h b/taglib/mod/modfile.h index f66a0ef3..7b1119c6 100644 --- a/taglib/mod/modfile.h +++ b/taglib/mod/modfile.h @@ -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. diff --git a/taglib/mod/modtag.cpp b/taglib/mod/modtag.cpp index 1dabe30e..89c21f09 100644 --- a/taglib/mod/modtag.cpp +++ b/taglib/mod/modtag.cpp @@ -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; +} diff --git a/taglib/mod/modtag.h b/taglib/mod/modtag.h index 253a4666..70f6bfc1 100644 --- a/taglib/mod/modtag.h +++ b/taglib/mod/modtag.h @@ -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 &); diff --git a/taglib/riff/aiff/aifffile.cpp b/taglib/riff/aiff/aifffile.cpp index b868ada4..5a00b807 100644 --- a/taglib/riff/aiff/aifffile.cpp +++ b/taglib/riff/aiff/aifffile.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #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; diff --git a/taglib/riff/aiff/aifffile.h b/taglib/riff/aiff/aifffile.h index cac42934..af7d7b7a 100644 --- a/taglib/riff/aiff/aifffile.h +++ b/taglib/riff/aiff/aifffile.h @@ -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. diff --git a/taglib/riff/wav/wavfile.cpp b/taglib/riff/wav/wavfile.cpp index 107d2b45..cb274dd1 100644 --- a/taglib/riff/wav/wavfile.cpp +++ b/taglib/riff/wav/wavfile.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #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; diff --git a/taglib/riff/wav/wavfile.h b/taglib/riff/wav/wavfile.h index 341932b9..8e75afdb 100644 --- a/taglib/riff/wav/wavfile.h +++ b/taglib/riff/wav/wavfile.h @@ -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. diff --git a/taglib/s3m/s3mfile.cpp b/taglib/s3m/s3mfile.cpp index 0c8a712d..bf487aef 100644 --- a/taglib/s3m/s3mfile.cpp +++ b/taglib/s3m/s3mfile.cpp @@ -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; diff --git a/taglib/s3m/s3mfile.h b/taglib/s3m/s3mfile.h index 6eb938a3..99c0402b 100644 --- a/taglib/s3m/s3mfile.h +++ b/taglib/s3m/s3mfile.h @@ -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. diff --git a/taglib/tag.cpp b/taglib/tag.cpp index 9e0ea258..04d0c461 100644 --- a/taglib/tag.cpp +++ b/taglib/tag.cpp @@ -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) diff --git a/taglib/toolkit/tfile.cpp b/taglib/toolkit/tfile.cpp index 9ac5f9bb..b08efbec 100644 --- a/taglib/toolkit/tfile.cpp +++ b/taglib/toolkit/tfile.cpp @@ -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(this)) - return dynamic_cast(this)->toDict(); + return dynamic_cast(this)->toDict(); if (dynamic_cast(this)) - return dynamic_cast(this)->toDict(); + return dynamic_cast(this)->toDict(); + if (dynamic_cast(this)) + return dynamic_cast(this)->toDict(); + if (dynamic_cast(this)) + return dynamic_cast(this)->toDict(); if (dynamic_cast(this)) - return dynamic_cast(this)->toDict(); + return dynamic_cast(this)->toDict(); if (dynamic_cast(this)) - return dynamic_cast(this)->toDict(); + return dynamic_cast(this)->toDict(); if (dynamic_cast(this)) return dynamic_cast(this)->toDict(); if (dynamic_cast(this)) - return dynamic_cast(this)->toDict(); + return dynamic_cast(this)->toDict(); if (dynamic_cast(this)) - return dynamic_cast(this)->toDict(); + return dynamic_cast(this)->toDict(); + if (dynamic_cast(this)) + return dynamic_cast(this)->toDict(); + if (dynamic_cast(this)) + return dynamic_cast(this)->toDict(); + if (dynamic_cast(this)) + return dynamic_cast(this)->toDict(); + if (dynamic_cast(this)) + return dynamic_cast(this)->toDict(); + if (dynamic_cast(this)) + return dynamic_cast(this)->toDict(); + if (dynamic_cast(this)) + return dynamic_cast(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(this)) - dynamic_cast< APE::File* >(this)->fromDict(dict); - else if (dynamic_cast(this)) - dynamic_cast< FLAC::File* >(this)->fromDict(dict); - else if (dynamic_cast(this)) - dynamic_cast< MPC::File* >(this)->fromDict(dict); - else if (dynamic_cast(this)) - dynamic_cast< MPEG::File* >(this)->fromDict(dict); - else if (dynamic_cast(this)) - dynamic_cast< Ogg::FLAC::File* >(this)->fromDict(dict); - else if (dynamic_cast(this)) - dynamic_cast< Ogg::Speex::File* >(this)->fromDict(dict); - else if (dynamic_cast(this)) - dynamic_cast< Ogg::Vorbis::File* >(this)->fromDict(dict); + if (dynamic_cast(this)) + dynamic_cast(this)->fromDict(dict); + else if (dynamic_cast(this)) + dynamic_cast(this)->fromDict(dict); + else if (dynamic_cast(this)) + dynamic_cast(this)->fromDict(dict); + else if (dynamic_cast(this)) + dynamic_cast(this)->fromDict(dict); + else if (dynamic_cast(this)) + dynamic_cast(this)->fromDict(dict); + else if (dynamic_cast(this)) + dynamic_cast(this)->fromDict(dict); + else if (dynamic_cast(this)) + dynamic_cast(this)->fromDict(dict); + else if (dynamic_cast(this)) + dynamic_cast(this)->fromDict(dict); + else if (dynamic_cast(this)) + dynamic_cast(this)->fromDict(dict); + else if (dynamic_cast(this)) + dynamic_cast(this)->fromDict(dict); + else if (dynamic_cast(this)) + dynamic_cast(this)->fromDict(dict); + else if (dynamic_cast(this)) + dynamic_cast(this)->fromDict(dict); + else if (dynamic_cast(this)) + dynamic_cast(this)->fromDict(dict); + else if (dynamic_cast(this)) + dynamic_cast(this)->fromDict(dict); + else if (dynamic_cast(this)) + dynamic_cast(this)->fromDict(dict); else tag()->fromDict(dict); diff --git a/taglib/trueaudio/trueaudiofile.cpp b/taglib/trueaudio/trueaudiofile.cpp index b584b7fd..6875dda7 100644 --- a/taglib/trueaudio/trueaudiofile.cpp +++ b/taglib/trueaudio/trueaudiofile.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #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(ID3v2Index, false)->toDict(); + if (d->hasID3v1) + return d->tag.access(ID3v1Index, false)->toDict(); + return TagLib::TagDict(); +} + +void TrueAudio::File::fromDict(const TagDict &dict) +{ + if (d->hasID3v2) + d->tag.access(ID3v2Index, false)->fromDict(dict); + else if (d->hasID3v1) + d->tag.access(ID3v1Index, false)->fromDict(dict); + else + d->tag.access(ID3v2Index, true)->fromDict(dict); +} + TrueAudio::Properties *TrueAudio::File::audioProperties() const { return d->properties; diff --git a/taglib/trueaudio/trueaudiofile.h b/taglib/trueaudio/trueaudiofile.h index 9c866233..2489c7c4 100644 --- a/taglib/trueaudio/trueaudiofile.h +++ b/taglib/trueaudio/trueaudiofile.h @@ -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. diff --git a/taglib/wavpack/wavpackfile.cpp b/taglib/wavpack/wavpackfile.cpp index 19e4c77d..6afa188d 100644 --- a/taglib/wavpack/wavpackfile.cpp +++ b/taglib/wavpack/wavpackfile.cpp @@ -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(APEIndex, false)->toDict(); + if (d->hasID3v1) + return d->tag.access(ID3v1Index, false)->toDict(); + return TagLib::TagDict(); +} + +void WavPack::File::fromDict(const TagDict &dict) +{ + if (d->hasAPE) + d->tag.access(APEIndex, false)->fromDict(dict); + else if (d->hasID3v1) + d->tag.access(ID3v1Index, false)->fromDict(dict); + else + d->tag.access(APE, true)->fromDict(dict); +} + WavPack::Properties *WavPack::File::audioProperties() const { return d->properties; diff --git a/taglib/wavpack/wavpackfile.h b/taglib/wavpack/wavpackfile.h index 5173c136..dcc57107 100644 --- a/taglib/wavpack/wavpackfile.h +++ b/taglib/wavpack/wavpackfile.h @@ -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. diff --git a/taglib/xm/xmfile.cpp b/taglib/xm/xmfile.cpp index 17aeab0a..bd450c85 100644 --- a/taglib/xm/xmfile.cpp +++ b/taglib/xm/xmfile.cpp @@ -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; diff --git a/taglib/xm/xmfile.h b/taglib/xm/xmfile.h index a4ae7244..27257fca 100644 --- a/taglib/xm/xmfile.h +++ b/taglib/xm/xmfile.h @@ -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.