8#include <c++utilities/conversion/stringconversion.h>
9#include <c++utilities/io/binarywriter.h>
90 for (
auto i = range.first; i != range.second; ++i) {
91 const auto &extendedField = i->second;
92 if (extendedId.matches(extendedField)) {
93 values.emplace_back(&extendedField.value());
94 for (
const auto &additionalData : extendedField.additionalData()) {
95 values.emplace_back(&additionalData.value);
111 for (
auto i = range.first; i != range.second; ++i) {
112 if (i->second.mean() == mean && i->second.name() == name) {
113 return i->second.value();
121 using namespace Mp4TagAtomIds;
193 using namespace Mp4TagAtomIds;
205 case PreDefinedGenre:
269 if (!field.value().isEmpty()) {
270 values.emplace_back(&field.value());
272 for (
const auto &
value : field.additionalData()) {
306 auto valuesIterator =
values.cbegin();
308 for (; valuesIterator !=
values.cend() && range.first != range.second;) {
309 if (!valuesIterator->isEmpty()) {
310 auto &extendedField = range.first->second;
311 if (extendedId.matches(extendedField) && (!extendedId.updateOnly || !extendedField.value().isEmpty())) {
312 extendedField.clearValue();
313 extendedField.setValue(*valuesIterator);
324 for (; valuesIterator !=
values.cend(); ++valuesIterator) {
325 if (valuesIterator->isEmpty()) {
327 std::forward_as_tuple(extendedId.mean, extendedId.name, *valuesIterator));
330 for (; range.first != range.second; ++range.first) {
331 range.first->second.clearValue();
347 for (
auto i = range.first; i != range.second; ++i) {
348 if (i->second.mean() == mean && i->second.name() == name) {
349 i->second.setValue(
value);
376 static const string context(
"parsing MP4 tag");
378 istream &stream = metaAtom.
container().stream();
379 BinaryReader &reader = metaAtom.
container().reader();
380 if (metaAtom.
totalSize() > numeric_limits<std::uint32_t>::max()) {
388 diag.emplace_back(
DiagLevel::Critical,
"Unable to parse child atoms of meta atom (stores hdlr and ilst atoms).", context);
392 int versionByte = reader.readByte();
393 if (versionByte != 0) {
396 if (reader.readUInt24BE()) {
399 if (reader.readInt32BE()) {
400 diag.emplace_back(
DiagLevel::Warning,
"Predefined 32-bit integer (hdlr atom) isn't set to 0.", context);
402 std::uint64_t handlerType = reader.readUInt64BE();
403 if ( (handlerType != 0x6d6469726170706c)) {
404 diag.emplace_back(
DiagLevel::Warning,
"Handler type (value in hdlr atom) is unknown. Trying to parse meta information anyhow.", context);
413 diag.emplace_back(
DiagLevel::Critical,
"Unable to parse child atoms of meta atom (stores hdlr and ilst atoms).", context);
416 diag.emplace_back(
DiagLevel::Warning,
"No ilst atom found (stores attached meta information).", context);
423 tagField.
reparse(*child, diag);
424 fields().emplace(child->id(), std::move(tagField));
477 m_omitPreDefinedGenre(m_tag.fields().count(m_tag.hasField(Mp4TagAtomIds::
Genre)))
479 m_maker.reserve(m_tag.fields().size());
480 for (
auto &field : m_tag.fields()) {
481 if (!field.second.value().isEmpty() && (!m_omitPreDefinedGenre || field.first != Mp4TagAtomIds::PreDefinedGenre)) {
483 m_ilstSize += m_maker.emplace_back(field.second.prepareMaking(diag)).requiredSize();
484 } catch (const Failure &) {
488 if (m_ilstSize != 8) {
489 m_metaSize += m_ilstSize;
491 if (m_metaSize >= numeric_limits<std::uint32_t>::max()) {
492 diag.emplace_back(
DiagLevel::Critical,
"Making such big tags is not implemented.",
"making MP4 tag");
493 throw NotImplementedException();
507 BinaryWriter writer(&stream);
508 writer.writeUInt32BE(
static_cast<std::uint32_t
>(m_metaSize));
509 writer.writeUInt32BE(Mp4AtomIds::Meta);
511 static const std::uint8_t hdlrData[37] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x68, 0x64, 0x6C, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00,
512 0x00, 0x00, 0x00, 0x6D, 0x64, 0x69, 0x72, 0x61, 0x70, 0x70, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
513 stream.write(
reinterpret_cast<const char *
>(hdlrData),
sizeof(hdlrData));
514 if (m_ilstSize != 8) {
516 writer.writeUInt32BE(
static_cast<std::uint32_t
>(m_ilstSize));
517 writer.writeUInt32BE(Mp4AtomIds::ItunesList);
519 for (
auto &maker : m_maker) {
524 diag.emplace_back(DiagLevel::Warning,
"Tag is empty.",
"making MP4 tag");
The Diagnostics class is a container for DiagMessage.
The class inherits from std::exception and serves as base class for exceptions thrown by the elements...
bool setValue(const IdentifierType &id, const TagValue &value)
Assigns the given value to the field with the specified id.
bool hasField(KnownField field) const
Returns an indication whether the specified field is present.
typename FieldMapBasedTagTraits< Mp4Tag >::FieldType::IdentifierType IdentifierType
const TagValue & value(const IdentifierType &id) const
Returns the value of the field with the specified id.
const std::multimap< IdentifierType, FieldType, Compare > & fields() const
typename FieldMapBasedTagTraits< Mp4Tag >::FieldType FieldType
std::vector< const TagValue * > values(const IdentifierType &id) const
Returns the values of the field with the specified id.
bool setValues(const IdentifierType &id, const std::vector< TagValue > &values)
Assigns the given values to the field with the specified id.
std::uint64_t startOffset() const
Returns the start offset in the related stream.
std::uint32_t headerSize() const
Returns the header size of the element in byte.
ImplementationType * childById(const IdentifierType &id, Diagnostics &diag)
Returns the first child with the specified id.
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.
ContainerType & container()
Returns the related container.
The Mp4Atom class helps to parse MP4 files.
The Mp4TagField class is used by Mp4Tag to store the fields.
void reparse(Mp4Atom &ilstChild, Diagnostics &diag)
Parses field information from the specified Mp4Atom.
The Mp4TagMaker class helps writing MP4 tags.
void make(std::ostream &stream, Diagnostics &diag)
Saves the tag (specified when constructing the object) to the specified stream.
Implementation of TagParser::Tag for the MP4 container.
std::vector< const TagValue * > values(KnownField field) const override
Returns the values of the specified field.
const TagValue & value(KnownField value) const override
Returns the value of the specified field.
bool hasField(KnownField value) const override
Returns an indication whether the specified field is present.
bool setValue(KnownField field, const TagValue &value) override
Assigns the given value to the specified field.
IdentifierType internallyGetFieldId(KnownField field) const
Mp4TagMaker prepareMaking(Diagnostics &diag)
Prepares making.
bool setValues(KnownField field, const std::vector< TagValue > &values) override
Assigns the given values to the field with the specified id.
void parse(Mp4Atom &metaAtom, Diagnostics &diag)
Parses tag information from the specified metaAtom.
void make(std::ostream &stream, Diagnostics &diag)
Writes tag information to the specified stream.
bool canEncodingBeUsed(TagTextEncoding encoding) const override
Returns an indication whether the specified encoding can be used to provide string values for the tag...
KnownField internallyGetKnownField(const IdentifierType &id) const
void internallyGetValuesFromField(const FieldType &field, std::vector< const TagValue * > &values) const
Adds values from additional data atoms as well.
The exception that is thrown when the data to be parsed holds no parsable information (e....
This exception is thrown when the an operation is invoked that has not been implemented yet.
The TagValue class wraps values of different types.
TagDataType type() const
Returns the type of the assigned value.
static const TagValue & empty()
Returns a default-constructed TagValue where TagValue::isNull() and TagValue::isEmpty() both return t...
bool isEmpty() const
Returns whether no or an empty value is assigned.
Contains all classes and functions of the TagInfo library.
KnownField
Specifies the field.
TagTextEncoding
Specifies the text encoding.
The Mp4ExtendedFieldId specifies parameter for an extended field denoted via Mp4TagAtomIds::Extended.
bool updateOnly
Whether only existing fields should be updated but no new extended field should be created.
std::string_view mean
mean parameter, usually Mp4TagExtendedMeanIds::iTunes
Mp4ExtendedFieldId(std::string_view mean, std::string_view name, bool updateOnly=false)
Constructs a new instance with the specified parameter.
std::string_view name
name parameter