+++ /dev/null
-/***************************************************************************
- copyright : (C) 2011 by Michael Helmling
- email : supermihi@web.de
- ***************************************************************************/
-
-/***************************************************************************
- * This library is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU Lesser General Public License version *
- * 2.1 as published by the Free Software Foundation. *
- * *
- * This library is distributed in the hope that it will be useful, but *
- * WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
- * Lesser General Public License for more details. *
- * *
- * You should have received a copy of the GNU Lesser General Public *
- * License along with this library; if not, write to the Free Software *
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
- * 02110-1301 USA *
- * *
- * Alternatively, this file is available under the Mozilla Public *
- * License Version 1.1. You may obtain a copy of the License at *
- * http://www.mozilla.org/MPL/ *
- ***************************************************************************/
-#include "tdebug.h"
-#include "id3v2dicttools.h"
-#include "tmap.h"
-
-#include "frames/textidentificationframe.h"
-#include "frames/commentsframe.h"
-#include "frames/urllinkframe.h"
-#include "frames/uniquefileidentifierframe.h"
-#include "frames/unsynchronizedlyricsframe.h"
-#include "id3v1genres.h"
-
-namespace TagLib {
- namespace ID3v2 {
-
- // list of deprecated frames and their successors
- static const uint deprecatedFramesSize = 4;
- static const char *deprecatedFrames[][2] = {
- {"TRDA", "TDRC"}, // 2.3 -> 2.4 (http://en.wikipedia.org/wiki/ID3)
- {"TDAT", "TDRC"}, // 2.3 -> 2.4
- {"TYER", "TDRC"}, // 2.3 -> 2.4
- {"TIME", "TDRC"}, // 2.3 -> 2.4
- };
-
- FrameIDMap &deprecationMap()
- {
- static FrameIDMap depMap;
- if (depMap.isEmpty())
- for(uint i = 0; i < deprecatedFramesSize; ++i)
- depMap[deprecatedFrames[i][0]] = deprecatedFrames[i][1];
- return depMap;
- }
-
- /*!
- * A map of translations frameID <-> tag used by the unified dictionary interface.
- */
- static const uint numid3frames = 55;
- static const char *id3frames[][2] = {
- // Text information frames
- { "TALB", "ALBUM"},
- { "TBPM", "BPM" },
- { "TCOM", "COMPOSER" },
- { "TCON", "GENRE" },
- { "TCOP", "COPYRIGHT" },
- { "TDEN", "ENCODINGTIME" },
- { "TDLY", "PLAYLISTDELAY" },
- { "TDOR", "ORIGINALDATE" },
- { "TDRC", "DATE" },
- // { "TRDA", "DATE" }, // id3 v2.3, replaced by TDRC in v2.4
- // { "TDAT", "DATE" }, // id3 v2.3, replaced by TDRC in v2.4
- // { "TYER", "DATE" }, // id3 v2.3, replaced by TDRC in v2.4
- // { "TIME", "DATE" }, // id3 v2.3, replaced by TDRC in v2.4
- { "TDRL", "RELEASEDATE" },
- { "TDTG", "TAGGINGDATE" },
- { "TENC", "ENCODEDBY" },
- { "TEXT", "LYRICIST" },
- { "TFLT", "FILETYPE" },
- { "TIPL", "INVOLVEDPEOPLE" },
- { "TIT1", "CONTENTGROUP" },
- { "TIT2", "TITLE"},
- { "TIT3", "SUBTITLE" },
- { "TKEY", "INITIALKEY" },
- { "TLAN", "LANGUAGE" },
- { "TLEN", "LENGTH" },
- { "TMCL", "MUSICIANCREDITS" },
- { "TMED", "MEDIATYPE" },
- { "TMOO", "MOOD" },
- { "TOAL", "ORIGINALALBUM" },
- { "TOFN", "ORIGINALFILENAME" },
- { "TOLY", "ORIGINALLYRICIST" },
- { "TOPE", "ORIGINALARTIST" },
- { "TOWN", "OWNER" },
- { "TPE1", "ARTIST"},
- { "TPE2", "ALBUMARTIST" }, // id3's spec says 'PERFORMER', but most programs use 'ALBUMARTIST'
- { "TPE3", "CONDUCTOR" },
- { "TPE4", "REMIXER" }, // could also be ARRANGER
- { "TPOS", "DISCNUMBER" },
- { "TPRO", "PRODUCEDNOTICE" },
- { "TPUB", "PUBLISHER" },
- { "TRCK", "TRACKNUMBER" },
- { "TRSN", "RADIOSTATION" },
- { "TRSO", "RADIOSTATIONOWNER" },
- { "TSOA", "ALBUMSORT" },
- { "TSOP", "ARTISTSORT" },
- { "TSOT", "TITLESORT" },
- { "TSO2", "ALBUMARTISTSORT" }, // non-standard, used by iTunes
- { "TSRC", "ISRC" },
- { "TSSE", "ENCODING" },
-
- // URL frames
- { "WCOP", "COPYRIGHTURL" },
- { "WOAF", "FILEWEBPAGE" },
- { "WOAR", "ARTISTWEBPAGE" },
- { "WOAS", "AUDIOSOURCEWEBPAGE" },
- { "WORS", "RADIOSTATIONWEBPAGE" },
- { "WPAY", "PAYMENTWEBPAGE" },
- { "WPUB", "PUBLISHERWEBPAGE" },
- { "WXXX", "URL"},
-
- // Other frames
- { "COMM", "COMMENT" },
- { "USLT", "LYRICS" },
- };
-
- Map<ByteVector, String> &idMap()
- {
- static Map<ByteVector, String> m;
- if (m.isEmpty())
- for (size_t i = 0; i < numid3frames; ++i)
- m[id3frames[i][0]] = id3frames[i][1];
- return m;
- }
-
- // list of TXXX frame description conversions
- static const uint txxxConversionSize = 4;
- static const char *txxxConversionFrames[][2] = {
- {"MusicBrainz Artist Id", "MUSICBRAINZ_ARTISTID"},
- {"MusicBrainz Disc Id", "MUSICBRAINZ_DISCID"},
- {"MusicBrainz Album Artist Id", "MUSICBRAINZ_ALBUMARTISTID"},
- {"MusicBrainz Album Id", "MUSICBRAINZ_ALBUMID"},
- {"MusicMagic Fingerprint", "MUSICIP_FINGERPRINT"},
- {"MusicIP PUID", "MUSICIP_PUID"},
- {"MusicBrainz Album Release Country", "RELEASECOUNTRY"},
- {"MusicBrainz Album Status", "MUSICBRAINZ_ALBUMSTATUS"},
- {"MusicBrainz Album Type", "MUSICBRAINZ_ALBUMTYPE"},
- {"MusicBrainz Release Group Id", "MUSICBRAINZ_RELEASE_GROUPID"},
- {"MusicBrainz Work Id", "MUSICBRAINZ_WORKID"},
- {"MusicBrainz Original Album Id", "MUSICBRAINZ_ORIGINALALBUMID"},
- {"Acoustid Fingerprint", "ACOUSTID_FINGERPRINT"},
- {"Acoustid Id", "ACOUSTID_ID"}
- };
-
- FrameIDMap &txxxConversionMap()
- {
- static FrameIDMap txxxMap;
- if (txxxMap.isEmpty())
- for(uint i = 0; i < txxxConversionSize; ++i)
- txxxMap[txxxConversionFrames[i][0]] = txxxConversionFrames[i][1];
- return txxxMap;
- }
- String frameIDToTagName(const ByteVector &id)
- {
- Map<ByteVector, String> &m = idMap();
- if (m.contains(id))
- return m[id];
- if (deprecationMap().contains(id))
- return m[deprecationMap()[id]];
- debug("unknown frame ID in frameIDToTagName(): " + id);
- return "UNKNOWNID3TAG#" + String(id) + "#"; //TODO: implement this nicer
- }
-
- ByteVector tagNameToFrameID(const String &s)
- {
- static Map<String, ByteVector> m;
- if (m.isEmpty())
- for (size_t i = 0; i < numid3frames; ++i)
- m[id3frames[i][1]] = id3frames[i][0];
- if (m.contains(s.upper()))
- return m[s];
- return "TXXX";
- }
-
- bool ignored(const ByteVector& id)
- {
- return !(id == "TXXX") && !idMap().contains(id) && !deprecated(id);
- }
-
- bool deprecated(const ByteVector& id)
- {
- return deprecationMap().contains(id);
- }
-
- String prepareTagName(const String &s) {
- int pos = s.find("::");
- return ((pos != -1) ? s.substr(pos+2) : s).upper();
- }
- /*
- * The following _parseXXX functions are to be replaced by implementations of a virtual
- * function in ID3v2::Frame ASAP.
- */
- KeyValuePair _parseUserTextIdentificationFrame(const UserTextIdentificationFrame *frame)
- {
- String tagName = frame->description();
- StringList l(frame->fieldList());
- // this is done because taglib stores the description also as first entry
- // in the field list. (why?)
- if (l.contains(tagName))
- l.erase(l.find(tagName));
- return KeyValuePair(prepareTagName(tagName), l);
- }
-
- Frame *_createUserTextIdentificationFrame(const String &tag, const StringList &values)
- {
- UserTextIdentificationFrame* frame = new UserTextIdentificationFrame();
- frame->setDescription(tag);
- frame->setText(values);
- return frame;
- }
-
- KeyValuePair _parseTextIdentificationFrame(const TextIdentificationFrame *frame)
- {
- String tagName = frameIDToTagName(frame->frameID());
- StringList l = frame->fieldList();
- if (tagName == "GENRE") {
- // Special case: Support ID3v1-style genre numbers. They are not officially supported in
- // ID3v2, however it seems that still a lot of programs use them.
- //
- for (StringList::Iterator lit = l.begin(); lit != l.end(); ++lit) {
- bool ok = false;
- int test = lit->toInt(&ok); // test if the genre value is an integer
- if (ok)
- *lit = ID3v1::genre(test);
- }
- }
- else if (tagName == "DATE") {
- for (StringList::Iterator lit = l.begin(); lit != l.end(); ++lit) {
- // ID3v2 specifies ISO8601 timestamps which contain a 'T' as separator between date and time.
- // Since this is unusual in other formats, the T is removed.
- //
- int tpos = lit->find("T");
- if (tpos != -1)
- (*lit)[tpos] = ' ';
- }
- }
- return KeyValuePair(tagName, l);
- }
-
- Frame *_createTextIdentificationFrame(const String &tag, const StringList &values)
- {
- StringList newValues(values); // create a copy because the following might modify
- // the easiest case: a normal text frame
- if (tag == "DATE") {
- // Handle ISO8601 date format
- for (StringList::Iterator lit = newValues.begin(); lit != newValues.end(); ++lit)
- if (lit->length() > 10 && (*lit)[10] == ' ')
- (*lit)[10] = 'T';
- }
- TextIdentificationFrame *frame = new TextIdentificationFrame(tagNameToFrameID(tag));
- frame->setText(newValues);
- return frame;
- }
-
- KeyValuePair _parseUserUrlLinkFrame(const UserUrlLinkFrame *frame)
- {
- String tagName = frame->description().upper();
- if (tagName == "")
- tagName = "URL";
- return KeyValuePair(tagName, frame->url());
- }
-
- /*!
- * Create a UserUrlLinkFrame. Note that this is valid only if values.size() == 1.
- */
- Frame *_createUserUrlLinkFrame(const String &tag, const StringList &values)
- {
- UserUrlLinkFrame* frame = new UserUrlLinkFrame();
- frame->setDescription(tag);
- frame->setUrl(values[0]);
- return frame;
- }
-
- KeyValuePair _parseUrlLinkFrame(const UrlLinkFrame *frame)
- {
- return KeyValuePair(frameIDToTagName(frame->frameID()) , frame->url());
- }
-
- /*!
- * Create a rUrlLinkFrame. Note that this is valid only if values.size() == 1.
- */
- Frame *_createUrlLinkFrame(const String &tag, const StringList &values)
- {
- UrlLinkFrame *frame = new UrlLinkFrame(tagNameToFrameID(tag));
- frame->setUrl(values[0]);
- return frame;
- }
-
- KeyValuePair _parseCommentsFrame(const CommentsFrame *frame)
- {
- String tagName = frame->description().upper();
- if (tagName.isEmpty())
- tagName = "COMMENT";
- return KeyValuePair(tagName, frame->text());
- }
-
- Frame *_createCommentsFrame(const String &tag, const StringList &values)
- {
- CommentsFrame *frame = new CommentsFrame(String::UTF8);
- frame->setText(values[0]);
- return frame;
- }
-
- KeyValuePair _parseUnsynchronizedLyricsFrame(const UnsynchronizedLyricsFrame *frame)
- {
- return KeyValuePair("LYRICS", frame->text());
- }
-
- Frame *_createUnsynchronizedLyricsFrame(const String &tag, const StringList &values)
- {
- UnsynchronizedLyricsFrame* frame = new UnsynchronizedLyricsFrame();
- frame->setDescription("");
- frame->setText(values[0]);
- return frame;
- }
-
- KeyValuePair parseFrame(const Frame *frame)
- {
- const ByteVector &id = frame->frameID();
- if (id == "TXXX")
- return _parseUserTextIdentificationFrame(dynamic_cast< const UserTextIdentificationFrame* >(frame));
- else if (id[0] == 'T')
- return _parseTextIdentificationFrame(dynamic_cast<const TextIdentificationFrame* >(frame));
- else if (id == "WXXX")
- return _parseUserUrlLinkFrame(dynamic_cast< const UserUrlLinkFrame* >(frame));
- else if (id[0] == 'W')
- return _parseUrlLinkFrame(dynamic_cast< const UrlLinkFrame* >(frame));
- else if (id == "COMM")
- return _parseCommentsFrame(dynamic_cast< const CommentsFrame* >(frame));
- else if (id == "USLT")
- return _parseUnsynchronizedLyricsFrame(dynamic_cast< const UnsynchronizedLyricsFrame* >(frame));
- else {
- debug("parsing unknown ID3 frame: " + id);
- return KeyValuePair("UNKNOWNID3TAG", frame->toString());
- }
- }
-
- Frame *createFrame(const String &tag, const StringList &values)
- {
- ByteVector id = tagNameToFrameID(tag);
- if (id == "TXXX" ||
- ((id[0] == 'W' || id == "COMM" || id == "USLT") && values.size() > 1))
- return _createUserTextIdentificationFrame(tag, values);
- else if (id[0] == 'T')
- return _createTextIdentificationFrame(tag, values);
- else if (id == "WXXX")
- return _createUserUrlLinkFrame(tag, values);
- else if (id[0] == 'W')
- return _createUrlLinkFrame(tag, values);
- else if (id == "COMM")
- return _createCommentsFrame(tag, values);
- else if (id == "USLT")
- return _createUnsynchronizedLyricsFrame(tag, values);
- return 0;
- }
- }
-}
+++ /dev/null
-/***************************************************************************
- copyright : (C) 2011 by Michael Helmling
- email : supermihi@web.de
- ***************************************************************************/
-
-/***************************************************************************
- * This library is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU Lesser General Public License version *
- * 2.1 as published by the Free Software Foundation. *
- * *
- * This library is distributed in the hope that it will be useful, but *
- * WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
- * Lesser General Public License for more details. *
- * *
- * You should have received a copy of the GNU Lesser General Public *
- * License along with this library; if not, write to the Free Software *
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
- * 02110-1301 USA *
- * *
- * Alternatively, this file is available under the Mozilla Public *
- * License Version 1.1. You may obtain a copy of the License at *
- * http://www.mozilla.org/MPL/ *
- ***************************************************************************/
-
-#ifndef ID3V2DICTTOOLS_H_
-#define ID3V2DICTTOOLS_H_
-
-#include "tstringlist.h"
-#include "taglib_export.h"
-#include "tmap.h"
-#include <utility>
-
-namespace TagLib {
- namespace ID3v2 {
- /*!
- * This file contains methods used by the unified dictionary interface for ID3v2 tags
- * (tag name conversion, handling of un-translatable frameIDs, ...).
- */
-
- typedef Map<ByteVector, ByteVector> FrameIDMap;
- typedef std::pair<String, StringList> KeyValuePair;
-
- class Frame;
- /*!
- * Returns an appropriate ID3 frame ID for the given free-form tag name. This method
- * will return TXXX if no specialized translation is found.
- */
- ByteVector TAGLIB_EXPORT tagNameToFrameID(const String &);
-
- /*!
- * Returns a free-form tag name for the given ID3 frame ID. Note that this does not work
- * for general frame IDs such as TXXX or WXXX.
- */
- String TAGLIB_EXPORT frameIDToTagName(const ByteVector &);
-
- /*!
- * Tell if the given frame ID is ignored by the unified dictionary subsystem. This is true
- * for frames that don't admit a textual representation, such as pictures or other binary
- * information, as well as invalid frames that violate the ID3 specification.
- *
- * These include:
- * - illegal frames violating the specification but seem to be used by some applications, e.g.
- * "TCMP", illegal 'Part of Compilation' frame set by iTunes (see http://www.id3.org/Compliance_Issues)
- * "NCON", illegal MusicMatch frame (see http://www.id3.org/Compliance_Issues)
- *
- * - frames without a meaningful textual representation -- might be implemented in some future release
- * "GEOB", no way to handle a general encapsulated object by the dict interface
- * "PRIV", private frames
- * "APIC", attached picture
- * "POPM", popularimeter
- * "RVA2", relative volume
- * "UFID", unique file identifier
- */
- bool TAGLIB_EXPORT ignored(const ByteVector &);
-
- /*!
- * Returns true if the given frame ID is deprecated according to the most recent ID3v2 standard.
- */
- bool TAGLIB_EXPORT deprecated(const ByteVector&);
-
- /*!
- * Parse the ID3v2::Frame *Frame* to a pair of a human-readable key (e.g. ARTIST) and
- * a StringList containing the values.
- */
- KeyValuePair parseFrame(const Frame*);
-
- /*!
- * Create an appropriate ID3v2::Frame for the given tag name and values.
- */
- Frame *createFrame(const String &tag, const StringList &values);
- /*!
- * prepare the given tag name for use in a unified dictionary: make it uppercase and
- * removes prefixes set by the ExFalso/QuodLibet package.
- */
- String prepareTagName(const String &);
-
-
- }
-}
-
-
-#endif /* ID3V2DICTTOOLS_H_ */