diff --git a/ext/libclementine-tagreader/tagreader.cpp b/ext/libclementine-tagreader/tagreader.cpp index 3eaf4c702..7d847984c 100644 --- a/ext/libclementine-tagreader/tagreader.cpp +++ b/ext/libclementine-tagreader/tagreader.cpp @@ -428,7 +428,8 @@ bool TagReader::SaveFile(const QString& filename, SetTextFrame("TCOM", song.composer(), tag); SetTextFrame("TPE2", song.albumartist(), tag); SetTextFrame("TCMP", std::string(song.compilation() ? "1" : "0"), tag); - SetTextFrame("TXXX", QString::number(song.rating()), tag); + SetUserTextFrame("FMPS_Rating", QString::number(song.rating()), tag); + SetUserTextFrame("FMPS_PlayCount", QString::number(song.playcount()), tag); } else if (TagLib::Ogg::Vorbis::File* file = dynamic_cast(fileref->file())) { TagLib::Ogg::XiphComment* tag = file->tag(); @@ -473,6 +474,34 @@ bool TagReader::SaveFile(const QString& filename, return ret; } +void TagReader::SetUserTextFrame(const QString& description, const QString& value, + TagLib::ID3v2::Tag* tag) const { + const QByteArray descr_utf8(description.toUtf8()); + const QByteArray value_utf8(value.toUtf8()); + SetUserTextFrame(std::string(descr_utf8.constData(), descr_utf8.length()), + std::string(value_utf8.constData(), value_utf8.length()), + tag); +} + +void TagReader::SetUserTextFrame(const std::string& description, + const std::string& value, + TagLib::ID3v2::Tag* tag) const { + const TagLib::String t_description = StdStringToTaglibString(description); + // Remove the frame if it already exists + TagLib::ID3v2::UserTextIdentificationFrame* frame = + TagLib::ID3v2::UserTextIdentificationFrame::find(tag, t_description); + if (frame) { + tag->removeFrame(frame); + } + + // Create and add a new frame + frame = new TagLib::ID3v2::UserTextIdentificationFrame(TagLib::String::UTF8); + + frame->setDescription(t_description); + frame->setText(StdStringToTaglibString(value)); + tag->addFrame(frame); +} + void TagReader::SetTextFrame(const char* id, const QString& value, TagLib::ID3v2::Tag* tag) const { const QByteArray utf8(value.toUtf8()); diff --git a/ext/libclementine-tagreader/tagreader.h b/ext/libclementine-tagreader/tagreader.h index 441ec72d6..a34211e6f 100644 --- a/ext/libclementine-tagreader/tagreader.h +++ b/ext/libclementine-tagreader/tagreader.h @@ -78,6 +78,11 @@ class TagReader { pb::tagreader::SongMetadata* song) const; pb::tagreader::SongMetadata_Type GuessFileType(TagLib::FileRef* fileref) const; + void SetUserTextFrame(const QString& description, const QString& value, + TagLib::ID3v2::Tag* tag) const; + void SetUserTextFrame(const std::string& description, const std::string& value, + TagLib::ID3v2::Tag* tag) const; + void SetTextFrame(const char* id, const QString& value, TagLib::ID3v2::Tag* tag) const; void SetTextFrame(const char* id, const std::string& value, diff --git a/tests/song_test.cpp b/tests/song_test.cpp index 96c7c0008..66957a237 100644 --- a/tests/song_test.cpp +++ b/tests/song_test.cpp @@ -55,6 +55,13 @@ class SongTest : public ::testing::Test { song.InitFromProtobuf(pb_song); return song; } + + static void WriteSongToFile(const Song& song, const QString& filename) { + TagReader tag_reader; + ::pb::tagreader::SongMetadata pb_song; + song.ToProtobuf(&pb_song); + tag_reader.SaveFile(filename, pb_song); + } }; @@ -96,6 +103,11 @@ TEST_F(SongTest, FMPSRatingUser) { TemporaryResource r(":/testdata/fmpsratinguser.mp3"); Song song = ReadSongFromFile(r.fileName()); EXPECT_FLOAT_EQ(0.10, song.rating()); + + song.set_rating(0.20); + WriteSongToFile(song, r.fileName()); + Song new_song = ReadSongFromFile(r.fileName()); + EXPECT_FLOAT_EQ(0.20, new_song.rating()); } TEST_F(SongTest, FMPSRatingBoth) { @@ -108,6 +120,11 @@ TEST_F(SongTest, FMPSPlayCount) { TemporaryResource r(":/testdata/fmpsplaycount.mp3"); Song song = ReadSongFromFile(r.fileName()); EXPECT_EQ(123, song.playcount()); + + song.set_playcount(69); + WriteSongToFile(song, r.fileName()); + Song new_song = ReadSongFromFile(r.fileName()); + EXPECT_EQ(69, new_song.playcount()); } TEST_F(SongTest, FMPSPlayCountUser) {