Skip to content

Commit

Permalink
Merge pull request #3536 from lvinken/269948-staff-2-single-staff-part
Browse files Browse the repository at this point in the history
269948 staff 2 single staff part
  • Loading branch information
lasconic committed Mar 13, 2018
2 parents ce6b003 + f18f6b9 commit c08fe0d
Show file tree
Hide file tree
Showing 9 changed files with 343 additions and 105 deletions.
38 changes: 25 additions & 13 deletions mscore/importmxmlpass1.cpp
Expand Up @@ -1854,6 +1854,22 @@ void MusicXMLParserPass1::midiInstrument(const QString& partId)
Q_ASSERT(_e.isEndElement() && _e.name() == "midi-instrument");
}

//---------------------------------------------------------
// setNumberOfStavesForPart
//---------------------------------------------------------

/**
Set number of staves for part \a partId to the max value
of the current value \a staves.
*/

static void setNumberOfStavesForPart(Part* const part, const int staves)
{
Q_ASSERT(part);
if (staves > part->nstaves())
part->setStaves(staves);
}

//---------------------------------------------------------
// part
//---------------------------------------------------------
Expand Down Expand Up @@ -1890,6 +1906,8 @@ void MusicXMLParserPass1::part()
skipLogCurrElem();
}

// Bug fix for Cubase 6.5.5..9.5.10 which generate <staff>2</staff> in a single staff part
setNumberOfStavesForPart(_partMap.value(id), _parts[id].maxStaff());
// allocate MuseScore staff to MusicXML voices
allocateStaves(_parts[id].voicelist);
// allocate MuseScore voice to MusicXML voices
Expand Down Expand Up @@ -2273,8 +2291,7 @@ void MusicXMLParserPass1::divisions()
//---------------------------------------------------------

/**
Set number of staves for part \a partId to the max value of the current value
and the value in the <staves> element.
Parse the /score-partwise/part/measure/attributes/staves node.
*/

void MusicXMLParserPass1::staves(const QString& partId)
Expand All @@ -2288,10 +2305,7 @@ void MusicXMLParserPass1::staves(const QString& partId)
return;
}

Part* part = _partMap.value(partId);
Q_ASSERT(part);
if (staves > part->nstaves())
part->setStaves(staves);
setNumberOfStavesForPart(_partMap.value(partId), staves);
}

//---------------------------------------------------------
Expand Down Expand Up @@ -2548,16 +2562,14 @@ void MusicXMLParserPass1::note(const QString& partId,
rest();
}
else if (_e.name() == "staff") {
QString strStaff = _e.readElementText();
staff = strStaff.toInt();
// Bug fix for Cubase 6.5.5 which generates <staff>2</staff> in a single staff part
// Same fix is required in pass 1 and pass 2
auto ok = false;
auto strStaff = _e.readElementText();
staff = strStaff.toInt(&ok);
_parts[partId].setMaxStaff(staff);
Part* part = _partMap.value(partId);
Q_ASSERT(part);
if (staff <= 0 || staff > part->nstaves()) {
if (!ok || staff <= 0 || staff > part->nstaves())
_logger->logError(QString("illegal staff '%1'").arg(strStaff), &_e);
staff = 1;
}
}
else if (_e.name() == "stem")
_e.skipCurrentElement(); // skip but don't log
Expand Down
173 changes: 88 additions & 85 deletions mscore/importmxmlpass2.cpp
Expand Up @@ -4200,14 +4200,11 @@ Note* MusicXMLParserPass2::note(const QString& partId,
mnp.displayStepOctave(_e);
}
else if (_e.name() == "staff") {
QString strStaff = _e.readElementText();
staff = strStaff.toInt();
// Bug fix for Cubase 6.5.5 which generates <staff>2</staff> in a single staff part
// Same fix is required in pass 1 and pass 2
Part* part = _pass1.getPart(partId);
Q_ASSERT(part);
if (staff <= 0 || staff > part->nstaves()) {
_logger->logError(QString("illegal staff '%1'").arg(strStaff), &_e);
auto ok = false;
auto strStaff = _e.readElementText();
staff = strStaff.toInt(&ok);
if (!ok) {
// error already reported in pass 1
staff = 1;
}
}
Expand Down Expand Up @@ -5776,88 +5773,94 @@ void MusicXMLParserPass2::notations(Note* note, ChordRest* cr, const int tick,
{
Q_ASSERT(_e.isStartElement() && _e.name() == "notations");

lastGraceAFter = false; // ensure default

Measure* measure = cr->measure();
int ticks = cr->duration().ticks();
int track = cr->track();

QString wavyLineType;
int wavyLineNo = 0;
QString arpeggioType;
SymId breath = SymId::noSym;
int tremoloNr = 0;
QString tremoloType;
QString placement;
QStringList dynamicslist;
// qreal rx = 0.0;
// qreal ry = 0.0;
// qreal yoffset = 0.0; // actually this is default-y
// qreal xoffset = 0.0; // not used
// bool hasYoffset = false;
QString chordLineType;

while (_e.readNextStartElement()) {
if (_e.name() == "slur") {
slur(cr, tick, track, lastGraceAFter);
}
else if (_e.name() == "tied") {
tied(note, track);
}
else if (_e.name() == "tuplet") {
tuplet(tupletDesc);
}
else if (_e.name() == "dynamics") {
placement = _e.attributes().value("placement").toString();
if (preferences.getBool(PREF_IMPORT_MUSICXML_IMPORTLAYOUT)) {
// ry = ee.attribute(QString("relative-y"), "0").toDouble() * -.1;
// rx = ee.attribute(QString("relative-x"), "0").toDouble() * .1;
// yoffset = _e.attributes().value("default-y").toDouble(&hasYoffset) * -0.1;
// xoffset = ee.attribute("default-x", "0.0").toDouble() * 0.1;
if (cr) {
lastGraceAFter = false; // ensure default

Measure* measure = cr->measure();
int ticks = cr->duration().ticks();
int track = cr->track();

QString wavyLineType;
int wavyLineNo = 0;
QString arpeggioType;
SymId breath = SymId::noSym;
int tremoloNr = 0;
QString tremoloType;
QString placement;
QStringList dynamicslist;
// qreal rx = 0.0;
// qreal ry = 0.0;
// qreal yoffset = 0.0; // actually this is default-y
// qreal xoffset = 0.0; // not used
// bool hasYoffset = false;
QString chordLineType;

while (_e.readNextStartElement()) {
if (_e.name() == "slur") {
slur(cr, tick, track, lastGraceAFter);
}
dynamics(placement, dynamicslist);
}
else if (_e.name() == "articulations") {
articulations(cr, breath, chordLineType);
}
else if (_e.name() == "fermata")
fermata(cr);
else if (_e.name() == "ornaments") {
ornaments(cr, wavyLineType, wavyLineNo, tremoloType, tremoloNr, lastGraceAFter);
}
else if (_e.name() == "technical") {
technical(note, cr);
}
else if (_e.name() == "arpeggiate") {
arpeggioType = _e.attributes().value("direction").toString();
if (arpeggioType == "") arpeggioType = "none";
_e.readNext();
}
else if (_e.name() == "non-arpeggiate") {
arpeggioType = "non-arpeggiate";
_e.readNext();
}
else if (_e.name() == "glissando" || _e.name() == "slide") {
glissando(note, tick, ticks, track);
else if (_e.name() == "tied") {
tied(note, track);
}
else if (_e.name() == "tuplet") {
tuplet(tupletDesc);
}
else if (_e.name() == "dynamics") {
placement = _e.attributes().value("placement").toString();
if (preferences.getBool(PREF_IMPORT_MUSICXML_IMPORTLAYOUT)) {
// ry = ee.attribute(QString("relative-y"), "0").toDouble() * -.1;
// rx = ee.attribute(QString("relative-x"), "0").toDouble() * .1;
// yoffset = _e.attributes().value("default-y").toDouble(&hasYoffset) * -0.1;
// xoffset = ee.attribute("default-x", "0.0").toDouble() * 0.1;
}
dynamics(placement, dynamicslist);
}
else if (_e.name() == "articulations") {
articulations(cr, breath, chordLineType);
}
else if (_e.name() == "fermata")
fermata(cr);
else if (_e.name() == "ornaments") {
ornaments(cr, wavyLineType, wavyLineNo, tremoloType, tremoloNr, lastGraceAFter);
}
else if (_e.name() == "technical") {
technical(note, cr);
}
else if (_e.name() == "arpeggiate") {
arpeggioType = _e.attributes().value("direction").toString();
if (arpeggioType == "") arpeggioType = "none";
_e.readNext();
}
else if (_e.name() == "non-arpeggiate") {
arpeggioType = "non-arpeggiate";
_e.readNext();
}
else if (_e.name() == "glissando" || _e.name() == "slide") {
glissando(note, tick, ticks, track);
}
else
skipLogCurrElem();
}
else
skipLogCurrElem();
}

addArpeggio(cr, arpeggioType, _logger, &_e);
addWavyLine(cr, tick, wavyLineNo, wavyLineType, _spanners, _trills, _logger, &_e);
addBreath(cr, tick, breath);
addTremolo(cr, tremoloNr, tremoloType, ticks, _tremStart, _logger, &_e);
addChordLine(note, chordLineType, _logger, &_e);
addArpeggio(cr, arpeggioType, _logger, &_e);
addWavyLine(cr, tick, wavyLineNo, wavyLineType, _spanners, _trills, _logger, &_e);
addBreath(cr, tick, breath);
addTremolo(cr, tremoloNr, tremoloType, ticks, _tremStart, _logger, &_e);
addChordLine(note, chordLineType, _logger, &_e);

// more than one dynamic ???
// LVIFIX: check import/export of <other-dynamics>unknown_text</...>
// TODO remove duplicate code (see MusicXml::direction)
for (QStringList::Iterator it = dynamicslist.begin(); it != dynamicslist.end(); ++it ) {
Dynamic* dyn = new Dynamic(_score);
dyn->setDynamicType(*it);
// more than one dynamic ???
// LVIFIX: check import/export of <other-dynamics>unknown_text</...>
// TODO remove duplicate code (see MusicXml::direction)
for (QStringList::Iterator it = dynamicslist.begin(); it != dynamicslist.end(); ++it ) {
Dynamic* dyn = new Dynamic(_score);
dyn->setDynamicType(*it);
//TODO:ws if (hasYoffset) dyn->textStyle().setYoff(yoffset);
addElemOffset(dyn, track, placement, measure, tick);
addElemOffset(dyn, track, placement, measure, tick);
}
}
else {
_logger->logDebugInfo("no note to attach to, skipping notations", &_e);
_e.skipCurrentElement();
}

Q_ASSERT(_e.isEndElement() && _e.name() == "notations");
Expand Down
11 changes: 8 additions & 3 deletions mscore/importxmlfirstpass.cpp
Expand Up @@ -29,6 +29,12 @@ void MusicXmlPart::addMeasureNumberAndDuration(QString measureNumber, Fraction m
measureDurations.append(measureDuration);
}

void MusicXmlPart::setMaxStaff(const int staff)
{
if (staff > _maxStaff)
_maxStaff = staff;
}

Fraction MusicXmlPart::measureDuration(int i) const
{
if (i >= 0 && i < measureDurations.size())
Expand All @@ -38,9 +44,8 @@ Fraction MusicXmlPart::measureDuration(int i) const

QString MusicXmlPart::toString() const
{
QString res;
res = QString("part id '%1' name '%2' print %3 abbr '%4' print %5\n")
.arg(id).arg(name).arg(printName).arg(abbr).arg(printAbbr);
auto res = QString("part id '%1' name '%2' print %3 abbr '%4' print %5 maxStaff %6\n")
.arg(id).arg(name).arg(printName).arg(abbr).arg(printAbbr).arg(_maxStaff);

for (VoiceList::const_iterator i = voicelist.constBegin(); i != voicelist.constEnd(); ++i) {
res += QString("voice %1 map staff data %2\n")
Expand Down
3 changes: 3 additions & 0 deletions mscore/importxmlfirstpass.h
Expand Up @@ -68,6 +68,8 @@ class MusicXmlPart {
void setPrintAbbr(bool b) { printAbbr = b; }
bool getPrintAbbr() const { return printAbbr; }
LyricNumberHandler& lyricNumberHandler() { return _lyricNumberHandler; }
void setMaxStaff(const int staff);
int maxStaff() const { return _maxStaff; }
private:
QString id;
QString name;
Expand All @@ -78,6 +80,7 @@ class MusicXmlPart {
QList<Fraction> measureDurations; // duration in fraction for every measure
QVector<MusicXmlOctaveShiftList> octaveShifts; // octave shift list for every staff
LyricNumberHandler _lyricNumberHandler;
int _maxStaff = 0; // maximum staff value found (1 based), 0 = none
};

} // namespace Ms
Expand Down
Expand Up @@ -19,7 +19,7 @@
Cubase 6.5.5 exports multi-staff parts as two separate parts, but leaves
number=... in the clef and still refers to staff 2 in the second part.
This results in incorrect staff numbers for in the second part.
MuseScore will overrule the staff and assume staff 1 was meant.
MuseScore will interpret the second part as a two staff part.
</miscellaneous-field>
</miscellaneous>
</identification>
Expand Down
Expand Up @@ -86,19 +86,34 @@
<beats>4</beats>
<beat-type>4</beat-type>
</time>
<clef>
<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 print-object="no">
<rest/>
<duration>4</duration>
<voice>1</voice>
<staff>1</staff>
</note>
<backup>
<duration>4</duration>
</backup>
<note>
<pitch>
<step>F</step>
<octave>3</octave>
</pitch>
<duration>4</duration>
<voice>1</voice>
<voice>5</voice>
<type>whole</type>
<staff>2</staff>
</note>
<barline location="right">
<bar-style>light-heavy</bar-style>
Expand Down

0 comments on commit c08fe0d

Please sign in to comment.