tag editor: improve tag writing abilities
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user