24#include "musx/dom/BaseClasses.h"
25#include "musx/dom/Others.h"
26#include "musx/dom/Details.h"
27#include "musx/xml/XmlInterface.h"
28#include "FactoryBase.h"
30#ifndef DOXYGEN_SHOULD_IGNORE_THIS
42inline Enclosure::Shape toEnum<Enclosure::Shape>(
const uint8_t& value)
44 if (value >=
static_cast<uint8_t
>(Enclosure::Shape::NoEnclosure) &&
45 value <=
static_cast<uint8_t
>(Enclosure::Shape::Octogon)) {
46 return static_cast<Enclosure::Shape
>(value);
48 MUSX_UNKNOWN_XML(
"Invalid <sides> value in XML for enclosure: " + std::to_string(value));
53struct FieldPopulator<TextExpressionEnclosure> :
private FieldPopulator<Enclosure>
55 using FieldPopulator<Enclosure>::populate;
59struct FieldPopulator<TextRepeatEnclosure> :
private FieldPopulator<Enclosure>
61 using FieldPopulator<Enclosure>::populate;
64MUSX_RESOLVER_ENTRY(KeyMapArray, {
66 auto arrays = document->getOthers()->getArray<KeyMapArray>(
SCORE_PARTID);
67 for (
const auto& array : arrays) {
68 auto trimSteps = [&](
size_t newSize) {
69 while (array->steps.size() > newSize) {
70 const auto& elt = array->steps[array->steps.size() - 1];
71 if (elt->diatonic || elt->hlevel != 0) {
74 array->steps.pop_back();
77 if (
auto keyFormat = document->getOthers()->get<others::KeyFormat>(
SCORE_PARTID, array->getCmper())) {
78 trimSteps(keyFormat->semitones);
79 if (keyFormat->scaleTones != array->countDiatonicSteps() || keyFormat->semitones != array->steps.size()) {
80 MUSX_INTEGRITY_ERROR(
"KeyMapArray " + std::to_string(array->getCmper()) +
" does not match KeyFormat.");
84 if (array->countDiatonicSteps() != 7 || array->steps.size() != 12) {
85 MUSX_INTEGRITY_ERROR(
"KeyMapArray " + std::to_string(array->getCmper()) +
" has no KeyFormat but does not match default values.");
92MUSX_RESOLVER_ENTRY(LayerAttributes, {
94 auto layers = document->getOthers()->getArray<LayerAttributes>(
SCORE_PARTID);
95 if (layers.size() != 4) {
96 MUSX_INTEGRITY_ERROR(
"Expected exactly 4 <layerAtts> elements.");
98 for (
size_t i = 0; i < layers.size(); i++) {
99 if (layers[i]->getCmper() != i) {
100 MUSX_INTEGRITY_ERROR(
"Expected <layerAtts> elements to have cmper values 0, 1, 2, 3 in order.");
106MUSX_RESOLVER_ENTRY(MarkingCategory, {
108 auto cats = document->getOthers()->getArray<MarkingCategory>(
SCORE_PARTID);
109 for (
const auto& cat : cats) {
110 if (cat->categoryType == MarkingCategory::CategoryType::Invalid) {
111 MUSX_INTEGRITY_ERROR(
"Encountered <markingsCategory> node (cmper " + std::to_string(cat->getCmper()) +
") with no categoryType");
117MUSX_RESOLVER_ENTRY(MultiStaffGroupId, {
119 auto parts = document->getOthers()->getArray<PartDefinition>(
SCORE_PARTID);
120 for (
const auto& part : parts) {
121 auto instGroups = document->getOthers()->getArray<MultiStaffGroupId>(part->getCmper());
122 for (
const auto& instance : instGroups) {
123 if (
auto group = document->getDetails()->get<details::StaffGroup>(part->getCmper(),
BASE_SYSTEM_ID, instance->staffGroupId)) {
124 group->multiStaffGroupId = instance->getCmper();
126 MUSX_INTEGRITY_ERROR(
"Group " + std::to_string(instance->staffGroupId) +
" appears in MultiStaffGroupId "
127 + std::to_string(instance->getCmper()) +
" but does not exist.");
134MUSX_RESOLVER_ENTRY(MultiStaffInstrumentGroup, {
136 auto instGroups = document->getOthers()->getArray<MultiStaffInstrumentGroup>(
SCORE_PARTID);
137 for (
const auto& instance : instGroups) {
138 for (
size_t x = 0; x < instance->staffNums.size(); x++) {
139 auto staff = instance->getStaffAtIndex(x);
141 if (staff->multiStaffInstId) {
143 "Staff " + std::to_string(staff->getCmper()) +
" appears in more than one instance of MultiStaffInstrumentGroup.");
145 staff->multiStaffInstId = instance->getCmper();
154MUSX_RESOLVER_ENTRY(Page, {
156 auto linkedParts = document->getOthers()->getArray<PartDefinition>(
SCORE_PARTID);
157 for (
const auto& part : linkedParts) {
158 auto pages = document->getOthers()->getArray<Page>(part->getCmper());
159 auto systems = document->getOthers()->getArray<StaffSystem>(part->getCmper());
160 for (
size_t x = 0; x < pages.size(); x++) {
161 auto page = pages[x];
162 if (!page->isBlank()) {
164 size_t nextIndex = x + 1;
165 while (nextIndex < pages.size()) {
166 auto nextPage = pages[nextIndex++];
167 if (!nextPage->isBlank()) {
168 return nextPage->firstSystem - 1;
173 if (*page->lastSystem < page->firstSystem) {
174 page->lastSystem = std::nullopt;
175 MUSX_INTEGRITY_ERROR(
"Page " + std::to_string(page->getCmper()) +
" of part " + part->getName()
176 +
" has a last system smaller than the first system.");
184MUSX_RESOLVER_ENTRY(ShapeExpressionDef, {
186 auto exps = document->getOthers()->getArray<ShapeExpressionDef>(
SCORE_PARTID);
187 for (
const auto& instance : exps) {
188 if (instance->categoryId) {
189 auto markingCat = document->getOthers()->get<MarkingCategory>(instance->getPartId(), instance->categoryId);
191 MUSX_INTEGRITY_ERROR(
"Marking category for shape expression " + std::to_string(instance->getCmper()) +
" does not exist.");
193 markingCat->shapeExpressions.emplace(instance->getCmper(), instance);
199MUSX_RESOLVER_ENTRY(Staff, {
201 auto instGroups = document->getOthers()->getArray<MultiStaffInstrumentGroup>(
SCORE_PARTID);
203 if (instGroups.empty()) {
209MUSX_RESOLVER_ENTRY(TextExpressionDef, {
211 auto exps = document->getOthers()->getArray<TextExpressionDef>(
SCORE_PARTID);
212 for (
const auto& instance : exps) {
213 if (instance->categoryId) {
214 auto markingCat = document->getOthers()->get<MarkingCategory>(instance->getPartId(), instance->categoryId);
216 MUSX_INTEGRITY_ERROR(
"Marking category for text expression " + std::to_string(instance->getCmper()) +
" does not exist.");
218 markingCat->textExpressions.emplace(instance->getCmper(), instance);
static void calcAutoNumberValues(const DocumentPtr &document)
Get the auto-numbering value for this staff, if applicable.
Definition Implementations.cpp:1931
@ Verbose
Informational messages that should only displayed when verbose logging is requested.
static void log(LogLevel level, const std::string &message)
Logs a message with a specific severity level.
Definition Logger.h:87
Classes in the OthersPool.
Definition BaseClasses.h:40
constexpr Cmper SCORE_PARTID
The part id of the score.
Definition Fundamentals.h:75
std::shared_ptr< Document > DocumentPtr
Shared Document pointer.
Definition BaseClasses.h:55
constexpr Cmper BASE_SYSTEM_ID
The base system cmper that gives a list of all available staves and their score order (others::Instru...
Definition Fundamentals.h:76
int16_t SystemCmper
Enigma systems Cmper (may be negative when not applicable)
Definition Fundamentals.h:66
Provides interfaces and optional implementations for traversing XML.
Definition PugiXmlImpl.h:33
object model for musx file (enigmaxml)
Definition BaseClasses.h:32