From 4c33af47da0cd706b3733843ae858ae6f764f151 Mon Sep 17 00:00:00 2001 From: Andrzej Rybczak Date: Wed, 12 Sep 2012 23:31:53 +0200 Subject: [PATCH] tag editor: improve tag writing abilities --- src/mutable_song.cpp | 5 +- src/tag_editor.cpp | 144 ++++++++++++++++++++++++------------------- 2 files changed, 83 insertions(+), 66 deletions(-) diff --git a/src/mutable_song.cpp b/src/mutable_song.cpp index dfa18d8b..64b2b24e 100644 --- a/src/mutable_song.cpp +++ b/src/mutable_song.cpp @@ -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 diff --git a/src/tag_editor.cpp b/src/tag_editor.cpp index 94ec5d23..c525c998 100644 --- a/src/tag_editor.cpp +++ b/src/tag_editor.cpp @@ -27,6 +27,7 @@ #include // taglib includes +#include "id3v1tag.h" #include "id3v2tag.h" #include "textidentificationframe.h" #include "mpegfile.h" @@ -79,11 +80,13 @@ bool isAnyModified(const NC::Menu &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 -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(f.file())) + if (auto mp3_file = dynamic_cast(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(f.file())) + else if (auto ogg_file = dynamic_cast(f.file())) { - WriteXiphComments(s, ogg_file->tag()); + writeXiphComments(s, ogg_file->tag()); } - else if (TagLib::FLAC::File *flac_file = dynamic_cast(f.file())) + else if (auto flac_file = dynamic_cast(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 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()