4 #include "../diagnostics.h" 6 #include <initializer_list> 22 using namespace MatroskaTagIds;
30 case KnownField::RecordDate:
38 case KnownField::PartNumber:
40 case KnownField::TotalParts:
44 case KnownField::EncoderSettings:
64 case KnownField::Length:
66 case KnownField::Language:
73 KnownField MatroskaTag::internallyGetKnownField(
const IdentifierType &
id)
const 75 using namespace MatroskaTagIds;
76 static const map<string, 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<uint32>::max()) {
116 diag.emplace_back(DiagLevel::Critical,
"Matroska tag is too big.", context);
119 m_size =
static_cast<uint32
>(tagElement.
totalSize());
122 switch (child->id()) {
126 field.
reparse(*child, diag,
true);
127 fields().emplace(field.
id(), move(field));
132 parseTargets(*child, diag);
164 prepareMaking(diag).make(stream);
176 static const string context(
"parsing targets of Matroska tag");
178 bool targetTypeValueFound =
false;
179 bool targetTypeFound =
false;
180 targetsElement.
parse(diag);
184 }
catch (
const Failure &) {
185 diag.emplace_back(DiagLevel::Critical,
"Unable to parse childs of Targets element.", context);
188 switch (child->id()) {
190 if (!targetTypeValueFound) {
191 m_target.setLevel(child->readUInteger());
192 targetTypeValueFound =
true;
195 DiagLevel::Warning,
"Targets element contains multiple TargetTypeValue elements. Surplus elements will be ignored.", context);
199 if (!targetTypeFound) {
200 m_target.setLevelName(child->readString());
201 targetTypeFound =
true;
204 DiagLevel::Warning,
"Targets element contains multiple TargetType elements. Surplus elements will be ignored.", context);
208 m_target.tracks().emplace_back(child->readUInteger());
211 m_target.editions().emplace_back(child->readUInteger());
214 m_target.chapters().emplace_back(child->readUInteger());
217 m_target.attachments().emplace_back(child->readUInteger());
220 diag.emplace_back(DiagLevel::Warning,
"Targets element contains unknown element. It will be ignored.", context);
223 if (!m_target.level()) {
224 m_target.setLevel(50);
239 MatroskaTagMaker::MatroskaTagMaker(MatroskaTag &tag, Diagnostics &diag)
244 if (m_tag.target().level() != 50) {
248 if (!m_tag.target().levelName().empty()) {
252 for (
const auto &v : initializer_list<vector<uint64>>{
253 m_tag.target().tracks(), m_tag.target().editions(), m_tag.target().chapters(), m_tag.target().attachments() }) {
261 m_maker.reserve(m_tag.fields().size());
262 m_simpleTagsSize = 0;
263 for (
auto &pair : m_tag.fields()) {
265 m_maker.emplace_back(pair.second.prepareMaking(diag));
266 m_simpleTagsSize += m_maker.back().requiredSize();
267 }
catch (
const Failure &) {
270 m_tagSize += m_simpleTagsSize;
286 stream.write(buff, 2);
288 stream.write(buff, len);
291 stream.write(buff, 2);
293 stream.write(buff, len);
295 if (t.
level() != 50) {
298 stream.write(buff, 2);
300 stream.put(static_cast<char>(0x80 | len));
301 stream.write(buff, len);
306 stream.write(buff, 2);
308 stream.write(buff, len);
312 typedef pair<uint16, vector<uint64>> p;
315 if (!pair.second.empty()) {
316 BE::getBytes(pair.first, buff);
317 for (
auto uid : pair.second) {
319 *(buff + 2) = static_cast<char>(0x80 | len);
320 stream.write(buff, 3 + len);
325 for (
const auto &maker : m_maker) {
TAG_PARSER_EXPORT const char * composer()
TAG_PARSER_EXPORT const char * language()
FieldMapBasedTagTraits< MatroskaTag >::FieldType::IdentifierType IdentifierType
This exception is thrown when the an operation is invoked that has not been implemented yet...
TAG_PARSER_EXPORT const char * description()
TAG_PARSER_EXPORT const char * lyricist()
TAG_PARSER_EXPORT const char * encoderSettings()
TAG_PARSER_EXPORT const char * genre()
const IdContainerType & attachments() const
Returns the attachments.
ImplementationType * firstChild()
Returns the first child of the element.
TAG_PARSER_EXPORT const char * dateRelease()
TAG_PARSER_EXPORT const char * rating()
static byte calculateSizeDenotationLength(uint64 size)
Returns the length of the size denotation for the specified size in byte.
uint64 level() const
Returns the level.
TAG_PARSER_EXPORT const char * lyrics()
The MatroskaTagMaker class helps writing Matroska "Tag"-elements storing tag information.
KnownField
Specifies the field.
TAG_PARSER_EXPORT const char * comment()
TAG_PARSER_EXPORT const char * partNumber()
static byte calculateUIntegerLength(uint64 integer)
Returns the length of the specified unsigned integer in byte.
The EbmlElement class helps to parse EBML files such as Matroska files.
uint64 totalSize() const
Returns the total size of the element.
The MatroskaTagField class is used by MatroskaTag to store the fields.
const TagTarget & target() const
Returns the target of tag.
TAG_PARSER_EXPORT const char * totalParts()
void parse(Diagnostics &diag)
Parses the header information of the element which is read from the related stream at the start offse...
static byte makeUInteger(uint64 value, char *buff)
Writes value to buff.
static byte makeSizeDenotation(uint64 size, char *buff)
Makes the size denotation for the specified size and stores it to buff.
The TagTarget class specifies the target of a tag.
TAG_PARSER_EXPORT const char * artist()
const IdentifierType & id() const
Returns the id of the current TagField.
TAG_PARSER_EXPORT const char * encoder()
TAG_PARSER_EXPORT const char * album()
TAG_PARSER_EXPORT const char * duration()
void make(std::ostream &stream) const
Saves the tag (specified when constructing the object) to the specified stream (makes a "Tag"-element...
const IdContainerType & tracks() const
Returns the tracks.
TAG_PARSER_EXPORT const char * dateRecorded()
TAG_PARSER_EXPORT const char * bps()
TAG_PARSER_EXPORT const char * actor()
The class inherits from std::exception and serves as base class for exceptions thrown by the elements...
const std::string & levelName() const
Returns the level name.
const IdContainerType & editions() const
Returns the editions.
const IdContainerType & chapters() const
Returns the chapters.
Contains all classes and functions of the TagInfo library.
TAG_PARSER_EXPORT const char * title()
void reparse(EbmlElement &simpleTagElement, Diagnostics &diag, bool parseNestedFields=true)
Parses field information from the specified EbmlElement.
The Diagnostics class is a container for DiagMessage.
TAG_PARSER_EXPORT const char * bpm()