From 415e68972ae2b4025387d15eeefe6f8825184774 Mon Sep 17 00:00:00 2001 From: Martchus Date: Thu, 26 May 2016 01:59:22 +0200 Subject: [PATCH] Improve handling of targets --- matroska/matroskatag.cpp | 3 +-- matroska/matroskatag.h | 17 +++++++++++----- matroska/matroskatagid.cpp | 27 ------------------------- matroska/matroskatagid.h | 19 +++++++++++++++--- mediafileinfo.h | 2 +- signature.cpp | 29 +++++++++++++++++++++++++++ signature.h | 4 ++++ tag.cpp | 2 +- tag.h | 40 ++++++++++++++++++++++++++++++++++++++ tagtarget.cpp | 30 ++++++++++++++++++++++++++-- tagtarget.h | 31 ++++++++++++++++++++++++++++- 11 files changed, 162 insertions(+), 42 deletions(-) diff --git a/matroska/matroskatag.cpp b/matroska/matroskatag.cpp index a063dc6..fde31be 100644 --- a/matroska/matroskatag.cpp +++ b/matroska/matroskatag.cpp @@ -1,6 +1,5 @@ #include "./matroskatag.h" #include "./ebmlelement.h" -#include "./matroskatagid.h" #include #include @@ -157,7 +156,7 @@ void MatroskaTag::parseTargets(EbmlElement &targetsElement) while(child) { try { child->parse(); - } catch (Failure &) { + } catch(const Failure &) { addNotification(NotificationType::Critical, "Unable to parse childs of Targets element.", context); break; } diff --git a/matroska/matroskatag.h b/matroska/matroskatag.h index 1b7e2c3..f7d6cb9 100644 --- a/matroska/matroskatag.h +++ b/matroska/matroskatag.h @@ -2,6 +2,7 @@ #define MEDIA_MATROSKATAG_H #include "./matroskatagfield.h" +#include "./matroskatagid.h" #include "../fieldbasedtag.h" @@ -56,6 +57,7 @@ public: TagTextEncoding proposedTextEncoding() const; bool canEncodingBeUsed(TagTextEncoding encoding) const; bool supportsTarget() const; + TagTargetLevel targetLevel() const; std::string fieldId(KnownField field) const; KnownField knownField(const std::string &id) const; @@ -68,17 +70,22 @@ private: void parseTargets(EbmlElement &targetsElement); }; -inline bool MatroskaTag::supportsTarget() const -{ - return true; -} - /*! * \brief Constructs a new tag. */ inline MatroskaTag::MatroskaTag() {} +inline bool MatroskaTag::supportsTarget() const +{ + return true; +} + +inline TagTargetLevel MatroskaTag::targetLevel() const +{ + return matroskaTagTargetLevel(m_target.level()); +} + inline TagType MatroskaTag::type() const { return TagType::MatroskaTag; diff --git a/matroska/matroskatagid.cpp b/matroska/matroskatagid.cpp index f267c76..913da8f 100644 --- a/matroska/matroskatagid.cpp +++ b/matroska/matroskatagid.cpp @@ -1,7 +1,5 @@ #include "./matroskatagid.h" -#include - using namespace std; namespace Media { @@ -10,29 +8,4 @@ namespace MatroskaTagIds { } -/*! - * \brief Returns a string for the specified \a targetTypeValue if - * known; otherwise returns an empty string. - */ -const char *matroskaTargetTypeName(uint32 targetTypeValue) -{ - if(targetTypeValue >= 70) { - return "collection"; - } else if(targetTypeValue >= 60) { - return "edition, issue, volume, opus, season, sequel"; - } else if(targetTypeValue >= 50) { - return "album, opera, concert, movie, episode"; - } else if(targetTypeValue >= 40) { - return "part, session"; - } else if(targetTypeValue >= 30) { - return "track, song, chapter"; - } else if(targetTypeValue >= 20) { - return "subtrack, part, movement, scene"; - } else if(targetTypeValue >= 10) { - return "shot"; - } else { - return ""; - } -} - } // namespace Media diff --git a/matroska/matroskatagid.h b/matroska/matroskatagid.h index 35e7abf..84f3307 100644 --- a/matroska/matroskatagid.h +++ b/matroska/matroskatagid.h @@ -1,8 +1,7 @@ #ifndef MEDIA_MATROSKATAGIDS_H #define MEDIA_MATROSKATAGIDS_H -#include -#include +#include "../tagtarget.h" namespace Media { @@ -337,7 +336,21 @@ inline LIB_EXPORT const char *termsOfUse() { } -LIB_EXPORT const char *matroskaTargetTypeName(uint32 targetTypeValue); +/*! + * \brief Returns the general TagTargetLevel for the Matroska specific \a targetLevelValue. + */ +inline LIB_EXPORT TagTargetLevel matroskaTagTargetLevel(uint64 targetLevelValue) +{ + return targetLevelValue > 70 ? TagTargetLevel::Collection : static_cast(targetLevelValue / 10); +} + +/*! + * \brief Returns the Matroska specific target level value for the specified general \a targetLevel. + */ +inline LIB_EXPORT uint64 matroskaTagTargetLevelValue(TagTargetLevel targetLevel) +{ + return static_cast(targetLevel) * 10; +} } // namespace Media diff --git a/mediafileinfo.h b/mediafileinfo.h index 3edf1f1..67c2276 100644 --- a/mediafileinfo.h +++ b/mediafileinfo.h @@ -330,7 +330,7 @@ inline bool MediaFileInfo::hasId3v1Tag() const */ inline bool MediaFileInfo::hasId3v2Tag() const { - return m_id3v2Tags.size(); + return !m_id3v2Tags.empty(); } /*! diff --git a/signature.cpp b/signature.cpp index 14bbde5..91a6063 100644 --- a/signature.cpp +++ b/signature.cpp @@ -1,4 +1,5 @@ #include "./signature.h" +#include "./matroska/matroskatagid.h" #include @@ -482,4 +483,32 @@ const char *containerMimeType(ContainerFormat containerFormat, MediaType mediaTy } } +/*! + * \brief Returns the general TagTargetLevel for the specified \a container format and raw \a targetLevelValue. + */ +TagTargetLevel containerTargetLevel(ContainerFormat containerFormat, uint64 targetLevelValue) +{ + switch(containerFormat) { + case ContainerFormat::Matroska: + case ContainerFormat::Webm: + return matroskaTagTargetLevel(targetLevelValue); + default: + return TagTargetLevel::Unspecified; + } +} + +/*! + * \brief Returns the raw target level value for the specified \a containerFormat and general \a targetLevel. + */ +uint64 containerTargetLevelValue(ContainerFormat containerFormat, TagTargetLevel targetLevel) +{ + switch(containerFormat) { + case ContainerFormat::Matroska: + case ContainerFormat::Webm: + return matroskaTagTargetLevelValue(targetLevel); + default: + return 0; + } +} + } diff --git a/signature.h b/signature.h index 32aa69e..21f5b05 100644 --- a/signature.h +++ b/signature.h @@ -8,6 +8,8 @@ namespace Media { +enum class TagTargetLevel : byte; + /*! * \brief Specifies the container format. * @@ -63,6 +65,8 @@ LIB_EXPORT const char *containerFormatName(ContainerFormat containerFormat); LIB_EXPORT const char *containerFormatAbbreviation(ContainerFormat containerFormat, MediaType mediaType = MediaType::Unknown, unsigned int version = 0); LIB_EXPORT const char *containerFormatSubversion(ContainerFormat containerFormat); LIB_EXPORT const char *containerMimeType(ContainerFormat containerFormat, MediaType mediaType = MediaType::Unknown); +LIB_EXPORT TagTargetLevel containerTargetLevel(ContainerFormat containerFormat, uint64 targetLevelValue); +LIB_EXPORT uint64 containerTargetLevelValue(ContainerFormat containerFormat, TagTargetLevel targetLevel); } diff --git a/tag.cpp b/tag.cpp index 1b63e8c..44f0d19 100644 --- a/tag.cpp +++ b/tag.cpp @@ -36,7 +36,7 @@ string Tag::toString() const stringstream ss; ss << typeName(); if(supportsTarget() && !target().isEmpty()) { - ss << " targeting " << target().toString(); + ss << " targeting " << targetString(); } return ss.str(); } diff --git a/tag.h b/tag.h index 9b46ade..298bd8b 100644 --- a/tag.h +++ b/tag.h @@ -115,6 +115,10 @@ public: virtual bool supportsTarget() const; const TagTarget &target() const; void setTarget(const TagTarget &target); + virtual TagTargetLevel targetLevel() const; + const char *targetLevelName() const; + bool isTargetingLevel(TagTargetLevel tagTargetLevel) const; + std::string targetString() const; virtual unsigned int fieldCount() const = 0; virtual bool supportsField(KnownField field) const = 0; virtual TagDataType proposedDataType(KnownField field) const; @@ -255,6 +259,42 @@ inline void Tag::setTarget(const TagTarget &target) m_target = target; } +/*! + * \brief Returns the name of the current tag target level. + * \remarks Returns TagTargetLevel::Unspecified if target levels are not supported by the tag. + */ +inline TagTargetLevel Tag::targetLevel() const +{ + return TagTargetLevel::Unspecified; +} + +/*! + * \brief Returns the name of the current target level. + * \remarks Returns nullptr if target levels are not supported by the tag. + */ +inline const char *Tag::targetLevelName() const +{ + return supportsTarget() ? tagTargetLevelName(targetLevel()) : nullptr; +} + +/*! + * \brief Returns whether the tag is targeting the specified \a tagTargetLevel. + * \remarks If targets are not supported by the tag it is considered targeting + * everything and hence this method returns always true in this case. + */ +inline bool Tag::isTargetingLevel(TagTargetLevel tagTargetLevel) const +{ + return !supportsTarget() || static_cast(targetLevel()) >= static_cast(tagTargetLevel); +} + +/*! + * \brief Returns the string representation for the assigned tag target. + */ +inline std::string Tag::targetString() const +{ + return target().toString(targetLevel()); +} + /*! * \brief Returns the proposed data type for the specified \a field as TagDataType. * diff --git a/tagtarget.cpp b/tagtarget.cpp index af41c3a..4f98353 100644 --- a/tagtarget.cpp +++ b/tagtarget.cpp @@ -11,6 +11,31 @@ using namespace ConversionUtilities; namespace Media { +/*! + * \brief Returns a string representation for the specified \a tagTargetLevel. + */ +const char *tagTargetLevelName(TagTargetLevel tagTargetLevel) +{ + switch(tagTargetLevel) { + case TagTargetLevel::Shot: + return "shot"; + case TagTargetLevel::Subtrack: + return "subtrack, part, movement, scene"; + case TagTargetLevel::Track: + return "track, song, chapter"; + case TagTargetLevel::Part: + return "part, session"; + case TagTargetLevel::Album: + return "album, opera, concert, movie, episode"; + case TagTargetLevel::Edition: + return "edition, issue, volume, opus, season, sequel"; + case TagTargetLevel::Collection: + return "collection"; + default: + return ""; + } +} + /*! * \class Media::TagTarget * \brief The TagTarget class specifies the target of a tag. @@ -30,8 +55,9 @@ namespace Media { /*! * \brief Returns the string representation of the current instance. + * \remarks Uses the specified \a tagTargetLevel if no levelName() is assigned. */ -string TagTarget::toString() const +string TagTarget::toString(TagTargetLevel tagTargetLevel) const { list parts; parts.emplace_back(); @@ -43,7 +69,7 @@ string TagTarget::toString() const if(!levelName().empty()) { name = levelName(); } else { - name = matroskaTargetTypeName(this->level()); + name = tagTargetLevelName(tagTargetLevel); } if(!name.empty()) { if(!level.empty()) { diff --git a/tagtarget.h b/tagtarget.h index b747070..eff622e 100644 --- a/tagtarget.h +++ b/tagtarget.h @@ -6,9 +6,27 @@ #include #include +#include namespace Media { +/*! + * \brief The TagTargetLevel enum specifies tag target levels. + */ +enum class TagTargetLevel : unsigned char +{ + Unspecified, + Shot, + Subtrack, + Track, + Part, + Album, + Edition, + Collection +}; + +LIB_EXPORT const char *tagTargetLevelName(TagTargetLevel tagTargetLevel); + class LIB_EXPORT TagTarget { public: @@ -31,7 +49,8 @@ public: IdContainerType &attachments(); bool isEmpty() const; void clear(); - std::string toString() const; + std::string toString(const std::function &tagTargetMapping) const; + std::string toString(TagTargetLevel tagTargetLevel) const; bool operator ==(const TagTarget &other) const; private: @@ -190,6 +209,16 @@ inline bool TagTarget::operator ==(const TagTarget &other) const && m_attachments == other.m_attachments; } +/*! + * \brief Returns the string representation of the current instance. + * \remarks Uses the specified \a tagTargetMapping function to map the assigned level() + * to a TagTargetLevel if no levelName() is assigned. + */ +inline std::string TagTarget::toString(const std::function &tagTargetMapping) const +{ + return toString(tagTargetMapping ? tagTargetMapping(this->level()) : TagTargetLevel::Unspecified); +} + } #endif // MEDIA_TAGTARGET_H