MuseScore/mscore/importxmlfirstpass.cpp

237 lines
7.1 KiB
C++

//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2013 - 2015 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 "importxmlfirstpass.h"
namespace Ms {
// TODO: move somewhere else
MusicXmlPart::MusicXmlPart(QString id, QString name)
: id(id), name(name)
{
octaveShifts.resize(MAX_STAVES);
}
void MusicXmlPart::addMeasureNumberAndDuration(QString measureNumber, Fraction measureDuration)
{
measureNumbers.append(measureNumber);
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())
return measureDurations.at(i);
return Fraction(0, 0); // return invalid fraction
}
QString MusicXmlPart::toString() const
{
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")
.arg(i.key() + 1)
.arg(i.value().toString());
}
for (int i = 0; i < measureNumbers.size(); ++i) {
if (i > 0)
res += "\n";
res += QString("measure %1 duration %2 (%3)")
.arg(measureNumbers.at(i))
.arg(measureDurations.at(i).print())
.arg(measureDurations.at(i).ticks());
}
return res;
}
int MusicXmlPart::octaveShift(const int staff, const Fraction f) const
{
if (staff < 0 || MAX_STAVES <= staff)
return 0;
if (f < Fraction(0, 1))
return 0;
return octaveShifts[staff].octaveShift(f);
}
void MusicXmlPart::addOctaveShift(const int staff, const int shift, const Fraction f)
{
if (staff < 0 || MAX_STAVES <= staff)
return;
if (f < Fraction(0, 1))
return;
octaveShifts[staff].addOctaveShift(shift, f);
}
void MusicXmlPart::calcOctaveShifts()
{
for (int i = 0; i < MAX_STAVES; ++i) {
octaveShifts[i].calcOctaveShiftShifts();
}
}
//---------------------------------------------------------
// instrument
//---------------------------------------------------------
const QString MusicXmlInstrList::instrument(const Fraction f) const
{
if (empty())
return "";
auto i = upper_bound(f);
if (i == begin())
return "";
--i;
return i->second;
}
//---------------------------------------------------------
// setInstrument
//---------------------------------------------------------
void MusicXmlInstrList::setInstrument(const QString instr, const Fraction f)
{
// TODO determine how to handle multiple instrument changes at the same time
// current implementation keeps the first one
if (!insert({ f, instr }).second)
qDebug("instr '%s', tick %s (%d): element already exists",
qPrintable(instr), qPrintable(f.print()), f.ticks());
//(*this)[f] = instr;
}
int MusicXmlOctaveShiftList::octaveShift(const Fraction f) const
{
if (empty())
return 0;
auto i = upper_bound(f);
if (i == begin())
return 0;
--i;
return i->second;
}
void MusicXmlOctaveShiftList::addOctaveShift(const int shift, const Fraction f)
{
Q_ASSERT(Fraction(0, 1) <= f);
//qDebug("addOctaveShift(shift %d f %s)", shift, qPrintable(f.print()));
auto i = find(f);
if (i == end()) {
//qDebug("addOctaveShift: not found, inserting");
insert({ f, shift });
}
else {
//qDebug("addOctaveShift: found %d, adding", (*this)[f]);
(*this)[f] += shift;
//qDebug("addOctaveShift: res %d", (*this)[f]);
}
}
void MusicXmlOctaveShiftList::calcOctaveShiftShifts()
{
/*
for (auto i = cbegin(); i != cend(); ++i)
qDebug(" [%s : %d]", qPrintable((*i).first.print()), (*i).second);
*/
// to each MusicXmlOctaveShiftList entry, add the sum of all previous ones
int currentShift = 0;
for (auto i = begin(); i != end(); ++i) {
currentShift += i->second;
i->second = currentShift;
}
/*
for (auto i = cbegin(); i != cend(); ++i)
qDebug(" [%s : %d]", qPrintable((*i).first.print()), (*i).second);
*/
}
//---------------------------------------------------------
// LyricNumberHandler
// collect lyric numbering information and determine order
//
// MusicXML lyrics may contain name and number attributes,
// plus position information (typically default-y).
// Name and number are simply tokens with no specified usage.
// Default-y cannot easily be used to determine the lyrics
// line, as it tends to differ per system depending on the
// actual notes present.
//
// Simply collecting all possible lyric number attributes
// within a MusicXML part and assigning lyrics position
// based on alphabetically sorting works well for all
// common MusicXML files.
//---------------------------------------------------------
//---------------------------------------------------------
// addNumber
//---------------------------------------------------------
void LyricNumberHandler::addNumber(const QString number)
{
if (_numberToNo.find(number) == _numberToNo.end())
_numberToNo[number] = -1; // unassiged
}
//---------------------------------------------------------
// toString
//---------------------------------------------------------
QString LyricNumberHandler::toString() const
{
QString res;
for (const auto& p : _numberToNo) {
if (!res.isEmpty())
res += " ";
res += QString("%1:%2").arg(p.first).arg(p.second);
}
return res;
}
//---------------------------------------------------------
// getLyricNo
//---------------------------------------------------------
int LyricNumberHandler::getLyricNo(const QString& number) const
{
const auto it = _numberToNo.find(number);
return it == _numberToNo.end() ? 0 : it->second;
}
//---------------------------------------------------------
// determineLyricNos
//---------------------------------------------------------
void LyricNumberHandler::determineLyricNos()
{
int i = 0;
for (auto& p : _numberToNo) {
p.second = i;
++i;
}
}
}