6 #include "../exceptions.h" 8 #include <c++utilities/conversion/stringconversion.h> 9 #include <c++utilities/io/binarywriter.h> 13 using namespace ConversionUtilities;
29 case KnownField::EncoderSettings:
56 case TagTextEncoding::Utf16BigEndian:
74 case KnownField::EncoderSettings:
89 std::vector<const TagValue *> Mp4Tag::values(
KnownField field)
const 95 for (
auto i = range.first; i != range.second; ++i) {
96 if (extendedId.
matches(i->second)) {
97 values.emplace_back(&i->second.value());
109 const TagValue &Mp4Tag::value(
const char *mean,
const char *name)
const 112 for (
auto i = range.first; i != range.second; ++i) {
113 if (i->second.mean() == mean && i->second.name() == name) {
114 return i->second.value();
117 return TagValue::empty();
122 using namespace Mp4TagAtomIds;
169 KnownField Mp4Tag::internallyGetKnownField(
const IdentifierType &
id)
const 171 using namespace Mp4TagAtomIds;
215 return KnownField::Invalid;
223 switch (value.
type()) {
224 case TagDataType::StandardGenreIndex:
231 case KnownField::EncoderSettings:
243 bool Mp4Tag::setValues(
KnownField field,
const std::vector<TagValue> &values)
247 auto valuesIterator = values.cbegin();
249 for (; valuesIterator != values.cend() && range.first != range.second;) {
250 if (!valuesIterator->isEmpty()) {
251 if (extendedId.
matches(range.first->second) && (!extendedId.
updateOnly || !range.first->second.value().isEmpty())) {
252 range.first->second.setValue(*valuesIterator);
260 for (; valuesIterator != values.cend(); ++valuesIterator) {
266 for (; range.first != range.second; ++range.first) {
267 range.first->second.setValue(
TagValue());
280 bool Mp4Tag::setValue(
const char *mean,
const char *name,
const TagValue &value)
283 for (
auto i = range.first; i != range.second; ++i) {
284 if (i->second.mean() == mean && i->second.name() == name) {
285 i->second.setValue(value);
312 static const string context(
"parsing MP4 tag");
313 istream &stream = metaAtom.
container().stream();
314 BinaryReader &reader = metaAtom.
container().reader();
315 if (metaAtom.
totalSize() > numeric_limits<uint32>::max()) {
316 diag.emplace_back(DiagLevel::Critical,
"Can't handle such big \"meta\" atoms.", context);
319 m_size = static_cast<uint32>(metaAtom.
totalSize());
324 diag.emplace_back(DiagLevel::Critical,
"Unable to parse child atoms of meta atom (stores hdlr and ilst atoms).", context);
327 stream.seekg(static_cast<streamoff>(subAtom->startOffset() + subAtom->headerSize()));
328 int versionByte = reader.readByte();
329 if (versionByte != 0) {
330 diag.emplace_back(DiagLevel::Warning,
"Version is unknown.", context);
332 if (reader.readUInt24BE()) {
333 diag.emplace_back(DiagLevel::Warning,
"Flags (hdlr atom) aren't set to 0.", context);
335 if (reader.readInt32BE()) {
336 diag.emplace_back(DiagLevel::Warning,
"Predefined 32-bit integer (hdlr atom) ins't set to 0.", context);
338 uint64 handlerType = reader.readUInt64BE();
339 if ( (handlerType != 0x6d6469726170706c)) {
340 diag.emplace_back(DiagLevel::Warning,
"Handler type (value in hdlr atom) is unknown. Trying to parse meta information anyhow.", context);
342 m_version = ConversionUtilities::numberToString(versionByte);
349 diag.emplace_back(DiagLevel::Critical,
"Unable to parse child atoms of meta atom (stores hdlr and ilst atoms).", context);
352 diag.emplace_back(DiagLevel::Warning,
"No ilst atom found (stores attached meta information).", context);
355 for (
auto *child = subAtom->firstChild(); child; child = child->nextSibling()) {
359 tagField.
reparse(*child, diag);
360 fields().emplace(child->id(), move(tagField));
389 prepareMaking(diag).make(stream, diag);
413 m_omitPreDefinedGenre(m_tag.fields().count(m_tag.hasField(Mp4TagAtomIds::
Genre)))
415 m_maker.reserve(m_tag.fields().size());
416 for (
auto &field : m_tag.fields()) {
419 m_maker.emplace_back(field.second.prepareMaking(diag));
420 m_ilstSize += m_maker.back().requiredSize();
421 }
catch (
const Failure &) {
425 if (m_ilstSize != 8) {
426 m_metaSize += m_ilstSize;
428 if (m_metaSize >= numeric_limits<uint32>::max()) {
429 diag.emplace_back(
DiagLevel::Critical,
"Making such big tags is not implemented.",
"making MP4 tag");
430 throw NotImplementedException();
444 BinaryWriter writer(&stream);
445 writer.writeUInt32BE(static_cast<uint32>(m_metaSize));
448 static const byte hdlrData[37] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x68, 0x64, 0x6C, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
449 0x00, 0x00, 0x6D, 0x64, 0x69, 0x72, 0x61, 0x70, 0x70, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
450 stream.write(reinterpret_cast<const char *>(hdlrData),
sizeof(hdlrData));
451 if (m_ilstSize != 8) {
453 writer.writeUInt32BE(static_cast<uint32>(m_ilstSize));
456 for (
auto &maker : m_maker) {
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.
typename FieldMapBasedTagTraits< Mp4Tag >::FieldType::IdentifierType IdentifierType
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.
typename FieldMapBasedTagTraits< Mp4Tag >::FieldType FieldType
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.
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 (e....
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.