tagparser/tag.h

242 lines
6.6 KiB
C++

#ifndef TAG_PARSER_TAG_H
#define TAG_PARSER_TAG_H
#include "./tagtarget.h"
#include "./tagvalue.h"
#include <c++utilities/conversion/types.h>
#include <c++utilities/io/binaryreader.h>
#include <string>
#include <type_traits>
namespace TagParser {
/*!
* \brief Specifies the tag type.
*
* \sa Tag::type()
*/
enum class TagType : unsigned int {
Unspecified = 0x00, /**< The tag type is unspecified. */
Id3v1Tag = 0x01, /**< The tag is a TagParser::Id3v1Tag. */
Id3v2Tag = 0x02, /**< The tag is a TagParser::Id3v2Tag. */
Mp4Tag = 0x04, /**< The tag is a TagParser::Mp4Tag. */
MatroskaTag = 0x08, /**< The tag is a TagParser::MatroskaTag. */
VorbisComment = 0x10, /**< The tag is a TagParser::VorbisComment. */
OggVorbisComment = 0x20 /**< The tag is a TagParser::OggVorbisComment. */
};
/*!
* \brief Specifies the field.
*
* These "known" fields are used to specify a field without using
* the field identifier used by the underlaying tag type.
*
* Not all fields are supported by all tag types (see Tag::supportsField()).
*
* \sa Tag::type()
*/
enum class KnownField : unsigned int {
Invalid = std::numeric_limits<unsigned int>::max(), /**< invalid field name, do not map this value when subclassing Tag */
Title = 0, /**< title */
Album, /**< album/collection */
Artist, /**< artist/band */
Genre, /**< genre */
Year, /**< year */
Comment, /**< comment */
Bpm, /**< beats per minute */
Bps, /**< beats per second */
Lyricist, /**< lyricist */
TrackPosition, /**< track/part number and total track/part count */
DiskPosition, /**< disk number and total disk count */
PartNumber, /**< track/part number */
TotalParts, /**< total track/part count */
Encoder, /**< encoder */
RecordDate, /**< record date */
Performers, /**< performers */
Length, /**< length */
Language, /**< language */
EncoderSettings, /**< encoder settings */
Lyrics, /**< lyrics */
SynchronizedLyrics, /**< synchronized lyrics */
Grouping, /**< grouping */
RecordLabel, /**< record label */
Cover, /**< cover */
Composer, /**< composer */
Rating, /**< rating */
Description, /**< description */
Vendor /**< vendor */
};
/*!
* \brief The first valid entry in the TagParser::KnownField enum.
*/
constexpr KnownField firstKnownField = KnownField::Title;
/*!
* \brief The last valid entry in the TagParser::KnownField enum.
*/
constexpr KnownField lastKnownField = KnownField::Vendor;
/*!
* \brief The number of valid entries in the TagParser::KnownField enum.
*/
constexpr unsigned int knownFieldArraySize = static_cast<unsigned int>(lastKnownField) + 1;
/*!
* \brief Returns the next known field. Returns KnownField::Invalid if there is not next field.
*/
constexpr KnownField nextKnownField(KnownField field)
{
return field == lastKnownField ? KnownField::Invalid : static_cast<KnownField>(static_cast<int>(field) + 1);
}
class TAG_PARSER_EXPORT Tag {
public:
virtual ~Tag();
virtual TagType type() const;
virtual const char *typeName() const;
std::string toString() const;
virtual TagTextEncoding proposedTextEncoding() const;
virtual bool canEncodingBeUsed(TagTextEncoding encoding) const;
virtual const TagValue &value(KnownField field) const = 0;
virtual std::vector<const TagValue *> values(KnownField field) const;
virtual bool setValue(KnownField field, const TagValue &value) = 0;
virtual bool setValues(KnownField field, const std::vector<TagValue> &values);
virtual bool hasField(KnownField field) const = 0;
virtual void removeAllFields() = 0;
const std::string &version() const;
uint32 size() const;
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;
virtual bool supportsDescription(KnownField field) const;
virtual bool supportsMimeType(KnownField field) const;
virtual bool supportsMultipleValues(KnownField field) const;
virtual unsigned int insertValues(const Tag &from, bool overwrite);
virtual void ensureTextValuesAreProperlyEncoded() = 0;
protected:
Tag();
std::string m_version;
uint32 m_size;
TagTarget m_target;
};
inline TagType Tag::type() const
{
return TagType::Unspecified;
}
inline const char *Tag::typeName() const
{
return "unspecified";
}
inline TagTextEncoding Tag::proposedTextEncoding() const
{
return TagTextEncoding::Latin1;
}
inline bool Tag::canEncodingBeUsed(TagTextEncoding encoding) const
{
return encoding == proposedTextEncoding();
}
inline const std::string &Tag::version() const
{
return m_version;
}
inline uint32 Tag::size() const
{
return m_size;
}
inline bool Tag::supportsTarget() const
{
return false;
}
inline const TagTarget &Tag::target() const
{
return m_target;
}
inline void Tag::setTarget(const TagTarget &target)
{
m_target = target;
}
inline TagTargetLevel Tag::targetLevel() const
{
return TagTargetLevel::Unspecified;
}
inline const char *Tag::targetLevelName() const
{
return supportsTarget() ? tagTargetLevelName(targetLevel()) : nullptr;
}
inline bool Tag::isTargetingLevel(TagTargetLevel tagTargetLevel) const
{
return !supportsTarget() || static_cast<byte>(targetLevel()) >= static_cast<byte>(tagTargetLevel);
}
inline std::string Tag::targetString() const
{
return target().toString(targetLevel());
}
inline TagDataType Tag::proposedDataType(KnownField field) const
{
switch (field) {
case KnownField::Bpm:
case KnownField::Bps:
case KnownField::Rating:
case KnownField::PartNumber:
case KnownField::TotalParts:
return TagDataType::Integer;
case KnownField::Cover:
return TagDataType::Picture;
case KnownField::Length:
return TagDataType::TimeSpan;
case KnownField::TrackPosition:
case KnownField::DiskPosition:
return TagDataType::PositionInSet;
case KnownField::Genre:
return TagDataType::StandardGenreIndex;
default:
return TagDataType::Text;
}
}
inline bool Tag::supportsDescription(KnownField) const
{
return false;
}
inline bool Tag::supportsMimeType(KnownField) const
{
return false;
}
inline bool Tag::supportsMultipleValues(KnownField) const
{
return false;
}
} // namespace TagParser
#endif // TAG_PARSER_TAG_H