From 6c8f2370878908e3d7cb31467fc8a853b4a5bd5e Mon Sep 17 00:00:00 2001 From: Martchus Date: Wed, 22 Apr 2020 19:48:27 +0200 Subject: [PATCH] Show warning when reading/writing ID3v2 frames not matching the tag version --- id3/id3v2frame.cpp | 22 ++++++++++++++++++++++ id3/id3v2frameids.cpp | 38 ++++++++++++++++++++++++++++++++++++++ id3/id3v2frameids.h | 2 ++ 3 files changed, 62 insertions(+) diff --git a/id3/id3v2frame.cpp b/id3/id3v2frame.cpp index 31d15ab..069a481 100644 --- a/id3/id3v2frame.cpp +++ b/id3/id3v2frame.cpp @@ -195,6 +195,15 @@ void Id3v2Frame::parse(BinaryReader &reader, std::uint32_t version, std::uint32_ } } + // add a warning if a frame appears in an ID3v2 tag known not to support it + if (version <= 3 && Id3v2FrameIds::isOnlyId3v24Id(version < 3 ? Id3v2FrameIds::convertToLongId(id()) : id())) { + diag.emplace_back(DiagLevel::Warning, + argsToString("The frame is only supported in ID3v2.4 and newer but the tag's version is ID3v2.", version, '.'), context); + } else if (version > 3 && Id3v2FrameIds::isPreId3v24Id(id())) { + diag.emplace_back(DiagLevel::Warning, + argsToString("The frame is only supported in ID3v2.3 and older but the tag's version is ID3v2.", version, '.'), context); + } + // frame size mustn't be 0 if (m_dataSize <= 0) { diag.emplace_back(DiagLevel::Warning, "The frame size is 0.", context); @@ -498,6 +507,19 @@ Id3v2FrameMaker::Id3v2FrameMaker(Id3v2Frame &frame, std::uint8_t version, Diagno } } + // add a warning if we're writing the frame for an ID3v2 tag known not to support it + if (version <= 3 && Id3v2FrameIds::isOnlyId3v24Id(version < 3 ? Id3v2FrameIds::convertToLongId(m_frameId) : m_frameId)) { + diag.emplace_back(DiagLevel::Warning, + argsToString("The frame is only supported in ID3v2.4 and newer but version of the tag being written is ID3v2.", version, + ". The frame is written nevertheless but other tools might not be able to deal with it."), + context); + } else if (version > 3 && Id3v2FrameIds::isPreId3v24Id(m_frameId)) { + diag.emplace_back(DiagLevel::Warning, + argsToString("The frame is only supported in ID3v2.3 and older but version of the tag being written is ID3v2.", version, + ". The frame is written nevertheless but other tools might not be able to deal with it."), + context); + } + // make actual data depending on the frame ID try { if (isTextFrame) { diff --git a/id3/id3v2frameids.cpp b/id3/id3v2frameids.cpp index 0dc7780..3da2765 100644 --- a/id3/id3v2frameids.cpp +++ b/id3/id3v2frameids.cpp @@ -144,6 +144,44 @@ std::uint32_t convertToLongId(std::uint32_t id) } } +/*! + * \brief Returns whether \a id is only supported in ID3v2.3.x and older and therefore can not be used in an ID3v2.4.x tag. + * \remarks + * - This function is intended to show warnings. Unknown IDs will be treated as supported everywhere. + * - Any short ID is obviously not ID3v2.4.x compatible. Only long IDs are considered here. Short IDs need to be converted to + * long IDs before passing them to this function. + */ +bool isPreId3v24Id(uint32_t id) +{ + switch (id) { + case lYear: + case lOriginalYear: + case lRecordingDates: + case lDate: + case lTime: + return true; + default: + return false; + } +} + +/*! + * \brief Returns whether \a id is only supported inID3v2.4.x and therefore can not be used in older versions. + * \remarks This function is intended to show warnings. Unknown IDs will be treated as supported everywhere. + */ +bool isOnlyId3v24Id(uint32_t id) +{ + switch (id) { + case lRecordingTime: + case lReleaseTime: + case lOriginalReleaseTime: + case lTaggingTime: + return true; + default: + return false; + } +} + } // namespace Id3v2FrameIds } // namespace TagParser diff --git a/id3/id3v2frameids.h b/id3/id3v2frameids.h index 53c2101..b3bb24c 100644 --- a/id3/id3v2frameids.h +++ b/id3/id3v2frameids.h @@ -78,6 +78,8 @@ enum KnownValue : std::uint32_t { TAG_PARSER_EXPORT std::uint32_t convertToShortId(std::uint32_t id); TAG_PARSER_EXPORT std::uint32_t convertToLongId(std::uint32_t id); +TAG_PARSER_EXPORT bool isPreId3v24Id(std::uint32_t id); +TAG_PARSER_EXPORT bool isOnlyId3v24Id(std::uint32_t id); /*! * \brief Returns an indication whether the specified \a id is a long frame id.