|
|
@ -97,42 +97,8 @@
|
|
|
|
#include "core/messagehandler.h"
|
|
|
|
#include "core/messagehandler.h"
|
|
|
|
#include "utilities/timeconstants.h"
|
|
|
|
#include "utilities/timeconstants.h"
|
|
|
|
|
|
|
|
|
|
|
|
class FileRefFactory {
|
|
|
|
#undef TStringToQString
|
|
|
|
public:
|
|
|
|
#undef QStringToTString
|
|
|
|
FileRefFactory() = default;
|
|
|
|
|
|
|
|
virtual ~FileRefFactory() = default;
|
|
|
|
|
|
|
|
virtual TagLib::FileRef *GetFileRef(const QString &filename) = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
Q_DISABLE_COPY(FileRefFactory)
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TagLibFileRefFactory : public FileRefFactory {
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
TagLibFileRefFactory() = default;
|
|
|
|
|
|
|
|
TagLib::FileRef *GetFileRef(const QString &filename) override {
|
|
|
|
|
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
|
|
|
|
return new TagLib::FileRef(filename.toStdWString().c_str());
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
return new TagLib::FileRef(QFile::encodeName(filename).constData());
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
Q_DISABLE_COPY(TagLibFileRefFactory)
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TagLib::String StdStringToTaglibString(const std::string &s) {
|
|
|
|
|
|
|
|
return TagLib::String(s.c_str(), TagLib::String::UTF8);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TagLib::String QStringToTaglibString(const QString &s) {
|
|
|
|
|
|
|
|
return TagLib::String(s.toUtf8().constData(), TagLib::String::UTF8);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
|
@ -182,6 +148,30 @@ constexpr char kASF_MusicBrainz_WorkID[] = "MusicBrainz/Work Id";
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class FileRefFactory {
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
FileRefFactory() = default;
|
|
|
|
|
|
|
|
virtual ~FileRefFactory() = default;
|
|
|
|
|
|
|
|
virtual TagLib::FileRef *GetFileRef(const QString &filename) = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
Q_DISABLE_COPY(FileRefFactory)
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TagLibFileRefFactory : public FileRefFactory {
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
TagLibFileRefFactory() = default;
|
|
|
|
|
|
|
|
TagLib::FileRef *GetFileRef(const QString &filename) override {
|
|
|
|
|
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
|
|
|
|
return new TagLib::FileRef(filename.toStdWString().c_str());
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
return new TagLib::FileRef(QFile::encodeName(filename).constData());
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
Q_DISABLE_COPY(TagLibFileRefFactory)
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
TagReaderTagLib::TagReaderTagLib() : factory_(new TagLibFileRefFactory) {}
|
|
|
|
TagReaderTagLib::TagReaderTagLib() : factory_(new TagLibFileRefFactory) {}
|
|
|
|
|
|
|
|
|
|
|
@ -235,28 +225,29 @@ TagReaderBase::Result TagReaderTagLib::ReadFile(const QString &filename, spb::ta
|
|
|
|
return Result::ErrorCode::FilenameMissing;
|
|
|
|
return Result::ErrorCode::FilenameMissing;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const QByteArray url(QUrl::fromLocalFile(filename).toEncoded());
|
|
|
|
|
|
|
|
const QFileInfo fileinfo(filename);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
qLog(Debug) << "Reading tags from" << filename;
|
|
|
|
qLog(Debug) << "Reading tags from" << filename;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const QFileInfo fileinfo(filename);
|
|
|
|
|
|
|
|
if (!fileinfo.exists()) {
|
|
|
|
|
|
|
|
qLog(Error) << "File" << filename << "does not exist";
|
|
|
|
|
|
|
|
return Result::ErrorCode::FileDoesNotExist;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const QByteArray url = QUrl::fromLocalFile(filename).toEncoded();
|
|
|
|
const QByteArray basefilename = fileinfo.fileName().toUtf8();
|
|
|
|
const QByteArray basefilename = fileinfo.fileName().toUtf8();
|
|
|
|
song->set_basefilename(basefilename.constData(), basefilename.length());
|
|
|
|
song->set_basefilename(basefilename.constData(), basefilename.length());
|
|
|
|
song->set_url(url.constData(), url.size());
|
|
|
|
song->set_url(url.constData(), url.size());
|
|
|
|
song->set_filesize(fileinfo.size());
|
|
|
|
song->set_filesize(fileinfo.size());
|
|
|
|
|
|
|
|
|
|
|
|
song->set_mtime(fileinfo.lastModified().isValid() ? std::max(fileinfo.lastModified().toSecsSinceEpoch(), 0LL) : 0LL);
|
|
|
|
song->set_mtime(fileinfo.lastModified().isValid() ? std::max(fileinfo.lastModified().toSecsSinceEpoch(), 0LL) : 0LL);
|
|
|
|
song->set_ctime(fileinfo.birthTime().isValid() ? std::max(fileinfo.birthTime().toSecsSinceEpoch(), 0LL) : fileinfo.lastModified().isValid() ? std::max(fileinfo.lastModified().toSecsSinceEpoch(), 0LL) : 0LL);
|
|
|
|
song->set_ctime(fileinfo.birthTime().isValid() ? std::max(fileinfo.birthTime().toSecsSinceEpoch(), 0LL) : fileinfo.lastModified().isValid() ? std::max(fileinfo.lastModified().toSecsSinceEpoch(), 0LL) : 0LL);
|
|
|
|
|
|
|
|
|
|
|
|
if (song->ctime() <= 0) {
|
|
|
|
if (song->ctime() <= 0) {
|
|
|
|
song->set_ctime(song->mtime());
|
|
|
|
song->set_ctime(song->mtime());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
song->set_lastseen(QDateTime::currentSecsSinceEpoch());
|
|
|
|
song->set_lastseen(QDateTime::currentSecsSinceEpoch());
|
|
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));
|
|
|
|
std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));
|
|
|
|
if (fileref->isNull()) {
|
|
|
|
if (!fileref || fileref->isNull()) {
|
|
|
|
qLog(Error) << "TagLib hasn't been able to read" << filename << "file";
|
|
|
|
qLog(Error) << "TagLib could not open file" << filename;
|
|
|
|
return Result::ErrorCode::FileOpenError;
|
|
|
|
return Result::ErrorCode::FileOpenError;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -270,10 +261,10 @@ TagReaderBase::Result TagReaderTagLib::ReadFile(const QString &filename, spb::ta
|
|
|
|
|
|
|
|
|
|
|
|
TagLib::Tag *tag = fileref->tag();
|
|
|
|
TagLib::Tag *tag = fileref->tag();
|
|
|
|
if (tag) {
|
|
|
|
if (tag) {
|
|
|
|
TStringToStdString(tag->title(), song->mutable_title());
|
|
|
|
AssignTagLibStringToStdString(tag->title(), song->mutable_title());
|
|
|
|
TStringToStdString(tag->artist(), song->mutable_artist()); // TPE1
|
|
|
|
AssignTagLibStringToStdString(tag->artist(), song->mutable_artist()); // TPE1
|
|
|
|
TStringToStdString(tag->album(), song->mutable_album());
|
|
|
|
AssignTagLibStringToStdString(tag->album(), song->mutable_album());
|
|
|
|
TStringToStdString(tag->genre(), song->mutable_genre());
|
|
|
|
AssignTagLibStringToStdString(tag->genre(), song->mutable_genre());
|
|
|
|
song->set_year(static_cast<int>(tag->year()));
|
|
|
|
song->set_year(static_cast<int>(tag->year()));
|
|
|
|
song->set_track(static_cast<int>(tag->track()));
|
|
|
|
song->set_track(static_cast<int>(tag->track()));
|
|
|
|
song->set_valid(true);
|
|
|
|
song->set_valid(true);
|
|
|
@ -312,7 +303,7 @@ TagReaderBase::Result TagReaderTagLib::ReadFile(const QString &filename, spb::ta
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (tag) TStringToStdString(tag->comment(), song->mutable_comment());
|
|
|
|
if (tag) AssignTagLibStringToStdString(tag->comment(), song->mutable_comment());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
else if (TagLib::WavPack::File *file_wavpack = dynamic_cast<TagLib::WavPack::File*>(fileref->file())) {
|
|
|
|
else if (TagLib::WavPack::File *file_wavpack = dynamic_cast<TagLib::WavPack::File*>(fileref->file())) {
|
|
|
@ -320,7 +311,7 @@ TagReaderBase::Result TagReaderTagLib::ReadFile(const QString &filename, spb::ta
|
|
|
|
if (file_wavpack->APETag()) {
|
|
|
|
if (file_wavpack->APETag()) {
|
|
|
|
ParseAPETag(file_wavpack->APETag()->itemListMap(), &disc, &compilation, song);
|
|
|
|
ParseAPETag(file_wavpack->APETag()->itemListMap(), &disc, &compilation, song);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (tag) TStringToStdString(tag->comment(), song->mutable_comment());
|
|
|
|
if (tag) AssignTagLibStringToStdString(tag->comment(), song->mutable_comment());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
else if (TagLib::APE::File *file_ape = dynamic_cast<TagLib::APE::File*>(fileref->file())) {
|
|
|
|
else if (TagLib::APE::File *file_ape = dynamic_cast<TagLib::APE::File*>(fileref->file())) {
|
|
|
@ -328,7 +319,7 @@ TagReaderBase::Result TagReaderTagLib::ReadFile(const QString &filename, spb::ta
|
|
|
|
ParseAPETag(file_ape->APETag()->itemListMap(), &disc, &compilation, song);
|
|
|
|
ParseAPETag(file_ape->APETag()->itemListMap(), &disc, &compilation, song);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
song->set_bitdepth(file_ape->audioProperties()->bitsPerSample());
|
|
|
|
song->set_bitdepth(file_ape->audioProperties()->bitsPerSample());
|
|
|
|
if (tag) TStringToStdString(tag->comment(), song->mutable_comment());
|
|
|
|
if (tag) AssignTagLibStringToStdString(tag->comment(), song->mutable_comment());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
else if (TagLib::MPEG::File *file_mpeg = dynamic_cast<TagLib::MPEG::File*>(fileref->file())) {
|
|
|
|
else if (TagLib::MPEG::File *file_mpeg = dynamic_cast<TagLib::MPEG::File*>(fileref->file())) {
|
|
|
@ -348,7 +339,7 @@ TagReaderBase::Result TagReaderTagLib::ReadFile(const QString &filename, spb::ta
|
|
|
|
if (mp4_tag->item("aART").isValid()) {
|
|
|
|
if (mp4_tag->item("aART").isValid()) {
|
|
|
|
TagLib::StringList album_artists = mp4_tag->item("aART").toStringList();
|
|
|
|
TagLib::StringList album_artists = mp4_tag->item("aART").toStringList();
|
|
|
|
if (!album_artists.isEmpty()) {
|
|
|
|
if (!album_artists.isEmpty()) {
|
|
|
|
TStringToStdString(album_artists.front(), song->mutable_albumartist());
|
|
|
|
AssignTagLibStringToStdString(album_artists.front(), song->mutable_albumartist());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -358,21 +349,21 @@ TagReaderBase::Result TagReaderTagLib::ReadFile(const QString &filename, spb::ta
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (mp4_tag->item("disk").isValid()) {
|
|
|
|
if (mp4_tag->item("disk").isValid()) {
|
|
|
|
disc = TStringToQString(TagLib::String::number(mp4_tag->item("disk").toIntPair().first));
|
|
|
|
disc = TagLibStringToQString(TagLib::String::number(mp4_tag->item("disk").toIntPair().first));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (mp4_tag->item("\251wrt").isValid()) {
|
|
|
|
if (mp4_tag->item("\251wrt").isValid()) {
|
|
|
|
TStringToStdString(mp4_tag->item("\251wrt").toStringList().toString(", "), song->mutable_composer());
|
|
|
|
AssignTagLibStringToStdString(mp4_tag->item("\251wrt").toStringList().toString(", "), song->mutable_composer());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (mp4_tag->item("\251grp").isValid()) {
|
|
|
|
if (mp4_tag->item("\251grp").isValid()) {
|
|
|
|
TStringToStdString(mp4_tag->item("\251grp").toStringList().toString(" "), song->mutable_grouping());
|
|
|
|
AssignTagLibStringToStdString(mp4_tag->item("\251grp").toStringList().toString(" "), song->mutable_grouping());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (mp4_tag->item("\251lyr").isValid()) {
|
|
|
|
if (mp4_tag->item("\251lyr").isValid()) {
|
|
|
|
TStringToStdString(mp4_tag->item("\251lyr").toStringList().toString(" "), song->mutable_lyrics());
|
|
|
|
AssignTagLibStringToStdString(mp4_tag->item("\251lyr").toStringList().toString(" "), song->mutable_lyrics());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (mp4_tag->item(kMP4_OriginalYear_ID).isValid()) {
|
|
|
|
if (mp4_tag->item(kMP4_OriginalYear_ID).isValid()) {
|
|
|
|
song->set_originalyear(TStringToQString(mp4_tag->item(kMP4_OriginalYear_ID).toStringList().toString('\n')).left(4).toInt());
|
|
|
|
song->set_originalyear(TagLibStringToQString(mp4_tag->item(kMP4_OriginalYear_ID).toStringList().toString('\n')).left(4).toInt());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (mp4_tag->item("cpil").isValid()) {
|
|
|
|
if (mp4_tag->item("cpil").isValid()) {
|
|
|
@ -382,7 +373,7 @@ TagReaderBase::Result TagReaderTagLib::ReadFile(const QString &filename, spb::ta
|
|
|
|
{
|
|
|
|
{
|
|
|
|
TagLib::MP4::Item item = mp4_tag->item(kMP4_FMPS_Playcount_ID);
|
|
|
|
TagLib::MP4::Item item = mp4_tag->item(kMP4_FMPS_Playcount_ID);
|
|
|
|
if (item.isValid()) {
|
|
|
|
if (item.isValid()) {
|
|
|
|
const int playcount = TStringToQString(item.toStringList().toString('\n')).toInt();
|
|
|
|
const int playcount = TagLibStringToQString(item.toStringList().toString('\n')).toInt();
|
|
|
|
if (song->playcount() <= 0 && playcount > 0) {
|
|
|
|
if (song->playcount() <= 0 && playcount > 0) {
|
|
|
|
song->set_playcount(static_cast<uint>(playcount));
|
|
|
|
song->set_playcount(static_cast<uint>(playcount));
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -392,51 +383,51 @@ TagReaderBase::Result TagReaderTagLib::ReadFile(const QString &filename, spb::ta
|
|
|
|
{
|
|
|
|
{
|
|
|
|
TagLib::MP4::Item item = mp4_tag->item(kMP4_FMPS_Rating_ID);
|
|
|
|
TagLib::MP4::Item item = mp4_tag->item(kMP4_FMPS_Rating_ID);
|
|
|
|
if (item.isValid()) {
|
|
|
|
if (item.isValid()) {
|
|
|
|
const float rating = TStringToQString(item.toStringList().toString('\n')).toFloat();
|
|
|
|
const float rating = TagLibStringToQString(item.toStringList().toString('\n')).toFloat();
|
|
|
|
if (song->rating() <= 0 && rating > 0) {
|
|
|
|
if (song->rating() <= 0 && rating > 0) {
|
|
|
|
song->set_rating(rating);
|
|
|
|
song->set_rating(rating);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TStringToStdString(mp4_tag->comment(), song->mutable_comment());
|
|
|
|
AssignTagLibStringToStdString(mp4_tag->comment(), song->mutable_comment());
|
|
|
|
|
|
|
|
|
|
|
|
if (mp4_tag->contains(kMP4_AcoustID_ID)) {
|
|
|
|
if (mp4_tag->contains(kMP4_AcoustID_ID)) {
|
|
|
|
TStringToStdString(mp4_tag->item(kMP4_AcoustID_ID).toStringList().toString(), song->mutable_acoustid_id());
|
|
|
|
AssignTagLibStringToStdString(mp4_tag->item(kMP4_AcoustID_ID).toStringList().toString(), song->mutable_acoustid_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (mp4_tag->contains(kMP4_AcoustID_Fingerprint)) {
|
|
|
|
if (mp4_tag->contains(kMP4_AcoustID_Fingerprint)) {
|
|
|
|
TStringToStdString(mp4_tag->item(kMP4_AcoustID_Fingerprint).toStringList().toString(), song->mutable_acoustid_fingerprint());
|
|
|
|
AssignTagLibStringToStdString(mp4_tag->item(kMP4_AcoustID_Fingerprint).toStringList().toString(), song->mutable_acoustid_fingerprint());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (mp4_tag->contains(kMP4_MusicBrainz_AlbumArtistID)) {
|
|
|
|
if (mp4_tag->contains(kMP4_MusicBrainz_AlbumArtistID)) {
|
|
|
|
TStringToStdString(mp4_tag->item(kMP4_MusicBrainz_AlbumArtistID).toStringList().toString(), song->mutable_musicbrainz_album_artist_id());
|
|
|
|
AssignTagLibStringToStdString(mp4_tag->item(kMP4_MusicBrainz_AlbumArtistID).toStringList().toString(), song->mutable_musicbrainz_album_artist_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (mp4_tag->contains(kMP4_MusicBrainz_ArtistID)) {
|
|
|
|
if (mp4_tag->contains(kMP4_MusicBrainz_ArtistID)) {
|
|
|
|
TStringToStdString(mp4_tag->item(kMP4_MusicBrainz_ArtistID).toStringList().toString(), song->mutable_musicbrainz_artist_id());
|
|
|
|
AssignTagLibStringToStdString(mp4_tag->item(kMP4_MusicBrainz_ArtistID).toStringList().toString(), song->mutable_musicbrainz_artist_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (mp4_tag->contains(kMP4_MusicBrainz_OriginalArtistID)) {
|
|
|
|
if (mp4_tag->contains(kMP4_MusicBrainz_OriginalArtistID)) {
|
|
|
|
TStringToStdString(mp4_tag->item(kMP4_MusicBrainz_OriginalArtistID).toStringList().toString(), song->mutable_musicbrainz_original_artist_id());
|
|
|
|
AssignTagLibStringToStdString(mp4_tag->item(kMP4_MusicBrainz_OriginalArtistID).toStringList().toString(), song->mutable_musicbrainz_original_artist_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (mp4_tag->contains(kMP4_MusicBrainz_AlbumID)) {
|
|
|
|
if (mp4_tag->contains(kMP4_MusicBrainz_AlbumID)) {
|
|
|
|
TStringToStdString(mp4_tag->item(kMP4_MusicBrainz_AlbumID).toStringList().toString(), song->mutable_musicbrainz_album_id());
|
|
|
|
AssignTagLibStringToStdString(mp4_tag->item(kMP4_MusicBrainz_AlbumID).toStringList().toString(), song->mutable_musicbrainz_album_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (mp4_tag->contains(kMP4_MusicBrainz_OriginalAlbumID)) {
|
|
|
|
if (mp4_tag->contains(kMP4_MusicBrainz_OriginalAlbumID)) {
|
|
|
|
TStringToStdString(mp4_tag->item(kMP4_MusicBrainz_OriginalAlbumID).toStringList().toString(), song->mutable_musicbrainz_original_album_id());
|
|
|
|
AssignTagLibStringToStdString(mp4_tag->item(kMP4_MusicBrainz_OriginalAlbumID).toStringList().toString(), song->mutable_musicbrainz_original_album_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (mp4_tag->contains(kMP4_MusicBrainz_RecordingID)) {
|
|
|
|
if (mp4_tag->contains(kMP4_MusicBrainz_RecordingID)) {
|
|
|
|
TStringToStdString(mp4_tag->item(kMP4_MusicBrainz_RecordingID).toStringList().toString(), song->mutable_musicbrainz_recording_id());
|
|
|
|
AssignTagLibStringToStdString(mp4_tag->item(kMP4_MusicBrainz_RecordingID).toStringList().toString(), song->mutable_musicbrainz_recording_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (mp4_tag->contains(kMP4_MusicBrainz_TrackID)) {
|
|
|
|
if (mp4_tag->contains(kMP4_MusicBrainz_TrackID)) {
|
|
|
|
TStringToStdString(mp4_tag->item(kMP4_MusicBrainz_TrackID).toStringList().toString(), song->mutable_musicbrainz_track_id());
|
|
|
|
AssignTagLibStringToStdString(mp4_tag->item(kMP4_MusicBrainz_TrackID).toStringList().toString(), song->mutable_musicbrainz_track_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (mp4_tag->contains(kMP4_MusicBrainz_DiscID)) {
|
|
|
|
if (mp4_tag->contains(kMP4_MusicBrainz_DiscID)) {
|
|
|
|
TStringToStdString(mp4_tag->item(kMP4_MusicBrainz_DiscID).toStringList().toString(), song->mutable_musicbrainz_disc_id());
|
|
|
|
AssignTagLibStringToStdString(mp4_tag->item(kMP4_MusicBrainz_DiscID).toStringList().toString(), song->mutable_musicbrainz_disc_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (mp4_tag->contains(kMP4_MusicBrainz_ReleaseGroupID)) {
|
|
|
|
if (mp4_tag->contains(kMP4_MusicBrainz_ReleaseGroupID)) {
|
|
|
|
TStringToStdString(mp4_tag->item(kMP4_MusicBrainz_ReleaseGroupID).toStringList().toString(), song->mutable_musicbrainz_release_group_id());
|
|
|
|
AssignTagLibStringToStdString(mp4_tag->item(kMP4_MusicBrainz_ReleaseGroupID).toStringList().toString(), song->mutable_musicbrainz_release_group_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (mp4_tag->contains(kMP4_MusicBrainz_WorkID)) {
|
|
|
|
if (mp4_tag->contains(kMP4_MusicBrainz_WorkID)) {
|
|
|
|
TStringToStdString(mp4_tag->item(kMP4_MusicBrainz_WorkID).toStringList().toString(), song->mutable_musicbrainz_work_id());
|
|
|
|
AssignTagLibStringToStdString(mp4_tag->item(kMP4_MusicBrainz_WorkID).toStringList().toString(), song->mutable_musicbrainz_work_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -447,27 +438,27 @@ TagReaderBase::Result TagReaderTagLib::ReadFile(const QString &filename, spb::ta
|
|
|
|
song->set_bitdepth(file_asf->audioProperties()->bitsPerSample());
|
|
|
|
song->set_bitdepth(file_asf->audioProperties()->bitsPerSample());
|
|
|
|
|
|
|
|
|
|
|
|
if (file_asf->tag()) {
|
|
|
|
if (file_asf->tag()) {
|
|
|
|
TStringToStdString(file_asf->tag()->comment(), song->mutable_comment());
|
|
|
|
AssignTagLibStringToStdString(file_asf->tag()->comment(), song->mutable_comment());
|
|
|
|
|
|
|
|
|
|
|
|
const TagLib::ASF::AttributeListMap &attributes_map = file_asf->tag()->attributeListMap();
|
|
|
|
const TagLib::ASF::AttributeListMap &attributes_map = file_asf->tag()->attributeListMap();
|
|
|
|
|
|
|
|
|
|
|
|
if (attributes_map.contains(kASF_OriginalDate_ID)) {
|
|
|
|
if (attributes_map.contains(kASF_OriginalDate_ID)) {
|
|
|
|
const TagLib::ASF::AttributeList &attributes = attributes_map[kASF_OriginalDate_ID];
|
|
|
|
const TagLib::ASF::AttributeList &attributes = attributes_map[kASF_OriginalDate_ID];
|
|
|
|
if (!attributes.isEmpty()) {
|
|
|
|
if (!attributes.isEmpty()) {
|
|
|
|
song->set_originalyear(TStringToQString(attributes.front().toString()).left(4).toInt());
|
|
|
|
song->set_originalyear(TagLibStringToQString(attributes.front().toString()).left(4).toInt());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (attributes_map.contains(kASF_OriginalYear_ID)) {
|
|
|
|
else if (attributes_map.contains(kASF_OriginalYear_ID)) {
|
|
|
|
const TagLib::ASF::AttributeList &attributes = attributes_map[kASF_OriginalYear_ID];
|
|
|
|
const TagLib::ASF::AttributeList &attributes = attributes_map[kASF_OriginalYear_ID];
|
|
|
|
if (!attributes.isEmpty()) {
|
|
|
|
if (!attributes.isEmpty()) {
|
|
|
|
song->set_originalyear(TStringToQString(attributes.front().toString()).left(4).toInt());
|
|
|
|
song->set_originalyear(TagLibStringToQString(attributes.front().toString()).left(4).toInt());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (attributes_map.contains("FMPS/Playcount")) {
|
|
|
|
if (attributes_map.contains("FMPS/Playcount")) {
|
|
|
|
const TagLib::ASF::AttributeList &attributes = attributes_map["FMPS/Playcount"];
|
|
|
|
const TagLib::ASF::AttributeList &attributes = attributes_map["FMPS/Playcount"];
|
|
|
|
if (!attributes.isEmpty()) {
|
|
|
|
if (!attributes.isEmpty()) {
|
|
|
|
int playcount = TStringToQString(attributes.front().toString()).toInt();
|
|
|
|
int playcount = TagLibStringToQString(attributes.front().toString()).toInt();
|
|
|
|
if (song->playcount() <= 0 && playcount > 0) {
|
|
|
|
if (song->playcount() <= 0 && playcount > 0) {
|
|
|
|
song->set_playcount(static_cast<uint>(playcount));
|
|
|
|
song->set_playcount(static_cast<uint>(playcount));
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -477,7 +468,7 @@ TagReaderBase::Result TagReaderTagLib::ReadFile(const QString &filename, spb::ta
|
|
|
|
if (attributes_map.contains("FMPS/Rating")) {
|
|
|
|
if (attributes_map.contains("FMPS/Rating")) {
|
|
|
|
const TagLib::ASF::AttributeList &attributes = attributes_map["FMPS/Rating"];
|
|
|
|
const TagLib::ASF::AttributeList &attributes = attributes_map["FMPS/Rating"];
|
|
|
|
if (!attributes.isEmpty()) {
|
|
|
|
if (!attributes.isEmpty()) {
|
|
|
|
float rating = TStringToQString(attributes.front().toString()).toFloat();
|
|
|
|
float rating = TagLibStringToQString(attributes.front().toString()).toFloat();
|
|
|
|
if (song->rating() <= 0 && rating > 0) {
|
|
|
|
if (song->rating() <= 0 && rating > 0) {
|
|
|
|
song->set_rating(rating);
|
|
|
|
song->set_rating(rating);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -485,41 +476,41 @@ TagReaderBase::Result TagReaderTagLib::ReadFile(const QString &filename, spb::ta
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (attributes_map.contains(kASF_AcoustID_ID)) {
|
|
|
|
if (attributes_map.contains(kASF_AcoustID_ID)) {
|
|
|
|
TStringToStdString(attributes_map[kASF_AcoustID_ID].front().toString(), song->mutable_acoustid_id());
|
|
|
|
AssignTagLibStringToStdString(attributes_map[kASF_AcoustID_ID].front().toString(), song->mutable_acoustid_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (attributes_map.contains(kASF_AcoustID_Fingerprint)) {
|
|
|
|
if (attributes_map.contains(kASF_AcoustID_Fingerprint)) {
|
|
|
|
TStringToStdString(attributes_map[kASF_AcoustID_Fingerprint].front().toString(), song->mutable_acoustid_fingerprint());
|
|
|
|
AssignTagLibStringToStdString(attributes_map[kASF_AcoustID_Fingerprint].front().toString(), song->mutable_acoustid_fingerprint());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (attributes_map.contains(kASF_MusicBrainz_AlbumArtistID)) {
|
|
|
|
if (attributes_map.contains(kASF_MusicBrainz_AlbumArtistID)) {
|
|
|
|
TStringToStdString(attributes_map[kASF_MusicBrainz_AlbumArtistID].front().toString(), song->mutable_musicbrainz_album_artist_id());
|
|
|
|
AssignTagLibStringToStdString(attributes_map[kASF_MusicBrainz_AlbumArtistID].front().toString(), song->mutable_musicbrainz_album_artist_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (attributes_map.contains(kASF_MusicBrainz_ArtistID)) {
|
|
|
|
if (attributes_map.contains(kASF_MusicBrainz_ArtistID)) {
|
|
|
|
TStringToStdString(attributes_map[kASF_MusicBrainz_ArtistID].front().toString(), song->mutable_musicbrainz_artist_id());
|
|
|
|
AssignTagLibStringToStdString(attributes_map[kASF_MusicBrainz_ArtistID].front().toString(), song->mutable_musicbrainz_artist_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (attributes_map.contains(kASF_MusicBrainz_OriginalArtistID)) {
|
|
|
|
if (attributes_map.contains(kASF_MusicBrainz_OriginalArtistID)) {
|
|
|
|
TStringToStdString(attributes_map[kASF_MusicBrainz_OriginalArtistID].front().toString(), song->mutable_musicbrainz_original_artist_id());
|
|
|
|
AssignTagLibStringToStdString(attributes_map[kASF_MusicBrainz_OriginalArtistID].front().toString(), song->mutable_musicbrainz_original_artist_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (attributes_map.contains(kASF_MusicBrainz_AlbumID)) {
|
|
|
|
if (attributes_map.contains(kASF_MusicBrainz_AlbumID)) {
|
|
|
|
TStringToStdString(attributes_map[kASF_MusicBrainz_AlbumID].front().toString(), song->mutable_musicbrainz_album_id());
|
|
|
|
AssignTagLibStringToStdString(attributes_map[kASF_MusicBrainz_AlbumID].front().toString(), song->mutable_musicbrainz_album_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (attributes_map.contains(kASF_MusicBrainz_OriginalAlbumID)) {
|
|
|
|
if (attributes_map.contains(kASF_MusicBrainz_OriginalAlbumID)) {
|
|
|
|
TStringToStdString(attributes_map[kASF_MusicBrainz_OriginalAlbumID].front().toString(), song->mutable_musicbrainz_original_album_id());
|
|
|
|
AssignTagLibStringToStdString(attributes_map[kASF_MusicBrainz_OriginalAlbumID].front().toString(), song->mutable_musicbrainz_original_album_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (attributes_map.contains(kASF_MusicBrainz_RecordingID)) {
|
|
|
|
if (attributes_map.contains(kASF_MusicBrainz_RecordingID)) {
|
|
|
|
TStringToStdString(attributes_map[kASF_MusicBrainz_RecordingID].front().toString(), song->mutable_musicbrainz_recording_id());
|
|
|
|
AssignTagLibStringToStdString(attributes_map[kASF_MusicBrainz_RecordingID].front().toString(), song->mutable_musicbrainz_recording_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (attributes_map.contains(kASF_MusicBrainz_TrackID)) {
|
|
|
|
if (attributes_map.contains(kASF_MusicBrainz_TrackID)) {
|
|
|
|
TStringToStdString(attributes_map[kASF_MusicBrainz_TrackID].front().toString(), song->mutable_musicbrainz_track_id());
|
|
|
|
AssignTagLibStringToStdString(attributes_map[kASF_MusicBrainz_TrackID].front().toString(), song->mutable_musicbrainz_track_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (attributes_map.contains(kASF_MusicBrainz_DiscID)) {
|
|
|
|
if (attributes_map.contains(kASF_MusicBrainz_DiscID)) {
|
|
|
|
TStringToStdString(attributes_map[kASF_MusicBrainz_DiscID].front().toString(), song->mutable_musicbrainz_disc_id());
|
|
|
|
AssignTagLibStringToStdString(attributes_map[kASF_MusicBrainz_DiscID].front().toString(), song->mutable_musicbrainz_disc_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (attributes_map.contains(kASF_MusicBrainz_ReleaseGroupID)) {
|
|
|
|
if (attributes_map.contains(kASF_MusicBrainz_ReleaseGroupID)) {
|
|
|
|
TStringToStdString(attributes_map[kASF_MusicBrainz_ReleaseGroupID].front().toString(), song->mutable_musicbrainz_release_group_id());
|
|
|
|
AssignTagLibStringToStdString(attributes_map[kASF_MusicBrainz_ReleaseGroupID].front().toString(), song->mutable_musicbrainz_release_group_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (attributes_map.contains(kASF_MusicBrainz_WorkID)) {
|
|
|
|
if (attributes_map.contains(kASF_MusicBrainz_WorkID)) {
|
|
|
|
TStringToStdString(attributes_map[kASF_MusicBrainz_WorkID].front().toString(), song->mutable_musicbrainz_work_id());
|
|
|
|
AssignTagLibStringToStdString(attributes_map[kASF_MusicBrainz_WorkID].front().toString(), song->mutable_musicbrainz_work_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -530,7 +521,7 @@ TagReaderBase::Result TagReaderTagLib::ReadFile(const QString &filename, spb::ta
|
|
|
|
if (file_mpc->APETag()) {
|
|
|
|
if (file_mpc->APETag()) {
|
|
|
|
ParseAPETag(file_mpc->APETag()->itemListMap(), &disc, &compilation, song);
|
|
|
|
ParseAPETag(file_mpc->APETag()->itemListMap(), &disc, &compilation, song);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (tag) TStringToStdString(tag->comment(), song->mutable_comment());
|
|
|
|
if (tag) AssignTagLibStringToStdString(tag->comment(), song->mutable_comment());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
else if (TagLib::RIFF::WAV::File *file_wav = dynamic_cast<TagLib::RIFF::WAV::File*>(fileref->file())) {
|
|
|
|
else if (TagLib::RIFF::WAV::File *file_wav = dynamic_cast<TagLib::RIFF::WAV::File*>(fileref->file())) {
|
|
|
@ -540,7 +531,7 @@ TagReaderBase::Result TagReaderTagLib::ReadFile(const QString &filename, spb::ta
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
else if (tag) {
|
|
|
|
else if (tag) {
|
|
|
|
TStringToStdString(tag->comment(), song->mutable_comment());
|
|
|
|
AssignTagLibStringToStdString(tag->comment(), song->mutable_comment());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!disc.isEmpty()) {
|
|
|
|
if (!disc.isEmpty()) {
|
|
|
@ -590,33 +581,25 @@ TagReaderBase::Result TagReaderTagLib::ReadFile(const QString &filename, spb::ta
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TagReaderTagLib::TStringToStdString(const TagLib::String &tag, std::string *output) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const QString tmp = TStringToQString(tag).trimmed();
|
|
|
|
|
|
|
|
const QByteArray data = tmp.toUtf8();
|
|
|
|
|
|
|
|
output->assign(data.constData(), data.size());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void TagReaderTagLib::ParseID3v2Tag(TagLib::ID3v2::Tag *tag, QString *disc, QString *compilation, spb::tagreader::SongMetadata *song) const {
|
|
|
|
void TagReaderTagLib::ParseID3v2Tag(TagLib::ID3v2::Tag *tag, QString *disc, QString *compilation, spb::tagreader::SongMetadata *song) const {
|
|
|
|
|
|
|
|
|
|
|
|
TagLib::ID3v2::FrameListMap map = tag->frameListMap();
|
|
|
|
TagLib::ID3v2::FrameListMap map = tag->frameListMap();
|
|
|
|
|
|
|
|
|
|
|
|
if (map.contains("TPOS")) *disc = TStringToQString(map["TPOS"].front()->toString()).trimmed();
|
|
|
|
if (map.contains("TPOS")) *disc = TagLibStringToQString(map["TPOS"].front()->toString()).trimmed();
|
|
|
|
if (map.contains("TCOM")) TStringToStdString(map["TCOM"].front()->toString(), song->mutable_composer());
|
|
|
|
if (map.contains("TCOM")) AssignTagLibStringToStdString(map["TCOM"].front()->toString(), song->mutable_composer());
|
|
|
|
|
|
|
|
|
|
|
|
// content group
|
|
|
|
// content group
|
|
|
|
if (map.contains("TIT1")) TStringToStdString(map["TIT1"].front()->toString(), song->mutable_grouping());
|
|
|
|
if (map.contains("TIT1")) AssignTagLibStringToStdString(map["TIT1"].front()->toString(), song->mutable_grouping());
|
|
|
|
|
|
|
|
|
|
|
|
// original artist/performer
|
|
|
|
// original artist/performer
|
|
|
|
if (map.contains("TOPE")) TStringToStdString(map["TOPE"].front()->toString(), song->mutable_performer());
|
|
|
|
if (map.contains("TOPE")) AssignTagLibStringToStdString(map["TOPE"].front()->toString(), song->mutable_performer());
|
|
|
|
|
|
|
|
|
|
|
|
// Skip TPE1 (which is the artist) here because we already fetched it
|
|
|
|
// Skip TPE1 (which is the artist) here because we already fetched it
|
|
|
|
|
|
|
|
|
|
|
|
// non-standard: Apple, Microsoft
|
|
|
|
// non-standard: Apple, Microsoft
|
|
|
|
if (map.contains("TPE2")) TStringToStdString(map["TPE2"].front()->toString(), song->mutable_albumartist());
|
|
|
|
if (map.contains("TPE2")) AssignTagLibStringToStdString(map["TPE2"].front()->toString(), song->mutable_albumartist());
|
|
|
|
|
|
|
|
|
|
|
|
if (map.contains("TCMP")) *compilation = TStringToQString(map["TCMP"].front()->toString()).trimmed();
|
|
|
|
if (map.contains("TCMP")) *compilation = TagLibStringToQString(map["TCMP"].front()->toString()).trimmed();
|
|
|
|
|
|
|
|
|
|
|
|
if (map.contains("TDOR")) {
|
|
|
|
if (map.contains("TDOR")) {
|
|
|
|
song->set_originalyear(map["TDOR"].front()->toString().substr(0, 4).toInt());
|
|
|
|
song->set_originalyear(map["TDOR"].front()->toString().substr(0, 4).toInt());
|
|
|
@ -626,10 +609,10 @@ void TagReaderTagLib::ParseID3v2Tag(TagLib::ID3v2::Tag *tag, QString *disc, QStr
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (map.contains("USLT")) {
|
|
|
|
if (map.contains("USLT")) {
|
|
|
|
TStringToStdString(map["USLT"].front()->toString(), song->mutable_lyrics());
|
|
|
|
AssignTagLibStringToStdString(map["USLT"].front()->toString(), song->mutable_lyrics());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (map.contains("SYLT")) {
|
|
|
|
else if (map.contains("SYLT")) {
|
|
|
|
TStringToStdString(map["SYLT"].front()->toString(), song->mutable_lyrics());
|
|
|
|
AssignTagLibStringToStdString(map["SYLT"].front()->toString(), song->mutable_lyrics());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (map.contains("APIC")) song->set_art_embedded(true);
|
|
|
|
if (map.contains("APIC")) song->set_art_embedded(true);
|
|
|
@ -638,8 +621,8 @@ void TagReaderTagLib::ParseID3v2Tag(TagLib::ID3v2::Tag *tag, QString *disc, QStr
|
|
|
|
for (uint i = 0; i < map["COMM"].size(); ++i) {
|
|
|
|
for (uint i = 0; i < map["COMM"].size(); ++i) {
|
|
|
|
const TagLib::ID3v2::CommentsFrame *frame = dynamic_cast<const TagLib::ID3v2::CommentsFrame*>(map["COMM"][i]);
|
|
|
|
const TagLib::ID3v2::CommentsFrame *frame = dynamic_cast<const TagLib::ID3v2::CommentsFrame*>(map["COMM"][i]);
|
|
|
|
|
|
|
|
|
|
|
|
if (frame && TStringToQString(frame->description()) != QLatin1String("iTunNORM")) {
|
|
|
|
if (frame && TagLibStringToQString(frame->description()) != QLatin1String("iTunNORM")) {
|
|
|
|
TStringToStdString(frame->text(), song->mutable_comment());
|
|
|
|
AssignTagLibStringToStdString(frame->text(), song->mutable_comment());
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -647,7 +630,7 @@ void TagReaderTagLib::ParseID3v2Tag(TagLib::ID3v2::Tag *tag, QString *disc, QStr
|
|
|
|
if (TagLib::ID3v2::UserTextIdentificationFrame *frame_fmps_playcount = TagLib::ID3v2::UserTextIdentificationFrame::find(tag, "FMPS_Playcount")) {
|
|
|
|
if (TagLib::ID3v2::UserTextIdentificationFrame *frame_fmps_playcount = TagLib::ID3v2::UserTextIdentificationFrame::find(tag, "FMPS_Playcount")) {
|
|
|
|
TagLib::StringList frame_field_list = frame_fmps_playcount->fieldList();
|
|
|
|
TagLib::StringList frame_field_list = frame_fmps_playcount->fieldList();
|
|
|
|
if (frame_field_list.size() > 1) {
|
|
|
|
if (frame_field_list.size() > 1) {
|
|
|
|
int playcount = TStringToQString(frame_field_list[1]).toInt();
|
|
|
|
int playcount = TagLibStringToQString(frame_field_list[1]).toInt();
|
|
|
|
if (song->playcount() <= 0 && playcount > 0) {
|
|
|
|
if (song->playcount() <= 0 && playcount > 0) {
|
|
|
|
song->set_playcount(playcount);
|
|
|
|
song->set_playcount(playcount);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -657,7 +640,7 @@ void TagReaderTagLib::ParseID3v2Tag(TagLib::ID3v2::Tag *tag, QString *disc, QStr
|
|
|
|
if (TagLib::ID3v2::UserTextIdentificationFrame *frame_fmps_rating = TagLib::ID3v2::UserTextIdentificationFrame::find(tag, "FMPS_Rating")) {
|
|
|
|
if (TagLib::ID3v2::UserTextIdentificationFrame *frame_fmps_rating = TagLib::ID3v2::UserTextIdentificationFrame::find(tag, "FMPS_Rating")) {
|
|
|
|
TagLib::StringList frame_field_list = frame_fmps_rating->fieldList();
|
|
|
|
TagLib::StringList frame_field_list = frame_fmps_rating->fieldList();
|
|
|
|
if (frame_field_list.size() > 1) {
|
|
|
|
if (frame_field_list.size() > 1) {
|
|
|
|
float rating = TStringToQString(frame_field_list[1]).toFloat();
|
|
|
|
float rating = TagLibStringToQString(frame_field_list[1]).toFloat();
|
|
|
|
if (song->rating() <= 0 && rating > 0 && rating <= 1.0) {
|
|
|
|
if (song->rating() <= 0 && rating > 0 && rating <= 1.0) {
|
|
|
|
song->set_rating(rating);
|
|
|
|
song->set_rating(rating);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -681,7 +664,7 @@ void TagReaderTagLib::ParseID3v2Tag(TagLib::ID3v2::Tag *tag, QString *disc, QStr
|
|
|
|
if (TagLib::ID3v2::UniqueFileIdentifierFrame *frame = dynamic_cast<TagLib::ID3v2::UniqueFileIdentifierFrame*>(map["UFID"][i])) {
|
|
|
|
if (TagLib::ID3v2::UniqueFileIdentifierFrame *frame = dynamic_cast<TagLib::ID3v2::UniqueFileIdentifierFrame*>(map["UFID"][i])) {
|
|
|
|
const TagLib::PropertyMap property_map = frame->asProperties();
|
|
|
|
const TagLib::PropertyMap property_map = frame->asProperties();
|
|
|
|
if (property_map.contains(kID3v2_MusicBrainz_RecordingID)) {
|
|
|
|
if (property_map.contains(kID3v2_MusicBrainz_RecordingID)) {
|
|
|
|
TStringToStdString(property_map[kID3v2_MusicBrainz_RecordingID].toString(), song->mutable_musicbrainz_recording_id());
|
|
|
|
AssignTagLibStringToStdString(property_map[kID3v2_MusicBrainz_RecordingID].toString(), song->mutable_musicbrainz_recording_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -693,37 +676,37 @@ void TagReaderTagLib::ParseID3v2Tag(TagLib::ID3v2::Tag *tag, QString *disc, QStr
|
|
|
|
const TagLib::StringList frame_field_list = frame->fieldList();
|
|
|
|
const TagLib::StringList frame_field_list = frame->fieldList();
|
|
|
|
if (frame_field_list.size() != 2) continue;
|
|
|
|
if (frame_field_list.size() != 2) continue;
|
|
|
|
if (frame->description() == kID3v2_AcoustID_ID) {
|
|
|
|
if (frame->description() == kID3v2_AcoustID_ID) {
|
|
|
|
TStringToStdString(frame_field_list.back(), song->mutable_acoustid_id());
|
|
|
|
AssignTagLibStringToStdString(frame_field_list.back(), song->mutable_acoustid_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (frame->description() == kID3v2_AcoustID_Fingerprint) {
|
|
|
|
if (frame->description() == kID3v2_AcoustID_Fingerprint) {
|
|
|
|
TStringToStdString(frame_field_list.back(), song->mutable_acoustid_fingerprint());
|
|
|
|
AssignTagLibStringToStdString(frame_field_list.back(), song->mutable_acoustid_fingerprint());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (frame->description() == kID3v2_MusicBrainz_AlbumArtistID) {
|
|
|
|
if (frame->description() == kID3v2_MusicBrainz_AlbumArtistID) {
|
|
|
|
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_album_artist_id());
|
|
|
|
AssignTagLibStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_album_artist_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (frame->description() == kID3v2_MusicBrainz_ArtistID) {
|
|
|
|
if (frame->description() == kID3v2_MusicBrainz_ArtistID) {
|
|
|
|
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_artist_id());
|
|
|
|
AssignTagLibStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_artist_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (frame->description() == kID3v2_MusicBrainz_OriginalArtistID) {
|
|
|
|
if (frame->description() == kID3v2_MusicBrainz_OriginalArtistID) {
|
|
|
|
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_original_artist_id());
|
|
|
|
AssignTagLibStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_original_artist_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (frame->description() == kID3v2_MusicBrainz_AlbumID) {
|
|
|
|
if (frame->description() == kID3v2_MusicBrainz_AlbumID) {
|
|
|
|
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_album_id());
|
|
|
|
AssignTagLibStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_album_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (frame->description() == kID3v2_MusicBrainz_OriginalAlbumID) {
|
|
|
|
if (frame->description() == kID3v2_MusicBrainz_OriginalAlbumID) {
|
|
|
|
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_original_album_id());
|
|
|
|
AssignTagLibStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_original_album_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (frame->description() == kID3v2_MusicBrainz_TrackID) {
|
|
|
|
if (frame->description() == kID3v2_MusicBrainz_TrackID) {
|
|
|
|
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_track_id());
|
|
|
|
AssignTagLibStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_track_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (frame->description() == kID3v2_MusicBrainz_DiscID) {
|
|
|
|
if (frame->description() == kID3v2_MusicBrainz_DiscID) {
|
|
|
|
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_disc_id());
|
|
|
|
AssignTagLibStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_disc_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (frame->description() == kID3v2_MusicBrainz_ReleaseGroupID) {
|
|
|
|
if (frame->description() == kID3v2_MusicBrainz_ReleaseGroupID) {
|
|
|
|
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_release_group_id());
|
|
|
|
AssignTagLibStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_release_group_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (frame->description() == kID3v2_MusicBrainz_WorkID) {
|
|
|
|
if (frame->description() == kID3v2_MusicBrainz_WorkID) {
|
|
|
|
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_work_id());
|
|
|
|
AssignTagLibStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_work_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -733,44 +716,44 @@ void TagReaderTagLib::ParseID3v2Tag(TagLib::ID3v2::Tag *tag, QString *disc, QStr
|
|
|
|
|
|
|
|
|
|
|
|
void TagReaderTagLib::ParseOggTag(const TagLib::Ogg::FieldListMap &map, QString *disc, QString *compilation, spb::tagreader::SongMetadata *song) const {
|
|
|
|
void TagReaderTagLib::ParseOggTag(const TagLib::Ogg::FieldListMap &map, QString *disc, QString *compilation, spb::tagreader::SongMetadata *song) const {
|
|
|
|
|
|
|
|
|
|
|
|
if (map.contains("COMPOSER")) TStringToStdString(map["COMPOSER"].front(), song->mutable_composer());
|
|
|
|
if (map.contains("COMPOSER")) AssignTagLibStringToStdString(map["COMPOSER"].front(), song->mutable_composer());
|
|
|
|
if (map.contains("PERFORMER")) TStringToStdString(map["PERFORMER"].front(), song->mutable_performer());
|
|
|
|
if (map.contains("PERFORMER")) AssignTagLibStringToStdString(map["PERFORMER"].front(), song->mutable_performer());
|
|
|
|
if (map.contains("CONTENT GROUP")) TStringToStdString(map["CONTENT GROUP"].front(), song->mutable_grouping());
|
|
|
|
if (map.contains("CONTENT GROUP")) AssignTagLibStringToStdString(map["CONTENT GROUP"].front(), song->mutable_grouping());
|
|
|
|
if (map.contains("GROUPING")) TStringToStdString(map["GROUPING"].front(), song->mutable_grouping());
|
|
|
|
if (map.contains("GROUPING")) AssignTagLibStringToStdString(map["GROUPING"].front(), song->mutable_grouping());
|
|
|
|
|
|
|
|
|
|
|
|
if (map.contains("ALBUMARTIST")) TStringToStdString(map["ALBUMARTIST"].front(), song->mutable_albumartist());
|
|
|
|
if (map.contains("ALBUMARTIST")) AssignTagLibStringToStdString(map["ALBUMARTIST"].front(), song->mutable_albumartist());
|
|
|
|
else if (map.contains("ALBUM ARTIST")) TStringToStdString(map["ALBUM ARTIST"].front(), song->mutable_albumartist());
|
|
|
|
else if (map.contains("ALBUM ARTIST")) AssignTagLibStringToStdString(map["ALBUM ARTIST"].front(), song->mutable_albumartist());
|
|
|
|
|
|
|
|
|
|
|
|
if (map.contains("ORIGINALDATE")) song->set_originalyear(TStringToQString(map["ORIGINALDATE"].front()).left(4).toInt());
|
|
|
|
if (map.contains("ORIGINALDATE")) song->set_originalyear(TagLibStringToQString(map["ORIGINALDATE"].front()).left(4).toInt());
|
|
|
|
else if (map.contains("ORIGINALYEAR")) song->set_originalyear(TStringToQString(map["ORIGINALYEAR"].front()).toInt());
|
|
|
|
else if (map.contains("ORIGINALYEAR")) song->set_originalyear(TagLibStringToQString(map["ORIGINALYEAR"].front()).toInt());
|
|
|
|
|
|
|
|
|
|
|
|
if (map.contains("DISCNUMBER")) *disc = TStringToQString(map["DISCNUMBER"].front()).trimmed();
|
|
|
|
if (map.contains("DISCNUMBER")) *disc = TagLibStringToQString(map["DISCNUMBER"].front()).trimmed();
|
|
|
|
if (map.contains("COMPILATION")) *compilation = TStringToQString(map["COMPILATION"].front()).trimmed();
|
|
|
|
if (map.contains("COMPILATION")) *compilation = TagLibStringToQString(map["COMPILATION"].front()).trimmed();
|
|
|
|
if (map.contains("COVERART")) song->set_art_embedded(true);
|
|
|
|
if (map.contains("COVERART")) song->set_art_embedded(true);
|
|
|
|
if (map.contains("METADATA_BLOCK_PICTURE")) song->set_art_embedded(true);
|
|
|
|
if (map.contains("METADATA_BLOCK_PICTURE")) song->set_art_embedded(true);
|
|
|
|
|
|
|
|
|
|
|
|
if (map.contains("FMPS_PLAYCOUNT") && song->playcount() <= 0) {
|
|
|
|
if (map.contains("FMPS_PLAYCOUNT") && song->playcount() <= 0) {
|
|
|
|
const int playcount = TStringToQString(map["FMPS_PLAYCOUNT"].front()).trimmed().toInt();
|
|
|
|
const int playcount = TagLibStringToQString(map["FMPS_PLAYCOUNT"].front()).trimmed().toInt();
|
|
|
|
song->set_playcount(static_cast<uint>(playcount));
|
|
|
|
song->set_playcount(static_cast<uint>(playcount));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (map.contains("FMPS_RATING") && song->rating() <= 0) song->set_rating(TStringToQString(map["FMPS_RATING"].front()).trimmed().toFloat());
|
|
|
|
if (map.contains("FMPS_RATING") && song->rating() <= 0) song->set_rating(TagLibStringToQString(map["FMPS_RATING"].front()).trimmed().toFloat());
|
|
|
|
|
|
|
|
|
|
|
|
if (map.contains("LYRICS")) TStringToStdString(map["LYRICS"].front(), song->mutable_lyrics());
|
|
|
|
if (map.contains("LYRICS")) AssignTagLibStringToStdString(map["LYRICS"].front(), song->mutable_lyrics());
|
|
|
|
else if (map.contains("UNSYNCEDLYRICS")) TStringToStdString(map["UNSYNCEDLYRICS"].front(), song->mutable_lyrics());
|
|
|
|
else if (map.contains("UNSYNCEDLYRICS")) AssignTagLibStringToStdString(map["UNSYNCEDLYRICS"].front(), song->mutable_lyrics());
|
|
|
|
|
|
|
|
|
|
|
|
if (map.contains("ACOUSTID_ID")) TStringToStdString(map["ACOUSTID_ID"].front(), song->mutable_acoustid_id());
|
|
|
|
if (map.contains("ACOUSTID_ID")) AssignTagLibStringToStdString(map["ACOUSTID_ID"].front(), song->mutable_acoustid_id());
|
|
|
|
if (map.contains("ACOUSTID_FINGERPRINT")) TStringToStdString(map["ACOUSTID_FINGERPRINT"].front(), song->mutable_acoustid_fingerprint());
|
|
|
|
if (map.contains("ACOUSTID_FINGERPRINT")) AssignTagLibStringToStdString(map["ACOUSTID_FINGERPRINT"].front(), song->mutable_acoustid_fingerprint());
|
|
|
|
|
|
|
|
|
|
|
|
if (map.contains("MUSICBRAINZ_ALBUMARTISTID")) TStringToStdString(map["MUSICBRAINZ_ALBUMARTISTID"].front(), song->mutable_musicbrainz_album_artist_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_ALBUMARTISTID")) AssignTagLibStringToStdString(map["MUSICBRAINZ_ALBUMARTISTID"].front(), song->mutable_musicbrainz_album_artist_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_ARTISTID")) TStringToStdString(map["MUSICBRAINZ_ARTISTID"].front(), song->mutable_musicbrainz_artist_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_ARTISTID")) AssignTagLibStringToStdString(map["MUSICBRAINZ_ARTISTID"].front(), song->mutable_musicbrainz_artist_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_ORIGINALARTISTID")) TStringToStdString(map["MUSICBRAINZ_ORIGINALARTISTID"].front(), song->mutable_musicbrainz_original_artist_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_ORIGINALARTISTID")) AssignTagLibStringToStdString(map["MUSICBRAINZ_ORIGINALARTISTID"].front(), song->mutable_musicbrainz_original_artist_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_ALBUMID")) TStringToStdString(map["MUSICBRAINZ_ALBUMID"].front(), song->mutable_musicbrainz_album_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_ALBUMID")) AssignTagLibStringToStdString(map["MUSICBRAINZ_ALBUMID"].front(), song->mutable_musicbrainz_album_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_ORIGINALALBUMID")) TStringToStdString(map["MUSICBRAINZ_ORIGINALALBUMID"].front(), song->mutable_musicbrainz_original_album_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_ORIGINALALBUMID")) AssignTagLibStringToStdString(map["MUSICBRAINZ_ORIGINALALBUMID"].front(), song->mutable_musicbrainz_original_album_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_TRACKID")) TStringToStdString(map["MUSICBRAINZ_TRACKID"].front(), song->mutable_musicbrainz_recording_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_TRACKID")) AssignTagLibStringToStdString(map["MUSICBRAINZ_TRACKID"].front(), song->mutable_musicbrainz_recording_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_RELEASETRACKID")) TStringToStdString(map["MUSICBRAINZ_RELEASETRACKID"].front(), song->mutable_musicbrainz_track_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_RELEASETRACKID")) AssignTagLibStringToStdString(map["MUSICBRAINZ_RELEASETRACKID"].front(), song->mutable_musicbrainz_track_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_DISCID")) TStringToStdString(map["MUSICBRAINZ_DISCID"].front(), song->mutable_musicbrainz_disc_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_DISCID")) AssignTagLibStringToStdString(map["MUSICBRAINZ_DISCID"].front(), song->mutable_musicbrainz_disc_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_RELEASEGROUPID")) TStringToStdString(map["MUSICBRAINZ_RELEASEGROUPID"].front(), song->mutable_musicbrainz_release_group_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_RELEASEGROUPID")) AssignTagLibStringToStdString(map["MUSICBRAINZ_RELEASEGROUPID"].front(), song->mutable_musicbrainz_release_group_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_WORKID")) TStringToStdString(map["MUSICBRAINZ_WORKID"].front(), song->mutable_musicbrainz_work_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_WORKID")) AssignTagLibStringToStdString(map["MUSICBRAINZ_WORKID"].front(), song->mutable_musicbrainz_work_id());
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -780,79 +763,79 @@ void TagReaderTagLib::ParseAPETag(const TagLib::APE::ItemListMap &map, QString *
|
|
|
|
if (it != map.end()) {
|
|
|
|
if (it != map.end()) {
|
|
|
|
TagLib::StringList album_artists = it->second.values();
|
|
|
|
TagLib::StringList album_artists = it->second.values();
|
|
|
|
if (!album_artists.isEmpty()) {
|
|
|
|
if (!album_artists.isEmpty()) {
|
|
|
|
TStringToStdString(album_artists.front(), song->mutable_albumartist());
|
|
|
|
AssignTagLibStringToStdString(album_artists.front(), song->mutable_albumartist());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (map.find("COVER ART (FRONT)") != map.end()) song->set_art_embedded(true);
|
|
|
|
if (map.find("COVER ART (FRONT)") != map.end()) song->set_art_embedded(true);
|
|
|
|
if (map.contains("COMPILATION")) {
|
|
|
|
if (map.contains("COMPILATION")) {
|
|
|
|
*compilation = TStringToQString(TagLib::String::number(map["COMPILATION"].toString().toInt()));
|
|
|
|
*compilation = TagLibStringToQString(TagLib::String::number(map["COMPILATION"].toString().toInt()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (map.contains("DISC")) {
|
|
|
|
if (map.contains("DISC")) {
|
|
|
|
*disc = TStringToQString(TagLib::String::number(map["DISC"].toString().toInt()));
|
|
|
|
*disc = TagLibStringToQString(TagLib::String::number(map["DISC"].toString().toInt()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (map.contains("PERFORMER")) {
|
|
|
|
if (map.contains("PERFORMER")) {
|
|
|
|
TStringToStdString(map["PERFORMER"].values().toString(", "), song->mutable_performer());
|
|
|
|
AssignTagLibStringToStdString(map["PERFORMER"].values().toString(", "), song->mutable_performer());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (map.contains("COMPOSER")) {
|
|
|
|
if (map.contains("COMPOSER")) {
|
|
|
|
TStringToStdString(map["COMPOSER"].values().toString(", "), song->mutable_composer());
|
|
|
|
AssignTagLibStringToStdString(map["COMPOSER"].values().toString(", "), song->mutable_composer());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (map.contains("GROUPING")) {
|
|
|
|
if (map.contains("GROUPING")) {
|
|
|
|
TStringToStdString(map["GROUPING"].values().toString(" "), song->mutable_grouping());
|
|
|
|
AssignTagLibStringToStdString(map["GROUPING"].values().toString(" "), song->mutable_grouping());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (map.contains("LYRICS")) {
|
|
|
|
if (map.contains("LYRICS")) {
|
|
|
|
TStringToStdString(map["LYRICS"].toString(), song->mutable_lyrics());
|
|
|
|
AssignTagLibStringToStdString(map["LYRICS"].toString(), song->mutable_lyrics());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (map.contains("FMPS_PLAYCOUNT")) {
|
|
|
|
if (map.contains("FMPS_PLAYCOUNT")) {
|
|
|
|
const int playcount = TStringToQString(map["FMPS_PLAYCOUNT"].toString()).toInt();
|
|
|
|
const int playcount = TagLibStringToQString(map["FMPS_PLAYCOUNT"].toString()).toInt();
|
|
|
|
if (song->playcount() <= 0 && playcount > 0) {
|
|
|
|
if (song->playcount() <= 0 && playcount > 0) {
|
|
|
|
song->set_playcount(static_cast<uint>(playcount));
|
|
|
|
song->set_playcount(static_cast<uint>(playcount));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (map.contains("FMPS_RATING")) {
|
|
|
|
if (map.contains("FMPS_RATING")) {
|
|
|
|
const float rating = TStringToQString(map["FMPS_RATING"].toString()).toFloat();
|
|
|
|
const float rating = TagLibStringToQString(map["FMPS_RATING"].toString()).toFloat();
|
|
|
|
if (song->rating() <= 0 && rating > 0) {
|
|
|
|
if (song->rating() <= 0 && rating > 0) {
|
|
|
|
song->set_rating(rating);
|
|
|
|
song->set_rating(rating);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (map.contains("ACOUSTID_ID")) TStringToStdString(map["ACOUSTID_ID"].toString(), song->mutable_acoustid_id());
|
|
|
|
if (map.contains("ACOUSTID_ID")) AssignTagLibStringToStdString(map["ACOUSTID_ID"].toString(), song->mutable_acoustid_id());
|
|
|
|
if (map.contains("ACOUSTID_FINGERPRINT")) TStringToStdString(map["ACOUSTID_FINGERPRINT"].toString(), song->mutable_acoustid_fingerprint());
|
|
|
|
if (map.contains("ACOUSTID_FINGERPRINT")) AssignTagLibStringToStdString(map["ACOUSTID_FINGERPRINT"].toString(), song->mutable_acoustid_fingerprint());
|
|
|
|
|
|
|
|
|
|
|
|
if (map.contains("MUSICBRAINZ_ALBUMARTISTID")) TStringToStdString(map["MUSICBRAINZ_ALBUMARTISTID"].toString(), song->mutable_musicbrainz_album_artist_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_ALBUMARTISTID")) AssignTagLibStringToStdString(map["MUSICBRAINZ_ALBUMARTISTID"].toString(), song->mutable_musicbrainz_album_artist_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_ARTISTID")) TStringToStdString(map["MUSICBRAINZ_ARTISTID"].toString(), song->mutable_musicbrainz_artist_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_ARTISTID")) AssignTagLibStringToStdString(map["MUSICBRAINZ_ARTISTID"].toString(), song->mutable_musicbrainz_artist_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_ORIGINALARTISTID")) TStringToStdString(map["MUSICBRAINZ_ORIGINALARTISTID"].toString(), song->mutable_musicbrainz_original_artist_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_ORIGINALARTISTID")) AssignTagLibStringToStdString(map["MUSICBRAINZ_ORIGINALARTISTID"].toString(), song->mutable_musicbrainz_original_artist_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_ALBUMID")) TStringToStdString(map["MUSICBRAINZ_ALBUMID"].toString(), song->mutable_musicbrainz_album_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_ALBUMID")) AssignTagLibStringToStdString(map["MUSICBRAINZ_ALBUMID"].toString(), song->mutable_musicbrainz_album_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_ORIGINALALBUMID")) TStringToStdString(map["MUSICBRAINZ_ORIGINALALBUMID"].toString(), song->mutable_musicbrainz_original_album_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_ORIGINALALBUMID")) AssignTagLibStringToStdString(map["MUSICBRAINZ_ORIGINALALBUMID"].toString(), song->mutable_musicbrainz_original_album_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_TRACKID")) TStringToStdString(map["MUSICBRAINZ_TRACKID"].toString(), song->mutable_musicbrainz_recording_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_TRACKID")) AssignTagLibStringToStdString(map["MUSICBRAINZ_TRACKID"].toString(), song->mutable_musicbrainz_recording_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_RELEASETRACKID")) TStringToStdString(map["MUSICBRAINZ_RELEASETRACKID"].toString(), song->mutable_musicbrainz_track_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_RELEASETRACKID")) AssignTagLibStringToStdString(map["MUSICBRAINZ_RELEASETRACKID"].toString(), song->mutable_musicbrainz_track_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_DISCID")) TStringToStdString(map["MUSICBRAINZ_DISCID"].toString(), song->mutable_musicbrainz_disc_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_DISCID")) AssignTagLibStringToStdString(map["MUSICBRAINZ_DISCID"].toString(), song->mutable_musicbrainz_disc_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_RELEASEGROUPID")) TStringToStdString(map["MUSICBRAINZ_RELEASEGROUPID"].toString(), song->mutable_musicbrainz_release_group_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_RELEASEGROUPID")) AssignTagLibStringToStdString(map["MUSICBRAINZ_RELEASEGROUPID"].toString(), song->mutable_musicbrainz_release_group_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_WORKID")) TStringToStdString(map["MUSICBRAINZ_WORKID"].toString(), song->mutable_musicbrainz_work_id());
|
|
|
|
if (map.contains("MUSICBRAINZ_WORKID")) AssignTagLibStringToStdString(map["MUSICBRAINZ_WORKID"].toString(), song->mutable_musicbrainz_work_id());
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TagReaderTagLib::SetVorbisComments(TagLib::Ogg::XiphComment *vorbis_comment, const spb::tagreader::SongMetadata &song) const {
|
|
|
|
void TagReaderTagLib::SetVorbisComments(TagLib::Ogg::XiphComment *vorbis_comment, const spb::tagreader::SongMetadata &song) const {
|
|
|
|
|
|
|
|
|
|
|
|
vorbis_comment->addField("COMPOSER", StdStringToTaglibString(song.composer()), true);
|
|
|
|
vorbis_comment->addField("COMPOSER", StdStringToTagLibString(song.composer()), true);
|
|
|
|
vorbis_comment->addField("PERFORMER", StdStringToTaglibString(song.performer()), true);
|
|
|
|
vorbis_comment->addField("PERFORMER", StdStringToTagLibString(song.performer()), true);
|
|
|
|
vorbis_comment->addField("GROUPING", StdStringToTaglibString(song.grouping()), true);
|
|
|
|
vorbis_comment->addField("GROUPING", StdStringToTagLibString(song.grouping()), true);
|
|
|
|
vorbis_comment->addField("DISCNUMBER", QStringToTaglibString(song.disc() <= 0 ? QString() : QString::number(song.disc())), true);
|
|
|
|
vorbis_comment->addField("DISCNUMBER", QStringToTagLibString(song.disc() <= 0 ? QString() : QString::number(song.disc())), true);
|
|
|
|
vorbis_comment->addField("COMPILATION", QStringToTaglibString(song.compilation() ? QStringLiteral("1") : QString()), true);
|
|
|
|
vorbis_comment->addField("COMPILATION", QStringToTagLibString(song.compilation() ? QStringLiteral("1") : QString()), true);
|
|
|
|
|
|
|
|
|
|
|
|
// Try to be coherent, the two forms are used but the first one is preferred
|
|
|
|
// Try to be coherent, the two forms are used but the first one is preferred
|
|
|
|
|
|
|
|
|
|
|
|
vorbis_comment->addField("ALBUMARTIST", StdStringToTaglibString(song.albumartist()), true);
|
|
|
|
vorbis_comment->addField("ALBUMARTIST", StdStringToTagLibString(song.albumartist()), true);
|
|
|
|
vorbis_comment->removeFields("ALBUM ARTIST");
|
|
|
|
vorbis_comment->removeFields("ALBUM ARTIST");
|
|
|
|
|
|
|
|
|
|
|
|
vorbis_comment->addField("LYRICS", StdStringToTaglibString(song.lyrics()), true);
|
|
|
|
vorbis_comment->addField("LYRICS", StdStringToTagLibString(song.lyrics()), true);
|
|
|
|
vorbis_comment->removeFields("UNSYNCEDLYRICS");
|
|
|
|
vorbis_comment->removeFields("UNSYNCEDLYRICS");
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -863,6 +846,11 @@ TagReaderBase::Result TagReaderTagLib::WriteFile(const QString &filename, const
|
|
|
|
return Result::ErrorCode::FilenameMissing;
|
|
|
|
return Result::ErrorCode::FilenameMissing;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!QFile::exists(filename)) {
|
|
|
|
|
|
|
|
qLog(Error) << "File" << filename << "does not exist";
|
|
|
|
|
|
|
|
return Result::ErrorCode::FileDoesNotExist;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const spb::tagreader::SongMetadata &song = request.metadata();
|
|
|
|
const spb::tagreader::SongMetadata &song = request.metadata();
|
|
|
|
const bool save_tags = request.has_save_tags() && request.save_tags();
|
|
|
|
const bool save_tags = request.has_save_tags() && request.save_tags();
|
|
|
|
const bool save_playcount = request.has_save_playcount() && request.save_playcount();
|
|
|
|
const bool save_playcount = request.has_save_playcount() && request.save_playcount();
|
|
|
@ -889,16 +877,16 @@ TagReaderBase::Result TagReaderTagLib::WriteFile(const QString &filename, const
|
|
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));
|
|
|
|
std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));
|
|
|
|
if (!fileref || fileref->isNull()) {
|
|
|
|
if (!fileref || fileref->isNull()) {
|
|
|
|
qLog(Error) << "TagLib hasn't been able to open" << filename << "file";
|
|
|
|
qLog(Error) << "TagLib could not open file" << filename;
|
|
|
|
return Result::ErrorCode::FileOpenError;
|
|
|
|
return Result::ErrorCode::FileOpenError;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (save_tags) {
|
|
|
|
if (save_tags) {
|
|
|
|
fileref->tag()->setTitle(song.title().empty() ? TagLib::String() : StdStringToTaglibString(song.title()));
|
|
|
|
fileref->tag()->setTitle(song.title().empty() ? TagLib::String() : StdStringToTagLibString(song.title()));
|
|
|
|
fileref->tag()->setArtist(song.artist().empty() ? TagLib::String() : StdStringToTaglibString(song.artist()));
|
|
|
|
fileref->tag()->setArtist(song.artist().empty() ? TagLib::String() : StdStringToTagLibString(song.artist()));
|
|
|
|
fileref->tag()->setAlbum(song.album().empty() ? TagLib::String() : StdStringToTaglibString(song.album()));
|
|
|
|
fileref->tag()->setAlbum(song.album().empty() ? TagLib::String() : StdStringToTagLibString(song.album()));
|
|
|
|
fileref->tag()->setGenre(song.genre().empty() ? TagLib::String() : StdStringToTaglibString(song.genre()));
|
|
|
|
fileref->tag()->setGenre(song.genre().empty() ? TagLib::String() : StdStringToTagLibString(song.genre()));
|
|
|
|
fileref->tag()->setComment(song.comment().empty() ? TagLib::String() : StdStringToTaglibString(song.comment()));
|
|
|
|
fileref->tag()->setComment(song.comment().empty() ? TagLib::String() : StdStringToTagLibString(song.comment()));
|
|
|
|
fileref->tag()->setYear(song.year() <= 0 ? 0 : song.year());
|
|
|
|
fileref->tag()->setYear(song.year() <= 0 ? 0 : song.year());
|
|
|
|
fileref->tag()->setTrack(song.track() <= 0 ? 0 : song.track());
|
|
|
|
fileref->tag()->setTrack(song.track() <= 0 ? 0 : song.track());
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1076,12 +1064,12 @@ void TagReaderTagLib::SaveID3v2Tag(TagLib::ID3v2::Tag *tag, const spb::tagreader
|
|
|
|
void TagReaderTagLib::SaveAPETag(TagLib::APE::Tag *tag, const spb::tagreader::SongMetadata &song) const {
|
|
|
|
void TagReaderTagLib::SaveAPETag(TagLib::APE::Tag *tag, const spb::tagreader::SongMetadata &song) const {
|
|
|
|
|
|
|
|
|
|
|
|
tag->setItem("album artist", TagLib::APE::Item("album artist", TagLib::StringList(song.albumartist().c_str())));
|
|
|
|
tag->setItem("album artist", TagLib::APE::Item("album artist", TagLib::StringList(song.albumartist().c_str())));
|
|
|
|
tag->addValue("disc", QStringToTaglibString(song.disc() <= 0 ? QString() : QString::number(song.disc())), true);
|
|
|
|
tag->addValue("disc", QStringToTagLibString(song.disc() <= 0 ? QString() : QString::number(song.disc())), true);
|
|
|
|
tag->setItem("composer", TagLib::APE::Item("composer", TagLib::StringList(song.composer().c_str())));
|
|
|
|
tag->setItem("composer", TagLib::APE::Item("composer", TagLib::StringList(song.composer().c_str())));
|
|
|
|
tag->setItem("grouping", TagLib::APE::Item("grouping", TagLib::StringList(song.grouping().c_str())));
|
|
|
|
tag->setItem("grouping", TagLib::APE::Item("grouping", TagLib::StringList(song.grouping().c_str())));
|
|
|
|
tag->setItem("performer", TagLib::APE::Item("performer", TagLib::StringList(song.performer().c_str())));
|
|
|
|
tag->setItem("performer", TagLib::APE::Item("performer", TagLib::StringList(song.performer().c_str())));
|
|
|
|
tag->setItem("lyrics", TagLib::APE::Item("lyrics", TagLib::String(song.lyrics())));
|
|
|
|
tag->setItem("lyrics", TagLib::APE::Item("lyrics", TagLib::String(song.lyrics())));
|
|
|
|
tag->addValue("compilation", QStringToTaglibString(song.compilation() ? QString::number(1) : QString()), true);
|
|
|
|
tag->addValue("compilation", QStringToTagLibString(song.compilation() ? QString::number(1) : QString()), true);
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -1115,7 +1103,7 @@ void TagReaderTagLib::SetTextFrame(const char *id, const std::string &value, Tag
|
|
|
|
for (int i = 0; i < frames_buffer.size(); ++i) {
|
|
|
|
for (int i = 0; i < frames_buffer.size(); ++i) {
|
|
|
|
TagLib::ID3v2::TextIdentificationFrame *frame = new TagLib::ID3v2::TextIdentificationFrame(frames_buffer.at(i));
|
|
|
|
TagLib::ID3v2::TextIdentificationFrame *frame = new TagLib::ID3v2::TextIdentificationFrame(frames_buffer.at(i));
|
|
|
|
if (i == 0) {
|
|
|
|
if (i == 0) {
|
|
|
|
frame->setText(StdStringToTaglibString(value));
|
|
|
|
frame->setText(StdStringToTagLibString(value));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// add frame takes ownership and clears the memory
|
|
|
|
// add frame takes ownership and clears the memory
|
|
|
|
tag->addFrame(frame);
|
|
|
|
tag->addFrame(frame);
|
|
|
@ -1133,7 +1121,7 @@ void TagReaderTagLib::SetUserTextFrame(const QString &description, const QString
|
|
|
|
|
|
|
|
|
|
|
|
void TagReaderTagLib::SetUserTextFrame(const std::string &description, const std::string &value, TagLib::ID3v2::Tag *tag) const {
|
|
|
|
void TagReaderTagLib::SetUserTextFrame(const std::string &description, const std::string &value, TagLib::ID3v2::Tag *tag) const {
|
|
|
|
|
|
|
|
|
|
|
|
const TagLib::String t_description = StdStringToTaglibString(description);
|
|
|
|
const TagLib::String t_description = StdStringToTagLibString(description);
|
|
|
|
TagLib::ID3v2::UserTextIdentificationFrame *frame = TagLib::ID3v2::UserTextIdentificationFrame::find(tag, t_description);
|
|
|
|
TagLib::ID3v2::UserTextIdentificationFrame *frame = TagLib::ID3v2::UserTextIdentificationFrame::find(tag, t_description);
|
|
|
|
if (frame) {
|
|
|
|
if (frame) {
|
|
|
|
tag->removeFrame(frame);
|
|
|
|
tag->removeFrame(frame);
|
|
|
@ -1142,7 +1130,7 @@ void TagReaderTagLib::SetUserTextFrame(const std::string &description, const std
|
|
|
|
// Create and add a new frame
|
|
|
|
// Create and add a new frame
|
|
|
|
frame = new TagLib::ID3v2::UserTextIdentificationFrame(TagLib::String::UTF8);
|
|
|
|
frame = new TagLib::ID3v2::UserTextIdentificationFrame(TagLib::String::UTF8);
|
|
|
|
frame->setDescription(t_description);
|
|
|
|
frame->setDescription(t_description);
|
|
|
|
frame->setText(StdStringToTaglibString(value));
|
|
|
|
frame->setText(StdStringToTagLibString(value));
|
|
|
|
tag->addFrame(frame);
|
|
|
|
tag->addFrame(frame);
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1171,7 +1159,7 @@ void TagReaderTagLib::SetUnsyncLyricsFrame(const std::string &value, TagLib::ID3
|
|
|
|
for (int i = 0; i < frames_buffer.size(); ++i) {
|
|
|
|
for (int i = 0; i < frames_buffer.size(); ++i) {
|
|
|
|
TagLib::ID3v2::UnsynchronizedLyricsFrame *frame = new TagLib::ID3v2::UnsynchronizedLyricsFrame(frames_buffer.at(i));
|
|
|
|
TagLib::ID3v2::UnsynchronizedLyricsFrame *frame = new TagLib::ID3v2::UnsynchronizedLyricsFrame(frames_buffer.at(i));
|
|
|
|
if (i == 0) {
|
|
|
|
if (i == 0) {
|
|
|
|
frame->setText(StdStringToTaglibString(value));
|
|
|
|
frame->setText(StdStringToTagLibString(value));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// add frame takes ownership and clears the memory
|
|
|
|
// add frame takes ownership and clears the memory
|
|
|
|
tag->addFrame(frame);
|
|
|
|
tag->addFrame(frame);
|
|
|
@ -1185,21 +1173,21 @@ TagReaderBase::Result TagReaderTagLib::LoadEmbeddedArt(const QString &filename,
|
|
|
|
return Result::ErrorCode::FilenameMissing;
|
|
|
|
return Result::ErrorCode::FilenameMissing;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!QFile::exists(filename)) {
|
|
|
|
|
|
|
|
qLog(Error) << "File" << filename << "does not exist";
|
|
|
|
|
|
|
|
return Result::ErrorCode::FileDoesNotExist;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
qLog(Debug) << "Loading art from" << filename;
|
|
|
|
qLog(Debug) << "Loading art from" << filename;
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));
|
|
|
|
TagLib::FileRef fileref(filename.toStdWString().c_str());
|
|
|
|
if (!fileref || fileref->isNull()) {
|
|
|
|
#else
|
|
|
|
qLog(Error) << "TagLib could not open file" << filename;
|
|
|
|
TagLib::FileRef fileref(QFile::encodeName(filename).constData());
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (fileref.isNull() || !fileref.file()) {
|
|
|
|
|
|
|
|
qLog(Error) << "TagLib hasn't been able to open file" << filename;
|
|
|
|
|
|
|
|
return Result::ErrorCode::FileOpenError;
|
|
|
|
return Result::ErrorCode::FileOpenError;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// FLAC
|
|
|
|
// FLAC
|
|
|
|
if (TagLib::FLAC::File *flac_file = dynamic_cast<TagLib::FLAC::File*>(fileref.file())) {
|
|
|
|
if (TagLib::FLAC::File *flac_file = dynamic_cast<TagLib::FLAC::File*>(fileref->file())) {
|
|
|
|
if (flac_file->xiphComment()) {
|
|
|
|
if (flac_file->xiphComment()) {
|
|
|
|
TagLib::List<TagLib::FLAC::Picture*> pictures = flac_file->pictureList();
|
|
|
|
TagLib::List<TagLib::FLAC::Picture*> pictures = flac_file->pictureList();
|
|
|
|
if (!pictures.isEmpty()) {
|
|
|
|
if (!pictures.isEmpty()) {
|
|
|
@ -1216,7 +1204,7 @@ TagReaderBase::Result TagReaderTagLib::LoadEmbeddedArt(const QString &filename,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// WavPack
|
|
|
|
// WavPack
|
|
|
|
if (TagLib::WavPack::File *wavpack_file = dynamic_cast<TagLib::WavPack::File*>(fileref.file())) {
|
|
|
|
if (TagLib::WavPack::File *wavpack_file = dynamic_cast<TagLib::WavPack::File*>(fileref->file())) {
|
|
|
|
if (wavpack_file->APETag()) {
|
|
|
|
if (wavpack_file->APETag()) {
|
|
|
|
data = LoadEmbeddedAPEArt(wavpack_file->APETag()->itemListMap());
|
|
|
|
data = LoadEmbeddedAPEArt(wavpack_file->APETag()->itemListMap());
|
|
|
|
if (!data.isEmpty()) {
|
|
|
|
if (!data.isEmpty()) {
|
|
|
@ -1226,7 +1214,7 @@ TagReaderBase::Result TagReaderTagLib::LoadEmbeddedArt(const QString &filename,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// APE
|
|
|
|
// APE
|
|
|
|
if (TagLib::APE::File *ape_file = dynamic_cast<TagLib::APE::File*>(fileref.file())) {
|
|
|
|
if (TagLib::APE::File *ape_file = dynamic_cast<TagLib::APE::File*>(fileref->file())) {
|
|
|
|
if (ape_file->APETag()) {
|
|
|
|
if (ape_file->APETag()) {
|
|
|
|
data = LoadEmbeddedAPEArt(ape_file->APETag()->itemListMap());
|
|
|
|
data = LoadEmbeddedAPEArt(ape_file->APETag()->itemListMap());
|
|
|
|
if (!data.isEmpty()) {
|
|
|
|
if (!data.isEmpty()) {
|
|
|
@ -1236,7 +1224,7 @@ TagReaderBase::Result TagReaderTagLib::LoadEmbeddedArt(const QString &filename,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// MPC
|
|
|
|
// MPC
|
|
|
|
if (TagLib::MPC::File *mpc_file = dynamic_cast<TagLib::MPC::File*>(fileref.file())) {
|
|
|
|
if (TagLib::MPC::File *mpc_file = dynamic_cast<TagLib::MPC::File*>(fileref->file())) {
|
|
|
|
if (mpc_file->APETag()) {
|
|
|
|
if (mpc_file->APETag()) {
|
|
|
|
data = LoadEmbeddedAPEArt(mpc_file->APETag()->itemListMap());
|
|
|
|
data = LoadEmbeddedAPEArt(mpc_file->APETag()->itemListMap());
|
|
|
|
if (!data.isEmpty()) {
|
|
|
|
if (!data.isEmpty()) {
|
|
|
@ -1246,7 +1234,7 @@ TagReaderBase::Result TagReaderTagLib::LoadEmbeddedArt(const QString &filename,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Ogg Vorbis / Opus / Speex
|
|
|
|
// Ogg Vorbis / Opus / Speex
|
|
|
|
if (TagLib::Ogg::XiphComment *xiph_comment = dynamic_cast<TagLib::Ogg::XiphComment*>(fileref.file()->tag())) {
|
|
|
|
if (TagLib::Ogg::XiphComment *xiph_comment = dynamic_cast<TagLib::Ogg::XiphComment*>(fileref->file()->tag())) {
|
|
|
|
TagLib::Ogg::FieldListMap map = xiph_comment->fieldListMap();
|
|
|
|
TagLib::Ogg::FieldListMap map = xiph_comment->fieldListMap();
|
|
|
|
|
|
|
|
|
|
|
|
TagLib::List<TagLib::FLAC::Picture*> pictures = xiph_comment->pictureList();
|
|
|
|
TagLib::List<TagLib::FLAC::Picture*> pictures = xiph_comment->pictureList();
|
|
|
@ -1272,7 +1260,7 @@ TagReaderBase::Result TagReaderTagLib::LoadEmbeddedArt(const QString &filename,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// MP3
|
|
|
|
// MP3
|
|
|
|
if (TagLib::MPEG::File *file_mp3 = dynamic_cast<TagLib::MPEG::File*>(fileref.file())) {
|
|
|
|
if (TagLib::MPEG::File *file_mp3 = dynamic_cast<TagLib::MPEG::File*>(fileref->file())) {
|
|
|
|
if (file_mp3->ID3v2Tag()) {
|
|
|
|
if (file_mp3->ID3v2Tag()) {
|
|
|
|
TagLib::ID3v2::FrameList apic_frames = file_mp3->ID3v2Tag()->frameListMap()["APIC"];
|
|
|
|
TagLib::ID3v2::FrameList apic_frames = file_mp3->ID3v2Tag()->frameListMap()["APIC"];
|
|
|
|
if (apic_frames.isEmpty()) {
|
|
|
|
if (apic_frames.isEmpty()) {
|
|
|
@ -1289,7 +1277,7 @@ TagReaderBase::Result TagReaderTagLib::LoadEmbeddedArt(const QString &filename,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// MP4/AAC
|
|
|
|
// MP4/AAC
|
|
|
|
if (TagLib::MP4::File *aac_file = dynamic_cast<TagLib::MP4::File*>(fileref.file())) {
|
|
|
|
if (TagLib::MP4::File *aac_file = dynamic_cast<TagLib::MP4::File*>(fileref->file())) {
|
|
|
|
TagLib::MP4::Tag *tag = aac_file->tag();
|
|
|
|
TagLib::MP4::Tag *tag = aac_file->tag();
|
|
|
|
if (tag && tag->item("covr").isValid()) {
|
|
|
|
if (tag && tag->item("covr").isValid()) {
|
|
|
|
const TagLib::MP4::CoverArtList &art_list = tag->item("covr").toCoverArtList();
|
|
|
|
const TagLib::MP4::CoverArtList &art_list = tag->item("covr").toCoverArtList();
|
|
|
@ -1334,7 +1322,7 @@ void TagReaderTagLib::SetEmbeddedArt(TagLib::FLAC::File *flac_file, TagLib::Ogg:
|
|
|
|
if (!data.isEmpty()) {
|
|
|
|
if (!data.isEmpty()) {
|
|
|
|
TagLib::FLAC::Picture *picture = new TagLib::FLAC::Picture();
|
|
|
|
TagLib::FLAC::Picture *picture = new TagLib::FLAC::Picture();
|
|
|
|
picture->setType(TagLib::FLAC::Picture::FrontCover);
|
|
|
|
picture->setType(TagLib::FLAC::Picture::FrontCover);
|
|
|
|
picture->setMimeType(QStringToTString(mime_type));
|
|
|
|
picture->setMimeType(QStringToTagLibString(mime_type));
|
|
|
|
picture->setData(TagLib::ByteVector(data.constData(), data.size()));
|
|
|
|
picture->setData(TagLib::ByteVector(data.constData(), data.size()));
|
|
|
|
flac_file->addPicture(picture);
|
|
|
|
flac_file->addPicture(picture);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1348,7 +1336,7 @@ void TagReaderTagLib::SetEmbeddedArt(TagLib::Ogg::XiphComment *xiph_comment, con
|
|
|
|
if (!data.isEmpty()) {
|
|
|
|
if (!data.isEmpty()) {
|
|
|
|
TagLib::FLAC::Picture *picture = new TagLib::FLAC::Picture();
|
|
|
|
TagLib::FLAC::Picture *picture = new TagLib::FLAC::Picture();
|
|
|
|
picture->setType(TagLib::FLAC::Picture::FrontCover);
|
|
|
|
picture->setType(TagLib::FLAC::Picture::FrontCover);
|
|
|
|
picture->setMimeType(QStringToTString(mime_type));
|
|
|
|
picture->setMimeType(QStringToTagLibString(mime_type));
|
|
|
|
picture->setData(TagLib::ByteVector(data.constData(), data.size()));
|
|
|
|
picture->setData(TagLib::ByteVector(data.constData(), data.size()));
|
|
|
|
xiph_comment->addPicture(picture);
|
|
|
|
xiph_comment->addPicture(picture);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1369,7 +1357,7 @@ void TagReaderTagLib::SetEmbeddedArt(TagLib::ID3v2::Tag *tag, const QByteArray &
|
|
|
|
TagLib::ID3v2::AttachedPictureFrame *frontcover = nullptr;
|
|
|
|
TagLib::ID3v2::AttachedPictureFrame *frontcover = nullptr;
|
|
|
|
frontcover = new TagLib::ID3v2::AttachedPictureFrame("APIC");
|
|
|
|
frontcover = new TagLib::ID3v2::AttachedPictureFrame("APIC");
|
|
|
|
frontcover->setType(TagLib::ID3v2::AttachedPictureFrame::FrontCover);
|
|
|
|
frontcover->setType(TagLib::ID3v2::AttachedPictureFrame::FrontCover);
|
|
|
|
frontcover->setMimeType(QStringToTString(mime_type));
|
|
|
|
frontcover->setMimeType(QStringToTagLibString(mime_type));
|
|
|
|
frontcover->setPicture(TagLib::ByteVector(data.constData(), data.size()));
|
|
|
|
frontcover->setPicture(TagLib::ByteVector(data.constData(), data.size()));
|
|
|
|
tag->addFrame(frontcover);
|
|
|
|
tag->addFrame(frontcover);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1409,21 +1397,21 @@ TagReaderBase::Result TagReaderTagLib::SaveEmbeddedArt(const QString &filename,
|
|
|
|
|
|
|
|
|
|
|
|
qLog(Debug) << "Saving art to" << filename;
|
|
|
|
qLog(Debug) << "Saving art to" << filename;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!QFile::exists(filename)) {
|
|
|
|
|
|
|
|
qLog(Error) << "File" << filename << "does not exist";
|
|
|
|
|
|
|
|
return Result::ErrorCode::FileDoesNotExist;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const Cover cover = LoadCoverFromRequest(filename, request);
|
|
|
|
const Cover cover = LoadCoverFromRequest(filename, request);
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));
|
|
|
|
TagLib::FileRef fileref(filename.toStdWString().c_str());
|
|
|
|
if (!fileref || fileref->isNull()) {
|
|
|
|
#else
|
|
|
|
|
|
|
|
TagLib::FileRef fileref(QFile::encodeName(filename).constData());
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (fileref.isNull() || !fileref.file()) {
|
|
|
|
|
|
|
|
qLog(Error) << "TagLib could not open file" << filename;
|
|
|
|
qLog(Error) << "TagLib could not open file" << filename;
|
|
|
|
return Result::ErrorCode::FileOpenError;
|
|
|
|
return Result::ErrorCode::FileOpenError;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// FLAC
|
|
|
|
// FLAC
|
|
|
|
if (TagLib::FLAC::File *flac_file = dynamic_cast<TagLib::FLAC::File*>(fileref.file())) {
|
|
|
|
if (TagLib::FLAC::File *flac_file = dynamic_cast<TagLib::FLAC::File*>(fileref->file())) {
|
|
|
|
TagLib::Ogg::XiphComment *xiph_comment = flac_file->xiphComment(true);
|
|
|
|
TagLib::Ogg::XiphComment *xiph_comment = flac_file->xiphComment(true);
|
|
|
|
if (xiph_comment) {
|
|
|
|
if (xiph_comment) {
|
|
|
|
SetEmbeddedArt(flac_file, xiph_comment, cover.data, cover.mime_type);
|
|
|
|
SetEmbeddedArt(flac_file, xiph_comment, cover.data, cover.mime_type);
|
|
|
@ -1431,12 +1419,12 @@ TagReaderBase::Result TagReaderTagLib::SaveEmbeddedArt(const QString &filename,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Ogg Vorbis / Opus / Speex
|
|
|
|
// Ogg Vorbis / Opus / Speex
|
|
|
|
else if (TagLib::Ogg::XiphComment *xiph_comment = dynamic_cast<TagLib::Ogg::XiphComment*>(fileref.file()->tag())) {
|
|
|
|
else if (TagLib::Ogg::XiphComment *xiph_comment = dynamic_cast<TagLib::Ogg::XiphComment*>(fileref->file()->tag())) {
|
|
|
|
SetEmbeddedArt(xiph_comment, cover.data, cover.mime_type);
|
|
|
|
SetEmbeddedArt(xiph_comment, cover.data, cover.mime_type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// MP3
|
|
|
|
// MP3
|
|
|
|
else if (TagLib::MPEG::File *file_mp3 = dynamic_cast<TagLib::MPEG::File*>(fileref.file())) {
|
|
|
|
else if (TagLib::MPEG::File *file_mp3 = dynamic_cast<TagLib::MPEG::File*>(fileref->file())) {
|
|
|
|
TagLib::ID3v2::Tag *tag = file_mp3->ID3v2Tag();
|
|
|
|
TagLib::ID3v2::Tag *tag = file_mp3->ID3v2Tag();
|
|
|
|
if (tag) {
|
|
|
|
if (tag) {
|
|
|
|
SetEmbeddedArt(tag, cover.data, cover.mime_type);
|
|
|
|
SetEmbeddedArt(tag, cover.data, cover.mime_type);
|
|
|
@ -1444,7 +1432,7 @@ TagReaderBase::Result TagReaderTagLib::SaveEmbeddedArt(const QString &filename,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// MP4/AAC
|
|
|
|
// MP4/AAC
|
|
|
|
else if (TagLib::MP4::File *aac_file = dynamic_cast<TagLib::MP4::File*>(fileref.file())) {
|
|
|
|
else if (TagLib::MP4::File *aac_file = dynamic_cast<TagLib::MP4::File*>(fileref->file())) {
|
|
|
|
TagLib::MP4::Tag *tag = aac_file->tag();
|
|
|
|
TagLib::MP4::Tag *tag = aac_file->tag();
|
|
|
|
if (tag) {
|
|
|
|
if (tag) {
|
|
|
|
SetEmbeddedArt(aac_file, tag, cover.data, cover.mime_type);
|
|
|
|
SetEmbeddedArt(aac_file, tag, cover.data, cover.mime_type);
|
|
|
@ -1457,7 +1445,7 @@ TagReaderBase::Result TagReaderTagLib::SaveEmbeddedArt(const QString &filename,
|
|
|
|
return Result::ErrorCode::Unsupported;
|
|
|
|
return Result::ErrorCode::Unsupported;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const bool success = fileref.file()->save();
|
|
|
|
const bool success = fileref->file()->save();
|
|
|
|
#ifdef Q_OS_LINUX
|
|
|
|
#ifdef Q_OS_LINUX
|
|
|
|
if (success) {
|
|
|
|
if (success) {
|
|
|
|
// Linux: inotify doesn't seem to notice the change to the file unless we change the timestamps as well. (this is what touch does)
|
|
|
|
// Linux: inotify doesn't seem to notice the change to the file unless we change the timestamps as well. (this is what touch does)
|
|
|
@ -1533,7 +1521,7 @@ void TagReaderTagLib::SetPlaycount(TagLib::MP4::Tag *tag, const uint playcount)
|
|
|
|
void TagReaderTagLib::SetPlaycount(TagLib::ASF::Tag *tag, const uint playcount) const {
|
|
|
|
void TagReaderTagLib::SetPlaycount(TagLib::ASF::Tag *tag, const uint playcount) const {
|
|
|
|
|
|
|
|
|
|
|
|
if (playcount > 0) {
|
|
|
|
if (playcount > 0) {
|
|
|
|
tag->setAttribute("FMPS/Playcount", TagLib::ASF::Attribute(QStringToTaglibString(QString::number(playcount))));
|
|
|
|
tag->setAttribute("FMPS/Playcount", TagLib::ASF::Attribute(QStringToTagLibString(QString::number(playcount))));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else {
|
|
|
|
tag->removeItem("FMPS/Playcount");
|
|
|
|
tag->removeItem("FMPS/Playcount");
|
|
|
@ -1549,9 +1537,14 @@ TagReaderBase::Result TagReaderTagLib::SaveSongPlaycountToFile(const QString &fi
|
|
|
|
|
|
|
|
|
|
|
|
qLog(Debug) << "Saving song playcount to" << filename;
|
|
|
|
qLog(Debug) << "Saving song playcount to" << filename;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!QFile::exists(filename)) {
|
|
|
|
|
|
|
|
qLog(Error) << "File" << filename << "does not exist";
|
|
|
|
|
|
|
|
return Result::ErrorCode::FileDoesNotExist;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));
|
|
|
|
std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));
|
|
|
|
if (!fileref || fileref->isNull()) {
|
|
|
|
if (!fileref || fileref->isNull()) {
|
|
|
|
qLog(Error) << "TagLib hasn't been able to open file" << filename;
|
|
|
|
qLog(Error) << "TagLib could not open file" << filename;
|
|
|
|
return Result::ErrorCode::FileOpenError;
|
|
|
|
return Result::ErrorCode::FileOpenError;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -1599,7 +1592,7 @@ TagReaderBase::Result TagReaderTagLib::SaveSongPlaycountToFile(const QString &fi
|
|
|
|
else if (TagLib::ASF::File *asf_file = dynamic_cast<TagLib::ASF::File*>(fileref->file())) {
|
|
|
|
else if (TagLib::ASF::File *asf_file = dynamic_cast<TagLib::ASF::File*>(fileref->file())) {
|
|
|
|
TagLib::ASF::Tag *tag = asf_file->tag();
|
|
|
|
TagLib::ASF::Tag *tag = asf_file->tag();
|
|
|
|
if (tag && playcount > 0) {
|
|
|
|
if (tag && playcount > 0) {
|
|
|
|
tag->addAttribute("FMPS/Playcount", TagLib::ASF::Attribute(QStringToTaglibString(QString::number(playcount))));
|
|
|
|
tag->addAttribute("FMPS/Playcount", TagLib::ASF::Attribute(QStringToTagLibString(QString::number(playcount))));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else {
|
|
|
@ -1621,7 +1614,7 @@ TagReaderBase::Result TagReaderTagLib::SaveSongPlaycountToFile(const QString &fi
|
|
|
|
void TagReaderTagLib::SetRating(TagLib::Ogg::XiphComment *xiph_comment, const float rating) const {
|
|
|
|
void TagReaderTagLib::SetRating(TagLib::Ogg::XiphComment *xiph_comment, const float rating) const {
|
|
|
|
|
|
|
|
|
|
|
|
if (rating > 0.0F) {
|
|
|
|
if (rating > 0.0F) {
|
|
|
|
xiph_comment->addField("FMPS_RATING", QStringToTaglibString(QString::number(rating)), true);
|
|
|
|
xiph_comment->addField("FMPS_RATING", QStringToTagLibString(QString::number(rating)), true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else {
|
|
|
|
xiph_comment->removeFields("FMPS_RATING");
|
|
|
|
xiph_comment->removeFields("FMPS_RATING");
|
|
|
@ -1632,7 +1625,7 @@ void TagReaderTagLib::SetRating(TagLib::Ogg::XiphComment *xiph_comment, const fl
|
|
|
|
void TagReaderTagLib::SetRating(TagLib::APE::Tag *tag, const float rating) const {
|
|
|
|
void TagReaderTagLib::SetRating(TagLib::APE::Tag *tag, const float rating) const {
|
|
|
|
|
|
|
|
|
|
|
|
if (rating > 0.0F) {
|
|
|
|
if (rating > 0.0F) {
|
|
|
|
tag->setItem("FMPS_Rating", TagLib::APE::Item("FMPS_Rating", TagLib::StringList(QStringToTaglibString(QString::number(rating)))));
|
|
|
|
tag->setItem("FMPS_Rating", TagLib::APE::Item("FMPS_Rating", TagLib::StringList(QStringToTagLibString(QString::number(rating)))));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else {
|
|
|
|
tag->removeItem("FMPS_Rating");
|
|
|
|
tag->removeItem("FMPS_Rating");
|
|
|
@ -1652,13 +1645,13 @@ void TagReaderTagLib::SetRating(TagLib::ID3v2::Tag *tag, const float rating) con
|
|
|
|
|
|
|
|
|
|
|
|
void TagReaderTagLib::SetRating(TagLib::MP4::Tag *tag, const float rating) const {
|
|
|
|
void TagReaderTagLib::SetRating(TagLib::MP4::Tag *tag, const float rating) const {
|
|
|
|
|
|
|
|
|
|
|
|
tag->setItem(kMP4_FMPS_Rating_ID, TagLib::StringList(QStringToTaglibString(QString::number(rating))));
|
|
|
|
tag->setItem(kMP4_FMPS_Rating_ID, TagLib::StringList(QStringToTagLibString(QString::number(rating))));
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TagReaderTagLib::SetRating(TagLib::ASF::Tag *tag, const float rating) const {
|
|
|
|
void TagReaderTagLib::SetRating(TagLib::ASF::Tag *tag, const float rating) const {
|
|
|
|
|
|
|
|
|
|
|
|
tag->addAttribute("FMPS/Rating", TagLib::ASF::Attribute(QStringToTaglibString(QString::number(rating))));
|
|
|
|
tag->addAttribute("FMPS/Rating", TagLib::ASF::Attribute(QStringToTagLibString(QString::number(rating))));
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -1670,14 +1663,18 @@ TagReaderBase::Result TagReaderTagLib::SaveSongRatingToFile(const QString &filen
|
|
|
|
|
|
|
|
|
|
|
|
qLog(Debug) << "Saving song rating to" << filename;
|
|
|
|
qLog(Debug) << "Saving song rating to" << filename;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!QFile::exists(filename)) {
|
|
|
|
|
|
|
|
qLog(Error) << "File" << filename << "does not exist";
|
|
|
|
|
|
|
|
return Result::ErrorCode::FileDoesNotExist;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (rating < 0) {
|
|
|
|
if (rating < 0) {
|
|
|
|
return Result::ErrorCode::Success;
|
|
|
|
return Result::ErrorCode::Success;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));
|
|
|
|
std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));
|
|
|
|
|
|
|
|
|
|
|
|
if (!fileref || fileref->isNull()) {
|
|
|
|
if (!fileref || fileref->isNull()) {
|
|
|
|
qLog(Error) << "TagLib hasn't been able to open file" << filename;
|
|
|
|
qLog(Error) << "TagLib could not open file" << filename;
|
|
|
|
return Result::ErrorCode::FileOpenError;
|
|
|
|
return Result::ErrorCode::FileOpenError;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|