diff --git a/autotests/samplefiles/test.flac b/autotests/samplefiles/test.flac index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@{ - Property::BitRate, - Property::Channels, - Property::Duration, - Property::SampleRate, - }; + Property::BitRate, + Property::Channels, + Property::Duration, + Property::SampleRate, +}; QTest::addColumn("path"); QTest::addColumn("mimeType"); QTest::addColumn>("expectedKeys"); QTest::addColumn("failMessage"); QTest::addRow("mp3") - << QFINDTESTDATA("samplefiles/no-meta/test.mp3") - << QStringLiteral("audio/mp3") - << expectedKeys << QString() - ; + << QFINDTESTDATA("samplefiles/no-meta/test.mp3") + << QStringLiteral("audio/mp3") + << expectedKeys << QString() + ; QTest::addRow("m4a") - << QFINDTESTDATA("samplefiles/no-meta/test.m4a") - << QStringLiteral("audio/mp4") - << expectedKeys << QString() - ; + << QFINDTESTDATA("samplefiles/no-meta/test.m4a") + << QStringLiteral("audio/mp4") + << expectedKeys << QString() + ; QTest::addRow("flac") - << QFINDTESTDATA("samplefiles/no-meta/test.flac") - << QStringLiteral("audio/flac") - << expectedKeys << QString() - ; + << QFINDTESTDATA("samplefiles/no-meta/test.flac") + << QStringLiteral("audio/flac") + << expectedKeys << QString() + ; QTest::addRow("opus") - << QFINDTESTDATA("samplefiles/no-meta/test.opus") - << QStringLiteral("audio/opus") - << expectedKeys << QString() - ; + << QFINDTESTDATA("samplefiles/no-meta/test.opus") + << QStringLiteral("audio/opus") + << expectedKeys << QString() + ; QTest::addRow("ogg") - << QFINDTESTDATA("samplefiles/no-meta/test.ogg") - << QStringLiteral("audio/ogg") - << expectedKeys << QString() - ; + << QFINDTESTDATA("samplefiles/no-meta/test.ogg") + << QStringLiteral("audio/ogg") + << expectedKeys << QString() + ; QTest::addRow("mpc") - << QFINDTESTDATA("samplefiles/no-meta/test.mpc") - << QStringLiteral("audio/x-musepack") - << expectedKeys << QString() - ; + << QFINDTESTDATA("samplefiles/no-meta/test.mpc") + << QStringLiteral("audio/x-musepack") + << expectedKeys << QString() + ; } @@ -400,15 +420,15 @@ } } else if (missingKeys.size()) { const auto message = QStringLiteral("Missing properties: %1") - .arg(propertyEnumNames(missingKeys.toList()).join(QLatin1String(", "))); + .arg(propertyEnumNames(missingKeys.toList()).join(QLatin1String(", "))); QWARN(qPrintable(message)); } QCOMPARE(resultKeys, expectedKeys); if (!failMessage.isEmpty()) { auto excessKeys = resultKeys.toSet() - expectedKeys.toSet(); const auto message = QStringLiteral("%1: %2") - .arg(failMessage) - .arg(propertyEnumNames(excessKeys.toList()).join(QLatin1String(", "))); + .arg(failMessage) + .arg(propertyEnumNames(excessKeys.toList()).join(QLatin1String(", "))); QEXPECT_FAIL("", qPrintable(message), Continue); } QCOMPARE(resultKeys, expectedKeys); diff --git a/src/extractors/taglibextractor.h b/src/extractors/taglibextractor.h --- a/src/extractors/taglibextractor.h +++ b/src/extractors/taglibextractor.h @@ -61,6 +61,10 @@ TagLib::String lyrics; TagLib::String compilation; TagLib::StringList genres; + QString replayGainAlbumGain; + QString replayGainAlbumPeak; + QString replayGainTrackGain; + QString replayGainTrackPeak; QVariant discNumber; QVariant opus; QVariant rating; diff --git a/src/extractors/taglibextractor.cpp b/src/extractors/taglibextractor.cpp --- a/src/extractors/taglibextractor.cpp +++ b/src/extractors/taglibextractor.cpp @@ -38,6 +38,8 @@ #include #include #include +#include + #include #include @@ -243,6 +245,33 @@ } } } + + // User Text Frame. + lstID3v2 = mpegFile.ID3v2Tag()->frameListMap()["TXXX"]; + if (!lstID3v2.isEmpty()) { + // look for ReplayGain tags + typedef TagLib::ID3v2::UserTextIdentificationFrame IdFrame; + + auto trackGainFrame = IdFrame::find(mpegFile.ID3v2Tag(), "replaygain_track_gain"); + if (trackGainFrame && !trackGainFrame->fieldList().isEmpty()) { + data.replayGainTrackGain = convertWCharsToQString(trackGainFrame->fieldList().back()); + } + + auto trackPeakFrame = IdFrame::find(mpegFile.ID3v2Tag(), "replaygain_track_peak"); + if (trackPeakFrame && !trackPeakFrame->fieldList().isEmpty()) { + data.replayGainTrackPeak = convertWCharsToQString(trackPeakFrame->fieldList().back()); + } + + auto albumGainFrame = IdFrame::find(mpegFile.ID3v2Tag(), "replaygain_album_gain"); + if (albumGainFrame && !albumGainFrame->fieldList().isEmpty()) { + data.replayGainAlbumGain = convertWCharsToQString(albumGainFrame->fieldList().back()); + } + + auto albumPeakFrame = IdFrame::find(mpegFile.ID3v2Tag(), "replaygain_album_peak"); + if (albumPeakFrame && !albumPeakFrame->fieldList().isEmpty()) { + data.replayGainAlbumPeak = convertWCharsToQString(albumPeakFrame->fieldList().back()); + } + } //TODO handle TIPL tag } @@ -473,6 +502,26 @@ Make it compatible with baloo rating with a range from 0 to 10 */ data.rating = (*itMPC).second.toString().toInt() / 10; } + + itMPC = lstMusepack.find("REPLAYGAIN_TRACK_GAIN"); + if (itMPC != lstMusepack.end()) { + data.replayGainTrackGain = convertWCharsToQString((*itMPC).second.toString()); + } + + itMPC = lstMusepack.find("REPLAYGAIN_TRACK_PEAK"); + if (itMPC != lstMusepack.end()) { + data.replayGainTrackPeak = convertWCharsToQString((*itMPC).second.toString()); + } + + itMPC = lstMusepack.find("REPLAYGAIN_ALBUM_GAIN"); + if (itMPC != lstMusepack.end()) { + data.replayGainAlbumGain = convertWCharsToQString((*itMPC).second.toString()); + } + + itMPC = lstMusepack.find("REPLAYGAIN_ALBUM_PEAK"); + if (itMPC != lstMusepack.end()) { + data.replayGainAlbumPeak = convertWCharsToQString((*itMPC).second.toString()); + } } void TagLibExtractor::extractOgg(TagLib::FileStream& stream, const QString& mimeType, ExtractedData& data) @@ -667,6 +716,26 @@ //make it compatible with baloo rating with a range from 0 to 10 data.rating = (*itOgg).second.toString("").toInt() / 10; } + + itOgg = lstOgg.find("REPLAYGAIN_TRACK_GAIN"); + if (itOgg != lstOgg.end()) { + data.replayGainTrackGain = convertWCharsToQString((*itOgg).second.toString("")); + } + + itOgg = lstOgg.find("REPLAYGAIN_TRACK_PEAK"); + if (itOgg != lstOgg.end()) { + data.replayGainTrackPeak = convertWCharsToQString((*itOgg).second.toString("")); + } + + itOgg = lstOgg.find("REPLAYGAIN_ALBUM_GAIN"); + if (itOgg != lstOgg.end()) { + data.replayGainAlbumGain = convertWCharsToQString((*itOgg).second.toString("")); + } + + itOgg = lstOgg.find("REPLAYGAIN_ALBUM_PEAK"); + if (itOgg != lstOgg.end()) { + data.replayGainAlbumPeak = convertWCharsToQString((*itOgg).second.toString("")); + } } } @@ -864,6 +933,48 @@ if (data.rating.isValid()) { result->add(Property::Rating, data.rating); } + + if (!data.replayGainAlbumGain.isEmpty()) { + /* remove " dB" suffix */ + if (data.replayGainAlbumGain.endsWith(QStringLiteral(" dB"), Qt::CaseInsensitive)) + { + data.replayGainAlbumGain.chop(3); + } + bool success = false; + double replayGainAlbumGain = data.replayGainAlbumGain.toDouble(&success); + if (success) { + result->add(Property::ReplayGainAlbumGain, replayGainAlbumGain); + } + } + + if (!data.replayGainAlbumPeak.isEmpty()) { + bool success = false; + double replayGainAlbumPeak = data.replayGainAlbumPeak.toDouble(&success); + if (success) { + result->add(Property::ReplayGainAlbumPeak, replayGainAlbumPeak); + } + } + + if (!data.replayGainTrackGain.isEmpty()) { + /* remove " dB" suffix */ + if (data.replayGainTrackGain.endsWith(QStringLiteral(" dB"), Qt::CaseInsensitive)) + { + data.replayGainTrackGain.chop(3); + } + bool success = false; + double replayGainTrackGain = data.replayGainTrackGain.toDouble(&success); + if (success) { + result->add(Property::ReplayGainTrackGain, replayGainTrackGain); + } + } + + if (!data.replayGainTrackPeak.isEmpty()) { + bool success = false; + double replayGainTrackPeak = data.replayGainTrackPeak.toDouble(&success); + if (success) { + result->add(Property::ReplayGainTrackPeak, replayGainTrackPeak); + } + } } TagLib::AudioProperties* audioProp = file.audioProperties(); diff --git a/src/properties.h b/src/properties.h --- a/src/properties.h +++ b/src/properties.h @@ -330,6 +330,24 @@ * Contains the lyrics of a song embedded in the file */ Lyrics, + /** + * Contains ReplayGain information for audio files + */ + ReplayGainAlbumPeak, + /** + * Contains ReplayGain information for audio files + * The album gain is given in "dB" + */ + ReplayGainAlbumGain, + /** + * Contains ReplayGain information for audio files + */ + ReplayGainTrackPeak, + /** + * Contains ReplayGain information for audio files + * The track gain is given in "dB" + */ + ReplayGainTrackGain, PropertyCount, LastProperty = PropertyCount-1, diff --git a/src/propertyinfo.cpp b/src/propertyinfo.cpp --- a/src/propertyinfo.cpp +++ b/src/propertyinfo.cpp @@ -425,6 +425,30 @@ d->valueType = QVariant::Int; break; + case Property::ReplayGainAlbumPeak: + d->name = QStringLiteral("replayGainAlbumPeak"); + d->displayName = i18nc("@label", "Replay Gain Album Peak"); + d->valueType = QVariant::Double; + break; + + case Property::ReplayGainAlbumGain: + d->name = QStringLiteral("replayGainAlbumGain"); + d->displayName = i18nc("@label", "Replay Gain Album Gain"); + d->valueType = QVariant::Double; + break; + + case Property::ReplayGainTrackPeak: + d->name = QStringLiteral("replayGainTrackPeak"); + d->displayName = i18nc("@label", "Replay Gain Track Peak"); + d->valueType = QVariant::Double; + break; + + case Property::ReplayGainTrackGain: + d->name = QStringLiteral("replayGainTrackGain"); + d->displayName = i18nc("@label", "Replay Gain Track Gain"); + d->valueType = QVariant::Double; + break; + case Property::Width: d->name = QStringLiteral("width"); d->displayName = i18nc("@label", "Width"); @@ -607,6 +631,10 @@ { QStringLiteral("compilation"), Property::Compilation }, { QStringLiteral("license"), Property::License }, { QStringLiteral("lyrics"), Property::Lyrics }, + { QStringLiteral("replaygainalbumpeak"), Property::ReplayGainAlbumPeak }, + { QStringLiteral("replaygainalbumgain"), Property::ReplayGainAlbumGain }, + { QStringLiteral("replaygaintrackpeak"), Property::ReplayGainTrackPeak }, + { QStringLiteral("replaygaintrackgain"), Property::ReplayGainTrackGain }, { QStringLiteral("creationdate"), Property::CreationDate }, { QStringLiteral("keywords"), Property::Keywords }, { QStringLiteral("width"), Property::Width },