tagparser/matroska/matroskachapter.cpp
Martchus 6b469f1c26 Add Locale class to deal with differently specified languages/countries
Different media/tag formats specify languages and countries
differently. This change introduces a Locale class to keep track
of the format being used. So far there are no automatic conversions
implemented so it is entirely up to the user to pass valid values using
a format which matches the one required by the media/tag format.

This change also adds support for Matroska's IETF elements so at least the
raw value can be read, written and is preserved.
2020-12-16 17:48:08 +01:00

138 lines
5.2 KiB
C++

#include "./matroskachapter.h"
#include "./ebmlelement.h"
#include "./matroskaid.h"
#include "../diagnostics.h"
#include <c++utilities/conversion/stringbuilder.h>
#include <memory>
using namespace std;
using namespace CppUtilities;
namespace TagParser {
/*!
* \class MatroskaChapter
* \brief The MatroskaChapter class provides an implementation of AbstractAttachment for Matroska files.
*/
/*!
* \brief Constructs a new MatroskaChapter for the specified \a chapterAtomElement.
*/
MatroskaChapter::MatroskaChapter(EbmlElement *chapterAtomElement)
: m_chapterAtomElement(chapterAtomElement)
{
}
/*!
* \brief Destroys the chapter.
*/
MatroskaChapter::~MatroskaChapter()
{
}
/*!
* \brief Parses the "ChapterAtom"-element which has been specified when constructing the object.
* \remarks
* - Fetches nested chapters but does not parse them.
* - Clears all previous parsing results.
*/
void MatroskaChapter::internalParse(Diagnostics &diag)
{
// clear previous values and status
static const string context("parsing \"ChapterAtom\"-element");
clear();
// iterate through children of "ChapterAtom"-element
for (EbmlElement *chapterAtomChild = m_chapterAtomElement->firstChild(); chapterAtomChild; chapterAtomChild = chapterAtomChild->nextSibling()) {
chapterAtomChild->parse(diag);
switch (chapterAtomChild->id()) {
case MatroskaIds::ChapterUID:
m_id = chapterAtomChild->readUInteger();
break;
case MatroskaIds::ChapterStringUID:
break;
case MatroskaIds::ChapterTimeStart:
m_startTime = TimeSpan(chapterAtomChild->readUInteger() / 100);
break;
case MatroskaIds::ChapterTimeEnd:
m_endTime = TimeSpan(chapterAtomChild->readUInteger() / 100);
break;
case MatroskaIds::ChapterFlagHidden:
m_hidden = chapterAtomChild->readUInteger() == 1;
break;
case MatroskaIds::ChapterFlagEnabled:
m_enabled = chapterAtomChild->readUInteger() == 1;
break;
case MatroskaIds::ChapterSegmentUID:
case MatroskaIds::ChapterSegmentEditionUID:
case MatroskaIds::ChapterPhysicalEquiv:
break;
case MatroskaIds::ChapterTrack:
for (EbmlElement *chapterTrackElement = chapterAtomChild->firstChild(); chapterTrackElement;
chapterTrackElement = chapterTrackElement->nextSibling()) {
chapterTrackElement->parse(diag);
switch (chapterTrackElement->id()) {
case MatroskaIds::ChapterTrack:
m_tracks.emplace_back(chapterTrackElement->readUInteger());
break;
default:
diag.emplace_back(DiagLevel::Warning,
"\"ChapterTrack\"-element contains unknown child element \"" % chapterAtomChild->idToString() + "\". It will be ignored.",
context);
}
}
break;
case MatroskaIds::ChapterDisplay:
m_names.emplace_back();
for (EbmlElement *chapterDisplayElement = chapterAtomChild->firstChild(); chapterDisplayElement;
chapterDisplayElement = chapterDisplayElement->nextSibling()) {
chapterDisplayElement->parse(diag);
switch (chapterDisplayElement->id()) {
case MatroskaIds::ChapString:
if (m_names.back().empty()) {
m_names.back().assign(chapterDisplayElement->readString());
} else {
diag.emplace_back(DiagLevel::Warning,
"\"ChapterDisplay\"-element contains multiple \"ChapString\"-elements. Surplus occurrences will be ignored.", context);
}
break;
case MatroskaIds::ChapLanguage:
m_names.back().locale().emplace_back(chapterDisplayElement->readString(), LocaleFormat::ISO_639_2_B);
break;
case MatroskaIds::ChapLanguageIETF:
m_names.back().locale().emplace_back(chapterDisplayElement->readString(), LocaleFormat::BCP_47);
break;
case MatroskaIds::ChapCountry:
m_names.back().locale().emplace_back(chapterDisplayElement->readString(), LocaleFormat::DomainCountry);
break;
}
}
break;
case MatroskaIds::ChapProcess:
break;
case MatroskaIds::ChapterAtom:
m_nestedChapters.emplace_back(make_unique<MatroskaChapter>(chapterAtomChild));
break;
default:
diag.emplace_back(DiagLevel::Warning,
"\"ChapterAtom\"-element contains unknown child element \"" % chapterAtomChild->idToString() + "\". It will be ignored.", context);
}
}
// "eng" is default language
for (LocaleAwareString &name : m_names) {
if (name.locale().empty()) {
name.locale().emplace_back("eng"sv, LocaleFormat::ISO_639_2_B);
}
}
}
void MatroskaChapter::clear()
{
AbstractChapter::clear();
m_nestedChapters.clear();
}
} // namespace TagParser