6 #include "../exceptions.h" 8 #include <c++utilities/conversion/stringconversion.h> 9 #include <c++utilities/io/binarywriter.h> 29 case KnownField::EncoderSettings:
53 case TagTextEncoding::Utf16BigEndian:
71 case KnownField::EncoderSettings:
86 std::vector<const TagValue *> Mp4Tag::values(
KnownField field)
const 92 for (
auto i = range.first; i != range.second; ++i) {
93 if (extendedId.
matches(i->second)) {
94 values.emplace_back(&i->second.value());
106 const TagValue &Mp4Tag::value(
const char *mean,
const char *name)
const 109 for (
auto i = range.first; i != range.second; ++i) {
110 if (i->second.mean() == mean && i->second.name() == name) {
111 return i->second.value();
114 return TagValue::empty();
120 const TagValue &Mp4Tag::value(
const string mean,
const string name)
const 122 return (this->*
static_cast<const TagValue &(
Mp4Tag::*)(
const string &,
const string &)const
>(&Mp4Tag::value))(mean, name);
127 using namespace Mp4TagAtomIds;
172 KnownField Mp4Tag::internallyGetKnownField(
const IdentifierType &
id)
const 174 using namespace Mp4TagAtomIds;
216 return KnownField::Invalid;
224 switch (value.
type()) {
225 case TagDataType::StandardGenreIndex:
232 case KnownField::EncoderSettings:
244 bool Mp4Tag::setValues(
KnownField field,
const std::vector<TagValue> &values)
248 auto valuesIterator = values.cbegin();
250 for (; valuesIterator != values.cend() && range.first != range.second;) {
251 if (!valuesIterator->isEmpty()) {
252 if (extendedId.
matches(range.first->second) && (!extendedId.
updateOnly || !range.first->second.value().isEmpty())) {
253 range.first->second.setValue(*valuesIterator);
261 for (; valuesIterator != values.cend(); ++valuesIterator) {
267 for (; range.first != range.second; ++range.first) {
268 range.first->second.setValue(
TagValue());
281 bool Mp4Tag::setValue(
const char *mean,
const char *name,
const TagValue &value)
284 for (
auto i = range.first; i != range.second; ++i) {
285 if (i->second.mean() == mean && i->second.name() == name) {
286 i->second.setValue(value);
297 bool Mp4Tag::setValue(
const string mean,
const string name,
const TagValue &value)
299 return (this->*
static_cast<bool (
Mp4Tag::*)(
const string &,
const string &,
const TagValue &)
>(&Mp4Tag::setValue))(mean, name, value);
321 static const string context(
"parsing MP4 tag");
322 istream &stream = metaAtom.
container().stream();
323 BinaryReader &reader = metaAtom.
container().reader();
324 if (metaAtom.
totalSize() > numeric_limits<uint32>::max()) {
325 diag.emplace_back(DiagLevel::Critical,
"Can't handle such big \"meta\" atoms.", context);
328 m_size =
static_cast<uint32
>(metaAtom.
totalSize());
333 diag.emplace_back(DiagLevel::Critical,
"Unable to parse child atoms of meta atom (stores hdlr and ilst atoms).", context);
337 int versionByte = reader.readByte();
338 if (versionByte != 0) {
339 diag.emplace_back(DiagLevel::Warning,
"Version is unknown.", context);
341 if (reader.readUInt24BE()) {
342 diag.emplace_back(DiagLevel::Warning,
"Flags (hdlr atom) aren't set to 0.", context);
344 if (reader.readInt32BE()) {
345 diag.emplace_back(DiagLevel::Warning,
"Predefined 32-bit integer (hdlr atom) ins't set to 0.", context);
347 uint64 handlerType = reader.readUInt64BE();
348 if ( (handlerType != 0x6d6469726170706c)) {
349 diag.emplace_back(DiagLevel::Warning,
"Handler type (value in hdlr atom) is unknown. Trying to parse meta information anyhow.", context);
351 m_version = ConversionUtilities::numberToString(versionByte);
358 diag.emplace_back(DiagLevel::Critical,
"Unable to parse child atoms of meta atom (stores hdlr and ilst atoms).", context);
361 diag.emplace_back(DiagLevel::Warning,
"No ilst atom found (stores attached meta information).", context);
364 for (
auto *child = subAtom->
firstChild(); child; child = child->nextSibling()) {
368 tagField.
reparse(*child, diag);
369 fields().emplace(child->id(), move(tagField));
398 prepareMaking(diag).make(stream, diag);
422 m_omitPreDefinedGenre(m_tag.fields().count(m_tag.hasField(Mp4TagAtomIds::
Genre)))
424 m_maker.reserve(m_tag.fields().size());
425 for (
auto &field : m_tag.fields()) {
428 m_maker.emplace_back(field.second.prepareMaking(diag));
429 m_ilstSize += m_maker.back().requiredSize();
430 }
catch (
const Failure &) {
434 if (m_ilstSize != 8) {
435 m_metaSize += m_ilstSize;
437 if (m_metaSize >= numeric_limits<uint32>::max()) {
438 diag.emplace_back(
DiagLevel::Critical,
"Making such big tags is not implemented.",
"making MP4 tag");
439 throw NotImplementedException();
453 BinaryWriter writer(&stream);
454 writer.writeUInt32BE(static_cast<uint32>(m_metaSize));
457 static const byte hdlrData[37] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x68, 0x64, 0x6C, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
458 0x00, 0x00, 0x6D, 0x64, 0x69, 0x72, 0x61, 0x70, 0x70, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
459 stream.write(reinterpret_cast<const char *>(hdlrData),
sizeof(hdlrData));
460 if (m_ilstSize != 8) {
462 writer.writeUInt32BE(static_cast<uint32>(m_ilstSize));
465 for (
auto &maker : m_maker) {
FieldMapBasedTagTraits< Mp4Tag >::FieldType::IdentifierType IdentifierType
This exception is thrown when the an operation is invoked that has not been implemented yet...
The FieldMapBasedTag provides a generic implementation of Tag which stores the tag fields using std::...
void make(std::ostream &stream, Diagnostics &diag)
Saves the tag (specified when constructing the object) to the specified stream.
const char * mean
mean parameter, usually Mp4TagExtendedMeanIds::iTunes
Implementation of TagParser::Tag for the MP4 container.
The Mp4TagField class is used by Mp4Tag to store the fields.
bool matches(const Mp4TagField &field) const
Returns whether the current parameter match the specified field.
ImplementationType * firstChild()
Returns the first child of the element.
uint64 startOffset() const
Returns the start offset in the related stream.
KnownField
Specifies the field.
The Mp4TagMaker class helps writing MP4 tags.
The Mp4Atom class helps to parse MP4 files.
uint64 totalSize() const
Returns the total size of the element.
The Mp4ExtendedFieldId specifies parameter for an extended field denoted via Mp4TagAtomIds::Extended...
const char * name
name parameter
bool isEmpty() const
Returns an indication whether an value is assigned.
Contains utility classes helping to read and write streams.
ContainerType & container()
Returns the related container.
FieldMapBasedTagTraits< Mp4Tag >::FieldType FieldType
void setMean(const std::string &mean)
Sets the "mean" for the "extended" field.
The exception that is thrown when the data to be parsed holds no parsable information.
uint32 headerSize() const
Returns the header size of the element in byte.
TagDataType type() const
Returns the type of the assigned value.
void reparse(Mp4Atom &ilstChild, Diagnostics &diag)
Parses field information from the specified Mp4Atom.
void setName(const std::string &name)
Sets the "name" for the "extended" field.
The TagValue class wraps values of different types.
The class inherits from std::exception and serves as base class for exceptions thrown by the elements...
bool updateOnly
Whether only existing fields should be updated but no new extended field should be created...
ImplementationType * childById(const IdentifierType &id, Diagnostics &diag)
Returns the first child with the specified id.
TagTextEncoding
Specifies the text encoding.
Contains all classes and functions of the TagInfo library.
The Diagnostics class is a container for DiagMessage.