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);
117 switch (child->id()) {
121 field.
reparse(*child, diag,
true);
122 fields().emplace(field.
id(), move(field));
127 parseTargets(*child, diag);
159 prepareMaking(diag).make(stream);
171 static const string context(
"parsing targets of Matroska tag");
173 bool targetTypeValueFound =
false;
174 bool targetTypeFound =
false;
175 targetsElement.
parse(diag);
179 }
catch (
const Failure &) {
180 diag.emplace_back(DiagLevel::Critical,
"Unable to parse childs of Targets element.", context);
183 switch (child->id()) {
185 if (!targetTypeValueFound) {
186 m_target.setLevel(child->readUInteger());
187 targetTypeValueFound =
true;
190 DiagLevel::Warning,
"Targets element contains multiple TargetTypeValue elements. Surplus elements will be ignored.", context);
194 if (!targetTypeFound) {
195 m_target.setLevelName(child->readString());
196 targetTypeFound =
true;
199 DiagLevel::Warning,
"Targets element contains multiple TargetType elements. Surplus elements will be ignored.", context);
203 m_target.tracks().emplace_back(child->readUInteger());
206 m_target.editions().emplace_back(child->readUInteger());
209 m_target.chapters().emplace_back(child->readUInteger());
212 m_target.attachments().emplace_back(child->readUInteger());
215 diag.emplace_back(DiagLevel::Warning,
"Targets element contains unknown element. It will be ignored.", context);
218 if (!m_target.level()) {
219 m_target.setLevel(50);
234 MatroskaTagMaker::MatroskaTagMaker(MatroskaTag &tag, Diagnostics &diag)
239 if (m_tag.target().level() != 50) {
243 if (!m_tag.target().levelName().empty()) {
247 for (
const auto &v : initializer_list<vector<uint64>>{
248 m_tag.target().tracks(), m_tag.target().editions(), m_tag.target().chapters(), m_tag.target().attachments() }) {
256 m_maker.reserve(m_tag.fields().size());
257 m_simpleTagsSize = 0;
258 for (
auto &pair : m_tag.fields()) {
260 m_maker.emplace_back(pair.second.prepareMaking(diag));
261 m_simpleTagsSize += m_maker.back().requiredSize();
262 }
catch (
const Failure &) {
265 m_tagSize += m_simpleTagsSize;
281 stream.write(buff, 2);
283 stream.write(buff, len);
286 stream.write(buff, 2);
288 stream.write(buff, len);
290 if (t.
level() != 50) {
293 stream.write(buff, 2);
295 stream.put(0x80 | len);
296 stream.write(buff, len);
301 stream.write(buff, 2);
303 stream.write(buff, len);
307 typedef pair<uint16, vector<uint64>> p;
310 if (!pair.second.empty()) {
311 BE::getBytes(pair.first, buff);
312 for (
auto uid : pair.second) {
314 *(buff + 2) = 0x80 | len;
315 stream.write(buff, 3 + len);
320 for (
const auto &maker : m_maker) {
TAG_PARSER_EXPORT const char * composer()
TAG_PARSER_EXPORT const char * language()
FieldMapBasedTagTraits< MatroskaTag >::FieldType::IdentifierType IdentifierType
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()
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.
uint64 totalSize() const
Returns the total size of the element.
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.
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()
const std::string & levelName() const
Returns the level name.
const IdContainerType & editions() const
Returns the editions.
const IdContainerType & chapters() const
Returns the chapters.
TAG_PARSER_EXPORT const char * title()
void reparse(EbmlElement &simpleTagElement, Diagnostics &diag, bool parseNestedFields=true)
Parses field information from the specified EbmlElement.
TAG_PARSER_EXPORT const char * bpm()