Skip to content

Commit

Permalink
fix #25088 [MusicXML] Import/export of metronome marking not working
Browse files Browse the repository at this point in the history
  • Loading branch information
lvinken committed May 10, 2014
1 parent f0941cf commit fcc5643
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 68 deletions.
19 changes: 17 additions & 2 deletions libmscore/tempotext.cpp
Expand Up @@ -119,6 +119,23 @@ int TempoText::findTempoDuration(const QString& s, int& len, TDuration& dur)

return -1;
}

//---------------------------------------------------------
// duration2tempoTextString
// find the tempoText string representation for duration
//---------------------------------------------------------

QString TempoText::duration2tempoTextString(const TDuration dur)
{
for (unsigned i = 0; i < sizeof(tp)/sizeof(*tp); ++i) {
if (tp[i].d == dur) {
QString res = tp[i].pattern;
res.remove("\\s*");
return res;
}
}
return "";
}

//---------------------------------------------------------
// textChanged
Expand All @@ -137,8 +154,6 @@ void TempoText::textChanged()
QStringList sl = re.capturedTexts();
if (sl.size() == 2) {
qreal nt = qreal(sl[1].toInt()) * tp[i].f;
qDebug("TempoText::textChanged() text '%s' nt %g",
qPrintable(text()), nt);
if (nt != _tempo) {
_tempo = qreal(sl[1].toInt()) * tp[i].f;
if(segment())
Expand Down
1 change: 1 addition & 0 deletions libmscore/tempotext.h
Expand Up @@ -55,6 +55,7 @@ class TempoText : public Text {
virtual void layout();

static int findTempoDuration(const QString& s, int& len, TDuration& dur);
static QString duration2tempoTextString(const TDuration dur);

QVariant getProperty(P_ID propertyId) const override;
bool setProperty(P_ID propertyId, const QVariant&) override;
Expand Down
56 changes: 22 additions & 34 deletions mscore/exportxml.cpp
Expand Up @@ -2594,9 +2594,11 @@ static void directionTag(Xml& xml, Attributes& attr, Element const* const el = 0
tagname += " placement=\"below\"";
}
else {
qDebug("directionTag() staf ely=%g elh=%g bby=%g bbh=%g",
el->y(), el->height(),
bb.y(), bb.height());
/*
qDebug("directionTag() staf ely=%g elh=%g bby=%g bbh=%g",
el->y(), el->height(),
bb.y(), bb.height());
*/
if (el->y() + el->height() / 2 < /*bb.y() +*/ bb.height() / 2)
tagname += " placement=\"above\"";
else
Expand Down Expand Up @@ -2659,19 +2661,12 @@ static void partGroupStart(Xml& xml, int number, int bracket)
static bool findUnit(TDuration::DurationType val, QString& unit)
{
unit = "";
qDebug("findUnit('%d')", val);
switch (val) {
//case 0xdd5c: unit = "breve"; break;
//case 0xdd5d: unit = "whole"; break;
case TDuration::V_HALF: unit = "half"; break;
case TDuration::V_QUARTER: unit = "quarter"; break;
case TDuration::V_EIGHT: unit = "eighth"; break;
//case 0xdd61: unit = "16th"; break;
//case 0xdd62: unit = "32nd"; break;
//case 0xdd63: unit = "64th"; break;
default: qDebug("findUnit: unknown DurationType %d", val);
}
qDebug(" unit='%s'", qPrintable(unit));
return true;
}

Expand All @@ -2683,47 +2678,37 @@ static bool findMetronome(QString words,
QString& wordsRight // words right of metronome
)
{
/*
QString hexWords;
for (int i = 0; i < words.length(); ++i) {
QString n;
n.setNum(words.at(i).unicode(),16);
if (i != 0) hexWords += " ";
hexWords += "0x";
hexWords += n;
}
*/
qDebug("findMetronome('%s')", qPrintable(words));
//qDebug("findMetronome('%s')", qPrintable(words));
wordsLeft = "";
hasParen = false;
metroLeft = "";
metroRight = "";
wordsRight = "";
int indEq = words.indexOf('=');
if (indEq <= 0)
return false;
int len1 = 0;
TDuration dur;
int pos1 = TempoText::findTempoDuration(words, len1, dur);
// find first note, limiting search to the part left of the first '=',
// to prevent matching the second note in a "note1 = note2" metronome
int pos1 = TempoText::findTempoDuration(words.left(indEq), len1, dur);
QRegExp eq("\\s*=\\s*");
int pos2 = eq.indexIn(words, pos1 + len1);
if (pos1 != -1 && pos2 == pos1 + len1) {
int len2 = eq.matchedLength();
/**/
qDebug(" pos1=%d len1=%d pos12=%d len2=%d",
pos1, len1, pos2, len2
);
dur.print();
/**/
if (words.length() > pos2 + len2) {
QString s1 = words.mid(0, pos1); // string to the left of metronome
QString s2 = words.mid(pos1, len1); // first note
QString s3 = words.mid(pos2, len2); // equals sign
QString s4 = words.mid(pos2 + len2); // string to the right of equals sign
/**/
/*
qDebug("found note and equals: '%s'%s'%s'%s'",
qPrintable(s1),
qPrintable(s2),
qPrintable(s3),
qPrintable(s4)
);
*/
// now determine what is to the right of the equals sign
// must have either a (dotted) note or a number at start of s4
int len3 = 0;
Expand All @@ -2735,23 +2720,26 @@ static bool findMetronome(QString words,
if (pos3 == 0)
len3 = nmb.matchedLength();
}
else
if (pos3 == -1)
// neither found
return false;

QString s5 = s4.mid(0, len3); // number or second note
QString s6 = s4.mid(len3); // string to the right of metronome
/*
qDebug("found right part: '%s'%s'",
qPrintable(s5),
qPrintable(s6)
);
*/

/**/
// determine if metronome has parentheses
// left part of string must end with parenthesis plus optional spaces
// right part of string must have parenthesis (but not in first pos)
int lparen = s1.indexOf("(");
int rparen = s6.indexOf(")");
hasParen = (lparen == s1.length() - 1 && rparen == 0);
qDebug(" lparen=%d rparen=%d hasP=%d", lparen, rparen, hasParen);
//qDebug(" lparen=%d rparen=%d hasP=%d", lparen, rparen, hasParen);

if (hasParen)
wordsLeft = s1.mid(0, lparen);
Expand All @@ -2764,14 +2752,14 @@ static bool findMetronome(QString words,
else
metroRight = s5;

/**/
/*
qDebug(" '%s'%s'%s'%s'",
qPrintable(wordsLeft),
qPrintable(metroLeft),
qPrintable(metroRight),
qPrintable(wordsRight)
);
/**/
*/
return true;
}
}
Expand Down
57 changes: 25 additions & 32 deletions mscore/importxml.cpp
Expand Up @@ -2443,17 +2443,6 @@ static void addElem(Element* el, bool /*hasYoffset*/, int staff, int rstaff, Sco
// metronome
//---------------------------------------------------------

static QString ucs4ToString(int uc)
{
QString s;
if (uc & 0xffff0000) {
s = QChar(QChar::highSurrogate(uc));
s += QChar(QChar::lowSurrogate(uc));
}
else
s = QChar(uc);
return s;
}
/**
Read the MusicXML metronome element.
*/
Expand All @@ -2475,42 +2464,45 @@ static QString ucs4ToString(int uc)
static void metronome(QDomElement e, Text* t)
{
if (!t) return;
bool textAdded = false;
QString tempoText = t->text();
QString perMinute;

QString parenth = e.attribute("parentheses");
if (parenth == "yes")
tempoText += "(";
TDuration dur1;
TDuration dur2;
for (e = e.firstChildElement(); !e.isNull(); e = e.nextSiblingElement()) {
QString txt = e.text();
if (e.tagName() == "beat-unit") {
if (textAdded) tempoText += " = ";
if (txt == "breve") tempoText += ucs4ToString(0x1d15c);
else if (txt == "whole") tempoText += ucs4ToString(0x1d15d);
else if (txt == "half") tempoText += ucs4ToString(0x1d15e);
else if (txt == "quarter") tempoText += ucs4ToString(0x1d15f);
else if (txt == "eighth") tempoText += ucs4ToString(0x1d160);
else if (txt == "16th") tempoText += ucs4ToString(0x1d161);
else if (txt == "32nd") tempoText += ucs4ToString(0x1d162);
else if (txt == "64th") tempoText += ucs4ToString(0x1d163);
else tempoText += txt;
textAdded = true;
}
// set first dur that is still invalid
if (!dur1.isValid()) dur1.setType(txt);
else if (!dur2.isValid()) dur2.setType(txt);
}
else if (e.tagName() == "beat-unit-dot") {
tempoText += ucs4ToString(0x1d16d);
textAdded = true;
}
if (dur2.isValid()) dur2.setDots(1);
else if (dur1.isValid()) dur1.setDots(1);
}
else if (e.tagName() == "per-minute") {
if (textAdded) tempoText += " = ";
tempoText += txt;
textAdded = true;
}
perMinute = txt;
}
else
domError(e);
} // for (e = e.firstChildElement(); ...

if (dur1.isValid())
tempoText += TempoText::duration2tempoTextString(dur1);
if (dur2.isValid()) {
tempoText += " = ";
tempoText += TempoText::duration2tempoTextString(dur2);
}
else if (perMinute != "") {
tempoText += " = ";
tempoText += perMinute;
}
if (parenth == "yes")
tempoText += ")";
t->setPlainText(tempoText);
t->setText(tempoText);
}

//---------------------------------------------------------
Expand Down Expand Up @@ -2813,6 +2805,7 @@ void MusicXml::direction(Measure* measure, int staff, QDomElement e)
t = new TempoText(score);
double tpo = tempo.toDouble()/60.0;
((TempoText*) t)->setTempo(tpo);
((TempoText*) t)->setFollowText(true);
score->setTempo(tick, tpo);
}
else {
Expand Down

0 comments on commit fcc5643

Please sign in to comment.