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 Enclosure::Shape result{};
45 if (value >=
static_cast<uint8_t
>(Enclosure::Shape::NoEnclosure) &&
46 value <=
static_cast<uint8_t
>(Enclosure::Shape::Octogon)) {
47 result =
static_cast<Enclosure::Shape
>(value);
49 MUSX_UNKNOWN_XML(
"Invalid <sides> value in XML for enclosure: " + std::to_string(value));
55struct FieldPopulator<DrumStaffStyle> :
private FieldPopulator<DrumStaff>
57 using FieldPopulator<DrumStaff>::populate;
61struct FieldPopulator<MarkingCategoryName> :
private FieldPopulator<OthersName>
63 using FieldPopulator<OthersName>::populate;
67struct FieldPopulator<NamePositionAbbreviated> :
private FieldPopulator<NamePositioning>
69 using FieldPopulator<NamePositioning>::populate;
73struct FieldPopulator<NamePositionStyleAbbreviated> :
private FieldPopulator<NamePositioning>
75 using FieldPopulator<NamePositioning>::populate;
79struct FieldPopulator<NamePositionFull> :
private FieldPopulator<NamePositioning>
81 using FieldPopulator<NamePositioning>::populate;
85struct FieldPopulator<NamePositionStyleFull> :
private FieldPopulator<NamePositioning>
87 using FieldPopulator<NamePositioning>::populate;
91struct FieldPopulator<RepeatBackIndividualPositioning> :
private FieldPopulator<RepeatIndividualPositioning>
93 using FieldPopulator<RepeatIndividualPositioning>::populate;
97struct FieldPopulator<RepeatEndingStartIndividualPositioning> :
private FieldPopulator<RepeatIndividualPositioning>
99 using FieldPopulator<RepeatIndividualPositioning>::populate;
103struct FieldPopulator<RepeatEndingTextIndividualPositioning> :
private FieldPopulator<RepeatIndividualPositioning>
105 using FieldPopulator<RepeatIndividualPositioning>::populate;
109struct FieldPopulator<TextRepeatIndividualPositioning> :
private FieldPopulator<RepeatIndividualPositioning>
111 using FieldPopulator<RepeatIndividualPositioning>::populate;
115struct FieldPopulator<StaffListCategoryName> :
private FieldPopulator<OthersName>
117 using FieldPopulator<OthersName>::populate;
121struct FieldPopulator<StaffListCategoryParts> :
private FieldPopulator<StaffList>
123 using FieldPopulator<StaffList>::populate;
127struct FieldPopulator<StaffListCategoryScore> :
private FieldPopulator<StaffList>
129 using FieldPopulator<StaffList>::populate;
133struct FieldPopulator<StaffListRepeatName> :
private FieldPopulator<OthersName>
135 using FieldPopulator<OthersName>::populate;
139struct FieldPopulator<StaffListRepeatParts> :
private FieldPopulator<StaffList>
141 using FieldPopulator<StaffList>::populate;
145struct FieldPopulator<StaffListRepeatPartsForced> :
private FieldPopulator<StaffList>
147 using FieldPopulator<StaffList>::populate;
151struct FieldPopulator<StaffListRepeatScore> :
private FieldPopulator<StaffList>
153 using FieldPopulator<StaffList>::populate;
157struct FieldPopulator<StaffListRepeatScoreForced> :
private FieldPopulator<StaffList>
159 using FieldPopulator<StaffList>::populate;
163struct FieldPopulator<TextExpressionEnclosure> :
private FieldPopulator<Enclosure>
165 using FieldPopulator<Enclosure>::populate;
169struct FieldPopulator<TextRepeatEnclosure> :
private FieldPopulator<Enclosure>
171 using FieldPopulator<Enclosure>::populate;
174MUSX_RESOLVER_ENTRY(KeyMapArray, {
176 auto arrays = document->getOthers()->getArray<KeyMapArray>(
SCORE_PARTID);
177 for (
const auto& array : arrays) {
178 KeyMapArray* mutableArray =
const_cast<KeyMapArray*
>(array.get());
179 auto trimSteps = [&](
size_t newSize) {
180 while (array->steps.size() > newSize) {
181 const auto& elt = array->steps[array->steps.size() - 1];
182 if (elt->diatonic || elt->hlevel != 0) {
185 mutableArray->steps.pop_back();
188 if (
auto keyFormat = document->getOthers()->get<others::KeyFormat>(
SCORE_PARTID, array->getCmper())) {
189 trimSteps(keyFormat->semitones);
190 if (keyFormat->scaleTones != array->countDiatonicSteps() || keyFormat->semitones != array->steps.size()) {
191 MUSX_INTEGRITY_ERROR(
"KeyMapArray " + std::to_string(array->getCmper()) +
" does not match KeyFormat.");
195 if (array->countDiatonicSteps() != 7 || array->steps.size() != 12) {
196 MUSX_INTEGRITY_ERROR(
"KeyMapArray " + std::to_string(array->getCmper()) +
" has no KeyFormat but does not match default values.");
203MUSX_RESOLVER_ENTRY(LayerAttributes, {
205 auto layers = document->getOthers()->getArray<LayerAttributes>(
SCORE_PARTID);
206 if (layers.size() != 4) {
207 MUSX_INTEGRITY_ERROR(
"Expected exactly 4 <layerAtts> elements.");
209 for (
size_t i = 0; i < layers.size(); i++) {
210 if (layers[i]->getCmper() != i) {
211 MUSX_INTEGRITY_ERROR(
"Expected <layerAtts> elements to have cmper values 0, 1, 2, 3 in order.");
217MUSX_RESOLVER_ENTRY(MarkingCategory, {
219 auto cats = document->getOthers()->getArray<MarkingCategory>(
SCORE_PARTID);
220 for (
const auto& cat : cats) {
221 if (cat->categoryType == MarkingCategory::CategoryType::Invalid) {
222 MUSX_INTEGRITY_ERROR(
"Encountered <markingsCategory> node (cmper " + std::to_string(cat->getCmper()) +
") with no categoryType");
228MUSX_RESOLVER_ENTRY(Measure, Measure::checkMeasureCmperSequence);
230MUSX_RESOLVER_ENTRY(MultiStaffGroupId, {
232 auto parts = document->getOthers()->getArray<PartDefinition>(
SCORE_PARTID);
233 for (
const auto& part : parts) {
234 auto instGroups = document->getOthers()->getArray<MultiStaffGroupId>(part->getCmper());
235 for (
const auto& instance : instGroups) {
236 if (
auto group = document->getDetails()->get<details::StaffGroup>(part->getCmper(), document->calcScrollViewCmper(part->getCmper()), instance->staffGroupId)) {
237 details::StaffGroup* mutableGroup =
const_cast<details::StaffGroup*
>(group.get());
238 mutableGroup->multiStaffGroupId = instance->getCmper();
239 }
else if (instance->staffGroupId != 0) {
240 MUSX_INTEGRITY_ERROR(
"Group " + std::to_string(instance->staffGroupId) +
" appears in MultiStaffGroupId "
241 + std::to_string(instance->getCmper()) +
" but does not exist.");
248MUSX_RESOLVER_ENTRY(MultiStaffInstrumentGroup, MultiStaffInstrumentGroup::calcAllMultiStaffGroupIds);
250MUSX_RESOLVER_ENTRY(Page, Page::calcSystemInfo);
252MUSX_RESOLVER_ENTRY(PartDefinition, {
254 auto parts = document->getOthers()->getArray<PartDefinition>(
SCORE_PARTID);
255 for (
const auto& part : parts) {
256 auto partGlobals = document->getOthers()->get<others::PartGlobals>(part->getCmper(),
MUSX_GLOBALS_CMPER);
258 MUSX_INTEGRITY_ERROR(
"Part " + std::to_string(part->getCmper()) +
" has no PartGlobals.");
264MUSX_RESOLVER_ENTRY(ShapeExpressionDef, {
266 auto exps = document->getOthers()->getArray<ShapeExpressionDef>(
SCORE_PARTID);
267 for (
const auto& instance : exps) {
268 if (instance->categoryId) {
269 auto markingCat = document->getOthers()->get<MarkingCategory>(instance->getSourcePartId(), instance->categoryId);
271 auto mutableMarkingCat =
const_cast<MarkingCategory*
>(markingCat.get());
272 mutableMarkingCat->shapeExpressions.emplace(instance->getCmper(), instance);
281MUSX_RESOLVER_ENTRY(Staff, {
283 others::Staff::calcAllRuntimeValues<others::Staff>(document);
284 auto instGroups = document->getOthers()->getArray<MultiStaffInstrumentGroup>(
SCORE_PARTID);
286 if (instGroups.empty()) {
292MUSX_RESOLVER_ENTRY(StaffStyle, {
294 others::Staff::calcAllRuntimeValues<others::StaffStyle>(document);
298MUSX_RESOLVER_ENTRY(TextExpressionDef, {
300 auto exps = document->getOthers()->getArray<TextExpressionDef>(
SCORE_PARTID);
301 for (
const auto& instance : exps) {
302 if (instance->categoryId) {
303 auto markingCat = document->getOthers()->get<MarkingCategory>(instance->getSourcePartId(), instance->categoryId);
305 auto mutableMarkingCat =
const_cast<MarkingCategory*
>(markingCat.get());
306 mutableMarkingCat->textExpressions.emplace(instance->getCmper(), instance);
static void calcAllAutoNumberValues(const DocumentPtr &document)
Get the auto-numbering value for this staff, if applicable.
Definition Staff.cpp:37
@ Info
Informational messages for general program operation.
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 CommonClasses.h:48
constexpr Cmper MUSX_GLOBALS_CMPER
The prefs cmper for global variables (used sparingly since Finale 26.2)
Definition Fundamentals.h:78
constexpr Cmper SCORE_PARTID
The part id of the score.
Definition Fundamentals.h:81
std::shared_ptr< Document > DocumentPtr
Shared Document pointer.
Definition DocumentElement.h:35
Provides interfaces and optional implementations for traversing XML.
Definition PugiXmlImpl.h:33
object model for musx file (enigmaxml)
Definition BaseClasses.h:38