Improve handling of targets

This commit is contained in:
Martchus 2016-05-26 01:59:22 +02:00
parent 0dc6d59240
commit 415e68972a
11 changed files with 162 additions and 42 deletions

View File

@ -1,6 +1,5 @@
#include "./matroskatag.h" #include "./matroskatag.h"
#include "./ebmlelement.h" #include "./ebmlelement.h"
#include "./matroskatagid.h"
#include <map> #include <map>
#include <initializer_list> #include <initializer_list>
@ -157,7 +156,7 @@ void MatroskaTag::parseTargets(EbmlElement &targetsElement)
while(child) { while(child) {
try { try {
child->parse(); child->parse();
} catch (Failure &) { } catch(const Failure &) {
addNotification(NotificationType::Critical, "Unable to parse childs of Targets element.", context); addNotification(NotificationType::Critical, "Unable to parse childs of Targets element.", context);
break; break;
} }

View File

@ -2,6 +2,7 @@
#define MEDIA_MATROSKATAG_H #define MEDIA_MATROSKATAG_H
#include "./matroskatagfield.h" #include "./matroskatagfield.h"
#include "./matroskatagid.h"
#include "../fieldbasedtag.h" #include "../fieldbasedtag.h"
@ -56,6 +57,7 @@ public:
TagTextEncoding proposedTextEncoding() const; TagTextEncoding proposedTextEncoding() const;
bool canEncodingBeUsed(TagTextEncoding encoding) const; bool canEncodingBeUsed(TagTextEncoding encoding) const;
bool supportsTarget() const; bool supportsTarget() const;
TagTargetLevel targetLevel() const;
std::string fieldId(KnownField field) const; std::string fieldId(KnownField field) const;
KnownField knownField(const std::string &id) const; KnownField knownField(const std::string &id) const;
@ -68,17 +70,22 @@ private:
void parseTargets(EbmlElement &targetsElement); void parseTargets(EbmlElement &targetsElement);
}; };
inline bool MatroskaTag::supportsTarget() const
{
return true;
}
/*! /*!
* \brief Constructs a new tag. * \brief Constructs a new tag.
*/ */
inline MatroskaTag::MatroskaTag() 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 inline TagType MatroskaTag::type() const
{ {
return TagType::MatroskaTag; return TagType::MatroskaTag;

View File

@ -1,7 +1,5 @@
#include "./matroskatagid.h" #include "./matroskatagid.h"
#include <string>
using namespace std; using namespace std;
namespace Media { 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 } // namespace Media

View File

@ -1,8 +1,7 @@
#ifndef MEDIA_MATROSKATAGIDS_H #ifndef MEDIA_MATROSKATAGIDS_H
#define MEDIA_MATROSKATAGIDS_H #define MEDIA_MATROSKATAGIDS_H
#include <c++utilities/application/global.h> #include "../tagtarget.h"
#include <c++utilities/conversion/types.h>
namespace Media { 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<TagTargetLevel>(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<uint64>(targetLevel) * 10;
}
} // namespace Media } // namespace Media

View File

@ -330,7 +330,7 @@ inline bool MediaFileInfo::hasId3v1Tag() const
*/ */
inline bool MediaFileInfo::hasId3v2Tag() const inline bool MediaFileInfo::hasId3v2Tag() const
{ {
return m_id3v2Tags.size(); return !m_id3v2Tags.empty();
} }
/*! /*!

View File

@ -1,4 +1,5 @@
#include "./signature.h" #include "./signature.h"
#include "./matroska/matroskatagid.h"
#include <c++utilities/conversion/binaryconversion.h> #include <c++utilities/conversion/binaryconversion.h>
@ -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;
}
}
} }

View File

@ -8,6 +8,8 @@
namespace Media { namespace Media {
enum class TagTargetLevel : byte;
/*! /*!
* \brief Specifies the container format. * \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 *containerFormatAbbreviation(ContainerFormat containerFormat, MediaType mediaType = MediaType::Unknown, unsigned int version = 0);
LIB_EXPORT const char *containerFormatSubversion(ContainerFormat containerFormat); LIB_EXPORT const char *containerFormatSubversion(ContainerFormat containerFormat);
LIB_EXPORT const char *containerMimeType(ContainerFormat containerFormat, MediaType mediaType = MediaType::Unknown); 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);
} }

View File

@ -36,7 +36,7 @@ string Tag::toString() const
stringstream ss; stringstream ss;
ss << typeName(); ss << typeName();
if(supportsTarget() && !target().isEmpty()) { if(supportsTarget() && !target().isEmpty()) {
ss << " targeting " << target().toString(); ss << " targeting " << targetString();
} }
return ss.str(); return ss.str();
} }

40
tag.h
View File

@ -115,6 +115,10 @@ public:
virtual bool supportsTarget() const; virtual bool supportsTarget() const;
const TagTarget &target() const; const TagTarget &target() const;
void setTarget(const TagTarget &target); 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 unsigned int fieldCount() const = 0;
virtual bool supportsField(KnownField field) const = 0; virtual bool supportsField(KnownField field) const = 0;
virtual TagDataType proposedDataType(KnownField field) const; virtual TagDataType proposedDataType(KnownField field) const;
@ -255,6 +259,42 @@ inline void Tag::setTarget(const TagTarget &target)
m_target = 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<byte>(targetLevel()) >= static_cast<byte>(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. * \brief Returns the proposed data type for the specified \a field as TagDataType.
* *

View File

@ -11,6 +11,31 @@ using namespace ConversionUtilities;
namespace Media { 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 * \class Media::TagTarget
* \brief The TagTarget class specifies the target of a tag. * \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. * \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<string> parts; list<string> parts;
parts.emplace_back(); parts.emplace_back();
@ -43,7 +69,7 @@ string TagTarget::toString() const
if(!levelName().empty()) { if(!levelName().empty()) {
name = levelName(); name = levelName();
} else { } else {
name = matroskaTargetTypeName(this->level()); name = tagTargetLevelName(tagTargetLevel);
} }
if(!name.empty()) { if(!name.empty()) {
if(!level.empty()) { if(!level.empty()) {

View File

@ -6,9 +6,27 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <functional>
namespace Media { 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 class LIB_EXPORT TagTarget
{ {
public: public:
@ -31,7 +49,8 @@ public:
IdContainerType &attachments(); IdContainerType &attachments();
bool isEmpty() const; bool isEmpty() const;
void clear(); void clear();
std::string toString() const; std::string toString(const std::function<TagTargetLevel(uint64)> &tagTargetMapping) const;
std::string toString(TagTargetLevel tagTargetLevel) const;
bool operator ==(const TagTarget &other) const; bool operator ==(const TagTarget &other) const;
private: private:
@ -190,6 +209,16 @@ inline bool TagTarget::operator ==(const TagTarget &other) const
&& m_attachments == other.m_attachments; && 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<TagTargetLevel(uint64)> &tagTargetMapping) const
{
return toString(tagTargetMapping ? tagTargetMapping(this->level()) : TagTargetLevel::Unspecified);
}
} }
#endif // MEDIA_TAGTARGET_H #endif // MEDIA_TAGTARGET_H