Skip to content

Commit 6c77ebd

Browse files
authored
Merge pull request #31789 from miiizen/31225-xmlSpannerCrash
Fix crash after stopping spanners more than once
2 parents 334fd34 + 67eb715 commit 6c77ebd

File tree

1 file changed

+53
-0
lines changed

1 file changed

+53
-0
lines changed

src/importexport/musicxml/internal/import/importmusicxmlpass2.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,17 @@ static Fraction lastChordTicks(const Segment* s, const Fraction& tick, const tra
201201
return Fraction(0, 1);
202202
}
203203

204+
static bool spannerExists(const std::vector<MusicXmlSpannerDesc>& spanners, int number, engraving::ElementType elementType)
205+
{
206+
for (const MusicXmlSpannerDesc& desc : spanners) {
207+
if (desc.nr == number && desc.tp == elementType) {
208+
return true;
209+
}
210+
}
211+
212+
return false;
213+
}
214+
204215
//---------------------------------------------------------
205216
// setExtend
206217
//---------------------------------------------------------
@@ -5075,6 +5086,12 @@ void MusicXmlParserDirection::bracket(const String& type, const int number,
50755086
const ElementType elementType = isWavy ? ElementType::TRILL : ElementType::TEXTLINE;
50765087
const MusicXmlExtendedSpannerDesc& spdesc = m_pass2.getSpanner({ elementType, number });
50775088
if (type == "start") {
5089+
if (spannerExists(starts, number, elementType)) {
5090+
m_logger->logError(String(u"%1 with number %2 already started").arg(TConv::userName(elementType).translated()).arg(number),
5091+
&m_e);
5092+
m_e.skipCurrentElement();
5093+
return;
5094+
}
50785095
SLine* sline = spdesc.isStopped ? spdesc.sp : 0;
50795096
if ((sline && sline->isTrill()) || (!sline && isWavy)) {
50805097
if (!sline) {
@@ -5135,6 +5152,12 @@ void MusicXmlParserDirection::bracket(const String& type, const int number,
51355152

51365153
starts.push_back(MusicXmlSpannerDesc(sline, elementType, number));
51375154
} else if (type == "stop") {
5155+
if (spannerExists(stops, number, elementType)) {
5156+
m_logger->logError(String(u"%1 with number %2 already stopped").arg(TConv::userName(elementType).translated()).arg(number),
5157+
&m_e);
5158+
m_e.skipCurrentElement();
5159+
return;
5160+
}
51385161
SLine* sline = spdesc.isStarted ? spdesc.sp : 0;
51395162
if ((sline && sline->isTrill()) || (!sline && isWavy)) {
51405163
if (!sline) {
@@ -5186,6 +5209,11 @@ void MusicXmlParserDirection::dashes(const String& type, const int number,
51865209
{
51875210
const MusicXmlExtendedSpannerDesc& spdesc = m_pass2.getSpanner({ ElementType::HAIRPIN, number });
51885211
if (type == u"start") {
5212+
if (spannerExists(starts, number, ElementType::HAIRPIN)) {
5213+
m_logger->logError(String(u"hairpin with number %1 already started").arg(number), &m_e);
5214+
m_e.skipCurrentElement();
5215+
return;
5216+
}
51895217
TextLineBase* b = spdesc.isStopped ? toTextLineBase(spdesc.sp) : Factory::createTextLine(m_score->dummy());
51905218
// if (placement.empty()) placement = "above"; // TODO ? set default
51915219

@@ -5210,6 +5238,11 @@ void MusicXmlParserDirection::dashes(const String& type, const int number,
52105238
// use MusicXML specific type instead
52115239
starts.push_back(MusicXmlSpannerDesc(b, ElementType::TEXTLINE, number));
52125240
} else if (type == u"stop") {
5241+
if (spannerExists(stops, number, ElementType::HAIRPIN)) {
5242+
m_logger->logError(String(u"hairpin with number %1 already stopped").arg(number), &m_e);
5243+
m_e.skipCurrentElement();
5244+
return;
5245+
}
52135246
TextLineBase* b = spdesc.isStarted ? toTextLineBase(spdesc.sp) : Factory::createTextLine(m_score->dummy());
52145247
stops.push_back(MusicXmlSpannerDesc(b, ElementType::TEXTLINE, number));
52155248
}
@@ -5230,6 +5263,11 @@ void MusicXmlParserDirection::octaveShift(const String& type, const int number,
52305263
{
52315264
const MusicXmlExtendedSpannerDesc& spdesc = m_pass2.getSpanner({ ElementType::OTTAVA, number });
52325265
if (type == u"up" || type == u"down") {
5266+
if (spannerExists(starts, number, ElementType::OTTAVA)) {
5267+
m_logger->logError(String(u"ottava with number %1 already started").arg(number), &m_e);
5268+
m_e.skipCurrentElement();
5269+
return;
5270+
}
52335271
int ottavasize = m_e.intAttribute("size");
52345272
if (!(ottavasize == 8 || ottavasize == 15)) {
52355273
m_logger->logError(String(u"unknown octave-shift size %1").arg(ottavasize), &m_e);
@@ -5257,6 +5295,11 @@ void MusicXmlParserDirection::octaveShift(const String& type, const int number,
52575295
starts.push_back(MusicXmlSpannerDesc(o, ElementType::OTTAVA, number));
52585296
}
52595297
} else if (type == u"stop") {
5298+
if (spannerExists(stops, number, ElementType::OTTAVA)) {
5299+
m_logger->logError(String(u"ottava with number %1 already stopped").arg(number), &m_e);
5300+
m_e.skipCurrentElement();
5301+
return;
5302+
}
52605303
Ottava* o = spdesc.isStarted ? toOttava(spdesc.sp) : Factory::createOttava(m_score->dummy());
52615304
stops.push_back(MusicXmlSpannerDesc(o, ElementType::OTTAVA, number));
52625305
}
@@ -5408,6 +5451,11 @@ void MusicXmlParserDirection::wedge(const String& type, const int number,
54085451
AsciiStringView niente = m_e.asciiAttribute("niente");
54095452
const MusicXmlExtendedSpannerDesc& spdesc = m_pass2.getSpanner({ ElementType::HAIRPIN, number });
54105453
if (type == "crescendo" || type == "diminuendo") {
5454+
if (spannerExists(starts, number, ElementType::HAIRPIN)) {
5455+
m_logger->logError(String(u"hairpin with number %1 already started").arg(number), &m_e);
5456+
m_e.skipCurrentElement();
5457+
return;
5458+
}
54115459
Hairpin* h = spdesc.isStopped ? toHairpin(spdesc.sp) : Factory::createHairpin(m_score->dummy()->segment());
54125460
h->setHairpinType(type == "crescendo"
54135461
? HairpinType::CRESC_HAIRPIN : HairpinType::DIM_HAIRPIN);
@@ -5428,6 +5476,11 @@ void MusicXmlParserDirection::wedge(const String& type, const int number,
54285476
}
54295477
starts.push_back(MusicXmlSpannerDesc(h, ElementType::HAIRPIN, number));
54305478
} else if (type == "stop") {
5479+
if (spannerExists(stops, number, ElementType::HAIRPIN)) {
5480+
m_logger->logError(String(u"hairpin with number %1 already stopped").arg(number), &m_e);
5481+
m_e.skipCurrentElement();
5482+
return;
5483+
}
54315484
Hairpin* h = spdesc.isStarted ? toHairpin(spdesc.sp) : Factory::createHairpin(m_score->dummy()->segment());
54325485
if (niente == "yes") {
54335486
h->setHairpinCircledTip(true);

0 commit comments

Comments
 (0)