eb836b5068
last part only needed for 2.2, but shouldn't harm in master, we're using double braces on other places too when initializing a std::array
178 lines
6.2 KiB
C++
178 lines
6.2 KiB
C++
//=============================================================================
|
|
// MuseScore
|
|
// Music Composition & Notation
|
|
//
|
|
// Copyright (C) 2018 Werner Schweer and others
|
|
//
|
|
// This program is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License version 2
|
|
// as published by the Free Software Foundation and appearing in
|
|
// the file LICENCE.GPL
|
|
//=============================================================================
|
|
|
|
#include "importmxmllogger.h"
|
|
#include "importmxmlnotepitch.h"
|
|
#include "musicxmlsupport.h"
|
|
|
|
namespace Ms {
|
|
|
|
//---------------------------------------------------------
|
|
// accidental
|
|
//---------------------------------------------------------
|
|
|
|
/**
|
|
Parse the /score-partwise/part/measure/note/accidental node.
|
|
Return the result as an Accidental.
|
|
*/
|
|
|
|
// TODO: split in reading parameters versus creation
|
|
|
|
static Accidental* accidental(QXmlStreamReader& e, Score* score)
|
|
{
|
|
Q_ASSERT(e.isStartElement() && e.name() == "accidental");
|
|
|
|
bool cautionary = e.attributes().value("cautionary") == "yes";
|
|
bool editorial = e.attributes().value("editorial") == "yes";
|
|
bool parentheses = e.attributes().value("parentheses") == "yes";
|
|
|
|
const auto s = e.readElementText();
|
|
const auto type = mxmlString2accidentalType(s);
|
|
|
|
if (type != AccidentalType::NONE) {
|
|
auto a = new Accidental(score);
|
|
a->setAccidentalType(type);
|
|
if (editorial || cautionary || parentheses) {
|
|
a->setBracket(AccidentalBracket(cautionary || parentheses));
|
|
a->setRole(AccidentalRole::USER);
|
|
}
|
|
return a;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// displayStepOctave
|
|
//---------------------------------------------------------
|
|
|
|
/**
|
|
Handle <display-step> and <display-octave> for <rest> and <unpitched>
|
|
*/
|
|
|
|
void mxmlNotePitch::displayStepOctave(QXmlStreamReader& e)
|
|
{
|
|
Q_ASSERT(e.isStartElement()
|
|
&& (e.name() == "rest" || e.name() == "unpitched"));
|
|
|
|
while (e.readNextStartElement()) {
|
|
if (e.name() == "display-step") {
|
|
const auto step = e.readElementText();
|
|
int pos = QString("CDEFGAB").indexOf(step);
|
|
if (step.size() == 1 && pos >=0 && pos < 7)
|
|
_displayStep = pos;
|
|
else
|
|
//logError(QString("invalid step '%1'").arg(strStep));
|
|
qDebug("invalid step '%s'", qPrintable(step)); // TODO
|
|
}
|
|
else if (e.name() == "display-octave") {
|
|
const auto oct = e.readElementText();
|
|
bool ok;
|
|
_displayOctave = oct.toInt(&ok);
|
|
if (!ok || _displayOctave < 0 || _displayOctave > 9) {
|
|
//logError(QString("invalid octave '%1'").arg(strOct));
|
|
qDebug("invalid octave '%s'", qPrintable(oct)); // TODO
|
|
_displayOctave = -1;
|
|
}
|
|
}
|
|
else
|
|
e.skipCurrentElement(); // TODO log
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// pitch
|
|
//---------------------------------------------------------
|
|
|
|
/**
|
|
Parse the /score-partwise/part/measure/note/pitch node.
|
|
*/
|
|
|
|
void mxmlNotePitch::pitch(QXmlStreamReader& e)
|
|
{
|
|
Q_ASSERT(e.isStartElement() && e.name() == "pitch");
|
|
|
|
// defaults
|
|
_step = -1;
|
|
_alter = 0;
|
|
_octave = -1;
|
|
|
|
while (e.readNextStartElement()) {
|
|
if (e.name() == "alter") {
|
|
const auto alter = e.readElementText();
|
|
bool ok;
|
|
_alter = MxmlSupport::stringToInt(alter, &ok); // fractions not supported by mscore
|
|
if (!ok || _alter < -2 || _alter > 2) {
|
|
_logger->logError(QString("invalid alter '%1'").arg(alter), &e);
|
|
bool ok2;
|
|
const auto altervalue = alter.toDouble(&ok2);
|
|
if (ok2 && (qAbs(altervalue) < 2.0) && (_accType == AccidentalType::NONE)) {
|
|
// try to see if a microtonal accidental is needed
|
|
_accType = microtonalGuess(altervalue);
|
|
}
|
|
_alter = 0;
|
|
}
|
|
}
|
|
else if (e.name() == "octave") {
|
|
const auto oct = e.readElementText();
|
|
bool ok;
|
|
_octave = oct.toInt(&ok);
|
|
if (!ok || _octave < 0 || _octave > 9) {
|
|
_logger->logError(QString("invalid octave '%1'").arg(oct), &e);
|
|
_octave = -1;
|
|
}
|
|
}
|
|
else if (e.name() == "step") {
|
|
const auto step = e.readElementText();
|
|
const auto pos = QString("CDEFGAB").indexOf(step);
|
|
if (step.size() == 1 && pos >=0 && pos < 7)
|
|
_step = pos;
|
|
else
|
|
_logger->logError(QString("invalid step '%1'").arg(step), &e);
|
|
}
|
|
else {
|
|
; // TODO skipLogCurrElem();
|
|
}
|
|
}
|
|
//qDebug("pitch step %d alter %d oct %d accid %hhd", step, alter, oct, accid);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// readProperties
|
|
//---------------------------------------------------------
|
|
|
|
/**
|
|
Handle selected child elements of the /score-partwise/part/measure/note node.
|
|
Return true if handled.
|
|
*/
|
|
|
|
bool mxmlNotePitch::readProperties(QXmlStreamReader& e, Score* score)
|
|
{
|
|
const QStringRef& tag(e.name());
|
|
|
|
if (tag == "accidental") {
|
|
_acc = accidental(e, score);
|
|
return true;
|
|
}
|
|
else if (tag == "unpitched") {
|
|
_unpitched = true;
|
|
displayStepOctave(e);
|
|
return true;
|
|
}
|
|
else if (tag == "pitch") {
|
|
pitch(e);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
}
|