From c8482cb36f461aa55a695adff2da7a5b9d0341bc Mon Sep 17 00:00:00 2001 From: David Lewis Date: Wed, 20 Nov 2024 18:04:04 +0000 Subject: [PATCH 1/7] New objects for score annotation --- include/vrv/annotscore.h | 79 ++++++++++++++++++++++++++++++++++ include/vrv/functorinterface.h | 5 +++ include/vrv/vrvdef.h | 1 + src/annotscore.cpp | 72 +++++++++++++++++++++++++++++++ src/functorinterface.cpp | 21 +++++++++ 5 files changed, 178 insertions(+) create mode 100644 include/vrv/annotscore.h create mode 100644 src/annotscore.cpp diff --git a/include/vrv/annotscore.h b/include/vrv/annotscore.h new file mode 100644 index 00000000000..dfb5885341a --- /dev/null +++ b/include/vrv/annotscore.h @@ -0,0 +1,79 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: annotscore.h +// Author: David Lewis +// Created: 2024 +// Copyright (c) Authors and others. All rights reserved. +///////////////////////////////////////////////////////////////////////////// + +#ifndef __VRV_ANNOTSCORE_H__ +#define __VRV_ANNOTSCORE_H__ + +#include "atts_cmn.h" +#include "controlelement.h" +#include "timeinterface.h" + +namespace vrv { + +//---------------------------------------------------------------------------- +// AnnotScore +//---------------------------------------------------------------------------- + +/** + * This class models the MEI element where @type is score. + */ +class AnnotScore : public ControlElement, public TextListInterface, public TimeSpanningInterface, public AttPlist { +public: + /** + * @name Constructors, destructors, and other standard methods + * Reset method reset all attribute classes + */ + ///@{ + AnnotScore(); + virtual ~AnnotScore(); + Object *Clone() const override { return new AnnotScore(*this); } + void Reset() override; + std::string GetClassName() const override { return "AnnotScore"; } + ///@} + + /** + * @name Getter to interfaces + */ + ///@{ + TimePointInterface *GetTimePointInterface() override { return vrv_cast(this); } + const TimePointInterface *GetTimePointInterface() const override + { + return vrv_cast(this); + } + TimeSpanningInterface *GetTimeSpanningInterface() override { return vrv_cast(this); } + const TimeSpanningInterface *GetTimeSpanningInterface() const override + { + return vrv_cast(this); + } + ///@} + + //----------// + // Functors // + //----------// + + /** + * Interface for class functor visitation + */ + ///@{ + FunctorCode Accept(Functor &functor) override; + FunctorCode Accept(ConstFunctor &functor) const override; + FunctorCode AcceptEnd(Functor &functor) override; + FunctorCode AcceptEnd(ConstFunctor &functor) const override; + ///@} + +protected: + // +private: + // +public: + // +private: +}; + +} // namespace vrv + +#endif diff --git a/include/vrv/functorinterface.h b/include/vrv/functorinterface.h index f24743f5839..f4faf6eb648 100644 --- a/include/vrv/functorinterface.h +++ b/include/vrv/functorinterface.h @@ -16,6 +16,7 @@ class Accid; class Alignment; class AlignmentReference; class AnchoredText; +class AnnotScore; class Arpeg; class Artic; class BarLine; @@ -280,6 +281,8 @@ class FunctorInterface { ///@{ virtual FunctorCode VisitAnchoredText(AnchoredText *anchoredText); virtual FunctorCode VisitAnchoredTextEnd(AnchoredText *anchoredText); + virtual FunctorCode VisitAnnotScore(AnnotScore *annotScore); + virtual FunctorCode VisitAnnotScoreEnd(AnnotScore *annotScore); virtual FunctorCode VisitArpeg(Arpeg *arpeg); virtual FunctorCode VisitArpegEnd(Arpeg *arpeg); virtual FunctorCode VisitBeamSpan(BeamSpan *beamSpan); @@ -653,6 +656,8 @@ class ConstFunctorInterface { ///@{ virtual FunctorCode VisitAnchoredText(const AnchoredText *anchoredText); virtual FunctorCode VisitAnchoredTextEnd(const AnchoredText *anchoredText); + virtual FunctorCode VisitAnnotScore(const AnnotScore *annotScore); + virtual FunctorCode VisitAnnotScoreEnd(const AnnotScore *annotScore); virtual FunctorCode VisitArpeg(const Arpeg *arpeg); virtual FunctorCode VisitArpegEnd(const Arpeg *arpeg); virtual FunctorCode VisitBeamSpan(const BeamSpan *beamSpan); diff --git a/include/vrv/vrvdef.h b/include/vrv/vrvdef.h index b596eac7762..0a13f7a8d17 100644 --- a/include/vrv/vrvdef.h +++ b/include/vrv/vrvdef.h @@ -176,6 +176,7 @@ enum ClassId : uint16_t { // Ids for ControlElement child classes CONTROL_ELEMENT, ANCHOREDTEXT, + ANNOTSCORE, ARPEG, BEAMSPAN, BRACKETSPAN, diff --git a/src/annotscore.cpp b/src/annotscore.cpp new file mode 100644 index 00000000000..4154cad5383 --- /dev/null +++ b/src/annotscore.cpp @@ -0,0 +1,72 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: annotscore.cpp +// Author: David Lewis +// Created: 2024 +// Copyright (c) Authors and others. All rights reserved. +///////////////////////////////////////////////////////////////////////////// + +#include "annotscore.h" + +//---------------------------------------------------------------------------- + +#include + +//---------------------------------------------------------------------------- + +#include "devicecontext.h" +#include "doc.h" +#include "functor.h" +#include "verticalaligner.h" +#include "vrv.h" + +namespace vrv { + +//---------------------------------------------------------------------------- +// AnnotScore +//---------------------------------------------------------------------------- + +static const ClassRegistrar s_factory("annot", ANNOTSCORE); + +AnnotScore::AnnotScore() + : ControlElement(ANNOTSCORE, "annot-"), TextListInterface(), TimeSpanningInterface(), AttPlist() +{ + this->RegisterInterface(TimeSpanningInterface::GetAttClasses(), TimeSpanningInterface::IsInterface()); + this->RegisterAttClass(ATT_PLIST); + + this->Reset(); +} + +AnnotScore::~AnnotScore() {} + +void AnnotScore::Reset() +{ + ControlElement::Reset(); + this->ResetPlist(); + TimeSpanningInterface::Reset(); +} + +//---------------------------------------------------------------------------- +// AnnotScore functor methods +//---------------------------------------------------------------------------- + +FunctorCode AnnotScore::Accept(Functor &functor) +{ + return functor.VisitAnnotScore(this); +} + +FunctorCode AnnotScore::Accept(ConstFunctor &functor) const +{ + return functor.VisitAnnotScore(this); +} + +FunctorCode AnnotScore::AcceptEnd(Functor &functor) +{ + return functor.VisitAnnotScoreEnd(this); +} + +FunctorCode AnnotScore::AcceptEnd(ConstFunctor &functor) const +{ + return functor.VisitAnnotScoreEnd(this); +} + +} // namespace vrv diff --git a/src/functorinterface.cpp b/src/functorinterface.cpp index 202645cbbbc..24fe2833366 100644 --- a/src/functorinterface.cpp +++ b/src/functorinterface.cpp @@ -11,6 +11,7 @@ #include "accid.h" #include "anchoredtext.h" +#include "annotscore.h" #include "arpeg.h" #include "artic.h" #include "barline.h" @@ -490,6 +491,16 @@ FunctorCode FunctorInterface::VisitAnchoredTextEnd(AnchoredText *anchoredText) return this->VisitControlElementEnd(anchoredText); } +FunctorCode FunctorInterface::VisitAnnotScore(AnnotScore *annotScore) +{ + return this->VisitControlElement(annotScore); +} + +FunctorCode FunctorInterface::VisitAnnotScoreEnd(AnnotScore *annotScore) +{ + return this->VisitControlElementEnd(annotScore); +} + FunctorCode FunctorInterface::VisitArpeg(Arpeg *arpeg) { return this->VisitControlElement(arpeg); @@ -1824,6 +1835,16 @@ FunctorCode ConstFunctorInterface::VisitAnchoredTextEnd(const AnchoredText *anch return this->VisitControlElementEnd(anchoredText); } +FunctorCode ConstFunctorInterface::VisitAnnotScore(const AnnotScore *annotScore) +{ + return this->VisitControlElement(annotScore); +} + +FunctorCode ConstFunctorInterface::VisitAnnotScoreEnd(const AnnotScore *annotScore) +{ + return this->VisitControlElementEnd(annotScore); +} + FunctorCode ConstFunctorInterface::VisitArpeg(const Arpeg *arpeg) { return this->VisitControlElement(arpeg); From 91c312c08f15dbef09e54af8f79e7d1e89e4534a Mon Sep 17 00:00:00 2001 From: David Lewis Date: Fri, 6 Dec 2024 15:20:19 +0000 Subject: [PATCH 2/7] Add read support for annot @type=score --- include/vrv/annotscore.h | 14 +++++++++++-- include/vrv/iomei.h | 7 +++++++ src/annotscore.cpp | 17 +++++++++++++++- src/iomei.cpp | 43 +++++++++++++++++++++++++++++++++++++++- 4 files changed, 77 insertions(+), 4 deletions(-) diff --git a/include/vrv/annotscore.h b/include/vrv/annotscore.h index dfb5885341a..ce099d6b725 100644 --- a/include/vrv/annotscore.h +++ b/include/vrv/annotscore.h @@ -9,7 +9,9 @@ #define __VRV_ANNOTSCORE_H__ #include "atts_cmn.h" +#include "atts_shared.h" #include "controlelement.h" +#include "editorial.h" #include "timeinterface.h" namespace vrv { @@ -21,7 +23,7 @@ namespace vrv { /** * This class models the MEI element where @type is score. */ -class AnnotScore : public ControlElement, public TextListInterface, public TimeSpanningInterface, public AttPlist { +class AnnotScore : public ControlElement, public TimeSpanningInterface, public AttPlist { public: /** * @name Constructors, destructors, and other standard methods @@ -30,7 +32,7 @@ class AnnotScore : public ControlElement, public TextListInterface, public TimeS ///@{ AnnotScore(); virtual ~AnnotScore(); - Object *Clone() const override { return new AnnotScore(*this); } + //Object *Clone() const override { return new AnnotScore(*this); } void Reset() override; std::string GetClassName() const override { return "AnnotScore"; } ///@} @@ -49,6 +51,14 @@ class AnnotScore : public ControlElement, public TextListInterface, public TimeS { return vrv_cast(this); } + + /** + * Add a text element to an annotation. + * Only supported elements will be actually added to the child list. + */ + bool IsSupportedChild(Object *object) override; + + ///@} //----------// diff --git a/include/vrv/iomei.h b/include/vrv/iomei.h index e58c74f20ce..8d5d22567a1 100644 --- a/include/vrv/iomei.h +++ b/include/vrv/iomei.h @@ -28,6 +28,7 @@ class Add; class AltSymInterface; class AnchoredText; class Annot; +class AnnotScore; class App; class AreaPosInterface; class Arpeg; @@ -800,6 +801,7 @@ class MEIInput : public Input { bool ReadAbbr(Object *parent, pugi::xml_node abbr, EditorialLevel level, Object *filter = NULL); bool ReadAdd(Object *parent, pugi::xml_node add, EditorialLevel level, Object *filter = NULL); bool ReadAnnot(Object *parent, pugi::xml_node annot); + bool ReadAnnotScore(Object *parent, pugi::xml_node annot); bool ReadApp(Object *parent, pugi::xml_node app, EditorialLevel level, Object *filter = NULL); bool ReadAppChildren(Object *parent, pugi::xml_node parentNode, EditorialLevel level, Object *filter = NULL); bool ReadChoice(Object *parent, pugi::xml_node choice, EditorialLevel level, Object *filter = NULL); @@ -865,6 +867,11 @@ class MEIInput : public Input { */ void ReadUnsupportedAttr(pugi::xml_node element, Object *object); + /** + * Returns true if the element is a 'score' annotation. Currently based on @type + */ + bool IsAnnotScore(pugi::xml_node element); + /** * Returns true if the element is name is an editorial element (e.g., "app", "supplied", etc.) */ diff --git a/src/annotscore.cpp b/src/annotscore.cpp index 4154cad5383..2e97e00b405 100644 --- a/src/annotscore.cpp +++ b/src/annotscore.cpp @@ -16,6 +16,7 @@ #include "devicecontext.h" #include "doc.h" #include "functor.h" +#include "text.h" #include "verticalaligner.h" #include "vrv.h" @@ -28,7 +29,7 @@ namespace vrv { static const ClassRegistrar s_factory("annot", ANNOTSCORE); AnnotScore::AnnotScore() - : ControlElement(ANNOTSCORE, "annot-"), TextListInterface(), TimeSpanningInterface(), AttPlist() + : ControlElement(ANNOTSCORE, "annot-"), AttPlist() { this->RegisterInterface(TimeSpanningInterface::GetAttClasses(), TimeSpanningInterface::IsInterface()); this->RegisterAttClass(ATT_PLIST); @@ -45,6 +46,20 @@ void AnnotScore::Reset() TimeSpanningInterface::Reset(); } +bool AnnotScore::IsSupportedChild(Object *child) +{ + if (child->IsTextElement()) { + assert(dynamic_cast(child)); + } + else if (child->Is(ANNOT)) { + assert(dynamic_cast(child)); + } + else { + return false; + } + return true; +} + //---------------------------------------------------------------------------- // AnnotScore functor methods //---------------------------------------------------------------------------- diff --git a/src/iomei.cpp b/src/iomei.cpp index 3e5436e9441..52b924b046e 100644 --- a/src/iomei.cpp +++ b/src/iomei.cpp @@ -20,6 +20,7 @@ #include "altsyminterface.h" #include "anchoredtext.h" #include "annot.h" +#include "annotscore.h" #include "app.h" #include "arpeg.h" #include "artic.h" @@ -5479,7 +5480,11 @@ bool MEIInput::ReadMeasureChildren(Object *parent, pugi::xml_node parentNode) this->NormalizeAttributes(current); // editorial if (this->IsEditorialElementName(currentName)) { - success = this->ReadEditorialElement(parent, current, EDITORIAL_MEASURE); + if(currentName == "annot" && this->IsAnnotScore(current)) { + success = this->ReadAnnotScore(parent, current); + } else { + success = this->ReadEditorialElement(parent, current, EDITORIAL_MEASURE); + } } // content else if (currentName == "anchoredText") { @@ -7683,6 +7688,36 @@ bool MEIInput::ReadAnnot(Object *parent, pugi::xml_node annot) } } +bool MEIInput::ReadAnnotScore(Object *parent, pugi::xml_node annot) +{ + AnnotScore *vrvAnnotScore = new AnnotScore(); + //this->ReadEditorialElement(annot, vrvAnnotScore); + + vrvAnnotScore->ReadPlist(annot); + //vrvAnnotScore->ReadSource(annot); + + parent->AddChild(vrvAnnotScore); + //vrvAnnotScore->m_content.reset(); + + bool hasNonTextContent = false; + // copy all the nodes inside into the document + for (pugi::xml_node child = annot.first_child(); child; child = child.next_sibling()) { + const std::string nodeName = child.name(); + if (!hasNonTextContent && (!nodeName.empty())) hasNonTextContent = true; + //vrvAnnotScore->m_content.append_copy(child); + } + this->ReadUnsupportedAttr(annot, vrvAnnotScore); + // Unless annot has only text we do not load children because they are preserved in Annot::m_content + if (hasNonTextContent) { + return true; + } + else { + //vrvAnnot->m_content.remove_children(); + return this->ReadTextChildren(vrvAnnotScore, annot, vrvAnnotScore); + } + +} + bool MEIInput::ReadApp(Object *parent, pugi::xml_node app, EditorialLevel level, Object *filter) { if (!m_hasScoreDef) { @@ -8281,6 +8316,12 @@ bool MEIInput::ReadXMLComment(Object *object, pugi::xml_node element) return true; } +bool MEIInput::IsAnnotScore(pugi::xml_node annot) { + // If the annotation is a score annotation, it'll have @type="score" (we can also guess) + std::string value = annot.attribute("type").value(); + return value == "score"; +} + bool MEIInput::IsEditorialElementName(std::string elementName) { auto i = std::find(MEIInput::s_editorialElementNames.begin(), MEIInput::s_editorialElementNames.end(), elementName); From afb6c9b1974f987412423e2f9166d4fba5a55b39 Mon Sep 17 00:00:00 2001 From: David Lewis Date: Wed, 11 Dec 2024 17:12:48 +0000 Subject: [PATCH 3/7] Read write round trip for score-type annot --- include/vrv/iomei.h | 1 + src/annotscore.cpp | 4 ++-- src/iomei.cpp | 26 ++++++++++++++++++++------ 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/include/vrv/iomei.h b/include/vrv/iomei.h index 8d5d22567a1..d0a8169f901 100644 --- a/include/vrv/iomei.h +++ b/include/vrv/iomei.h @@ -433,6 +433,7 @@ class MEIOutput : public Output { */ ///@{ void WriteAnchoredText(pugi::xml_node currentNode, AnchoredText *anchoredText); + void WriteAnnotScore(pugi::xml_node currentNode, AnnotScore *annotScore); void WriteArpeg(pugi::xml_node currentNode, Arpeg *arpeg); void WriteBeamSpan(pugi::xml_node currentNode, BeamSpan *beamSpan); void WriteBracketSpan(pugi::xml_node currentNode, BracketSpan *bracketSpan); diff --git a/src/annotscore.cpp b/src/annotscore.cpp index 2e97e00b405..1210dbdb39d 100644 --- a/src/annotscore.cpp +++ b/src/annotscore.cpp @@ -26,10 +26,10 @@ namespace vrv { // AnnotScore //---------------------------------------------------------------------------- -static const ClassRegistrar s_factory("annot", ANNOTSCORE); +static const ClassRegistrar s_factory("annotScore", ANNOTSCORE); AnnotScore::AnnotScore() - : ControlElement(ANNOTSCORE, "annot-"), AttPlist() + : ControlElement(ANNOTSCORE, "annotscore-"), AttPlist() { this->RegisterInterface(TimeSpanningInterface::GetAttClasses(), TimeSpanningInterface::IsInterface()); this->RegisterAttClass(ATT_PLIST); diff --git a/src/iomei.cpp b/src/iomei.cpp index 52b924b046e..13dcdf5a9f8 100644 --- a/src/iomei.cpp +++ b/src/iomei.cpp @@ -472,8 +472,10 @@ bool MEIOutput::WriteObjectInternal(Object *object, bool useCustomScoreDef) else if (object->Is(ANCHOREDTEXT)) { m_currentNode = m_currentNode.append_child("anchoredText"); this->WriteAnchoredText(m_currentNode, vrv_cast(object)); - } - else if (object->Is(ARPEG)) { + } else if (object->Is(ANNOTSCORE)){ + m_currentNode = m_currentNode.append_child("annot"); + this->WriteAnnotScore(m_currentNode, vrv_cast(object)); + } else if (object->Is(ARPEG)) { m_currentNode = m_currentNode.append_child("arpeg"); this->WriteArpeg(m_currentNode, vrv_cast(object)); } @@ -833,12 +835,10 @@ bool MEIOutput::WriteObjectInternal(Object *object, bool useCustomScoreDef) else if (object->Is(ANNOT)) { m_currentNode = m_currentNode.append_child("annot"); this->WriteAnnot(m_currentNode, vrv_cast(object)); - } - else if (object->Is(APP)) { + } else if (object->Is(APP)) { m_currentNode = m_currentNode.append_child("app"); this->WriteApp(m_currentNode, vrv_cast(object)); - } - else if (object->Is(CHOICE)) { + } else if (object->Is(CHOICE)) { m_currentNode = m_currentNode.append_child("choice"); this->WriteChoice(m_currentNode, vrv_cast(object)); } @@ -1961,6 +1961,20 @@ void MEIOutput::WriteAnchoredText(pugi::xml_node currentNode, AnchoredText *anch this->WriteTextDirInterface(currentNode, anchoredText); } +void MEIOutput::WriteAnnotScore(pugi::xml_node currentNode, AnnotScore *annotScore) +{ + assert(annotScore); + + this->WriteControlElement(currentNode, annotScore); + annotScore->WritePlist(currentNode); + // FIXME: currently ignoring annot contents +/* // special case where we keep the pugi::nodes + for (pugi::xml_node child = annotScore->m_content.first_child(); child; child = child.next_sibling()) { + currentNode.append_copy(child); + } + */ +} + void MEIOutput::WriteArpeg(pugi::xml_node currentNode, Arpeg *arpeg) { assert(arpeg); From ee5e353334ba944df0a09107c2912590361eb123 Mon Sep 17 00:00:00 2001 From: David Lewis Date: Tue, 17 Dec 2024 13:45:09 +0000 Subject: [PATCH 4/7] Code linting --- include/vrv/annotscore.h | 5 ++--- src/annotscore.cpp | 3 +-- src/iohumdrum.cpp | 4 ++-- src/iomei.cpp | 47 ++++++++++++++++++++++------------------ src/iomusxml.cpp | 10 ++++----- 5 files changed, 36 insertions(+), 33 deletions(-) diff --git a/include/vrv/annotscore.h b/include/vrv/annotscore.h index ce099d6b725..b35110d445a 100644 --- a/include/vrv/annotscore.h +++ b/include/vrv/annotscore.h @@ -23,7 +23,7 @@ namespace vrv { /** * This class models the MEI element where @type is score. */ -class AnnotScore : public ControlElement, public TimeSpanningInterface, public AttPlist { +class AnnotScore : public ControlElement, public TimeSpanningInterface, public AttPlist { public: /** * @name Constructors, destructors, and other standard methods @@ -32,7 +32,7 @@ class AnnotScore : public ControlElement, public TimeSpanningInterface, public ///@{ AnnotScore(); virtual ~AnnotScore(); - //Object *Clone() const override { return new AnnotScore(*this); } + // Object *Clone() const override { return new AnnotScore(*this); } void Reset() override; std::string GetClassName() const override { return "AnnotScore"; } ///@} @@ -58,7 +58,6 @@ class AnnotScore : public ControlElement, public TimeSpanningInterface, public */ bool IsSupportedChild(Object *object) override; - ///@} //----------// diff --git a/src/annotscore.cpp b/src/annotscore.cpp index 1210dbdb39d..7b37810eb87 100644 --- a/src/annotscore.cpp +++ b/src/annotscore.cpp @@ -28,8 +28,7 @@ namespace vrv { static const ClassRegistrar s_factory("annotScore", ANNOTSCORE); -AnnotScore::AnnotScore() - : ControlElement(ANNOTSCORE, "annotscore-"), AttPlist() +AnnotScore::AnnotScore() : ControlElement(ANNOTSCORE, "annotscore-"), AttPlist() { this->RegisterInterface(TimeSpanningInterface::GetAttClasses(), TimeSpanningInterface::IsInterface()); this->RegisterAttClass(ATT_PLIST); diff --git a/src/iohumdrum.cpp b/src/iohumdrum.cpp index e4a02f50c36..428ceab63f3 100644 --- a/src/iohumdrum.cpp +++ b/src/iohumdrum.cpp @@ -2939,7 +2939,7 @@ void HumdrumInput::createDigitalSource(pugi::xml_node sourceDesc) pugi::xml_node bibl = source.append_child("bibl"); bibl.append_copy(m_simpleTitle); for (pugi::xml_node_iterator childIt = m_simpleComposersDoc.begin(); childIt != m_simpleComposersDoc.end(); - ++childIt) { + ++childIt) { bibl.append_copy(*childIt); } @@ -3691,7 +3691,7 @@ void HumdrumInput::createPrintedSource(pugi::xml_node sourceDesc) bibl.append_copy(m_simpleTitle); for (pugi::xml_node_iterator childIt = m_simpleComposersDoc.begin(); childIt != m_simpleComposersDoc.end(); - ++childIt) { + ++childIt) { bibl.append_copy(*childIt); } diff --git a/src/iomei.cpp b/src/iomei.cpp index 00ccad15152..2aa66a0f2b9 100644 --- a/src/iomei.cpp +++ b/src/iomei.cpp @@ -472,10 +472,12 @@ bool MEIOutput::WriteObjectInternal(Object *object, bool useCustomScoreDef) else if (object->Is(ANCHOREDTEXT)) { m_currentNode = m_currentNode.append_child("anchoredText"); this->WriteAnchoredText(m_currentNode, vrv_cast(object)); - } else if (object->Is(ANNOTSCORE)){ - m_currentNode = m_currentNode.append_child("annot"); - this->WriteAnnotScore(m_currentNode, vrv_cast(object)); - } else if (object->Is(ARPEG)) { + } + else if (object->Is(ANNOTSCORE)) { + m_currentNode = m_currentNode.append_child("annot"); + this->WriteAnnotScore(m_currentNode, vrv_cast(object)); + } + else if (object->Is(ARPEG)) { m_currentNode = m_currentNode.append_child("arpeg"); this->WriteArpeg(m_currentNode, vrv_cast(object)); } @@ -835,10 +837,12 @@ bool MEIOutput::WriteObjectInternal(Object *object, bool useCustomScoreDef) else if (object->Is(ANNOT)) { m_currentNode = m_currentNode.append_child("annot"); this->WriteAnnot(m_currentNode, vrv_cast(object)); - } else if (object->Is(APP)) { + } + else if (object->Is(APP)) { m_currentNode = m_currentNode.append_child("app"); this->WriteApp(m_currentNode, vrv_cast(object)); - } else if (object->Is(CHOICE)) { + } + else if (object->Is(CHOICE)) { m_currentNode = m_currentNode.append_child("choice"); this->WriteChoice(m_currentNode, vrv_cast(object)); } @@ -1972,11 +1976,11 @@ void MEIOutput::WriteAnnotScore(pugi::xml_node currentNode, AnnotScore *annotSco this->WriteControlElement(currentNode, annotScore); annotScore->WritePlist(currentNode); // FIXME: currently ignoring annot contents -/* // special case where we keep the pugi::nodes - for (pugi::xml_node child = annotScore->m_content.first_child(); child; child = child.next_sibling()) { - currentNode.append_copy(child); - } - */ + /* // special case where we keep the pugi::nodes + for (pugi::xml_node child = annotScore->m_content.first_child(); child; child = child.next_sibling()) { + currentNode.append_copy(child); + } + */ } void MEIOutput::WriteArpeg(pugi::xml_node currentNode, Arpeg *arpeg) @@ -5485,9 +5489,10 @@ bool MEIInput::ReadMeasureChildren(Object *parent, pugi::xml_node parentNode) this->NormalizeAttributes(current); // editorial if (this->IsEditorialElementName(currentName)) { - if(currentName == "annot" && this->IsAnnotScore(current)) { + if (currentName == "annot" && this->IsAnnotScore(current)) { success = this->ReadAnnotScore(parent, current); - } else { + } + else { success = this->ReadEditorialElement(parent, current, EDITORIAL_MEASURE); } } @@ -7687,21 +7692,21 @@ bool MEIInput::ReadAnnot(Object *parent, pugi::xml_node annot) bool MEIInput::ReadAnnotScore(Object *parent, pugi::xml_node annot) { - AnnotScore *vrvAnnotScore = new AnnotScore(); - //this->ReadEditorialElement(annot, vrvAnnotScore); + AnnotScore *vrvAnnotScore = new AnnotScore(); + // this->ReadEditorialElement(annot, vrvAnnotScore); vrvAnnotScore->ReadPlist(annot); - //vrvAnnotScore->ReadSource(annot); + // vrvAnnotScore->ReadSource(annot); parent->AddChild(vrvAnnotScore); - //vrvAnnotScore->m_content.reset(); + // vrvAnnotScore->m_content.reset(); bool hasNonTextContent = false; // copy all the nodes inside into the document for (pugi::xml_node child = annot.first_child(); child; child = child.next_sibling()) { const std::string nodeName = child.name(); if (!hasNonTextContent && (!nodeName.empty())) hasNonTextContent = true; - //vrvAnnotScore->m_content.append_copy(child); + // vrvAnnotScore->m_content.append_copy(child); } this->ReadUnsupportedAttr(annot, vrvAnnotScore); // Unless annot has only text we do not load children because they are preserved in Annot::m_content @@ -7709,10 +7714,9 @@ bool MEIInput::ReadAnnotScore(Object *parent, pugi::xml_node annot) return true; } else { - //vrvAnnot->m_content.remove_children(); + // vrvAnnot->m_content.remove_children(); return this->ReadTextChildren(vrvAnnotScore, annot, vrvAnnotScore); } - } bool MEIInput::ReadApp(Object *parent, pugi::xml_node app, EditorialLevel level, Object *filter) @@ -8313,7 +8317,8 @@ bool MEIInput::ReadXMLComment(Object *object, pugi::xml_node element) return true; } -bool MEIInput::IsAnnotScore(pugi::xml_node annot) { +bool MEIInput::IsAnnotScore(pugi::xml_node annot) +{ // If the annotation is a score annotation, it'll have @type="score" (we can also guess) std::string value = annot.attribute("type").value(); return value == "score"; diff --git a/src/iomusxml.cpp b/src/iomusxml.cpp index eb9d68fb6de..27b267a541d 100644 --- a/src/iomusxml.cpp +++ b/src/iomusxml.cpp @@ -3492,7 +3492,7 @@ void MusicXmlInput::ReadMusicXmlNote( m_trillStack.push_back({ trill, openTrill }); } for (pugi::xml_node xmlAccidMark = xmlTrill.node().next_sibling("accidental-mark"); xmlAccidMark; - xmlAccidMark = xmlAccidMark.next_sibling("accidental-mark")) { + xmlAccidMark = xmlAccidMark.next_sibling("accidental-mark")) { if (HasAttributeWithValue(xmlAccidMark, "placement", "below")) { trill->SetAccidlower(ConvertAccidentalToAccid(xmlAccidMark.text().as_string())); } @@ -3530,7 +3530,7 @@ void MusicXmlInput::ReadMusicXmlNote( turn->SetPlace(turn->AttPlacementRelStaff::StrToStaffrel(xmlTurn.node().attribute("placement").as_string())); turn->SetForm(turnLog_FORM_upper); for (pugi::xml_node xmlAccidMark = xmlTurn.node().next_sibling("accidental-mark"); xmlAccidMark; - xmlAccidMark = xmlAccidMark.next_sibling("accidental-mark")) { + xmlAccidMark = xmlAccidMark.next_sibling("accidental-mark")) { if (HasAttributeWithValue(xmlAccidMark, "placement", "above")) { turn->SetAccidupper(ConvertAccidentalToAccid(xmlAccidMark.text().as_string())); } @@ -4691,7 +4691,7 @@ std::pair, int> MusicXmlInput::GetMeterSigGrpValues(const pugi: int maxUnit = 0; std::vector meterCounts; for (auto iter1 = beats.begin(), iter2 = beat_type.begin(); (iter1 != beats.end()) && (iter2 != beat_type.end()); - ++iter1, ++iter2) { + ++iter1, ++iter2) { // Process current beat/beat-type combination and add it to the meterSigGrp MeterSig *meterSig = new MeterSig(); data_METERCOUNT_pair count = meterSig->AttMeterSigLog::StrToMetercountPair(iter1->node().text().as_string()); @@ -4739,8 +4739,8 @@ std::string MusicXmlInput::GetOrnamentGlyphNumber(int attributes) const static std::map precomposedNames = { { APPR_Above | FORM_Inverted, "U+E5C6" }, { APPR_Below | FORM_Inverted, "U+E5B5" }, { APPR_Above | FORM_Normal, "U+E5C7" }, { APPR_Below | FORM_Normal, "U+E5B8" }, - { FORM_Inverted | DEP_Above, "U+E5BB" }, { FORM_Inverted | DEP_Below, "U+E5C8" } - // these values need to be matched with proper SMuFL codes first + { FORM_Inverted | DEP_Above, "U+E5BB" }, + { FORM_Inverted | DEP_Below, "U+E5C8" } // these values need to be matched with proper SMuFL codes first /*, { FORM_Normal | DEP_Above, "U+????" }, { FORM_Normal | DEP_Below, "U+????" }, { APPR_Above | FORM_Normal | DEP_Above, "U+????" }, { APPR_Above | FORM_Normal | DEP_Above, "U+????" }, { APPR_Above | FORM_Normal | DEP_Below, "U+????" }, From bb9a4beb144eddbc7817246097ba7eb369cb8792 Mon Sep 17 00:00:00 2001 From: David Lewis Date: Tue, 17 Dec 2024 14:09:30 +0000 Subject: [PATCH 5/7] Code tidying src/iomei.cpp Co-authored-by: Laurent Pugin --- src/iomei.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/iomei.cpp b/src/iomei.cpp index 2aa66a0f2b9..f82ae3140d4 100644 --- a/src/iomei.cpp +++ b/src/iomei.cpp @@ -8321,7 +8321,7 @@ bool MEIInput::IsAnnotScore(pugi::xml_node annot) { // If the annotation is a score annotation, it'll have @type="score" (we can also guess) std::string value = annot.attribute("type").value(); - return value == "score"; + return (value == "score"); } bool MEIInput::IsEditorialElementName(std::string elementName) From b24b7155a97a4dfb0ecd461dcafa9d7d531f98a8 Mon Sep 17 00:00:00 2001 From: David Lewis Date: Tue, 17 Dec 2024 14:20:54 +0000 Subject: [PATCH 6/7] Remove cancelled code, tidy comments --- src/iomei.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/iomei.cpp b/src/iomei.cpp index f82ae3140d4..b197c6c5d65 100644 --- a/src/iomei.cpp +++ b/src/iomei.cpp @@ -1975,12 +1975,7 @@ void MEIOutput::WriteAnnotScore(pugi::xml_node currentNode, AnnotScore *annotSco this->WriteControlElement(currentNode, annotScore); annotScore->WritePlist(currentNode); - // FIXME: currently ignoring annot contents - /* // special case where we keep the pugi::nodes - for (pugi::xml_node child = annotScore->m_content.first_child(); child; child = child.next_sibling()) { - currentNode.append_copy(child); - } - */ + // Currently ignoring annot contents -- normal annot looks at child elements here } void MEIOutput::WriteArpeg(pugi::xml_node currentNode, Arpeg *arpeg) @@ -7693,20 +7688,18 @@ bool MEIInput::ReadAnnot(Object *parent, pugi::xml_node annot) bool MEIInput::ReadAnnotScore(Object *parent, pugi::xml_node annot) { AnnotScore *vrvAnnotScore = new AnnotScore(); - // this->ReadEditorialElement(annot, vrvAnnotScore); + // Note: there probably needs to be more in here (see model methods) vrvAnnotScore->ReadPlist(annot); - // vrvAnnotScore->ReadSource(annot); parent->AddChild(vrvAnnotScore); - // vrvAnnotScore->m_content.reset(); bool hasNonTextContent = false; // copy all the nodes inside into the document for (pugi::xml_node child = annot.first_child(); child; child = child.next_sibling()) { const std::string nodeName = child.name(); if (!hasNonTextContent && (!nodeName.empty())) hasNonTextContent = true; - // vrvAnnotScore->m_content.append_copy(child); + // This is also orphan code -- we can't copy the contents here } this->ReadUnsupportedAttr(annot, vrvAnnotScore); // Unless annot has only text we do not load children because they are preserved in Annot::m_content @@ -7714,7 +7707,7 @@ bool MEIInput::ReadAnnotScore(Object *parent, pugi::xml_node annot) return true; } else { - // vrvAnnot->m_content.remove_children(); + // Again, this is code that may not apply for annotScore return this->ReadTextChildren(vrvAnnotScore, annot, vrvAnnotScore); } } From 5d6aaaf07548e2025eba794cb9bde079fc6fe84b Mon Sep 17 00:00:00 2001 From: David Lewis Date: Tue, 17 Dec 2024 14:23:51 +0000 Subject: [PATCH 7/7] Linting with clang 18 --- src/iomusxml.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/iomusxml.cpp b/src/iomusxml.cpp index 27b267a541d..60c50fa09f6 100644 --- a/src/iomusxml.cpp +++ b/src/iomusxml.cpp @@ -3492,7 +3492,7 @@ void MusicXmlInput::ReadMusicXmlNote( m_trillStack.push_back({ trill, openTrill }); } for (pugi::xml_node xmlAccidMark = xmlTrill.node().next_sibling("accidental-mark"); xmlAccidMark; - xmlAccidMark = xmlAccidMark.next_sibling("accidental-mark")) { + xmlAccidMark = xmlAccidMark.next_sibling("accidental-mark")) { if (HasAttributeWithValue(xmlAccidMark, "placement", "below")) { trill->SetAccidlower(ConvertAccidentalToAccid(xmlAccidMark.text().as_string())); } @@ -3530,7 +3530,7 @@ void MusicXmlInput::ReadMusicXmlNote( turn->SetPlace(turn->AttPlacementRelStaff::StrToStaffrel(xmlTurn.node().attribute("placement").as_string())); turn->SetForm(turnLog_FORM_upper); for (pugi::xml_node xmlAccidMark = xmlTurn.node().next_sibling("accidental-mark"); xmlAccidMark; - xmlAccidMark = xmlAccidMark.next_sibling("accidental-mark")) { + xmlAccidMark = xmlAccidMark.next_sibling("accidental-mark")) { if (HasAttributeWithValue(xmlAccidMark, "placement", "above")) { turn->SetAccidupper(ConvertAccidentalToAccid(xmlAccidMark.text().as_string())); } @@ -4691,7 +4691,7 @@ std::pair, int> MusicXmlInput::GetMeterSigGrpValues(const pugi: int maxUnit = 0; std::vector meterCounts; for (auto iter1 = beats.begin(), iter2 = beat_type.begin(); (iter1 != beats.end()) && (iter2 != beat_type.end()); - ++iter1, ++iter2) { + ++iter1, ++iter2) { // Process current beat/beat-type combination and add it to the meterSigGrp MeterSig *meterSig = new MeterSig(); data_METERCOUNT_pair count = meterSig->AttMeterSigLog::StrToMetercountPair(iter1->node().text().as_string());