diff --git a/fieldbasedtag.h b/fieldbasedtag.h index 6fe6da1..c3d63e2 100644 --- a/fieldbasedtag.h +++ b/fieldbasedtag.h @@ -8,6 +8,16 @@ namespace Media { +/*! + * \class Media::FieldMapBasedTagTraits + * \brief Defines traits for the specified \a ImplementationType. + * + * A template specialization for each FieldMapBasedTag subclass must be provided. + */ +template +class FieldMapBasedTagTraits +{}; + /*! * \class Media::FieldMapBasedTag * \brief The FieldMapBasedTag provides a generic implementation of Tag which stores @@ -21,38 +31,46 @@ namespace Media { * * \tparam Compare Specifies the key comparsion function. Default is std::less. */ -template > +template class FieldMapBasedTag : public Tag { public: + friend class FieldMapBasedTagTraits; + typedef typename FieldMapBasedTagTraits::implementationType implementationType; + typedef typename FieldMapBasedTagTraits::fieldType fieldType; + typedef typename FieldMapBasedTagTraits::fieldType::identifierType identifierType; + typedef typename FieldMapBasedTagTraits::compare compare; + FieldMapBasedTag(); - virtual const TagValue &value(const typename FieldType::identifierType &id) const; // FIXME: use static polymorphism + TagType type() const; + const char *typeName() const; + TagTextEncoding proposedTextEncoding() const; + virtual const TagValue &value(const identifierType &id) const; // FIXME: use static polymorphism const TagValue &value(KnownField field) const; - std::vector values(const typename FieldType::identifierType &id) const; + std::vector values(const identifierType &id) const; std::vector values(KnownField field) const; - virtual bool setValue(const typename FieldType::identifierType &id, const TagValue &value); // FIXME: use static polymorphism + virtual bool setValue(const identifierType &id, const TagValue &value); // FIXME: use static polymorphism bool setValue(KnownField field, const TagValue &value); - bool setValues(const typename FieldType::identifierType &id, const std::vector &values); + bool setValues(const identifierType &id, const std::vector &values); bool setValues(KnownField field, const std::vector &values); bool hasField(KnownField field) const; - virtual bool hasField(const typename FieldType::identifierType &id) const; // FIXME: use static polymorphism + virtual bool hasField(const identifierType &id) const; // FIXME: use static polymorphism void removeAllFields(); - const std::multimap &fields() const; - std::multimap &fields(); + const std::multimap &fields() const; + std::multimap &fields(); unsigned int fieldCount() const; - virtual typename FieldType::identifierType fieldId(KnownField value) const = 0; // FIXME: use static polymorphism - virtual KnownField knownField(const typename FieldType::identifierType &id) const = 0; // FIXME: use static polymorphism + virtual identifierType fieldId(KnownField value) const = 0; // FIXME: use static polymorphism + virtual KnownField knownField(const identifierType &id) const = 0; // FIXME: use static polymorphism bool supportsField(KnownField field) const; using Tag::proposedDataType; - virtual TagDataType proposedDataType(const typename FieldType::identifierType &id) const; // FIXME: use static polymorphism - int insertFields(const FieldMapBasedTag &from, bool overwrite); + virtual TagDataType proposedDataType(const identifierType &id) const; // FIXME: use static polymorphism + int insertFields(const FieldMapBasedTag &from, bool overwrite); unsigned int insertValues(const Tag &from, bool overwrite); void ensureTextValuesAreProperlyEncoded(); - typedef FieldType fieldType; private: - std::multimap m_fields; + std::multimap m_fields; }; /*! @@ -72,23 +90,41 @@ private: /*! * \brief Constructs a new FieldMapBasedTag. */ -template -FieldMapBasedTag::FieldMapBasedTag() +template +FieldMapBasedTag::FieldMapBasedTag() {} +template +TagType FieldMapBasedTag::type() const +{ + return ImplementationType::tagType; +} + +template +const char *FieldMapBasedTag::typeName() const +{ + return ImplementationType::tagName; +} + +template +TagTextEncoding FieldMapBasedTag::proposedTextEncoding() const +{ + return ImplementationType::defaultTextEncoding; +} + /*! * \brief Returns the value of the field with the specified \a id. * \sa Tag::value() */ -template -inline const TagValue &FieldMapBasedTag::value(const typename FieldType::identifierType &id) const +template +inline const TagValue &FieldMapBasedTag::value(const identifierType &id) const { auto i = m_fields.find(id); return i != m_fields.end() ? i->second.value() : TagValue::empty(); } -template -inline const TagValue &FieldMapBasedTag::value(KnownField field) const +template +inline const TagValue &FieldMapBasedTag::value(KnownField field) const { return value(fieldId(field)); } @@ -97,8 +133,8 @@ inline const TagValue &FieldMapBasedTag::value(KnownField fi * \brief Returns the values of the field with the specified \a id. * \sa Tag::values() */ -template -inline std::vector FieldMapBasedTag::values(const typename FieldType::identifierType &id) const +template +inline std::vector FieldMapBasedTag::values(const identifierType &id) const { auto range = m_fields.equal_range(id); std::vector values; @@ -110,14 +146,14 @@ inline std::vector FieldMapBasedTag::value return values; } -template -inline std::vector FieldMapBasedTag::values(KnownField field) const +template +inline std::vector FieldMapBasedTag::values(KnownField field) const { return values(fieldId(field)); } -template -inline bool FieldMapBasedTag::setValue(KnownField field, const TagValue &value) +template +inline bool FieldMapBasedTag::setValue(KnownField field, const TagValue &value) { return setValue(fieldId(field), value); } @@ -126,14 +162,14 @@ inline bool FieldMapBasedTag::setValue(KnownField field, con * \brief Assigns the given \a value to the field with the specified \a id. * \sa Tag::setValue() */ -template -bool FieldMapBasedTag::setValue(const typename FieldType::identifierType &id, const Media::TagValue &value) +template +bool FieldMapBasedTag::setValue(const identifierType &id, const Media::TagValue &value) { auto i = m_fields.find(id); if(i != m_fields.end()) { // field already exists -> set its value i->second.setValue(value); } else if(!value.isEmpty()) { // field doesn't exist -> create new one if value is not null - m_fields.insert(std::make_pair(id, FieldType(id, value))); + m_fields.insert(std::make_pair(id, fieldType(id, value))); } else { // otherwise return false return false; } @@ -146,8 +182,8 @@ bool FieldMapBasedTag::setValue(const typename FieldType::id * method will replace all currently assigned values with the specified \a values. * \sa Tag::setValues() */ -template -bool FieldMapBasedTag::setValues(const typename FieldType::identifierType &id, const std::vector &values) +template +bool FieldMapBasedTag::setValues(const identifierType &id, const std::vector &values) { auto valuesIterator = values.cbegin(); auto range = m_fields.equal_range(id); @@ -161,7 +197,7 @@ bool FieldMapBasedTag::setValues(const typename FieldType::i } // add remaining specified values (there are more specified values than existing ones) for(; valuesIterator != values.cend(); ++valuesIterator) { - m_fields.insert(std::make_pair(id, FieldType(id, *valuesIterator))); + m_fields.insert(std::make_pair(id, fieldType(id, *valuesIterator))); } // remove remaining existing values (there are more existing values than specified ones) for(; range.first != range.second; ++range.first) { @@ -176,14 +212,14 @@ bool FieldMapBasedTag::setValues(const typename FieldType::i * method will replace all currently assigned values with the specified \a values. * \sa Tag::setValues() */ -template -bool FieldMapBasedTag::setValues(KnownField field, const std::vector &values) +template +bool FieldMapBasedTag::setValues(KnownField field, const std::vector &values) { return setValues(fieldId(field), values); } -template -inline bool FieldMapBasedTag::hasField(KnownField field) const +template +inline bool FieldMapBasedTag::hasField(KnownField field) const { return hasField(fieldId(field)); } @@ -191,8 +227,8 @@ inline bool FieldMapBasedTag::hasField(KnownField field) con /*! * \brief Returns an indication whether the field with the specified \a id is present. */ -template -inline bool FieldMapBasedTag::hasField(const typename FieldType::identifierType &id) const +template +inline bool FieldMapBasedTag::hasField(const identifierType &id) const { for (auto range = m_fields.equal_range(id); range.first != range.second; ++range.first) { if(!range.first->second.value().isEmpty()) { @@ -202,8 +238,8 @@ inline bool FieldMapBasedTag::hasField(const typename FieldT return false; } -template -inline void FieldMapBasedTag::removeAllFields() +template +inline void FieldMapBasedTag::removeAllFields() { m_fields.clear(); } @@ -211,8 +247,8 @@ inline void FieldMapBasedTag::removeAllFields() /*! * \brief Returns the fields of the tag by providing direct access to the field map of the tag. */ -template -inline const std::multimap &FieldMapBasedTag::fields() const +template +inline auto FieldMapBasedTag::fields() const -> const std::multimap & { return m_fields; } @@ -220,14 +256,14 @@ inline const std::multimap -inline std::multimap &FieldMapBasedTag::fields() +template +inline auto FieldMapBasedTag::fields() -> std::multimap & { return m_fields; } -template -unsigned int FieldMapBasedTag::fieldCount() const +template +unsigned int FieldMapBasedTag::fieldCount() const { unsigned int count = 0; for(const auto &field : m_fields) { @@ -238,18 +274,18 @@ unsigned int FieldMapBasedTag::fieldCount() const return count; } -template -inline bool FieldMapBasedTag::supportsField(KnownField field) const +template +inline bool FieldMapBasedTag::supportsField(KnownField field) const { - static typename FieldType::identifierType def; + static identifierType def; return fieldId(field) != def; } /*! * \brief Returns the proposed data type for the field with the specified \a id. */ -template -inline TagDataType FieldMapBasedTag::proposedDataType(const typename FieldType::identifierType &id) const +template +inline TagDataType FieldMapBasedTag::proposedDataType(const identifierType &id) const { return Tag::proposedDataType(knownField(id)); } @@ -260,18 +296,18 @@ inline TagDataType FieldMapBasedTag::proposedDataType(const * \param overwrite Indicates whether existing fields should be overwritten. * \return Returns the number of fields that have been inserted. */ -template -int FieldMapBasedTag::insertFields(const FieldMapBasedTag &from, bool overwrite) +template +int FieldMapBasedTag::insertFields(const FieldMapBasedTag &from, bool overwrite) { int fieldsInserted = 0; for(const auto &pair : from.fields()) { - const FieldType &fromField = pair.second; + const fieldType &fromField = pair.second; if(fromField.value().isEmpty()) continue; bool fieldInserted = false; auto range = fields().equal_range(fromField.id()); for(auto i = range.first; i != range.second; ++i) { - FieldType &ownField = i->second; + fieldType &ownField = i->second; if((fromField.isTypeInfoAssigned() && ownField.isTypeInfoAssigned() && fromField.typeInfo() == ownField.typeInfo()) || (!fromField.isTypeInfoAssigned() && ! ownField.isTypeInfoAssigned())) { @@ -291,19 +327,19 @@ int FieldMapBasedTag::insertFields(const FieldMapBasedTag -unsigned int FieldMapBasedTag::insertValues(const Tag &from, bool overwrite) +template +unsigned int FieldMapBasedTag::insertValues(const Tag &from, bool overwrite) { if(type() == from.type()) { // the tags are of the same type, we can insert the fields directly - return insertFields(static_cast &>(from), overwrite); + return insertFields(static_cast &>(from), overwrite); } else { return Tag::insertValues(from, overwrite); } } -template -void FieldMapBasedTag::ensureTextValuesAreProperlyEncoded() +template +void FieldMapBasedTag::ensureTextValuesAreProperlyEncoded() { for(auto &field : fields()) { field.second.value().convertDataEncodingForTag(this); diff --git a/generictagfield.h b/generictagfield.h index 4e218aa..b422c84 100644 --- a/generictagfield.h +++ b/generictagfield.h @@ -12,7 +12,7 @@ class TagField; * \class Media::TagFieldTraits * \brief Defines traits for the specified \a ImplementationType. * - * A template specialization for each TagField derivat must be provided. + * A template specialization for each TagField subclass must be provided. */ template class TagFieldTraits diff --git a/id3/id3v1tag.cpp b/id3/id3v1tag.cpp index 05c6dd3..1e69b23 100644 --- a/id3/id3v1tag.cpp +++ b/id3/id3v1tag.cpp @@ -30,7 +30,7 @@ TagType Id3v1Tag::type() const const char *Id3v1Tag::typeName() const { - return "ID3v1 tag"; + return tagName; } bool Id3v1Tag::canEncodingBeUsed(TagTextEncoding encoding) const diff --git a/id3/id3v1tag.h b/id3/id3v1tag.h index cde5543..f09cbbe 100644 --- a/id3/id3v1tag.h +++ b/id3/id3v1tag.h @@ -12,6 +12,7 @@ public: Id3v1Tag(); static constexpr TagType tagType = TagType::Id3v1Tag; + static constexpr const char *tagName = "ID3v1 tag"; TagType type() const; const char *typeName() const; bool canEncodingBeUsed(TagTextEncoding encoding) const; diff --git a/id3/id3v2tag.cpp b/id3/id3v2tag.cpp index 7a549a8..f1380d6 100644 --- a/id3/id3v2tag.cpp +++ b/id3/id3v2tag.cpp @@ -147,16 +147,6 @@ TagDataType Id3v2Tag::proposedDataType(const uint32 &id) const } } -const TagValue &Id3v2Tag::value(const typename Id3v2Frame::identifierType &id) const -{ - return FieldMapBasedTag::value(id); -} - -bool Id3v2Tag::setValue(const typename Id3v2Frame::identifierType &id, const TagValue &value) -{ - return FieldMapBasedTag::setValue(id, value); -} - /*! * \brief Parses tag information from the specified \a stream. * diff --git a/id3/id3v2tag.h b/id3/id3v2tag.h index eec1331..fcf56f6 100644 --- a/id3/id3v2tag.h +++ b/id3/id3v2tag.h @@ -52,23 +52,33 @@ inline uint64 Id3v2TagMaker::requiredSize() const return m_requiredSize; } -class TAG_PARSER_EXPORT Id3v2Tag : public FieldMapBasedTag +/*! + * \brief Defines traits for the TagField implementation of the Id3v2Tag class. + */ +template <> +class TAG_PARSER_EXPORT FieldMapBasedTagTraits +{ +public: + typedef Id3v2Tag implementationType; + typedef Id3v2Frame fieldType; + typedef FrameComparer compare; +}; + +class TAG_PARSER_EXPORT Id3v2Tag : public FieldMapBasedTag { public: Id3v2Tag(); static constexpr TagType tagType = TagType::Id3v2Tag; - TagType type() const; - const char *typeName() const; + static constexpr const char *tagName = "ID3v2 tag"; + static constexpr TagTextEncoding defaultTextEncoding = TagTextEncoding::Utf16LittleEndian; TagTextEncoding proposedTextEncoding() const; bool canEncodingBeUsed(TagTextEncoding encoding) const; uint32 fieldId(KnownField value) const; KnownField knownField(const uint32 &id) const; TagDataType proposedDataType(const uint32 &id) const; - using FieldMapBasedTag::value; - const TagValue &value(const typename Id3v2Frame::identifierType &id) const; - using FieldMapBasedTag::setValue; - bool setValue(const typename Id3v2Frame::identifierType &id, const TagValue &value); + using FieldMapBasedTag::value; + using FieldMapBasedTag::setValue; bool supportsDescription(KnownField field) const; bool supportsMimeType(KnownField field) const; @@ -109,16 +119,6 @@ inline Id3v2Tag::Id3v2Tag() : m_paddingSize(0) {} -inline TagType Id3v2Tag::type() const -{ - return TagType::Id3v2Tag; -} - -inline const char *Id3v2Tag::typeName() const -{ - return "ID3v2 tag"; -} - inline TagTextEncoding Id3v2Tag::proposedTextEncoding() const { return m_majorVersion > 3 ? TagTextEncoding::Utf8 : TagTextEncoding::Utf16LittleEndian; diff --git a/matroska/matroskatag.h b/matroska/matroskatag.h index f82f429..c13b489 100644 --- a/matroska/matroskatag.h +++ b/matroska/matroskatag.h @@ -47,16 +47,26 @@ inline uint64 MatroskaTagMaker::requiredSize() const return m_totalSize; } -class TAG_PARSER_EXPORT MatroskaTag : public FieldMapBasedTag +/*! + * \brief Defines traits for the TagField implementation of the MatroskaTag class. + */ +template <> +class TAG_PARSER_EXPORT FieldMapBasedTagTraits +{ +public: + typedef MatroskaTag implementationType; + typedef MatroskaTagField fieldType; + typedef std::less compare; +}; + +class TAG_PARSER_EXPORT MatroskaTag : public FieldMapBasedTag { public: MatroskaTag(); static constexpr TagType tagType = TagType::MatroskaTag; - // FIXME: implement type() and typeName() in FieldMapBasedTag - TagType type() const; - const char *typeName() const; - TagTextEncoding proposedTextEncoding() const; + static constexpr const char *tagName = "Matroska tag"; + static constexpr TagTextEncoding defaultTextEncoding = TagTextEncoding::Utf8; bool canEncodingBeUsed(TagTextEncoding encoding) const; bool supportsTarget() const; TagTargetLevel targetLevel() const; @@ -88,21 +98,6 @@ inline TagTargetLevel MatroskaTag::targetLevel() const return matroskaTagTargetLevel(m_target.level()); } -inline TagType MatroskaTag::type() const -{ - return TagType::MatroskaTag; -} - -inline const char *MatroskaTag::typeName() const -{ - return "Matroska tag"; -} - -inline TagTextEncoding MatroskaTag::proposedTextEncoding() const -{ - return TagTextEncoding::Utf8; -} - inline bool MatroskaTag::canEncodingBeUsed(TagTextEncoding encoding) const { return encoding == TagTextEncoding::Utf8; diff --git a/mp4/mp4tag.cpp b/mp4/mp4tag.cpp index 88787b2..d0852d8 100644 --- a/mp4/mp4tag.cpp +++ b/mp4/mp4tag.cpp @@ -59,16 +59,16 @@ const TagValue &Mp4Tag::value(KnownField field) const { switch(field) { case KnownField::Genre: { - const TagValue &value = FieldMapBasedTag::value(Mp4TagAtomIds::Genre); + const TagValue &value = FieldMapBasedTag::value(Mp4TagAtomIds::Genre); if(!value.isEmpty()) { return value; } else { - return FieldMapBasedTag::value(Mp4TagAtomIds::PreDefinedGenre); + return FieldMapBasedTag::value(Mp4TagAtomIds::PreDefinedGenre); } } case KnownField::EncoderSettings: return this->value(Mp4TagExtendedMeanIds::iTunes, Mp4TagExtendedNameIds::cdec); case KnownField::RecordLabel: { - const TagValue &value = FieldMapBasedTag::value(Mp4TagAtomIds::RecordLabel); + const TagValue &value = FieldMapBasedTag::value(Mp4TagAtomIds::RecordLabel); if(!value.isEmpty()) { return value; } else { @@ -76,13 +76,13 @@ const TagValue &Mp4Tag::value(KnownField field) const } } default: - return FieldMapBasedTag::value(field); + return FieldMapBasedTag::value(field); } } std::vector Mp4Tag::values(KnownField field) const { - auto values = FieldMapBasedTag::values(field); + auto values = FieldMapBasedTag::values(field); const Mp4ExtendedFieldId extendedId(field); if(extendedId) { auto range = fields().equal_range(Mp4TagAtomIds::Extended); @@ -180,10 +180,10 @@ bool Mp4Tag::setValue(KnownField field, const TagValue &value) switch(value.type()) { case TagDataType::StandardGenreIndex: fields().erase(Mp4TagAtomIds::Genre); - return FieldMapBasedTag::setValue(Mp4TagAtomIds::PreDefinedGenre, value); + return FieldMapBasedTag::setValue(Mp4TagAtomIds::PreDefinedGenre, value); default: fields().erase(Mp4TagAtomIds::PreDefinedGenre); - return FieldMapBasedTag::setValue(Mp4TagAtomIds::Genre, value); + return FieldMapBasedTag::setValue(Mp4TagAtomIds::Genre, value); } case KnownField::EncoderSettings: return setValue(Mp4TagExtendedMeanIds::iTunes, Mp4TagExtendedNameIds::cdec, value); @@ -193,7 +193,7 @@ bool Mp4Tag::setValue(KnownField field, const TagValue &value) } FALLTHROUGH; default: - return FieldMapBasedTag::setValue(field, value); + return FieldMapBasedTag::setValue(field, value); } } @@ -225,7 +225,7 @@ bool Mp4Tag::setValues(KnownField field, const std::vector &values) range.first->second.setValue(TagValue()); } } - return FieldMapBasedTag::setValues(field, values); + return FieldMapBasedTag::setValues(field, values); } /*! @@ -260,10 +260,10 @@ bool Mp4Tag::hasField(KnownField field) const { switch(field) { case KnownField::Genre: - return FieldMapBasedTag::hasField(Mp4TagAtomIds::PreDefinedGenre) - || FieldMapBasedTag::hasField(Mp4TagAtomIds::Genre); + return FieldMapBasedTag::hasField(Mp4TagAtomIds::PreDefinedGenre) + || FieldMapBasedTag::hasField(Mp4TagAtomIds::Genre); default: - return FieldMapBasedTag::hasField(field); + return FieldMapBasedTag::hasField(field); } } diff --git a/mp4/mp4tag.h b/mp4/mp4tag.h index c39d2d0..d75711f 100644 --- a/mp4/mp4tag.h +++ b/mp4/mp4tag.h @@ -87,39 +87,50 @@ inline uint64 Mp4TagMaker::requiredSize() const return m_metaSize; } -class TAG_PARSER_EXPORT Mp4Tag : public FieldMapBasedTag +/*! + * \brief Defines traits for the TagField implementation of the Mp4Tag class. + */ +template <> +class TAG_PARSER_EXPORT FieldMapBasedTagTraits +{ +public: + typedef Mp4Tag implementationType; + typedef Mp4TagField fieldType; + typedef std::less compare; +}; + +class TAG_PARSER_EXPORT Mp4Tag : public FieldMapBasedTag { public: Mp4Tag(); static constexpr TagType tagType = TagType::Mp4Tag; - TagType type() const; - const char *typeName() const; - TagTextEncoding proposedTextEncoding() const; + static constexpr const char *tagName = "MP4/iTunes tag"; + static constexpr TagTextEncoding defaultTextEncoding = TagTextEncoding::Utf8; bool canEncodingBeUsed(TagTextEncoding encoding) const; uint32 fieldId(KnownField field) const; KnownField knownField(const uint32 &id) const; bool supportsField(KnownField field) const; - using FieldMapBasedTag::value; + using FieldMapBasedTag::value; const TagValue &value(KnownField value) const; - using FieldMapBasedTag::values; + using FieldMapBasedTag::values; std::vector values(KnownField field) const; #ifdef LEGACY_API const TagValue &value(const std::string mean, const std::string name) const; #endif const TagValue &value(const std::string &mean, const std::string &name) const; const TagValue &value(const char *mean, const char *name) const; - using FieldMapBasedTag::setValue; + using FieldMapBasedTag::setValue; bool setValue(KnownField field, const TagValue &value); - using FieldMapBasedTag::setValues; + using FieldMapBasedTag::setValues; bool setValues(KnownField field, const std::vector &values); #ifdef LEGACY_API bool setValue(const std::string mean, const std::string name, const TagValue &value); #endif bool setValue(const std::string &mean, const std::string &name, const TagValue &value); bool setValue(const char *mean, const char *name, const TagValue &value); - using FieldMapBasedTag::hasField; + using FieldMapBasedTag::hasField; bool hasField(KnownField value) const; void parse(Mp4Atom &metaAtom); @@ -133,28 +144,13 @@ public: inline Mp4Tag::Mp4Tag() {} -inline TagType Mp4Tag::type() const -{ - return TagType::Mp4Tag; -} - -inline const char *Mp4Tag::typeName() const -{ - return "MP4/iTunes tag"; -} - -inline TagTextEncoding Mp4Tag::proposedTextEncoding() const -{ - return TagTextEncoding::Utf8; -} - inline bool Mp4Tag::supportsField(KnownField field) const { switch(field) { case KnownField::EncoderSettings: return true; default: - return FieldMapBasedTag::supportsField(field); + return FieldMapBasedTag::supportsField(field); } } diff --git a/vorbis/vorbiscomment.cpp b/vorbis/vorbiscomment.cpp index 5f8c067..e835e1d 100644 --- a/vorbis/vorbiscomment.cpp +++ b/vorbis/vorbiscomment.cpp @@ -29,7 +29,7 @@ const TagValue &VorbisComment::value(KnownField field) const case KnownField::Vendor: return vendor(); default: - return FieldMapBasedTag::value(field); + return FieldMapBasedTag::value(field); } } @@ -40,7 +40,7 @@ bool VorbisComment::setValue(KnownField field, const TagValue &value) setVendor(value); return true; default: - return FieldMapBasedTag::setValue(field, value); + return FieldMapBasedTag::setValue(field, value); } } diff --git a/vorbis/vorbiscomment.h b/vorbis/vorbiscomment.h index ae9b6ee..725b089 100644 --- a/vorbis/vorbiscomment.h +++ b/vorbis/vorbiscomment.h @@ -12,15 +12,26 @@ namespace Media { class OggIterator; class VorbisComment; -class TAG_PARSER_EXPORT VorbisComment : public FieldMapBasedTag +/*! + * \brief Defines traits for the TagField implementation of the VorbisComment class. + */ +template <> +class TAG_PARSER_EXPORT FieldMapBasedTagTraits +{ +public: + typedef VorbisComment implementationType; + typedef VorbisCommentField fieldType; + typedef CaseInsensitiveStringComparer compare; +}; + +class TAG_PARSER_EXPORT VorbisComment : public FieldMapBasedTag { public: VorbisComment(); static constexpr TagType tagType = TagType::VorbisComment; - TagType type() const; - const char *typeName() const; - TagTextEncoding proposedTextEncoding() const; + static constexpr const char *tagName = "Vorbis comment"; + static constexpr TagTextEncoding defaultTextEncoding = TagTextEncoding::Utf8; bool canEncodingBeUsed(TagTextEncoding encoding) const; const TagValue &value(KnownField field) const; @@ -49,21 +60,6 @@ private: inline VorbisComment::VorbisComment() {} -inline TagType VorbisComment::type() const -{ - return TagType::VorbisComment; -} - -inline const char *VorbisComment::typeName() const -{ - return "Vorbis comment"; -} - -inline TagTextEncoding VorbisComment::proposedTextEncoding() const -{ - return TagTextEncoding::Utf8; -} - inline bool VorbisComment::canEncodingBeUsed(TagTextEncoding encoding) const { return encoding == TagTextEncoding::Utf8;