Merge pull request #5077 from lvinken/280607-musicxml-top-text-export
fix #280607 - Musicxml export - top texts don't export
This commit is contained in:
commit
e8670cc7eb
3 changed files with 378 additions and 35 deletions
|
@ -4227,6 +4227,29 @@ static const FretDiagram* findFretDiagram(int strack, int etrack, int track, Seg
|
|||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// commonAnnotations
|
||||
//---------------------------------------------------------
|
||||
|
||||
static bool commonAnnotations(ExportMusicXml* exp, const Element* e, int sstaff)
|
||||
{
|
||||
if (e->isSymbol())
|
||||
exp->symbol(toSymbol(e), sstaff);
|
||||
else if (e->isTempoText())
|
||||
exp->tempoText(toTempoText(e), sstaff);
|
||||
else if (e->isStaffText() || e->isSystemText() || e->isText() || e->isInstrumentChange())
|
||||
//exp->words(toText(e), sstaff); TODO
|
||||
exp->words(static_cast<const Text*>(e), sstaff);
|
||||
else if (e->isDynamic())
|
||||
exp->dynamic(toDynamic(e), sstaff);
|
||||
else if (e->isRehearsalMark())
|
||||
exp->rehearsal(toRehearsalMark(e), sstaff);
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// annotations
|
||||
//---------------------------------------------------------
|
||||
|
@ -4235,7 +4258,7 @@ static const FretDiagram* findFretDiagram(int strack, int etrack, int track, Seg
|
|||
// in MusicXML they are combined in the harmony element. This means they have to be matched.
|
||||
// TODO: replace/repair current algorithm (which can only handle one FRET_DIAGRAM and one HARMONY)
|
||||
|
||||
static void annotations(ExportMusicXml* exp, XmlWriter&, int strack, int etrack, int track, int sstaff, Segment* seg)
|
||||
static void annotations(ExportMusicXml* exp, int strack, int etrack, int track, int sstaff, Segment* seg)
|
||||
{
|
||||
if (seg->segmentType() == SegmentType::ChordRest) {
|
||||
|
||||
|
@ -4250,40 +4273,20 @@ static void annotations(ExportMusicXml* exp, XmlWriter&, int strack, int etrack,
|
|||
wtrack = findTrackForAnnotations(e->track(), seg);
|
||||
|
||||
if (track == wtrack) {
|
||||
switch (e->type()) {
|
||||
case ElementType::SYMBOL:
|
||||
exp->symbol(static_cast<const Symbol*>(e), sstaff);
|
||||
break;
|
||||
case ElementType::TEMPO_TEXT:
|
||||
exp->tempoText(static_cast<const TempoText*>(e), sstaff);
|
||||
break;
|
||||
case ElementType::STAFF_TEXT:
|
||||
case ElementType::TEXT:
|
||||
case ElementType::INSTRUMENT_CHANGE:
|
||||
exp->words(static_cast<const Text*>(e), sstaff);
|
||||
break;
|
||||
case ElementType::DYNAMIC:
|
||||
exp->dynamic(static_cast<const Dynamic*>(e), sstaff);
|
||||
break;
|
||||
case ElementType::HARMONY:
|
||||
// qDebug("annotations seg %p found harmony %p", seg, e);
|
||||
exp->harmony(static_cast<const Harmony*>(e), fd /*, sstaff */);
|
||||
fd = 0; // make sure to write only once ...
|
||||
break;
|
||||
case ElementType::REHEARSAL_MARK:
|
||||
exp->rehearsal(static_cast<const RehearsalMark*>(e), sstaff);
|
||||
break;
|
||||
case ElementType::FIGURED_BASS: // handled separately by figuredBass()
|
||||
case ElementType::FRET_DIAGRAM: // handled using findFretDiagram()
|
||||
case ElementType::JUMP: // ignore
|
||||
break;
|
||||
default:
|
||||
qDebug("annotations: direction type %s at tick %d not implemented",
|
||||
Element::name(e->type()), seg->tick().ticks());
|
||||
break;
|
||||
if (commonAnnotations(exp, e, sstaff))
|
||||
; // already handled
|
||||
else if (e->isHarmony()) {
|
||||
// qDebug("annotations seg %p found harmony %p", seg, e);
|
||||
exp->harmony(toHarmony(e), fd);
|
||||
fd = nullptr; // make sure to write only once ...
|
||||
}
|
||||
else if (e->isFiguredBass() || e->isFretDiagram() || e->isJump())
|
||||
; // handled separately by figuredBass(), findFretDiagram() or ignored
|
||||
else
|
||||
qDebug("annotations: direction type %s at tick %d not implemented",
|
||||
Element::name(e->type()), seg->tick().ticks());
|
||||
}
|
||||
} // for
|
||||
}
|
||||
if (fd)
|
||||
// found fd but no harmony, cannot write (MusicXML would be invalid)
|
||||
qDebug("annotations seg %p found fretboard diagram %p w/o harmony: cannot write",
|
||||
|
@ -5260,6 +5263,32 @@ static void writeInstrumentDetails(XmlWriter& xml, const Part* part)
|
|||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// annotationsWithoutNote
|
||||
//---------------------------------------------------------
|
||||
|
||||
/**
|
||||
Write the annotations that could not be attached to notes.
|
||||
*/
|
||||
|
||||
static void annotationsWithoutNote(ExportMusicXml* exp, const int strack, const int staves, const Measure* const measure)
|
||||
{
|
||||
for (auto segment = measure->first(); segment; segment = segment->next()) {
|
||||
if (segment->segmentType() == SegmentType::ChordRest) {
|
||||
for (const auto element : segment->annotations()) {
|
||||
if (!element->isFiguredBass() && !element->isHarmony()) { // handled elsewhere
|
||||
const auto wtrack = findTrackForAnnotations(element->track(), segment); // track to write annotation
|
||||
if (strack <= element->track() && element->track() < (strack + VOICES * staves) && wtrack < 0) {
|
||||
exp->moveToTick(element->tick());
|
||||
commonAnnotations(exp, element, staves > 1 ? 1 : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// write
|
||||
//---------------------------------------------------------
|
||||
|
@ -5336,7 +5365,6 @@ void ExportMusicXml::write(QIODevice* dev)
|
|||
continue;
|
||||
Measure* m = static_cast<Measure*>(mb);
|
||||
|
||||
|
||||
// pickup and other irregular measures need special care
|
||||
QString measureTag = "measure number=";
|
||||
if ((irregularMeasureNo + measureNo) == 2 && m->irregular()) {
|
||||
|
@ -5430,7 +5458,7 @@ void ExportMusicXml::write(QIODevice* dev)
|
|||
// handle annotations and spanners (directions attached to this note or rest)
|
||||
if (el->isChordRest()) {
|
||||
_attr.doAttr(_xml, false);
|
||||
annotations(this, _xml, strack, etrack, st, sstaff, seg);
|
||||
annotations(this, strack, etrack, st, sstaff, seg);
|
||||
// look for more harmony
|
||||
for (Segment* seg1 = seg->next(); seg1; seg1 = seg1->next()) {
|
||||
if (seg1->isChordRestType()) {
|
||||
|
@ -5459,6 +5487,10 @@ void ExportMusicXml::write(QIODevice* dev)
|
|||
} // for (Segment* seg = ...
|
||||
_attr.stop(_xml);
|
||||
} // for (int st = ...
|
||||
|
||||
// write the annotations that could not be attached to notes
|
||||
annotationsWithoutNote(this, strack, staves, m);
|
||||
|
||||
// move to end of measure (in case of incomplete last voice)
|
||||
#ifdef DEBUG_TICK
|
||||
qDebug("end of measure");
|
||||
|
|
310
mtest/musicxml/io/testDirections2.xml
Normal file
310
mtest/musicxml/io/testDirections2.xml
Normal file
|
@ -0,0 +1,310 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 3.1 Partwise//EN" "http://www.musicxml.org/dtds/partwise.dtd">
|
||||
<score-partwise version="3.1">
|
||||
<work>
|
||||
<work-number>MuseScore testfile</work-number>
|
||||
<work-title>Directions 2</work-title>
|
||||
</work>
|
||||
<identification>
|
||||
<creator type="composer">Leon Vinken</creator>
|
||||
<encoding>
|
||||
<software>MuseScore 0.7.0</software>
|
||||
<encoding-date>2007-09-10</encoding-date>
|
||||
<supports element="accidental" type="yes"/>
|
||||
<supports element="beam" type="yes"/>
|
||||
<supports element="print" attribute="new-page" type="no"/>
|
||||
<supports element="print" attribute="new-system" type="no"/>
|
||||
<supports element="stem" type="yes"/>
|
||||
</encoding>
|
||||
</identification>
|
||||
<part-list>
|
||||
<score-part id="P1">
|
||||
<part-name>Flute</part-name>
|
||||
<part-abbreviation>Fl.</part-abbreviation>
|
||||
<score-instrument id="P1-I1">
|
||||
<instrument-name>Flute</instrument-name>
|
||||
</score-instrument>
|
||||
<midi-device id="P1-I1" port="1"></midi-device>
|
||||
<midi-instrument id="P1-I1">
|
||||
<midi-channel>1</midi-channel>
|
||||
<midi-program>74</midi-program>
|
||||
<volume>78.7402</volume>
|
||||
<pan>0</pan>
|
||||
</midi-instrument>
|
||||
</score-part>
|
||||
<score-part id="P2">
|
||||
<part-name>Piano</part-name>
|
||||
<part-abbreviation>Pno.</part-abbreviation>
|
||||
<score-instrument id="P2-I1">
|
||||
<instrument-name>Piano</instrument-name>
|
||||
</score-instrument>
|
||||
<midi-device id="P2-I1" port="1"></midi-device>
|
||||
<midi-instrument id="P2-I1">
|
||||
<midi-channel>2</midi-channel>
|
||||
<midi-program>1</midi-program>
|
||||
<volume>78.7402</volume>
|
||||
<pan>0</pan>
|
||||
</midi-instrument>
|
||||
</score-part>
|
||||
<score-part id="P3">
|
||||
<part-name>Contrabass</part-name>
|
||||
<part-abbreviation>Cb.</part-abbreviation>
|
||||
<score-instrument id="P3-I1">
|
||||
<instrument-name>Contrabass</instrument-name>
|
||||
</score-instrument>
|
||||
<midi-device id="P3-I1" port="1"></midi-device>
|
||||
<midi-instrument id="P3-I1">
|
||||
<midi-channel>3</midi-channel>
|
||||
<midi-program>44</midi-program>
|
||||
<volume>78.7402</volume>
|
||||
<pan>0</pan>
|
||||
</midi-instrument>
|
||||
</score-part>
|
||||
</part-list>
|
||||
<part id="P1">
|
||||
<measure number="1">
|
||||
<attributes>
|
||||
<divisions>1</divisions>
|
||||
<key>
|
||||
<fifths>0</fifths>
|
||||
</key>
|
||||
<time>
|
||||
<beats>4</beats>
|
||||
<beat-type>4</beat-type>
|
||||
</time>
|
||||
<clef>
|
||||
<sign>G</sign>
|
||||
<line>2</line>
|
||||
</clef>
|
||||
</attributes>
|
||||
<direction placement="above">
|
||||
<direction-type>
|
||||
<words font-weight="bold" font-size="12">Lento</words>
|
||||
</direction-type>
|
||||
<sound tempo="52.5"/>
|
||||
</direction>
|
||||
<note>
|
||||
<rest/>
|
||||
<duration>4</duration>
|
||||
<voice>1</voice>
|
||||
</note>
|
||||
</measure>
|
||||
<measure number="2">
|
||||
<note>
|
||||
<rest/>
|
||||
<duration>4</duration>
|
||||
<voice>1</voice>
|
||||
</note>
|
||||
<backup>
|
||||
<duration>3</duration>
|
||||
</backup>
|
||||
<direction placement="above">
|
||||
<direction-type>
|
||||
<words font-weight="bold" font-size="12">Andante</words>
|
||||
</direction-type>
|
||||
<sound tempo="91.9998"/>
|
||||
</direction>
|
||||
<forward>
|
||||
<duration>3</duration>
|
||||
</forward>
|
||||
</measure>
|
||||
<measure number="3">
|
||||
<note>
|
||||
<rest/>
|
||||
<duration>4</duration>
|
||||
<voice>1</voice>
|
||||
</note>
|
||||
<backup>
|
||||
<duration>2</duration>
|
||||
</backup>
|
||||
<direction placement="above">
|
||||
<direction-type>
|
||||
<rehearsal font-weight="bold" font-size="14">A</rehearsal>
|
||||
</direction-type>
|
||||
</direction>
|
||||
<forward>
|
||||
<duration>2</duration>
|
||||
</forward>
|
||||
<barline location="right">
|
||||
<bar-style>light-heavy</bar-style>
|
||||
</barline>
|
||||
</measure>
|
||||
</part>
|
||||
<part id="P2">
|
||||
<measure number="1">
|
||||
<attributes>
|
||||
<divisions>1</divisions>
|
||||
<key>
|
||||
<fifths>0</fifths>
|
||||
</key>
|
||||
<time>
|
||||
<beats>4</beats>
|
||||
<beat-type>4</beat-type>
|
||||
</time>
|
||||
<staves>2</staves>
|
||||
<clef number="1">
|
||||
<sign>G</sign>
|
||||
<line>2</line>
|
||||
</clef>
|
||||
<clef number="2">
|
||||
<sign>F</sign>
|
||||
<line>4</line>
|
||||
</clef>
|
||||
</attributes>
|
||||
<note>
|
||||
<rest/>
|
||||
<duration>4</duration>
|
||||
<voice>1</voice>
|
||||
<staff>1</staff>
|
||||
</note>
|
||||
<backup>
|
||||
<duration>4</duration>
|
||||
</backup>
|
||||
<note>
|
||||
<rest/>
|
||||
<duration>4</duration>
|
||||
<voice>5</voice>
|
||||
<staff>2</staff>
|
||||
</note>
|
||||
</measure>
|
||||
<measure number="2">
|
||||
<note>
|
||||
<rest/>
|
||||
<duration>4</duration>
|
||||
<voice>1</voice>
|
||||
<staff>1</staff>
|
||||
</note>
|
||||
<backup>
|
||||
<duration>4</duration>
|
||||
</backup>
|
||||
<note>
|
||||
<rest/>
|
||||
<duration>4</duration>
|
||||
<voice>5</voice>
|
||||
<staff>2</staff>
|
||||
</note>
|
||||
</measure>
|
||||
<measure number="3">
|
||||
<note>
|
||||
<rest/>
|
||||
<duration>4</duration>
|
||||
<voice>1</voice>
|
||||
<staff>1</staff>
|
||||
</note>
|
||||
<backup>
|
||||
<duration>4</duration>
|
||||
</backup>
|
||||
<note>
|
||||
<rest/>
|
||||
<duration>4</duration>
|
||||
<voice>5</voice>
|
||||
<staff>2</staff>
|
||||
</note>
|
||||
<barline location="right">
|
||||
<bar-style>light-heavy</bar-style>
|
||||
</barline>
|
||||
</measure>
|
||||
</part>
|
||||
<part id="P3">
|
||||
<measure number="1">
|
||||
<attributes>
|
||||
<divisions>1</divisions>
|
||||
<key>
|
||||
<fifths>0</fifths>
|
||||
</key>
|
||||
<time>
|
||||
<beats>4</beats>
|
||||
<beat-type>4</beat-type>
|
||||
</time>
|
||||
<clef>
|
||||
<sign>F</sign>
|
||||
<line>4</line>
|
||||
</clef>
|
||||
<transpose>
|
||||
<diatonic>0</diatonic>
|
||||
<chromatic>0</chromatic>
|
||||
<octave-change>-1</octave-change>
|
||||
</transpose>
|
||||
</attributes>
|
||||
<note>
|
||||
<rest/>
|
||||
<duration>1</duration>
|
||||
<voice>1</voice>
|
||||
<type>quarter</type>
|
||||
</note>
|
||||
<note>
|
||||
<rest/>
|
||||
<duration>1</duration>
|
||||
<voice>1</voice>
|
||||
<type>quarter</type>
|
||||
</note>
|
||||
<note>
|
||||
<rest/>
|
||||
<duration>1</duration>
|
||||
<voice>1</voice>
|
||||
<type>quarter</type>
|
||||
</note>
|
||||
<note>
|
||||
<rest/>
|
||||
<duration>1</duration>
|
||||
<voice>1</voice>
|
||||
<type>quarter</type>
|
||||
</note>
|
||||
</measure>
|
||||
<measure number="2">
|
||||
<note>
|
||||
<rest/>
|
||||
<duration>1</duration>
|
||||
<voice>1</voice>
|
||||
<type>quarter</type>
|
||||
</note>
|
||||
<note>
|
||||
<rest/>
|
||||
<duration>1</duration>
|
||||
<voice>1</voice>
|
||||
<type>quarter</type>
|
||||
</note>
|
||||
<note>
|
||||
<rest/>
|
||||
<duration>1</duration>
|
||||
<voice>1</voice>
|
||||
<type>quarter</type>
|
||||
</note>
|
||||
<note>
|
||||
<rest/>
|
||||
<duration>1</duration>
|
||||
<voice>1</voice>
|
||||
<type>quarter</type>
|
||||
</note>
|
||||
</measure>
|
||||
<measure number="3">
|
||||
<note>
|
||||
<rest/>
|
||||
<duration>1</duration>
|
||||
<voice>1</voice>
|
||||
<type>quarter</type>
|
||||
</note>
|
||||
<note>
|
||||
<rest/>
|
||||
<duration>1</duration>
|
||||
<voice>1</voice>
|
||||
<type>quarter</type>
|
||||
</note>
|
||||
<note>
|
||||
<rest/>
|
||||
<duration>1</duration>
|
||||
<voice>1</voice>
|
||||
<type>quarter</type>
|
||||
</note>
|
||||
<note>
|
||||
<rest/>
|
||||
<duration>1</duration>
|
||||
<voice>1</voice>
|
||||
<type>quarter</type>
|
||||
</note>
|
||||
<barline location="right">
|
||||
<bar-style>light-heavy</bar-style>
|
||||
</barline>
|
||||
</measure>
|
||||
</part>
|
||||
</score-partwise>
|
|
@ -69,6 +69,7 @@ private slots:
|
|||
void dcalCoda() { mxmlIoTest("testDCalCoda"); }
|
||||
void dcalFine() { mxmlIoTest("testDCalFine"); }
|
||||
void directions1() { mxmlIoTest("testDirections1"); }
|
||||
void directions2() { mxmlIoTest("testDirections2"); }
|
||||
void divisionsDefinedTooLate1() { mxmlIoTestRef("testDivsDefinedTooLate1"); }
|
||||
void divisionsDefinedTooLate2() { mxmlIoTestRef("testDivsDefinedTooLate2"); }
|
||||
void doubleClefError() { mxmlIoTestRef("testDoubleClefError"); }
|
||||
|
|
Loading…
Reference in a new issue