mirror of
https://github.com/taglib/taglib.git
synced 2026-02-12 19:23:02 -05:00
Merge branch 'master' into taglib2
Conflicts: taglib/mp4/mp4tag.cpp taglib/mp4/mp4tag.h taglib/toolkit/tfile.cpp
This commit is contained in:
@ -29,6 +29,7 @@
|
||||
|
||||
#include <tdebug.h>
|
||||
#include <tbytevectorlist.h>
|
||||
#include <tpropertymap.h>
|
||||
#include <tstring.h>
|
||||
#include "asffile.h"
|
||||
#include "asftag.h"
|
||||
@ -403,6 +404,21 @@ ASF::Tag *ASF::File::tag() const
|
||||
return d->tag;
|
||||
}
|
||||
|
||||
PropertyMap ASF::File::properties() const
|
||||
{
|
||||
return d->tag->properties();
|
||||
}
|
||||
|
||||
void ASF::File::removeUnsupportedProperties(const StringList &properties)
|
||||
{
|
||||
d->tag->removeUnsupportedProperties(properties);
|
||||
}
|
||||
|
||||
PropertyMap ASF::File::setProperties(const PropertyMap &properties)
|
||||
{
|
||||
return d->tag->setProperties(properties);
|
||||
}
|
||||
|
||||
ASF::Properties *ASF::File::audioProperties() const
|
||||
{
|
||||
return d->properties;
|
||||
|
||||
@ -90,6 +90,22 @@ namespace TagLib {
|
||||
*/
|
||||
virtual Tag *tag() const;
|
||||
|
||||
/*!
|
||||
* Implements the unified property interface -- export function.
|
||||
*/
|
||||
PropertyMap properties() const;
|
||||
|
||||
/*!
|
||||
* Removes unsupported properties. Forwards to the actual Tag's
|
||||
* removeUnsupportedProperties() function.
|
||||
*/
|
||||
void removeUnsupportedProperties(const StringList &properties);
|
||||
|
||||
/*!
|
||||
* Implements the unified property interface -- import function.
|
||||
*/
|
||||
PropertyMap setProperties(const PropertyMap &);
|
||||
|
||||
/*!
|
||||
* Returns the ASF audio properties for this file.
|
||||
*/
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <tpropertymap.h>
|
||||
#include "asftag.h"
|
||||
|
||||
using namespace TagLib;
|
||||
@ -196,3 +197,162 @@ bool ASF::Tag::isEmpty() const
|
||||
d->attributeListMap.isEmpty();
|
||||
}
|
||||
|
||||
static const char *keyTranslation[][2] = {
|
||||
{ "WM/AlbumTitle", "ALBUM" },
|
||||
{ "WM/Composer", "COMPOSER" },
|
||||
{ "WM/Writer", "WRITER" },
|
||||
{ "WM/Conductor", "CONDUCTOR" },
|
||||
{ "WM/ModifiedBy", "REMIXER" },
|
||||
{ "WM/Year", "DATE" },
|
||||
{ "WM/OriginalReleaseYear", "ORIGINALDATE" },
|
||||
{ "WM/Producer", "PRODUCER" },
|
||||
{ "WM/ContentGroupDescription", "GROUPING" },
|
||||
{ "WM/SubTitle", "SUBTITLE" },
|
||||
{ "WM/SetSubTitle", "DISCSUBTITLE" },
|
||||
{ "WM/TrackNumber", "TRACKNUMBER" },
|
||||
{ "WM/PartOfSet", "DISCNUMBER" },
|
||||
{ "WM/Genre", "GENRE" },
|
||||
{ "WM/BeatsPerMinute", "BPM" },
|
||||
{ "WM/Mood", "MOOD" },
|
||||
{ "WM/ISRC", "ISRC" },
|
||||
{ "WM/Lyrics", "LYRICS" },
|
||||
{ "WM/Media", "MEDIA" },
|
||||
{ "WM/Publisher", "LABEL" },
|
||||
{ "WM/CatalogNo", "CATALOGNUMBER" },
|
||||
{ "WM/Barcode", "BARCODE" },
|
||||
{ "WM/EncodedBy", "ENCODEDBY" },
|
||||
{ "WM/AlbumSortOrder", "ALBUMSORT" },
|
||||
{ "WM/AlbumArtistSortOrder", "ALBUMARTISTSORT" },
|
||||
{ "WM/ArtistSortOrder", "ARTISTSORT" },
|
||||
{ "WM/TitleSortOrder", "TITLESORT" },
|
||||
{ "WM/Script", "SCRIPT" },
|
||||
{ "WM/Language", "LANGUAGE" },
|
||||
{ "MusicBrainz/Track Id", "MUSICBRAINZ_TRACKID" },
|
||||
{ "MusicBrainz/Artist Id", "MUSICBRAINZ_ARTISTID" },
|
||||
{ "MusicBrainz/Album Id", "MUSICBRAINZ_ALBUMID" },
|
||||
{ "MusicBrainz/Album Artist Id", "MUSICBRAINZ_ALBUMARTISTID" },
|
||||
{ "MusicBrainz/Release Group Id", "MUSICBRAINZ_RELEASEGROUPID" },
|
||||
{ "MusicBrainz/Work Id", "MUSICBRAINZ_WORKID" },
|
||||
{ "MusicIP/PUID", "MUSICIP_PUID" },
|
||||
{ "Acoustid/Id", "ACOUSTID_ID" },
|
||||
{ "Acoustid/Fingerprint", "ACOUSTID_FINGERPRINT" },
|
||||
};
|
||||
|
||||
PropertyMap ASF::Tag::properties() const
|
||||
{
|
||||
static Map<String, String> keyMap;
|
||||
if(keyMap.isEmpty()) {
|
||||
int numKeys = sizeof(keyTranslation) / sizeof(keyTranslation[0]);
|
||||
for(int i = 0; i < numKeys; i++) {
|
||||
keyMap[keyTranslation[i][0]] = keyTranslation[i][1];
|
||||
}
|
||||
}
|
||||
|
||||
PropertyMap props;
|
||||
|
||||
if(!d->title.isEmpty()) {
|
||||
props["TITLE"] = d->title;
|
||||
}
|
||||
if(!d->artist.isEmpty()) {
|
||||
props["ARTIST"] = d->artist;
|
||||
}
|
||||
if(!d->copyright.isEmpty()) {
|
||||
props["COPYRIGHT"] = d->copyright;
|
||||
}
|
||||
if(!d->comment.isEmpty()) {
|
||||
props["COMMENT"] = d->comment;
|
||||
}
|
||||
|
||||
ASF::AttributeListMap::ConstIterator it = d->attributeListMap.begin();
|
||||
for(; it != d->attributeListMap.end(); ++it) {
|
||||
if(keyMap.contains(it->first)) {
|
||||
String key = keyMap[it->first];
|
||||
AttributeList::ConstIterator it2 = it->second.begin();
|
||||
for(; it2 != it->second.end(); ++it2) {
|
||||
if(key == "TRACKNUMBER") {
|
||||
if(it2->type() == ASF::Attribute::DWordType)
|
||||
props.insert(key, String::number(it2->toUInt()));
|
||||
else
|
||||
props.insert(key, it2->toString());
|
||||
}
|
||||
else {
|
||||
props.insert(key, it2->toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
props.unsupportedData().append(it->first);
|
||||
}
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
void ASF::Tag::removeUnsupportedProperties(const StringList &props)
|
||||
{
|
||||
StringList::ConstIterator it = props.begin();
|
||||
for(; it != props.end(); ++it)
|
||||
d->attributeListMap.erase(*it);
|
||||
}
|
||||
|
||||
PropertyMap ASF::Tag::setProperties(const PropertyMap &props)
|
||||
{
|
||||
static Map<String, String> reverseKeyMap;
|
||||
if(reverseKeyMap.isEmpty()) {
|
||||
int numKeys = sizeof(keyTranslation) / sizeof(keyTranslation[0]);
|
||||
for(int i = 0; i < numKeys; i++) {
|
||||
reverseKeyMap[keyTranslation[i][1]] = keyTranslation[i][0];
|
||||
}
|
||||
}
|
||||
|
||||
PropertyMap origProps = properties();
|
||||
PropertyMap::ConstIterator it = origProps.begin();
|
||||
for(; it != origProps.end(); ++it) {
|
||||
if(!props.contains(it->first) || props[it->first].isEmpty()) {
|
||||
if(it->first == "TITLE") {
|
||||
d->title = String::null;
|
||||
}
|
||||
else if(it->first == "ARTIST") {
|
||||
d->artist = String::null;
|
||||
}
|
||||
else if(it->first == "COMMENT") {
|
||||
d->comment = String::null;
|
||||
}
|
||||
else if(it->first == "COPYRIGHT") {
|
||||
d->copyright = String::null;
|
||||
}
|
||||
else {
|
||||
d->attributeListMap.erase(reverseKeyMap[it->first]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PropertyMap ignoredProps;
|
||||
it = props.begin();
|
||||
for(; it != props.end(); ++it) {
|
||||
if(reverseKeyMap.contains(it->first)) {
|
||||
String name = reverseKeyMap[it->first];
|
||||
removeItem(name);
|
||||
StringList::ConstIterator it2 = it->second.begin();
|
||||
for(; it2 != it->second.end(); ++it2) {
|
||||
addAttribute(name, *it2);
|
||||
}
|
||||
}
|
||||
else if(it->first == "TITLE") {
|
||||
d->title = it->second.toString();
|
||||
}
|
||||
else if(it->first == "ARTIST") {
|
||||
d->artist = it->second.toString();
|
||||
}
|
||||
else if(it->first == "COMMENT") {
|
||||
d->comment = it->second.toString();
|
||||
}
|
||||
else if(it->first == "COPYRIGHT") {
|
||||
d->copyright = it->second.toString();
|
||||
}
|
||||
else {
|
||||
ignoredProps.insert(it->first, it->second);
|
||||
}
|
||||
}
|
||||
|
||||
return ignoredProps;
|
||||
}
|
||||
|
||||
@ -176,6 +176,10 @@ namespace TagLib {
|
||||
*/
|
||||
void addAttribute(const String &name, const Attribute &attribute);
|
||||
|
||||
PropertyMap properties() const;
|
||||
void removeUnsupportedProperties(const StringList& properties);
|
||||
PropertyMap setProperties(const PropertyMap &properties);
|
||||
|
||||
private:
|
||||
|
||||
class TagPrivate;
|
||||
|
||||
Reference in New Issue
Block a user