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;
129 case KnownField::RecordDate:
170 KnownField Mp4Tag::internallyGetKnownField(
const IdentifierType &
id)
const
172 using namespace Mp4TagAtomIds;
181 return KnownField::RecordDate;
216 return KnownField::Invalid;
225 switch (value.
type()) {
226 case TagDataType::StandardGenreIndex:
233 case KnownField::EncoderSettings:
245 bool Mp4Tag::setValues(
KnownField field,
const std::vector<TagValue> &values)
249 auto valuesIterator = values.cbegin();
251 for (; valuesIterator != values.cend() && range.first != range.second;) {
252 if (!valuesIterator->isEmpty()) {
253 if (extendedId.
matches(range.first->second) && (!extendedId.
updateOnly || !range.first->second.value().isEmpty())) {
254 range.first->second.setValue(*valuesIterator);
262 for (; valuesIterator != values.cend(); ++valuesIterator) {
268 for (; range.first != range.second; ++range.first) {
269 range.first->second.setValue(
TagValue());
282 bool Mp4Tag::setValue(
const char *mean,
const char *name,
const TagValue &value)
285 for (
auto i = range.first; i != range.second; ++i) {
286 if (i->second.mean() == mean && i->second.name() == name) {
287 i->second.setValue(value);
314 static const string context(
"parsing MP4 tag");
315 istream &stream = metaAtom.
container().stream();
316 BinaryReader &reader = metaAtom.
container().reader();
317 if (metaAtom.
totalSize() > numeric_limits<std::uint32_t>::max()) {
318 diag.emplace_back(DiagLevel::Critical,
"Can't handle such big \"meta\" atoms.", context);
321 m_size =
static_cast<std::uint32_t
>(metaAtom.
totalSize());
326 diag.emplace_back(DiagLevel::Critical,
"Unable to parse child atoms of meta atom (stores hdlr and ilst atoms).", context);
330 int versionByte = reader.readByte();
331 if (versionByte != 0) {
332 diag.emplace_back(DiagLevel::Warning,
"Version is unknown.", context);
334 if (reader.readUInt24BE()) {
335 diag.emplace_back(DiagLevel::Warning,
"Flags (hdlr atom) aren't set to 0.", context);
337 if (reader.readInt32BE()) {
338 diag.emplace_back(DiagLevel::Warning,
"Predefined 32-bit integer (hdlr atom) ins't set to 0.", context);
340 std::uint64_t handlerType = reader.readUInt64BE();
341 if ( (handlerType != 0x6d6469726170706c)) {
342 diag.emplace_back(DiagLevel::Warning,
"Handler type (value in hdlr atom) is unknown. Trying to parse meta information anyhow.", context);
344 m_version = numberToString(versionByte);
351 diag.emplace_back(DiagLevel::Critical,
"Unable to parse child atoms of meta atom (stores hdlr and ilst atoms).", context);
354 diag.emplace_back(DiagLevel::Warning,
"No ilst atom found (stores attached meta information).", context);
357 for (
auto *child = subAtom->
firstChild(); child; child = child->nextSibling()) {
361 tagField.
reparse(*child, diag);
362 fields().emplace(child->id(), move(tagField));
391 prepareMaking(diag).make(stream, diag);
415 m_omitPreDefinedGenre(m_tag.fields().count(m_tag.hasField(Mp4TagAtomIds::
Genre)))
417 m_maker.reserve(m_tag.fields().size());
418 for (
auto &field : m_tag.fields()) {
421 m_maker.emplace_back(field.second.prepareMaking(diag));
422 m_ilstSize += m_maker.back().requiredSize();
423 }
catch (
const Failure &) {
427 if (m_ilstSize != 8) {
428 m_metaSize += m_ilstSize;
430 if (m_metaSize >= numeric_limits<std::uint32_t>::max()) {
431 diag.emplace_back(
DiagLevel::Critical,
"Making such big tags is not implemented.",
"making MP4 tag");
432 throw NotImplementedException();
446 BinaryWriter writer(&stream);
447 writer.writeUInt32BE(
static_cast<std::uint32_t
>(m_metaSize));
450 static const std::uint8_t hdlrData[37] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x68, 0x64, 0x6C, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00,
451 0x00, 0x00, 0x00, 0x6D, 0x64, 0x69, 0x72, 0x61, 0x70, 0x70, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
452 stream.write(
reinterpret_cast<const char *
>(hdlrData),
sizeof(hdlrData));
453 if (m_ilstSize != 8) {
455 writer.writeUInt32BE(
static_cast<std::uint32_t
>(m_ilstSize));
458 for (
auto &maker : m_maker) {