6 #include "../exceptions.h"
8 #include <c++utilities/conversion/stringconversion.h>
9 #include <c++utilities/io/binarywriter.h>
28 case KnownField::EncoderSettings:
55 case TagTextEncoding::Utf16BigEndian:
73 case KnownField::EncoderSettings:
88 std::vector<const TagValue *> Mp4Tag::values(
KnownField field)
const
94 for (
auto i = range.first; i != range.second; ++i) {
95 if (extendedId.
matches(i->second)) {
96 values.emplace_back(&i->second.value());
108 const TagValue &Mp4Tag::value(
const char *mean,
const char *name)
const
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();
116 return TagValue::empty();
121 using namespace Mp4TagAtomIds;
169 KnownField Mp4Tag::internallyGetKnownField(
const IdentifierType &
id)
const
171 using namespace Mp4TagAtomIds;
215 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);
313 static const string context(
"parsing MP4 tag");
314 istream &stream = metaAtom.
container().stream();
315 BinaryReader &reader = metaAtom.
container().reader();
316 if (metaAtom.
totalSize() > numeric_limits<std::uint32_t>::max()) {
317 diag.emplace_back(DiagLevel::Critical,
"Can't handle such big \"meta\" atoms.", context);
320 m_size =
static_cast<std::uint32_t
>(metaAtom.
totalSize());
325 diag.emplace_back(DiagLevel::Critical,
"Unable to parse child atoms of meta atom (stores hdlr and ilst atoms).", context);
329 int versionByte = reader.readByte();
330 if (versionByte != 0) {
331 diag.emplace_back(DiagLevel::Warning,
"Version is unknown.", context);
333 if (reader.readUInt24BE()) {
334 diag.emplace_back(DiagLevel::Warning,
"Flags (hdlr atom) aren't set to 0.", context);
336 if (reader.readInt32BE()) {
337 diag.emplace_back(DiagLevel::Warning,
"Predefined 32-bit integer (hdlr atom) ins't set to 0.", context);
339 std::uint64_t handlerType = reader.readUInt64BE();
340 if ( (handlerType != 0x6d6469726170706c)) {
341 diag.emplace_back(DiagLevel::Warning,
"Handler type (value in hdlr atom) is unknown. Trying to parse meta information anyhow.", context);
343 m_version = numberToString(versionByte);
350 diag.emplace_back(DiagLevel::Critical,
"Unable to parse child atoms of meta atom (stores hdlr and ilst atoms).", context);
353 diag.emplace_back(DiagLevel::Warning,
"No ilst atom found (stores attached meta information).", context);
356 for (
auto *child = subAtom->
firstChild(); child; child = child->nextSibling()) {
360 tagField.
reparse(*child, diag);
361 fields().emplace(child->id(), move(tagField));
390 prepareMaking(diag).make(stream, diag);
414 m_omitPreDefinedGenre(m_tag.fields().count(m_tag.hasField(Mp4TagAtomIds::
Genre)))
416 m_maker.reserve(m_tag.fields().size());
417 for (
auto &field : m_tag.fields()) {
420 m_maker.emplace_back(field.second.prepareMaking(diag));
421 m_ilstSize += m_maker.back().requiredSize();
422 }
catch (
const Failure &) {
426 if (m_ilstSize != 8) {
427 m_metaSize += m_ilstSize;
429 if (m_metaSize >= numeric_limits<std::uint32_t>::max()) {
430 diag.emplace_back(
DiagLevel::Critical,
"Making such big tags is not implemented.",
"making MP4 tag");
431 throw NotImplementedException();
445 BinaryWriter writer(&stream);
446 writer.writeUInt32BE(
static_cast<std::uint32_t
>(m_metaSize));
449 static const std::uint8_t hdlrData[37] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x68, 0x64, 0x6C, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00,
450 0x00, 0x00, 0x00, 0x6D, 0x64, 0x69, 0x72, 0x61, 0x70, 0x70, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
451 stream.write(
reinterpret_cast<const char *
>(hdlrData),
sizeof(hdlrData));
452 if (m_ilstSize != 8) {
454 writer.writeUInt32BE(
static_cast<std::uint32_t
>(m_ilstSize));
457 for (
auto &maker : m_maker) {