6#include <initializer_list>
8#include <unordered_map>
22 using namespace MatroskaTagIds;
25 return std::string(artist());
27 return std::string(album());
29 return std::string(comment());
31 return std::string(dateRecorded());
33 return std::string(dateRelease());
35 return std::string(title());
37 return std::string(genre());
39 return std::string(partNumber());
41 return std::string(totalParts());
43 return std::string(encoder());
45 return std::string(encoderSettings());
47 return std::string(bpm());
49 return std::string(bps());
51 return std::string(rating());
53 return std::string(description());
55 return std::string(lyrics());
57 return std::string(label());
59 return std::string(actor());
61 return std::string(lyricist());
63 return std::string(composer());
65 return std::string(duration());
67 return std::string(language());
69 return std::string(accompaniment());
71 return std::string(subtitle());
73 return std::string(leadPerformer());
75 return std::string(arranger());
77 return std::string(conductor());
79 return std::string(director());
81 return std::string(assistantDirector());
83 return std::string(directorOfPhotography());
85 return std::string(soundEngineer());
87 return std::string(artDirector());
89 return std::string(productionDesigner());
91 return std::string(choregrapher());
93 return std::string(costumeDesigner());
95 return std::string(actor());
97 return std::string(character());
99 return std::string(writtenBy());
101 return std::string(screenplayBy());
103 return std::string(editedBy());
105 return std::string(producer());
107 return std::string(coproducer());
109 return std::string(executiveProducer());
111 return std::string(distributedBy());
113 return std::string(masteredBy());
115 return std::string(encodedBy());
117 return std::string(mixedBy());
119 return std::string(remixedBy());
121 return std::string(productionStudio());
123 return std::string(thanksTo());
125 return std::string(publisher());
127 return std::string(mood());
129 return std::string(originalMediaType());
131 return std::string(contentType());
133 return std::string(subject());
135 return std::string(keywords());
137 return std::string(summary());
139 return std::string(synopsis());
141 return std::string(initialKey());
143 return std::string(period());
145 return std::string(lawRating());
147 return std::string(dateEncoded());
149 return std::string(dateTagged());
151 return std::string(dateDigitized());
153 return std::string(dateWritten());
155 return std::string(datePurchased());
157 return std::string(recordingLocation());
159 return std::string(compositionLocation());
161 return std::string(composerNationality());
163 return std::string(playCounter());
165 return std::string(measure());
167 return std::string(tuning());
169 return std::string(isrc());
171 return std::string(mcdi());
173 return std::string(isbn());
175 return std::string(barcode());
177 return std::string(catalogNumber());
179 return std::string(labelCode());
181 return std::string(lccn());
183 return std::string(imdb());
185 return std::string(tmdb());
187 return std::string(tvdb());
189 return std::string(purchaseItem());
191 return std::string(purchaseInfo());
193 return std::string(purchaseOwner());
195 return std::string(purchasePrice());
197 return std::string(purchaseCurrency());
199 return std::string(copyright());
201 return std::string(productionCopyright());
203 return std::string(license());
205 return std::string(termsOfUse());
207 return std::string();
213 using namespace MatroskaTagIds;
214 static const std::unordered_map<std::string_view, KnownField> fieldMap({
331 static const string context(
"parsing Matroska tag");
333 tagElement.
parse(diag);
334 if (tagElement.
totalSize() > numeric_limits<std::uint32_t>::max()) {
342 switch (child->id()) {
346 field.reparse(*child, diag,
true);
348 auto normalizedId = field.id();
351 field.id() = std::move(normalizedId);
354 fields().emplace(field.id(), std::move(field));
360 parseTargets(*child, diag);
375 static const string context(
"parsing targets of Matroska tag");
377 bool targetTypeValueFound =
false;
378 bool targetTypeFound =
false;
379 targetsElement.
parse(diag);
383 }
catch (
const Failure &) {
384 diag.emplace_back(
DiagLevel::Critical,
"Unable to parse children of Targets element.", context);
387 switch (child->id()) {
389 if (!targetTypeValueFound) {
391 targetTypeValueFound =
true;
394 DiagLevel::Warning,
"Targets element contains multiple TargetTypeValue elements. Surplus elements will be ignored.", context);
398 if (!targetTypeFound) {
400 targetTypeFound =
true;
403 DiagLevel::Warning,
"Targets element contains multiple TargetType elements. Surplus elements will be ignored.", context);
419 diag.emplace_back(
DiagLevel::Warning,
"Targets element contains unknown element. It will be ignored.", context);
438MatroskaTagMaker::MatroskaTagMaker(
MatroskaTag &tag, Diagnostics &diag)
443 if (m_tag.target().level() != 50) {
445 m_targetsSize += 2u + 1u + EbmlElement::calculateUIntegerLength(m_tag.target().level());
447 if (!m_tag.target().levelName().empty()) {
449 m_targetsSize += 2u + EbmlElement::calculateSizeDenotationLength(m_tag.target().levelName().size()) + m_tag.target().levelName().size();
451 for (
const auto &v : initializer_list<vector<std::uint64_t>>{
452 m_tag.target().tracks(), m_tag.target().editions(), m_tag.target().chapters(), m_tag.target().attachments() }) {
460 m_maker.reserve(m_tag.fields().size());
461 m_simpleTagsSize = 0;
462 for (
auto &pair : m_tag.fields()) {
463 if (pair.second.value().isNull()) {
467 m_maker.emplace_back(pair.second.prepareMaking(diag));
468 m_simpleTagsSize += m_maker.back().requiredSize();
469 }
catch (
const Failure &) {
472 m_tagSize += m_simpleTagsSize;
488 stream.write(buff, 2);
490 stream.write(buff, len);
493 stream.write(buff, 2);
495 stream.write(buff, len);
497 if (t.
level() != 50) {
500 stream.write(buff, 2);
502 stream.put(
static_cast<char>(0x80 | len));
503 stream.write(buff, len);
508 stream.write(buff, 2);
510 stream.write(buff, len);
511 stream.write(t.
levelName().c_str(),
static_cast<std::streamsize
>(t.
levelName().size()));
514 using p = pair<std::uint16_t, vector<std::uint64_t>>;
517 if (!pair.second.empty()) {
518 BE::getBytes(pair.first, buff);
519 for (
auto uid : pair.second) {
521 *(buff + 2) =
static_cast<char>(0x80 | len);
522 stream.write(buff, 3 + len);
527 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
const std::multimap< IdentifierType, FieldType, Compare > & fields() const
KnownField knownField(const IdentifierType &id) const
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.
static void normalizeId(std::string &id)
Ensures the specified id is upper-case as recommended by the Matroska spec.
void make(std::ostream &stream) const
Saves the tag (specified when constructing the object) to the specified stream (makes a "Tag"-element...
void parse(EbmlElement &tagElement, Diagnostics &diag)
Parses tag information from the specified tagElement.
void parse2(EbmlElement &tagElement, MatroskaTagFlags flags, Diagnostics &diag)
Parses tag information from the specified tagElement.
IdentifierType internallyGetFieldId(KnownField field) const
KnownField internallyGetKnownField(const IdentifierType &id) const
This exception is thrown when the an operation is invoked that has not been implemented yet.
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.
void clear()
Clears the TagTarget.
const IdContainerType & attachments() const
Returns the attachments.
void setLevel(std::uint64_t level)
Sets the level.
void setLevelName(const std::string &levelName)
Sets the level name.
const TagTarget & target() const
Contains all classes and functions of the TagInfo library.
KnownField
Specifies the field.
MatroskaTagFlags
The MatroskaTagFlags enum specifies flags which controls parsing and making of Matroska tags.