4 #include "../diagnostics.h"
6 #include <initializer_list>
8 #include <unordered_map>
22 using namespace MatroskaTagIds;
25 return std::string(
artist());
27 return std::string(
album());
30 case KnownField::RecordDate:
32 case KnownField::ReleaseDate:
35 return std::string(
title());
37 return std::string(
genre());
38 case KnownField::PartNumber:
40 case KnownField::TotalParts:
44 case KnownField::EncoderSettings:
47 return std::string(
bpm());
49 return std::string(
bps());
51 return std::string(
rating());
55 return std::string(
lyrics());
57 return std::string(
label());
59 return std::string(
actor());
64 case KnownField::Length:
66 case KnownField::Language:
73 KnownField MatroskaTag::internallyGetKnownField(
const IdentifierType &
id)
const
75 using namespace MatroskaTagIds;
76 static const std::unordered_map<std::string_view, KnownField> fieldMap({
88 {
bps(), KnownField::Bps },
97 {
language(), KnownField::Language },
99 const auto knownField(fieldMap.find(
id));
100 return knownField != fieldMap.cend() ? knownField->second : KnownField::Invalid;
112 static const string context(
"parsing Matroska tag");
113 tagElement.
parse(diag);
114 if (tagElement.
totalSize() > numeric_limits<std::uint32_t>::max()) {
116 diag.emplace_back(DiagLevel::Critical,
"Matroska tag is too big.", context);
119 m_size =
static_cast<std::uint32_t
>(tagElement.
totalSize());
122 switch (child->id()) {
126 field.
reparse(*child, diag,
true);
127 fields().emplace(field.
id(), move(field));
132 parseTargets(*child, diag);
147 static const string context(
"parsing targets of Matroska tag");
149 bool targetTypeValueFound =
false;
150 bool targetTypeFound =
false;
151 targetsElement.
parse(diag);
155 }
catch (
const Failure &) {
156 diag.emplace_back(DiagLevel::Critical,
"Unable to parse children of Targets element.", context);
159 switch (child->id()) {
161 if (!targetTypeValueFound) {
162 m_target.setLevel(child->readUInteger());
163 targetTypeValueFound =
true;
166 DiagLevel::Warning,
"Targets element contains multiple TargetTypeValue elements. Surplus elements will be ignored.", context);
170 if (!targetTypeFound) {
171 m_target.setLevelName(child->readString());
172 targetTypeFound =
true;
175 DiagLevel::Warning,
"Targets element contains multiple TargetType elements. Surplus elements will be ignored.", context);
179 m_target.tracks().emplace_back(child->readUInteger());
182 m_target.editions().emplace_back(child->readUInteger());
185 m_target.chapters().emplace_back(child->readUInteger());
188 m_target.attachments().emplace_back(child->readUInteger());
191 diag.emplace_back(DiagLevel::Warning,
"Targets element contains unknown element. It will be ignored.", context);
194 if (!m_target.level()) {
195 m_target.setLevel(50);
210 MatroskaTagMaker::MatroskaTagMaker(MatroskaTag &tag, Diagnostics &diag)
215 if (m_tag.target().level() != 50) {
219 if (!m_tag.target().levelName().empty()) {
223 for (
const auto &v : initializer_list<vector<std::uint64_t>>{
224 m_tag.target().tracks(), m_tag.target().editions(), m_tag.target().chapters(), m_tag.target().attachments() }) {
232 m_maker.reserve(m_tag.fields().size());
233 m_simpleTagsSize = 0;
234 for (
auto &pair : m_tag.fields()) {
236 m_maker.emplace_back(pair.second.prepareMaking(diag));
237 m_simpleTagsSize += m_maker.back().requiredSize();
238 }
catch (
const Failure &) {
241 m_tagSize += m_simpleTagsSize;
257 stream.write(buff, 2);
259 stream.write(buff, len);
262 stream.write(buff, 2);
264 stream.write(buff, len);
266 if (t.
level() != 50) {
269 stream.write(buff, 2);
271 stream.put(
static_cast<char>(0x80 | len));
272 stream.write(buff, len);
277 stream.write(buff, 2);
279 stream.write(buff, len);
280 stream.write(t.
levelName().c_str(),
static_cast<std::streamsize
>(t.
levelName().size()));
283 using p = pair<std::uint16_t, vector<std::uint64_t>>;
286 if (!pair.second.empty()) {
287 BE::getBytes(pair.first, buff);
288 for (
auto uid : pair.second) {
290 *(buff + 2) =
static_cast<char>(0x80 | len);
291 stream.write(buff, 3 + len);
296 for (
const auto &maker : m_maker) {
The Diagnostics class is a container for DiagMessage.
The EbmlElement class helps to parse EBML files such as Matroska files.
static std::uint8_t makeUInteger(std::uint64_t value, char *buff)
Writes value to buff.
static std::uint8_t calculateSizeDenotationLength(std::uint64_t size)
Returns the length of the size denotation for the specified size in byte.
static std::uint8_t makeSizeDenotation(std::uint64_t size, char *buff)
Makes the size denotation for the specified size and stores it to buff.
static std::uint8_t calculateUIntegerLength(std::uint64_t integer)
Returns the length of the specified unsigned integer in byte.
The class inherits from std::exception and serves as base class for exceptions thrown by the elements...
typename FieldMapBasedTagTraits< MatroskaTag >::FieldType::IdentifierType IdentifierType
ImplementationType * nextSibling()
Returns the next sibling of the element.
ImplementationType * firstChild()
Returns the first child of the element.
std::uint64_t totalSize() const
Returns the total size of the element.
void parse(Diagnostics &diag)
Parses the header information of the element which is read from the related stream at the start offse...
The MatroskaTagField class is used by MatroskaTag to store the fields.
void reparse(EbmlElement &simpleTagElement, Diagnostics &diag, bool parseNestedFields=true)
Parses field information from the specified EbmlElement.
void make(std::ostream &stream) const
Saves the tag (specified when constructing the object) to the specified stream (makes a "Tag"-element...
This exception is thrown when the an operation is invoked that has not been implemented yet.
const IdentifierType & id() const
Returns the id of the current TagField.
The TagTarget class specifies the target of a tag.
const IdContainerType & tracks() const
Returns the tracks.
const IdContainerType & chapters() const
Returns the chapters.
std::uint64_t level() const
Returns the level.
const std::string & levelName() const
Returns the level name.
const IdContainerType & editions() const
Returns the editions.
const IdContainerType & attachments() const
Returns the attachments.
const TagTarget & target() const
Returns the target of tag.
constexpr TAG_PARSER_EXPORT std::string_view bps()
constexpr TAG_PARSER_EXPORT std::string_view rating()
constexpr TAG_PARSER_EXPORT std::string_view album()
constexpr TAG_PARSER_EXPORT std::string_view encoderSettings()
constexpr TAG_PARSER_EXPORT std::string_view description()
constexpr TAG_PARSER_EXPORT std::string_view title()
constexpr TAG_PARSER_EXPORT std::string_view comment()
constexpr TAG_PARSER_EXPORT std::string_view language()
constexpr TAG_PARSER_EXPORT std::string_view actor()
constexpr TAG_PARSER_EXPORT std::string_view composer()
constexpr TAG_PARSER_EXPORT std::string_view partNumber()
constexpr TAG_PARSER_EXPORT std::string_view bpm()
constexpr TAG_PARSER_EXPORT std::string_view genre()
constexpr TAG_PARSER_EXPORT std::string_view duration()
constexpr TAG_PARSER_EXPORT std::string_view artist()
constexpr TAG_PARSER_EXPORT std::string_view lyrics()
constexpr TAG_PARSER_EXPORT std::string_view encoder()
constexpr TAG_PARSER_EXPORT std::string_view dateRelease()
constexpr TAG_PARSER_EXPORT std::string_view totalParts()
constexpr TAG_PARSER_EXPORT std::string_view dateRecorded()
constexpr TAG_PARSER_EXPORT std::string_view lyricist()
Contains all classes and functions of the TagInfo library.
KnownField
Specifies the field.