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)
{
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);
// set next tag to be empty, so tags with bigger indexes won't be read
(this->*set)("", i);
}
bool MutableSong::isModified() const

View File

@@ -27,6 +27,7 @@
#include <stdexcept>
// taglib includes
#include "id3v1tag.h"
#include "id3v2tag.h"
#include "textidentificationframe.h"
#include "mpegfile.h"
@@ -79,11 +80,13 @@ bool isAnyModified(const NC::Menu<MPD::MutableSong> &m);
std::string CapitalizeFirstLetters(const std::string &s);
void CapitalizeFirstLetters(MPD::MutableSong &s);
void LowerAllLetters(MPD::MutableSong &s);
void GetTagList(TagLib::StringList &list, const MPD::MutableSong &s, MPD::Song::GetFunction f);
template <typename T>
void WriteID3v2(const TagLib::ByteVector &type, TagLib::ID3v2::Tag *tag, const T &list);
void WriteXiphComments(const MPD::MutableSong &s, TagLib::Ogg::XiphComment *tag);
TagLib::StringList tagList(const MPD::MutableSong &s, MPD::Song::GetFunction f);
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 SavePatternList();
@@ -1039,43 +1042,21 @@ bool TagEditor::WriteTags(MPD::MutableSong &s)
TagLib::FileRef f(path_to_file.c_str());
if (!f.isNull())
{
f.tag()->setTitle(ToWString(s.getTitle()));
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()))
if (auto mp3_file = dynamic_cast<TagLib::MPEG::File *>(f.file()))
{
TagLib::ID3v2::Tag *tag = mp3_file->ID3v2Tag(1);
TagLib::StringList list;
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
clearID3v1Tags(mp3_file->ID3v1Tag());
writeID3v2Tags(s, mp3_file->ID3v2Tag(true));
}
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())
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();
unsigned pos = 0;
for (std::string value; !(value = (s.*f)(pos)).empty(); ++pos)
list.append(ToWString(value));
TagLib::StringList result;
unsigned idx = 0;
for (std::string value; !(value = (s.*f)(idx)).empty(); ++idx)
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->removeFrames(type);
TextIdentificationFrame *frame = new TextIdentificationFrame(type, TagLib::String::UTF8);
frame->setText(list);
tag->addFrame(frame);
tag->setTitle(TagLib::String::null);
tag->setArtist(TagLib::String::null);
tag->setAlbum(TagLib::String::null);
tag->setYear(0);
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->addField("DISCNUMBER", ToWString(s.getDisc())); // disc
tag->removeField("ALBUM ARTIST"); // album artist
GetTagList(list, s, &MPD::Song::getAlbumArtist);
for (TagLib::StringList::ConstIterator it = list.begin(); it != list.end(); ++it)
tag->addField("ALBUM ARTIST", *it, 0);
tag->removeField("COMPOSER"); // composer
GetTagList(list, s, &MPD::Song::getComposer);
for (TagLib::StringList::ConstIterator it = list.begin(); it != list.end(); ++it)
tag->addField("COMPOSER", *it, 0);
tag->removeField("PERFORMER"); // performer
GetTagList(list, s, &MPD::Song::getPerformer);
for (TagLib::StringList::ConstIterator it = list.begin(); it != list.end(); ++it)
tag->addField("PERFORMER", *it, 0);
tag->setTitle(ToWString(s.getTitle()));
tag->setArtist(ToWString(s.getArtist()));
tag->setAlbum(ToWString(s.getAlbum()));
tag->setYear(stringToInt(s.getDate()));
tag->setTrack(stringToInt(s.getTrack()));
tag->setGenre(ToWString(s.getGenre()));
tag->setComment(ToWString(s.getComment()));
}
void writeID3v2Tags(const MPD::MutableSong &s, TagLib::ID3v2::Tag *tag)
{
auto writeID3v2 = [&](const TagLib::ByteVector &type, const TagLib::StringList &list) {
tag->removeFrames(type);
auto frame = new TagLib::ID3v2::TextIdentificationFrame(type, TagLib::String::UTF8);
frame->setText(list);
tag->addFrame(frame);
};
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()