6 #include "../exceptions.h" 8 #include <c++utilities/io/binarywriter.h> 9 #include <c++utilities/conversion/stringconversion.h> 29 case KnownField::EncoderSettings:
51 case TagTextEncoding::Utf16BigEndian:
68 }
case KnownField::EncoderSettings:
83 std::vector<const TagValue *> Mp4Tag::values(
KnownField field)
const 89 for(
auto i = range.first; i != range.second; ++i) {
90 if(extendedId.
matches(i->second)) {
91 values.emplace_back(&i->second.value());
103 const TagValue &Mp4Tag::value(
const char *mean,
const char *name)
const 106 for(
auto i = range.first; i != range.second; ++i) {
107 if(i->second.mean() == mean && i->second.name() == name) {
108 return i->second.value();
111 return TagValue::empty();
117 const TagValue &Mp4Tag::value(
const string mean,
const string name)
const 119 return (this->*
static_cast<const TagValue &(
Mp4Tag::*)(
const string &,
const string &) const
>(&Mp4Tag::value))(mean, name);
124 using namespace Mp4TagAtomIds;
151 using namespace Mp4TagAtomIds;
172 default:
return KnownField::Invalid;
180 switch(value.
type()) {
181 case TagDataType::StandardGenreIndex:
188 case KnownField::EncoderSettings:
200 bool Mp4Tag::setValues(
KnownField field,
const std::vector<TagValue> &values)
204 auto valuesIterator = values.cbegin();
206 for(; valuesIterator != values.cend() && range.first != range.second;) {
207 if(!valuesIterator->isEmpty()) {
208 if(extendedId.
matches(range.first->second)
209 && (!extendedId.
updateOnly || !range.first->second.value().isEmpty())) {
210 range.first->second.setValue(*valuesIterator);
218 for(; valuesIterator != values.cend(); ++valuesIterator) {
224 for(; range.first != range.second; ++range.first) {
225 range.first->second.setValue(
TagValue());
238 bool Mp4Tag::setValue(
const char *mean,
const char *name,
const TagValue &value)
241 for(
auto i = range.first; i != range.second; ++i) {
242 if(i->second.mean() == mean && i->second.name() == name) {
243 i->second.setValue(value);
254 bool Mp4Tag::setValue(
const string mean,
const string name,
const TagValue &value)
256 return (this->*
static_cast<bool(
Mp4Tag::*)(
const string &,
const string &,
const TagValue &)
>(&Mp4Tag::setValue))(mean, name, value);
280 static const string context(
"parsing MP4 tag");
281 istream &stream = metaAtom.
container().stream();
282 BinaryReader &reader = metaAtom.
container().reader();
288 addNotification(NotificationType::Critical,
"Unable to parse child atoms of meta atom (stores hdlr and ilst atoms).", context);
292 int versionByte = reader.readByte();
293 if(versionByte != 0) {
294 addNotification(NotificationType::Warning,
"Version is unknown.", context);
296 if(reader.readUInt24BE()) {
297 addNotification(NotificationType::Warning,
"Flags (hdlr atom) aren't set to 0.", context);
299 if(reader.readInt32BE()) {
300 addNotification(NotificationType::Warning,
"Predefined 32-bit integer (hdlr atom) ins't set to 0.", context);
302 uint64 handlerType = reader.readUInt64BE();
303 if((handlerType != 0x6d6469726170706c)) {
304 addNotification(NotificationType::Warning,
"Handler type (value in hdlr atom) is unknown. Trying to parse meta information anyhow.", context);
306 m_version = ConversionUtilities::numberToString(versionByte);
314 addNotification(NotificationType::Critical,
"Unable to parse child atoms of meta atom (stores hdlr and ilst atoms).", context);
318 for(
Mp4Atom *child : *subAtom) {
323 fields().insert(pair<fieldType::identifierType, fieldType>(child->id(), tagField));
326 addNotifications(context, *child);
327 addNotifications(context, tagField);
330 addNotification(NotificationType::Warning,
"No ilst atom found (stores attached meta information).", context);
357 void Mp4Tag::make(ostream &stream)
359 prepareMaking().make(stream);
373 Mp4TagMaker::Mp4TagMaker(
Mp4Tag &tag) :
380 m_omitPreDefinedGenre(m_tag.fields().count(m_tag.hasField(Mp4TagAtomIds::
Genre)))
382 m_tag.invalidateStatus();
383 m_maker.reserve(m_tag.fields().size());
384 for(
auto &field : m_tag.fields()) {
385 if(!field.second.value().isEmpty() &&
388 m_maker.emplace_back(field.second.prepareMaking());
389 m_ilstSize += m_maker.back().requiredSize();
390 }
catch(
const Failure &) {
393 m_tag.addNotifications(field.second);
396 if(m_ilstSize != 8) {
397 m_metaSize += m_ilstSize;
411 BinaryWriter writer(&stream);
412 writer.writeUInt32BE(m_metaSize);
415 static const byte hdlrData[37] = {
416 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x68, 0x64, 0x6C, 0x72, 0x00, 0x00,
417 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6D, 0x64, 0x69, 0x72, 0x61, 0x70, 0x70, 0x6C,
418 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
420 stream.write(reinterpret_cast<const char *>(hdlrData),
sizeof(hdlrData));
421 if(m_ilstSize != 8) {
423 writer.writeUInt32BE(m_ilstSize);
426 for(
auto &maker : m_maker) {
Contains utility classes helping to read and write streams.