6 #include "../exceptions.h" 8 #include <c++utilities/conversion/stringconversion.h> 9 #include <c++utilities/io/binarywriter.h> 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;
167 KnownField Mp4Tag::internallyGetKnownField(
const IdentifierType &
id)
const 169 using namespace Mp4TagAtomIds;
211 return KnownField::Invalid;
219 switch (value.
type()) {
220 case TagDataType::StandardGenreIndex:
227 case KnownField::EncoderSettings:
239 bool Mp4Tag::setValues(
KnownField field,
const std::vector<TagValue> &values)
243 auto valuesIterator = values.cbegin();
245 for (; valuesIterator != values.cend() && range.first != range.second;) {
246 if (!valuesIterator->isEmpty()) {
247 if (extendedId.
matches(range.first->second) && (!extendedId.
updateOnly || !range.first->second.value().isEmpty())) {
248 range.first->second.setValue(*valuesIterator);
256 for (; valuesIterator != values.cend(); ++valuesIterator) {
262 for (; range.first != range.second; ++range.first) {
263 range.first->second.setValue(
TagValue());
276 bool Mp4Tag::setValue(
const char *mean,
const char *name,
const TagValue &value)
279 for (
auto i = range.first; i != range.second; ++i) {
280 if (i->second.mean() == mean && i->second.name() == name) {
281 i->second.setValue(value);
308 static const string context(
"parsing MP4 tag");
309 istream &stream = metaAtom.
container().stream();
310 BinaryReader &reader = metaAtom.
container().reader();
311 if (metaAtom.
totalSize() > numeric_limits<uint32>::max()) {
312 diag.emplace_back(DiagLevel::Critical,
"Can't handle such big \"meta\" atoms.", context);
315 m_size =
static_cast<uint32
>(metaAtom.
totalSize());
320 diag.emplace_back(DiagLevel::Critical,
"Unable to parse child atoms of meta atom (stores hdlr and ilst atoms).", context);
324 int versionByte = reader.readByte();
325 if (versionByte != 0) {
326 diag.emplace_back(DiagLevel::Warning,
"Version is unknown.", context);
328 if (reader.readUInt24BE()) {
329 diag.emplace_back(DiagLevel::Warning,
"Flags (hdlr atom) aren't set to 0.", context);
331 if (reader.readInt32BE()) {
332 diag.emplace_back(DiagLevel::Warning,
"Predefined 32-bit integer (hdlr atom) ins't set to 0.", context);
334 uint64 handlerType = reader.readUInt64BE();
335 if ( (handlerType != 0x6d6469726170706c)) {
336 diag.emplace_back(DiagLevel::Warning,
"Handler type (value in hdlr atom) is unknown. Trying to parse meta information anyhow.", context);
338 m_version = ConversionUtilities::numberToString(versionByte);
345 diag.emplace_back(DiagLevel::Critical,
"Unable to parse child atoms of meta atom (stores hdlr and ilst atoms).", context);
348 diag.emplace_back(DiagLevel::Warning,
"No ilst atom found (stores attached meta information).", context);
351 for (
auto *child = subAtom->
firstChild(); child; child = child->nextSibling()) {
355 tagField.
reparse(*child, diag);
356 fields().emplace(child->id(), move(tagField));
385 prepareMaking(diag).make(stream, diag);
409 m_omitPreDefinedGenre(m_tag.fields().count(m_tag.hasField(Mp4TagAtomIds::
Genre)))
411 m_maker.reserve(m_tag.fields().size());
412 for (
auto &field : m_tag.fields()) {
415 m_maker.emplace_back(field.second.prepareMaking(diag));
416 m_ilstSize += m_maker.back().requiredSize();
417 }
catch (
const Failure &) {
421 if (m_ilstSize != 8) {
422 m_metaSize += m_ilstSize;
424 if (m_metaSize >= numeric_limits<uint32>::max()) {
425 diag.emplace_back(
DiagLevel::Critical,
"Making such big tags is not implemented.",
"making MP4 tag");
426 throw NotImplementedException();
440 BinaryWriter writer(&stream);
441 writer.writeUInt32BE(static_cast<uint32>(m_metaSize));
444 static const byte hdlrData[37] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x68, 0x64, 0x6C, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
445 0x00, 0x00, 0x6D, 0x64, 0x69, 0x72, 0x61, 0x70, 0x70, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
446 stream.write(reinterpret_cast<const char *>(hdlrData),
sizeof(hdlrData));
447 if (m_ilstSize != 8) {
449 writer.writeUInt32BE(static_cast<uint32>(m_ilstSize));
452 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
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.
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.
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.