tag editor: improve tag writing abilities

This commit is contained in:
Andrzej Rybczak
2012-09-12 23:31:53 +02:00
parent d55070754d
commit 4c33af47da
2 changed files with 83 additions and 66 deletions

View File

@@ -169,8 +169,11 @@ void MutableSong::setDuration(unsigned int duration)
void MutableSong::setTags(SetFunction set, const std::string &value, const std::string &delimiter) void MutableSong::setTags(SetFunction set, const std::string &value, const std::string &delimiter)
{ {
auto tags = split(value, delimiter); auto tags = split(value, delimiter);
for (size_t i = 0; i < tags.size(); ++i) size_t i = 0;
for (; i < tags.size(); ++i)
(this->*set)(tags[i], i); (this->*set)(tags[i], i);
// set next tag to be empty, so tags with bigger indexes won't be read
(this->*set)("", i);
} }
bool MutableSong::isModified() const bool MutableSong::isModified() const

View File

@@ -27,6 +27,7 @@
#include <stdexcept> #include <stdexcept>
// taglib includes // taglib includes
#include "id3v1tag.h"
#include "id3v2tag.h" #include "id3v2tag.h"
#include "textidentificationframe.h" #include "textidentificationframe.h"
#include "mpegfile.h" #include "mpegfile.h"
@@ -79,11 +80,13 @@ bool isAnyModified(const NC::Menu<MPD::MutableSong> &m);
std::string CapitalizeFirstLetters(const std::string &s); std::string CapitalizeFirstLetters(const std::string &s);
void CapitalizeFirstLetters(MPD::MutableSong &s); void CapitalizeFirstLetters(MPD::MutableSong &s);
void LowerAllLetters(MPD::MutableSong &s); void LowerAllLetters(MPD::MutableSong &s);
void GetTagList(TagLib::StringList &list, const MPD::MutableSong &s, MPD::Song::GetFunction f);
template <typename T> TagLib::StringList tagList(const MPD::MutableSong &s, MPD::Song::GetFunction f);
void WriteID3v2(const TagLib::ByteVector &type, TagLib::ID3v2::Tag *tag, const T &list);
void WriteXiphComments(const MPD::MutableSong &s, TagLib::Ogg::XiphComment *tag); void clearID3v1Tags(TagLib::ID3v1::Tag *tag);
void writeCommonTags(const MPD::MutableSong &s, TagLib::Tag *tag);
void writeID3v2Tags(const MPD::MutableSong &s, TagLib::ID3v2::Tag *tag);
void writeXiphComments(const MPD::MutableSong &s, TagLib::Ogg::XiphComment *tag);
void GetPatternList(); void GetPatternList();
void SavePatternList(); void SavePatternList();
@@ -1039,43 +1042,21 @@ bool TagEditor::WriteTags(MPD::MutableSong &s)
TagLib::FileRef f(path_to_file.c_str()); TagLib::FileRef f(path_to_file.c_str());
if (!f.isNull()) if (!f.isNull())
{ {
f.tag()->setTitle(ToWString(s.getTitle())); if (auto mp3_file = dynamic_cast<TagLib::MPEG::File *>(f.file()))
f.tag()->setArtist(ToWString(s.getArtist()));
f.tag()->setAlbum(ToWString(s.getAlbum()));
f.tag()->setYear(stringToInt(s.getDate()));
f.tag()->setTrack(stringToInt(s.getTrack()));
f.tag()->setGenre(ToWString(s.getGenre()));
f.tag()->setComment(ToWString(s.getComment()));
if (TagLib::MPEG::File *mp3_file = dynamic_cast<TagLib::MPEG::File *>(f.file()))
{ {
TagLib::ID3v2::Tag *tag = mp3_file->ID3v2Tag(1); clearID3v1Tags(mp3_file->ID3v1Tag());
TagLib::StringList list; writeID3v2Tags(s, mp3_file->ID3v2Tag(true));
WriteID3v2("TIT2", tag, ToWString(s.getTitle())); // title
WriteID3v2("TPE1", tag, ToWString(s.getArtist())); // artist
WriteID3v2("TALB", tag, ToWString(s.getAlbum())); // album
WriteID3v2("TDRC", tag, ToWString(s.getDate())); // date
WriteID3v2("TRCK", tag, ToWString(s.getTrack())); // track
WriteID3v2("TCON", tag, ToWString(s.getGenre())); // genre
WriteID3v2("TPOS", tag, ToWString(s.getDisc())); // disc
GetTagList(list, s, &MPD::Song::getAlbumArtist);
WriteID3v2("TPE2", tag, list); // album artist
GetTagList(list, s, &MPD::Song::getComposer);
WriteID3v2("TCOM", tag, list); // composer
GetTagList(list, s, &MPD::Song::getPerformer);
WriteID3v2("TPE3", tag, list); // performer
} }
else if (TagLib::Ogg::Vorbis::File *ogg_file = dynamic_cast<TagLib::Ogg::Vorbis::File *>(f.file())) else if (auto ogg_file = dynamic_cast<TagLib::Ogg::Vorbis::File *>(f.file()))
{ {
WriteXiphComments(s, ogg_file->tag()); writeXiphComments(s, ogg_file->tag());
} }
else if (TagLib::FLAC::File *flac_file = dynamic_cast<TagLib::FLAC::File *>(f.file())) else if (auto flac_file = dynamic_cast<TagLib::FLAC::File *>(f.file()))
{ {
WriteXiphComments(s, flac_file->xiphComment(1)); writeXiphComments(s, flac_file->xiphComment(true));
} }
else
writeCommonTags(s, f.tag());
if (!f.save()) if (!f.save())
return false; return false;
@@ -1155,43 +1136,76 @@ void LowerAllLetters(MPD::MutableSong &s)
} }
} }
void GetTagList(TagLib::StringList &list, const MPD::MutableSong &s, MPD::Song::GetFunction f) TagLib::StringList tagList(const MPD::MutableSong &s, MPD::Song::GetFunction f)
{ {
list.clear(); TagLib::StringList result;
unsigned pos = 0; unsigned idx = 0;
for (std::string value; !(value = (s.*f)(pos)).empty(); ++pos) for (std::string value; !(value = (s.*f)(idx)).empty(); ++idx)
list.append(ToWString(value)); result.append(ToWString(value));
return result;
} }
template <typename T> void WriteID3v2(const TagLib::ByteVector &type, TagLib::ID3v2::Tag *tag, const T &list) void clearID3v1Tags(TagLib::ID3v1::Tag *tag)
{ {
using TagLib::ID3v2::TextIdentificationFrame; tag->setTitle(TagLib::String::null);
tag->removeFrames(type); tag->setArtist(TagLib::String::null);
TextIdentificationFrame *frame = new TextIdentificationFrame(type, TagLib::String::UTF8); tag->setAlbum(TagLib::String::null);
frame->setText(list); tag->setYear(0);
tag->addFrame(frame); tag->setTrack(0);
tag->setGenre(TagLib::String::null);
tag->setComment(TagLib::String::null);
} }
void WriteXiphComments(const MPD::MutableSong &s, TagLib::Ogg::XiphComment *tag) void writeCommonTags(const MPD::MutableSong &s, TagLib::Tag *tag)
{ {
TagLib::StringList list; tag->setTitle(ToWString(s.getTitle()));
tag->setArtist(ToWString(s.getArtist()));
tag->addField("DISCNUMBER", ToWString(s.getDisc())); // disc tag->setAlbum(ToWString(s.getAlbum()));
tag->setYear(stringToInt(s.getDate()));
tag->removeField("ALBUM ARTIST"); // album artist tag->setTrack(stringToInt(s.getTrack()));
GetTagList(list, s, &MPD::Song::getAlbumArtist); tag->setGenre(ToWString(s.getGenre()));
for (TagLib::StringList::ConstIterator it = list.begin(); it != list.end(); ++it) tag->setComment(ToWString(s.getComment()));
tag->addField("ALBUM ARTIST", *it, 0); }
tag->removeField("COMPOSER"); // composer void writeID3v2Tags(const MPD::MutableSong &s, TagLib::ID3v2::Tag *tag)
GetTagList(list, s, &MPD::Song::getComposer); {
for (TagLib::StringList::ConstIterator it = list.begin(); it != list.end(); ++it) auto writeID3v2 = [&](const TagLib::ByteVector &type, const TagLib::StringList &list) {
tag->addField("COMPOSER", *it, 0); tag->removeFrames(type);
auto frame = new TagLib::ID3v2::TextIdentificationFrame(type, TagLib::String::UTF8);
tag->removeField("PERFORMER"); // performer frame->setText(list);
GetTagList(list, s, &MPD::Song::getPerformer); tag->addFrame(frame);
for (TagLib::StringList::ConstIterator it = list.begin(); it != list.end(); ++it) };
tag->addField("PERFORMER", *it, 0); writeID3v2("TIT2", tagList(s, &MPD::Song::getTitle));
writeID3v2("TPE1", tagList(s, &MPD::Song::getArtist));
writeID3v2("TPE2", tagList(s, &MPD::Song::getAlbumArtist));
writeID3v2("TALB", tagList(s, &MPD::Song::getAlbum));
writeID3v2("TDRC", tagList(s, &MPD::Song::getDate));
writeID3v2("TRCK", tagList(s, &MPD::Song::getTrack));
writeID3v2("TCON", tagList(s, &MPD::Song::getGenre));
writeID3v2("TCOM", tagList(s, &MPD::Song::getComposer));
writeID3v2("TPE3", tagList(s, &MPD::Song::getPerformer));
writeID3v2("TPOS", tagList(s, &MPD::Song::getDisc));
writeID3v2("COMM", tagList(s, &MPD::Song::getComment));
}
void writeXiphComments(const MPD::MutableSong &s, TagLib::Ogg::XiphComment *tag)
{
auto writeXiph = [&](const TagLib::String &type, const TagLib::StringList &list) {
tag->removeField(type);
for (auto it = list.begin(); it != list.end(); ++it)
tag->addField(type, *it, false);
};
writeXiph("TITLE", tagList(s, &MPD::Song::getTitle));
writeXiph("ARTIST", tagList(s, &MPD::Song::getArtist));
writeXiph("ALBUM ARTIST", tagList(s, &MPD::Song::getAlbumArtist));
writeXiph("ALBUM", tagList(s, &MPD::Song::getAlbum));
writeXiph("DATE", tagList(s, &MPD::Song::getDate));
writeXiph("TRACKNUMBER", tagList(s, &MPD::Song::getTrack));
writeXiph("GENRE", tagList(s, &MPD::Song::getGenre));
writeXiph("COMPOSER", tagList(s, &MPD::Song::getComposer));
writeXiph("PERFORMER", tagList(s, &MPD::Song::getPerformer));
writeXiph("DISC", tagList(s, &MPD::Song::getDisc));
writeXiph("COMMENT", tagList(s, &MPD::Song::getComment));
} }
void GetPatternList() void GetPatternList()