Ported s3m; removed old id3v2dicttools.

This commit is contained in:
Michael Helmling 2012-02-14 21:29:30 +01:00
parent d2c43d7174
commit 48aaaf8dc4
4 changed files with 10 additions and 481 deletions

View File

@ -1,368 +0,0 @@
/***************************************************************************
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;
}
}
}

View File

@ -1,103 +0,0 @@
/***************************************************************************
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_ */

View File

@ -67,14 +67,14 @@ Mod::Tag *S3M::File::tag() const
return &d->tag;
}
TagDict S3M::File::toDict() const
PropertyMap S3M::File::properties() const
{
return d->tag.toDict();
return d->tag.properties();
}
void S3M::File::fromDict(const TagDict &tagDict)
PropertyMap S3M::File::setProperties(const PropertyMap &properties)
{
d->tag.fromDict(tagDict);
return d->tag.setProperties(properties);
}
S3M::Properties *S3M::File::audioProperties() const

View File

@ -61,16 +61,16 @@ namespace TagLib {
Mod::Tag *tag() const;
/*!
* Implements the unified tag dictionary interface -- export function.
* Forwards to Mod::Tag::toDict().
* Implements the unified property interface -- export function.
* Forwards to Mod::Tag::properties().
*/
TagDict toDict() const;
PropertyMap properties() const;
/*!
* Implements the unified tag dictionary interface -- import function.
* Forwards to Mod::Tag::fromDict().
* Implements the unified property interface -- import function.
* Forwards to Mod::Tag::setProperties().
*/
void fromDict(const TagDict &);
PropertyMap setProperties(const PropertyMap &);
/*!
* Returns the S3M::Properties for this file. If no audio properties