2e1c495a74
Seems to happen only under on Linux Mint 17.1, gcc 5.1. Happens in libmscore/staff.cpp due to argument being a `class enum : signed short`. Also fix a bug with a wrong argument numbering in libmscore/groups.cpp and adjusting all Xml:tagE() calls (in mscore/exportxml.cpp) to use Qt argument style. See discussion in the developers' mailing list, http://dev-list.musescore.org/running-tests-on-mac-via-xcode-td7579199.html
257 lines
8.8 KiB
C++
257 lines
8.8 KiB
C++
//=============================================================================
|
|
// MuseScore
|
|
// Music Composition & Notation
|
|
//
|
|
// Copyright (C) 2013 Werner Schweer
|
|
//
|
|
// 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 "groups.h"
|
|
#include "durationtype.h"
|
|
#include "chordrest.h"
|
|
#include "staff.h"
|
|
#include "tuplet.h"
|
|
#include "xml.h"
|
|
|
|
namespace Ms {
|
|
|
|
//---------------------------------------------------------
|
|
// noteGroups
|
|
//---------------------------------------------------------
|
|
|
|
static std::vector<NoteGroup> noteGroups {
|
|
{ Fraction(2,2),
|
|
Groups( { { 4, 512}, { 8, 272}, {12, 512}, {16, 273}, {20, 512}, {24, 272}, {28, 512} })
|
|
},
|
|
{ Fraction(4,4),
|
|
Groups( { { 4, 512}, { 8, 272}, {12, 512}, {16, 273}, {20, 512}, {24, 272}, {28, 512} })
|
|
},
|
|
{ Fraction(3,4),
|
|
Groups( { { 4, 512}, { 8, 273}, { 12, 512}, {16, 273}, { 20, 512} })
|
|
},
|
|
{ Fraction(2,4),
|
|
Groups( { { 4, 512}, { 8, 273}, { 12, 512}, {0, 0} })
|
|
},
|
|
{ Fraction(6,8),
|
|
Groups( { { 4, 512}, { 8, 512}, { 12, 273}, { 16, 512}, { 20, 512}, {0, 0} })
|
|
},
|
|
{ Fraction(9,8),
|
|
Groups( { { 4, 512}, { 8, 512}, { 12, 273}, { 16, 512}, { 20, 512}, {24, 273}, { 18, 512}, { 32, 512} })
|
|
},
|
|
{ Fraction(12,8),
|
|
Groups( { { 4, 512}, { 8, 512}, { 12, 273}, { 16, 512}, { 20, 512}, {24, 273}, { 18, 512}, { 32, 512}, {36, 273}, { 40, 512}, { 44, 512} })
|
|
},
|
|
{ Fraction(6,4),
|
|
Groups( { { 4, 512}, { 8, 512}, { 12, 512}, { 16, 512}, { 20, 512}, { 24, 273}, { 28, 512}, { 32, 512}, { 36, 512}, { 40, 512}, { 44, 512} })
|
|
},
|
|
{ Fraction(3,2),
|
|
Groups( { { 4, 512}, { 8, 272}, { 12, 512}, { 16, 273}, { 20, 512}, { 24, 272}, { 28, 512}, { 32, 273}, { 36, 512}, { 40, 272}, { 44, 512} })
|
|
},
|
|
{ Fraction(5,4),
|
|
Groups( { { 4, 512}, { 8, 512}, { 12, 512}, { 16, 512}, { 20, 512}, { 24, 273}, { 28, 512}, { 32, 512}, { 36, 512} })
|
|
},
|
|
{ Fraction(7,8),
|
|
Groups( { { 4, 512}, { 8, 512}, { 12, 273}, { 16, 512}, { 20, 273}, { 24, 512} })
|
|
},
|
|
{ Fraction(5,8),
|
|
Groups( { { 4, 512}, { 8, 512}, { 12, 273}, { 16, 512} })
|
|
},
|
|
};
|
|
|
|
//---------------------------------------------------------
|
|
// endBeam
|
|
//---------------------------------------------------------
|
|
|
|
Beam::Mode Groups::endBeam(ChordRest* cr, ChordRest* prev)
|
|
{
|
|
if (cr->isGrace() || cr->beamMode() != Beam::Mode::AUTO)
|
|
return cr->beamMode();
|
|
Q_ASSERT(cr->staff());
|
|
|
|
TDuration d = cr->durationType();
|
|
const Groups& g = cr->staff()->group(cr->tick());
|
|
Fraction stretch = cr->staff()->timeStretch(cr->tick());
|
|
int tick = (cr->rtick() * stretch.numerator()) / stretch.denominator();
|
|
|
|
Beam::Mode val = g.beamMode(tick, d.type());
|
|
|
|
// context-dependent checks
|
|
if (val == Beam::Mode::AUTO && tick) {
|
|
// if current or previous cr is in tuplet (but not both in same tuplet):
|
|
// consider it as if this were next shorter duration
|
|
if (prev && (cr->tuplet() != prev->tuplet()) && (d == prev->durationType())) {
|
|
if (d >= TDuration::DurationType::V_EIGHTH)
|
|
val = g.beamMode(tick, TDuration::DurationType::V_16TH);
|
|
else if (d == TDuration::DurationType::V_16TH)
|
|
val = g.beamMode(tick, TDuration::DurationType::V_32ND);
|
|
else
|
|
val = g.beamMode(tick, TDuration::DurationType::V_64TH);
|
|
}
|
|
// if there is a hole between previous and current cr, break beam
|
|
// exclude tuplets from this check; tick calculations can be unreliable
|
|
// and they seem to be handled well anyhow
|
|
if (cr->voice() && prev && !prev->tuplet() && prev->tick() + prev->actualTicks() < cr->tick())
|
|
val = Beam::Mode::BEGIN;
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// beamMode
|
|
// tick is relative to begin of measure
|
|
//---------------------------------------------------------
|
|
|
|
Beam::Mode Groups::beamMode(int tick, TDuration::DurationType d) const
|
|
{
|
|
int shift;
|
|
switch (d) {
|
|
case TDuration::DurationType::V_EIGHTH: shift = 0; break;
|
|
case TDuration::DurationType::V_16TH: shift = 4; break;
|
|
case TDuration::DurationType::V_32ND: shift = 8; break;
|
|
default:
|
|
return Beam::Mode::AUTO;
|
|
}
|
|
for (const GroupNode& e : *this) {
|
|
if (e.pos * 60 < tick)
|
|
continue;
|
|
if (e.pos * 60 > tick)
|
|
break;
|
|
|
|
int action = (e.action >> shift) & 0xf;
|
|
switch (action) {
|
|
case 0: return Beam::Mode::AUTO;
|
|
case 1: return Beam::Mode::BEGIN;
|
|
case 2: return Beam::Mode::BEGIN32;
|
|
case 3: return Beam::Mode::BEGIN64;
|
|
default:
|
|
qDebug(" Groups::beamMode: bad action %d", action);
|
|
return Beam::Mode::AUTO;
|
|
}
|
|
}
|
|
return Beam::Mode::AUTO;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// endings
|
|
//---------------------------------------------------------
|
|
|
|
const Groups& Groups::endings(const Fraction& f)
|
|
{
|
|
for (const NoteGroup& g : noteGroups) {
|
|
if (g.timeSig.identical(f)) {
|
|
return g.endings;
|
|
}
|
|
}
|
|
NoteGroup g;
|
|
g.timeSig = f;
|
|
noteGroups.push_back(g);
|
|
|
|
int pos = 0;
|
|
switch(f.denominator()) {
|
|
case 2: pos = 16; break;
|
|
case 4: pos = 8; break;
|
|
case 8: pos = 4; break;
|
|
case 16: pos = 2; break;
|
|
case 32: pos = 1; break;
|
|
break;
|
|
}
|
|
for (int i = 1; i < f.numerator(); ++i) {
|
|
GroupNode n;
|
|
n.pos = pos * i;
|
|
n.action = 0x111;
|
|
g.endings.push_back(n);
|
|
}
|
|
return noteGroups.back().endings;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// write
|
|
//---------------------------------------------------------
|
|
|
|
void Groups::write(Xml& xml) const
|
|
{
|
|
xml.stag("Groups");
|
|
for (const GroupNode& n : *this)
|
|
xml.tagE(QString("Node pos=\"%1\" action=\"%2\"")
|
|
.arg(n.pos).arg(n.action));
|
|
xml.etag();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// read
|
|
//---------------------------------------------------------
|
|
|
|
void Groups::read(XmlReader& e)
|
|
{
|
|
while (e.readNextStartElement()) {
|
|
const QStringRef& tag(e.name());
|
|
if (tag == "Node") {
|
|
GroupNode n;
|
|
n.pos = e.intAttribute("pos");
|
|
n.action = e.intAttribute("action");
|
|
push_back(n);
|
|
e.skipCurrentElement();
|
|
}
|
|
else
|
|
e.unknown();
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// addStop
|
|
//---------------------------------------------------------
|
|
|
|
void Groups::addStop(int pos, TDuration::DurationType d, Beam::Mode bm)
|
|
{
|
|
int shift;
|
|
switch (d) {
|
|
case TDuration::DurationType::V_EIGHTH: shift = 0; break;
|
|
case TDuration::DurationType::V_16TH: shift = 4; break;
|
|
case TDuration::DurationType::V_32ND: shift = 8; break;
|
|
default:
|
|
return;
|
|
}
|
|
int action;
|
|
if (bm == Beam::Mode::BEGIN)
|
|
action = 1;
|
|
else if (bm == Beam::Mode::BEGIN32)
|
|
action = 2;
|
|
else if (bm == Beam::Mode::BEGIN64)
|
|
action = 3;
|
|
else
|
|
return;
|
|
|
|
pos /= 60;
|
|
action <<= shift;
|
|
|
|
auto i = begin();
|
|
for (; i != end(); ++i) {
|
|
if (i->pos == pos) {
|
|
i->action = (i->action & ~(0xf << shift)) | action;
|
|
return;
|
|
}
|
|
if (i->pos > pos)
|
|
break;
|
|
}
|
|
insert(i, GroupNode({ pos, action }));
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// dump
|
|
//---------------------------------------------------------
|
|
|
|
void Groups::dump(const char* m) const
|
|
{
|
|
qDebug("%s", m);
|
|
for (const GroupNode& n : *this) {
|
|
qDebug(" group tick %d action 0x%02x", n.pos * 60, n.action);
|
|
}
|
|
}
|
|
|
|
}
|
|
|