Replacd integer midi tick values by fractions.

- tick names a position on the time axis
- tick is always a Fraction()
- only Measure() and Segment() (and Tuplet?) have a tick value
- tick() for an generic element return only a sensible value if isMeasure() or isSegment() or isSegment(parent())

- "ticks" names a duration stored in a Fraction()
- the tick value for an Segment is relative to its measure

- rename "duration" to "ticks"
- rename afrac() to tick()
- rename rfrac() to rtick()
- rename some variables, changing "fraction" into "tick"
  (example: actualFraction() into actualTicks())

- Lyrics ticks are written as Fraction, on read if xmlreader sees a "/" it reads a fraction
  else midi ticks for backwards compatibility
This commit is contained in:
ws 2019-01-30 15:13:54 +01:00
parent 6469ea48c6
commit ec3be9a99a
239 changed files with 3638 additions and 4382 deletions

View file

@ -290,7 +290,7 @@ void Ambitus::layout()
qreal _spatium = spatium();
Staff* stf = nullptr;
if (segm && track() > -1) {
int tick = segm->tick();
Fraction tick = segm->tick();
stf = score()->staff(staffIdx());
lineDist = stf->lineDistance(tick) * _spatium;
numOfLines = stf->lines(tick);
@ -453,7 +453,7 @@ void Ambitus::draw(QPainter* p) const
// draw ledger lines (if not in a palette)
if (segment() && track() > -1) {
int tick = segment()->tick();
Fraction tick = segment()->tick();
Staff* stf = score()->staff(staffIdx());
qreal lineDist = stf->lineDistance(tick);
int numOfLines = stf->lines(tick);

View file

@ -74,7 +74,7 @@ static void undoChangeBarLineType(BarLine* bl, BarLineType barType)
}
}
else if (segmentType == SegmentType::BeginBarLine) {
Segment* segment1 = m->undoGetSegmentR(SegmentType::BeginBarLine, 0);
Segment* segment1 = m->undoGetSegmentR(SegmentType::BeginBarLine, Fraction(0, 1));
for (Element* e : segment1->elist()) {
if (e) {
e->score()->undo(new ChangeProperty(e, Pid::BARLINE_TYPE, QVariant::fromValue(barType), PropertyFlags::NOSTYLE));
@ -303,7 +303,7 @@ void BarLine::getY() const
// after skipping ones with hideSystemBarLine set
// and accounting for staves that are shown but have invisible measures
int tick = segment()->measure()->tick();
Fraction tick = segment()->measure()->tick();
const StaffType* st1 = staff1->staffType(tick);
int from = _spanFrom;
@ -343,8 +343,7 @@ void BarLine::drawDots(QPainter* painter, qreal x) const
y2l = 2.5 * _spatium;
}
else {
Staff* staff = score()->staff(staffIdx());
const StaffType* st = staff->staffType(tick());
const StaffType* st = staffType();
//workaround to make new Bravura font work correctly with repeatDots
qreal offset = score()->scoreFont()->name() == "Bravura" ? 0 : 0.5 * score()->spatium() * mag();
@ -499,7 +498,7 @@ void BarLine::draw(QPainter* painter) const
QFont f("FreeSerif");
f.setPointSizeF(12 * spatium() * MScore::pixelRatio / SPATIUM20);
f.setBold(true);
QString str = m->len() > m->timesig() ? "+" : "-";
QString str = m->ticks() > m->timesig() ? "+" : "-";
QRectF r = QFontMetricsF(f, MScore::paintDevice()).boundingRect(str);
painter->setFont(f);
painter->drawText(-r.width(), 0.0, str);
@ -1334,9 +1333,9 @@ QString BarLine::accessibleExtraInfo() const
}
}
int tick = seg->tick();
Fraction tick = seg->tick();
auto spanners = score()->spannerMap().findOverlapping(tick, tick);
auto spanners = score()->spannerMap().findOverlapping(tick.ticks(), tick.ticks());
for (auto interval : spanners) {
Spanner* s = interval.value;
if (!score()->selectionFilter().canSelect(s))

View file

@ -260,7 +260,7 @@ bool Beam::twoBeamedNotes()
if (c1->notes().size() != 1 || c2->notes().size() != 1)
return false;
int upDnLimit = staff()->lines(0) - 1; // was '4' hard-coded in the next 2 lines
int upDnLimit = staff()->lines(Fraction(0, 1)) - 1; // was '4' hard-coded in the next 2 lines
int dist1 = c1->upLine() - upDnLimit;
int dist2 = c2->upLine() - upDnLimit;
if ((dist1 == -dist2) || (-dist1 == dist2)) {
@ -303,11 +303,11 @@ void Beam::layout1()
Chord* c2 = 0;
// TAB's with stem beside staves have special layout
if (staff()->isTabStaff(0) && !staff()->staffType(0)->stemThrough()) {
if (staff()->isTabStaff(Fraction(0,1)) && !staff()->staffType(Fraction(0,1))->stemThrough()) {
//TABULATURES: all beams (and related chords) are:
// UP or DOWN according to TAB duration position
// slope 0
_up = !staff()->staffType(0)->stemsDown();
_up = !staff()->staffType(Fraction(0,1))->stemsDown();
slope = 0.0;
_cross = false;
minMove = maxMove = 0; // no cross-beaming in TAB's!
@ -322,7 +322,7 @@ void Beam::layout1()
}
}
}
else if (staff()->isDrumStaff(0)) {
else if (staff()->isDrumStaff(Fraction(0,1))) {
if (_direction != Direction::AUTO)
_up = _direction == Direction::UP;
else {
@ -346,7 +346,7 @@ void Beam::layout1()
int mUp = 0;
int mDown = 0;
int upDnLimit = staff()->lines(0) - 1; // was '4' hard-coded in following code
int upDnLimit = staff()->lines(Fraction(0,1)) - 1; // was '4' hard-coded in following code
int staffIdx = -1;
for (ChordRest* cr : _elements) {
@ -460,11 +460,11 @@ void Beam::layoutGraceNotes()
//
// determine beam stem direction
//
if (staff()->isTabStaff(0)) {
if (staff()->isTabStaff(Fraction(0,1))) {
//TABULATURES: all beams (and related chords) are:
// UP or DOWN according to TAB duration position
// slope 0
_up = !staff()->staffType(0)->stemsDown();
_up = !staff()->staffType(Fraction(0,1))->stemsDown();
}
else {
if (_direction != Direction::AUTO)
@ -1099,7 +1099,7 @@ static int adjust(qreal _spatium4, int slant, const std::vector<ChordRest*>& cl)
// on tab staff, reduce a bit the stems (value 4 is experimental)
// TODO : proper fix should adapt all the numeric vaues used in Beam::computeStemLen() below
// to variable line distance
if (c1->staff() && c1->staff()->isTabStaff(0)) {
if (c1->staff() && c1->staff()->isTabStaff(Fraction(0,1))) {
ml = (ml != 0) ? ml - 4 : 0;
return ml;
}
@ -1180,7 +1180,7 @@ void Beam::computeStemLen(const std::vector<ChordRest*>& cl, qreal& py1, int bea
qreal _spatium = spatium();
qreal _spatium4 = _spatium * .25;
// TAB: scale to staff line distance for vert. pos. within a staff
qreal _spStaff4 = staff()->isTabStaff(0) ? _spatium4 * staff()->lineDistance(0) : _spatium4;
qreal _spStaff4 = staff()->isTabStaff(Fraction(0,1)) ? _spatium4 * staff()->lineDistance(Fraction(0,1)) : _spatium4;
const ChordRest* c1 = cl.front();
const ChordRest* c2 = cl.back();
qreal dx = c2->pagePos().x() - c1->pagePos().x();
@ -1524,8 +1524,8 @@ void Beam::layout2(std::vector<ChordRest*>crl, SpannerSegmentType, int frag)
size_t n = crl.size();
const StaffType* tab = 0;
if (staff()->isTabStaff(0) )
tab = staff()->staffType(0);
if (staff()->isTabStaff(Fraction(0,1)) )
tab = staff()->staffType(Fraction(0,1));
if (tab && !tab->stemThrough()) {
//
// TAB STAVES with stems beside staves: beam position is fixed depending on TAB parameters and chordrest up/down
@ -1825,7 +1825,7 @@ void Beam::layout2(std::vector<ChordRest*>crl, SpannerSegmentType, int frag)
// unless this is start of sub-beam
const Groups& g = cr1->staff()->group(cr1->measure()->tick());
Fraction stretch = cr1->staff()->timeStretch(cr1->measure()->tick());
int currentTick = (cr1->rtick() * stretch.numerator()) / stretch.denominator();
int currentTick = (cr1->rtick() * stretch).ticks();
Beam::Mode bm = g.beamMode(currentTick, currentDuration.type());
int beamsIn;
if (bm == Beam::Mode::BEGIN32)
@ -1836,7 +1836,7 @@ void Beam::layout2(std::vector<ChordRest*>crl, SpannerSegmentType, int frag)
beamsIn = prevCR->durationType().hooks();
// remember, we are checking whether nextCR would have started sub-beam *if* same duration as this
int nextTick = (nextCR->rtick() * stretch.numerator()) / stretch.denominator();
int nextTick = (nextCR->rtick() * stretch).ticks();
bm = g.beamMode(nextTick, currentDuration.type());
if (currentHooks - beamsOut > 1 && beamsIn > beamsOut && currentHooks > beamsIn) {
@ -1854,8 +1854,8 @@ void Beam::layout2(std::vector<ChordRest*>crl, SpannerSegmentType, int frag)
else {
// determine if this is a logical group end as per 2) above
int baseTick = tuplet ? tuplet->tick() : cr1->measure()->tick();
int tickNext = nextCR->tick() - baseTick;
Fraction baseTick = tuplet ? tuplet->tick() : cr1->measure()->tick();;
Fraction tickNext = nextCR->tick() - baseTick;
if (tuplet) {
// for tuplets with odd ratios, apply ratio
// thus, we are performing calculation relative to apparent rather than actual beat
@ -1863,20 +1863,20 @@ void Beam::layout2(std::vector<ChordRest*>crl, SpannerSegmentType, int frag)
// see https://musescore.org/en/node/58061
Fraction r = tuplet->ratio();
if (r.numerator() & 1)
tickNext = (tickNext * r.numerator()) / r.denominator();
tickNext = tickNext * r;
}
// determine the tick length of a chord with one beam level less than this
// (i.e. twice the ticks of this)
int tickMod = cr1->duration().ticks() * 2; // (tickNext - (crl[c1]->tick() - baseTick)) * 2;
int tickMod = cr1->ticks().ticks() * 2; // (tickNext - (crl[c1]->tick() - baseTick)) * 2;
// if this completes, within the measure or tuplet, a unit of tickMod length, flip beam to left
// (allow some tolerance for tick rounding in tuplets
// without tuplet tolerance, could be simplified)
static const int BEAM_TUPLET_TOLERANCE = 6;
int mod = tickNext % tickMod;
int mod = tickNext.ticks() % tickMod;
if (mod <= BEAM_TUPLET_TOLERANCE || (tickMod - mod) <= BEAM_TUPLET_TOLERANCE)
len = -len;
}
@ -2453,18 +2453,18 @@ void Beam::addSkyline(Skyline& sk)
// tick
//---------------------------------------------------------
int Beam::tick() const
Fraction Beam::tick() const
{
return _elements.empty() ? 0 : _elements.front()->tick();
return _elements.empty() ? Fraction(0, 1) : _elements.front()->segment()->tick();
}
//---------------------------------------------------------
// rtick
//---------------------------------------------------------
int Beam::rtick() const
Fraction Beam::rtick() const
{
return _elements.empty() ? 0 : _elements.front()->rtick();
return _elements.empty() ? Fraction(0, 1) : _elements.front()->segment()->rtick();
}
}

View file

@ -88,8 +88,8 @@ class Beam final : public Element {
virtual void editDrag(EditData&) override;
virtual void updateGrips(EditData&) const override;
virtual int tick() const override;
virtual int rtick() const override;
virtual Fraction tick() const override;
virtual Fraction rtick() const override;
virtual void write(XmlWriter& xml) const override;
virtual void read(XmlReader&) override;

View file

@ -94,7 +94,7 @@ qDebug("checkScore: remove empty ChordRest segment");
ChordRest* lcr = 0;
for (int staffIdx = 0; staffIdx < _staves.size(); ++staffIdx) {
int track = staffIdx * VOICES;
int tick = 0;
Fraction tick = Fraction(0,1);
Staff* st = staff(staffIdx);
for (Segment* s = firstMeasure()->first(SegmentType::ChordRest); s; s = s->next1(SegmentType::ChordRest)) {
ChordRest* cr = toChordRest(s->element(track));
@ -103,17 +103,17 @@ qDebug("checkScore: remove empty ChordRest segment");
if (s->tick() != tick) {
if (lcr) {
Fraction timeStretch = st->timeStretch(lcr->tick());
Fraction f = cr->globalDuration() * timeStretch;
Fraction f = cr->globalTicks() * timeStretch;
qDebug("Chord/Rest gap at tick %d(%s+%d)-%d(%s) staffIdx %d measure %d (len = %d)",
tick, lcr->name(), f.ticks(),
s->tick(), cr->name(), staffIdx, cr->measure()->no(),
cr->tick() - tick);
tick.ticks(), lcr->name(), f.ticks(),
s->tick().ticks(), cr->name(), staffIdx, cr->measure()->no(),
(cr->tick() - tick).ticks());
}
else {
qDebug("Chord/Rest gap at tick %d-%d(%s) staffIdx %d measure %d (len = %d)",
tick,
s->tick(), cr->name(), staffIdx, cr->measure()->no(),
cr->tick() - tick);
tick.ticks(),
s->tick().ticks(), cr->name(), staffIdx, cr->measure()->no(),
(cr->tick() - tick).ticks());
}
#if 0
if (cr->tick() > tick) {
@ -154,9 +154,9 @@ qDebug(" - Rest %d/%d", d.fraction().numerator(), d.fraction().denominator(
tick = s->tick();
}
Fraction timeStretch = st->timeStretch(tick);
Fraction f = cr->globalDuration() * timeStretch;
Fraction f = cr->globalTicks() * timeStretch;
// qDebug("%s %d + %d = %d", cr->name(), tick, f.ticks(), tick + f.ticks());
tick += f.ticks();
tick += f;
lcr = cr;
}
}
@ -174,7 +174,7 @@ bool Score::sanityCheck(const QString& name)
int mNumber = 1;
QString error;
for (Measure* m = firstMeasure(); m; m = m->nextMeasure()) {
Fraction mLen = m->len();
Fraction mLen = m->ticks();
int endStaff = staves().size();
for (int staffIdx = 0; staffIdx < endStaff; ++staffIdx) {
Rest* fmrest0 = 0; // full measure rest in voice 0
@ -187,7 +187,7 @@ bool Score::sanityCheck(const QString& name)
ChordRest* cr = toChordRest(s->element(staffIdx * VOICES + v));
if (cr == 0)
continue;
voices[v] += cr->actualFraction();
voices[v] += cr->actualTicks();
if (v == 0 && cr->isRest()) {
Rest* r = toRest(cr);
if (r->durationType().isMeasure()) {
@ -207,8 +207,8 @@ bool Score::sanityCheck(const QString& name)
// try to fix a bad full measure rest
if (fmrest0) {
// fmrest0->setDuration(mLen * fmrest0->staff()->timeStretch(fmrest0->tick()));
fmrest0->setDuration(mLen);
if (fmrest0->actualFraction() != mLen)
fmrest0->setTicks(mLen);
if (fmrest0->actualTicks() != mLen)
fprintf(stderr,"whoo???\n");
}
}
@ -259,7 +259,7 @@ bool Score::checkKeys()
{
bool rc = true;
for (int i = 0; i < nstaves(); ++i) {
Key k = staff(i)->key(0);
Key k = staff(i)->key(Fraction(0,1));
for (Measure* m = firstMeasure(); m; m = m->nextMeasure()) {
Segment* s = m->findSegment(SegmentType::KeySig, m->tick());
if (s) {
@ -268,7 +268,7 @@ bool Score::checkKeys()
k = toKeySig(element)->key();
}
if (staff(i)->key(m->tick()) != k) {
qDebug("measure %d (tick %d) : key %d, map %d", m->no(), m->tick(), int(k),
qDebug("measure %d (tick %d) : key %d, map %d", m->no(), m->tick().ticks(), int(k),
int(staff(i)->key(m->tick())));
rc = false;
}
@ -322,17 +322,20 @@ bool Score::checkClefs()
void Measure::fillGap(const Fraction& pos, const Fraction& len, int track, const Fraction& stretch)
{
qDebug("measure %6d pos %d, len %d/%d, stretch %d/%d track %d",
tick(), pos.ticks(), len.numerator(), len.denominator(), stretch.numerator(), stretch.denominator(),
tick().ticks(),
pos.ticks(),
len.numerator(), len.denominator(),
stretch.numerator(), stretch.denominator(),
track);
TDuration d;
d.setVal(len.ticks());
if (d.isValid()) {
Rest* rest = new Rest(score());
rest->setDuration(len);
rest->setTicks(len);
rest->setDurationType(d);
rest->setTrack(track);
rest->setGap(true);
score()->undoAddCR(rest, this, (pos / stretch).ticks() + tick());
score()->undoAddCR(rest, this, (pos / stretch) + tick());
}
}
@ -348,31 +351,31 @@ void Measure::checkMeasure(int staffIdx)
if (isMMRest())
return;
int strack = staffIdx * VOICES;
int dtrack = strack + (hasVoices(staffIdx) ? VOICES : 1);
int strack = staffIdx * VOICES;
int dtrack = strack + (hasVoices(staffIdx) ? VOICES : 1);
Fraction stretch = score()->staff(staffIdx)->timeStretch(tick());
Fraction f = len() * stretch;
Fraction f = ticks() * stretch;
for (int track = strack; track < dtrack; track++) {
Fraction expectedPos = 0;
Fraction currentPos = 0;
Fraction expectedPos = Fraction(0,1);
Fraction currentPos = Fraction(0,1);
// printf("Check measure==\n");
for (Segment* seg = first(SegmentType::ChordRest); seg; seg = seg->next(SegmentType::ChordRest)) {
Element* e = seg->element(track);
if (!e)
continue;
ChordRest* cr = toChordRest(e);
currentPos = seg->rfrac() * stretch;
// printf(" %d/%d ", seg->rfrac().numerator(), seg->rfrac().denominator());
// fflush(stdout);
currentPos = seg->rtick() * stretch;
if (currentPos < expectedPos)
qDebug("overlap measure %6d at %d-%d track %d", tick(), (currentPos/stretch).ticks(), (expectedPos/stretch).ticks(), track);
else if (currentPos > expectedPos)
if (currentPos < expectedPos) {
qDebug("in measure overrun %6d at %d-%d track %d", tick().ticks(), (currentPos/stretch).ticks(), (expectedPos/stretch).ticks(), track);
break;
}
else if (currentPos > expectedPos) {
qDebug("in measure underrun %6d at %d-%d track %d", tick().ticks(), (currentPos/stretch).ticks(), (expectedPos/stretch).ticks(), track);
fillGap(expectedPos, currentPos - expectedPos, track, stretch);
}
DurationElement* de = cr;
Tuplet* tuplet = cr->topTuplet();
@ -380,16 +383,15 @@ void Measure::checkMeasure(int staffIdx)
seg = skipTuplet(tuplet);
de = tuplet;
}
// printf(" + %d/%d\n", de->duration().numerator(), de->duration().denominator());
expectedPos = currentPos + de->duration();
expectedPos = currentPos + de->ticks();
}
if (f > expectedPos) {
// don't fill empty voices
if (expectedPos != 0)
fillGap(expectedPos, len() - expectedPos, track, stretch);
if (expectedPos.isNotZero())
fillGap(expectedPos, ticks() - expectedPos, track, stretch);
}
else if (f < expectedPos)
qDebug("overfilled measure %6d, %d > %d, track %d", tick(), expectedPos.ticks(), f.ticks(), track);
qDebug("measure overrun %6d, %d > %d, track %d", tick().ticks(), expectedPos.ticks(), f.ticks(), track);
}
}

View file

@ -437,7 +437,7 @@ void Chord::setTremolo(Tremolo* tr)
if (_tremolo) {
if (_tremolo->twoNotes()) {
TDuration d;
const Fraction f = duration();
const Fraction f = ticks();
if (f.numerator() > 0)
d = TDuration(f);
else {
@ -673,14 +673,14 @@ void Chord::addLedgerLines()
bool staffVisible = true;
if (segment()) { //not palette
int tick = segment()->tick();
int idx = staffIdx() + staffMove();
track = staff2track(idx);
Staff* st = score()->staff(idx);
lineBelow = (st->lines(tick) - 1) * 2;
lineDistance = st->lineDistance(tick);
mag = staff()->mag(tick);
staffVisible = !staff()->invisible();
Fraction tick = segment()->tick();
int idx = staffIdx() + staffMove();
track = staff2track(idx);
Staff* st = score()->staff(idx);
lineBelow = (st->lines(tick) - 1) * 2;
lineDistance = st->lineDistance(tick);
mag = staff()->mag(tick);
staffVisible = !staff()->invisible();
}
// need ledger lines?
@ -1930,7 +1930,7 @@ void Chord::layoutPitched()
// allocate enough room for glissandi
if (_endsGlissando) {
if (rtick() // if not at beginning of measure
if (!rtick().isZero() // if not at beginning of measure
|| graceNotesBefore.size() > 0) // or there are graces before
lll += _spatium * 0.5 + minTieLength;
// special case of system-initial glissando final note is handled in Glissando::layout() itself
@ -2261,7 +2261,7 @@ void Chord::layoutTablature()
// allocate enough room for glissandi
if (_endsGlissando) {
if (rtick()) // if not at beginning of measure
if (!rtick().isZero()) // if not at beginning of measure
lll += (0.5 + score()->styleS(Sid::MinTieLength).val()) * _spatium;
// special case of system-initial glissando final note is handled in Glissando::layout() itself
}
@ -2513,7 +2513,7 @@ Element* Chord::drop(EditData& data)
return 0;
}
Chord* ch2 = toChord(s->element(track()));
if (ch2->duration() != duration()) {
if (ch2->ticks() != ticks()) {
qDebug("no matching chord for second note of tremolo found");
delete e;
return 0;

View file

@ -166,19 +166,19 @@ void ChordRest::writeProperties(XmlWriter& xml) const
if (actualDurationType().isValid())
xml.tag("durationType", actualDurationType().name());
if (!duration().isZero() && (!actualDurationType().fraction().isValid()
|| (actualDurationType().fraction() != duration()))) {
xml.tag("duration", duration());
//xml.tagE("duration z=\"%d\" n=\"%d\"", duration().numerator(), duration().denominator());
if (!ticks().isZero() && (!actualDurationType().fraction().isValid()
|| (actualDurationType().fraction() != ticks()))) {
xml.tag("duration", ticks());
//xml.tagE("duration z=\"%d\" n=\"%d\"", ticks().numerator(), ticks().denominator());
}
for (Lyrics* lyrics : _lyrics)
lyrics->write(xml);
if (!isGrace()) {
Fraction t(globalDuration());
Fraction t(globalTicks());
if (staff())
t /= staff()->timeStretch(xml.curTick());
xml.incCurTick(t.ticks());
xml.incCurTick(t);
}
for (auto i : score()->spanner()) { // TODO: dont search whole list
Spanner* s = i.second;
@ -209,21 +209,21 @@ bool ChordRest::readProperties(XmlReader& e)
// OTOH, freshly created (un-initialized) rests have numerator == 0 (< 4/4)
// (see Fraction() constructor in fraction.h; this happens for instance
// when pasting selection from clipboard): they should not be converted
duration().numerator() != 0 &&
ticks().numerator() != 0 &&
// rest durations are initialized to full measure duration when
// created upon reading the <Rest> tag (see Measure::read() )
// so a V_WHOLE rest in a measure of 4/4 or less => V_MEASURE
(actualDurationType()==TDuration::DurationType::V_WHOLE && duration() <= Fraction(4, 4)) ) {
(actualDurationType()==TDuration::DurationType::V_WHOLE && ticks() <= Fraction(4, 4)) ) {
// old pre 2.0 scores: convert
setDurationType(TDuration::DurationType::V_MEASURE);
}
else // not from old score: set duration fraction from duration type
setDuration(actualDurationType().fraction());
setTicks(actualDurationType().fraction());
}
else {
if (score()->mscVersion() <= 114) {
SigEvent event = score()->sigmap()->timesig(e.tick());
setDuration(event.timesig());
setTicks(event.timesig());
}
}
}
@ -261,7 +261,7 @@ bool ChordRest::readProperties(XmlReader& e)
else if (tag == "small")
_small = e.readInt();
else if (tag == "duration")
setDuration(e.readFraction());
setTicks(e.readFraction());
else if (tag == "ticklen") { // obsolete (version < 1.12)
int mticks = score()->sigmap()->timesig(e.tick()).timesig().ticks();
int i = e.readInt();
@ -269,11 +269,11 @@ bool ChordRest::readProperties(XmlReader& e)
i = mticks;
if ((type() == ElementType::REST) && (mticks == i)) {
setDurationType(TDuration::DurationType::V_MEASURE);
setDuration(Fraction::fromTicks(i));
setTicks(Fraction::fromTicks(i));
}
else {
Fraction f = Fraction::fromTicks(i);
setDuration(f);
setTicks(f);
setDurationType(TDuration(f));
}
}
@ -409,7 +409,7 @@ Element* ChordRest::drop(EditData& data)
int bt = tick() + actualTicks(); // this could make sense if we allowed breath marks in voice > 1
#else
Segment* next = segment()->nextCR(track);
int bt = next ? next->tick() : score()->lastSegment()->tick();
Fraction bt = next ? next->tick() : score()->lastSegment()->tick();
#endif
// TODO: insert automatically in all staves?
@ -506,7 +506,7 @@ Element* ChordRest::drop(EditData& data)
nval.headGroup = note->headGroup();
nval.fret = note->fret();
nval.string = note->string();
score()->setNoteRest(segment(), track(), nval, duration(), Direction::AUTO);
score()->setNoteRest(segment(), track(), nval, ticks(), Direction::AUTO);
delete e;
}
break;
@ -531,8 +531,8 @@ Element* ChordRest::drop(EditData& data)
case ElementType::SYSTEM_TEXT:
case ElementType::STAFF_STATE:
case ElementType::INSTRUMENT_CHANGE:
if (e->isInstrumentChange() && part()->instruments()->find(tick()) != part()->instruments()->end()) {
qDebug()<<"InstrumentChange already exists at tick = "<<tick();
if (e->isInstrumentChange() && part()->instruments()->find(tick().ticks()) != part()->instruments()->end()) {
qDebug()<<"InstrumentChange already exists at tick = "<<tick().ticks();
delete e;
return 0;
}
@ -556,10 +556,9 @@ Element* ChordRest::drop(EditData& data)
FiguredBass * fb = toFiguredBass(e);
fb->setParent( segment() );
fb->setTrack( (track() / VOICES) * VOICES );
fb->setTicks( duration().ticks() );
fb->setTicks(ticks() );
fb->setOnNote(true);
FiguredBass::addFiguredBassToSegment(segment(),
fb->track(), fb->ticks(), &bNew);
FiguredBass::addFiguredBassToSegment(segment(), fb->track(), fb->ticks(), &bNew);
if (bNew)
score()->undoAddElement(e);
return e;
@ -642,9 +641,9 @@ void ChordRest::setDurationType(const QString& s)
_crossMeasure = CrossMeasure::UNKNOWN;
}
void ChordRest::setDurationType(int ticks)
void ChordRest::setDurationType(const Fraction& ticks)
{
_durationType.setVal(ticks);
_durationType.setVal(ticks.ticks());
_crossMeasure = CrossMeasure::UNKNOWN;
}
@ -900,19 +899,22 @@ void ChordRest::writeBeam(XmlWriter& xml) const
Segment* ChordRest::nextSegmentAfterCR(SegmentType types) const
{
Fraction end = tick() + actualTicks();
for (Segment* s = segment()->next1MM(types); s; s = s->next1MM(types)) {
// chordrest ends at afrac+actualFraction
// we return the segment at or after the end of the chordrest
// Segment::afrac() is based on ticks; use DurationElement::afrac() if possible
Element* e = s;
if (s->segmentType() == SegmentType::ChordRest)
if (s->isChordRestType()) {
// Find the first non-NULL element in the segment
for (Element* ee : s->elist())
for (Element* ee : s->elist()) {
if (ee) {
e = ee;
break;
}
if (e->afrac() >= afrac() + actualFraction())
}
}
if (e->tick() >= end)
return s;
}
return 0;
@ -1136,7 +1138,7 @@ QString ChordRest::accessibleExtraInfo() const
}
SpannerMap& smap = score()->spannerMap();
auto spanners = smap.findOverlapping(tick(), tick());
auto spanners = smap.findOverlapping(tick().ticks(), tick().ticks());
for (auto interval : spanners) {
Spanner* s = interval.value;
if (!score()->selectionFilter().canSelect(s))
@ -1184,7 +1186,7 @@ Shape ChordRest::shape() const
// for horizontal spacing we only need the lyrics width:
x1 = qMin(x1, l->bbox().x() - margin + l->pos().x());
x2 = qMax(x2, l->bbox().x() + l->bbox().width() + margin + l->pos().x());
if (l->ticks() == Lyrics::TEMP_MELISMA_TICKS)
if (l->ticks() == Fraction::fromTicks(Lyrics::TEMP_MELISMA_TICKS))
x2 += spatium();
adjustWidth = true;
}
@ -1273,26 +1275,24 @@ void ChordRest::removeMarkings(bool /* keepTremolo */)
bool ChordRest::isBefore(ChordRest* o)
{
if (!o)
if (!o || this == o)
return true;
if (this == o)
return true;
int otick = o->tick();
int t = tick();
int otick = o->tick().ticks();
int t = tick().ticks();
if (t == otick) { // At least one of the chord is a grace, order the grace notes
bool oGraceAfter = o->isGraceAfter();
bool graceAfter = isGraceAfter();
bool oGrace = o->isGrace();
bool grace = isGrace();
bool graceAfter = isGraceAfter();
bool oGrace = o->isGrace();
bool grace = isGrace();
// normal note are initialized at graceIndex 0 and graceIndex is 0 based
int oGraceIndex = oGrace ? toChord(o)->graceIndex() + 1 : 0;
int graceIndex = grace ? toChord(this)->graceIndex() + 1 : 0;
int oGraceIndex = oGrace ? toChord(o)->graceIndex() + 1 : 0;
int graceIndex = grace ? toChord(this)->graceIndex() + 1 : 0;
if (oGrace)
oGraceIndex = toChord(o->parent())->graceNotes().size() - oGraceIndex;
if (grace)
graceIndex = toChord(parent())->graceNotes().size() - graceIndex;
otick = otick + (oGraceAfter ? 1 : -1) * oGraceIndex;
t = t + (graceAfter ? 1 : -1) * graceIndex;
t = t + (graceAfter ? 1 : -1) * graceIndex;
}
return t < otick;
}
@ -1306,7 +1306,7 @@ void ChordRest::undoAddAnnotation(Element* a)
Segment* seg = segment();
Measure* m = measure();
if (m && m->isMMRest())
seg = m->mmRestFirst()->findSegmentR(SegmentType::ChordRest, 0);
seg = m->mmRestFirst()->findSegmentR(SegmentType::ChordRest, Fraction(0,1));
a->setTrack(a->systemFlag() ? 0 : track());
a->setParent(seg);

View file

@ -40,12 +40,9 @@ class Spanner;
enum class SegmentType;
//-------------------------------------------------------------------
// @@ ChordRest
/// Virtual base class. Chords and rests can be part of a beam
// ChordRest
// Virtual base class. Chords and rests can be part of a beam
//
// @P beamMode enum (Beam.AUTO, .BEGIN, .MID, .END, .NONE, .BEGIN32, .BEGIN64, .INVALID)
// @P durationType int
// @P small bool small chord/rest
//-------------------------------------------------------------------
class ChordRest : public DurationElement {
@ -123,14 +120,13 @@ class ChordRest : public DurationElement {
const TDuration actualDurationType() const { return _durationType; }
void setDurationType(TDuration::DurationType t);
void setDurationType(const QString& s);
void setDurationType(int ticks);
void setDurationType(const Fraction& ticks);
void setDurationType(TDuration v);
void setDots(int n) { _durationType.setDots(n); }
int dots() const { return _crossMeasure == CrossMeasure::FIRST ? _crossMeasureTDur.dots()
: (_crossMeasure == CrossMeasure::SECOND ? 0 : _durationType.dots()); }
int actualDots() const { return _durationType.dots(); }
int durationTypeTicks() { return _crossMeasure == CrossMeasure::FIRST ? _crossMeasureTDur.ticks()
: _durationType.ticks(); }
Fraction durationTypeTicks() { return _crossMeasure == CrossMeasure::FIRST ? _crossMeasureTDur.ticks() : _durationType.ticks(); }
QString durationUserName() const;
virtual void setTrack(int val) override;
@ -149,7 +145,7 @@ class ChordRest : public DurationElement {
CrossMeasure crossMeasure() const { return _crossMeasure; }
void setCrossMeasure(CrossMeasure val) { _crossMeasure = val; }
virtual void crossMeasureSetup(bool /*on*/) { }
virtual void crossMeasureSetup(bool /*on*/) { }
// the following two functions should not be used, unless absolutely necessary;
// the cross-measure duration is best managed through setDuration() and crossMeasureSetup()
TDuration crossMeasureDurationType() const { return _crossMeasureTDur; }

View file

@ -132,18 +132,18 @@ void Clef::layout()
// check clef visibility and type compatibility
if (clefSeg && staff()) {
int tick = clefSeg->tick();
const StaffType* staffType = staff()->constStaffType(tick);
bool show = staffType->genClef(); // check staff type allows clef display
Fraction tick = clefSeg->tick();
StaffType* st = staffType();
bool show = st->genClef(); // check staff type allows clef display
// check clef is compatible with staff type group:
if (ClefInfo::staffGroup(clefType()) != staffType->group()) {
if (tick > 0 && !generated()) // if clef is not generated, hide it
if (ClefInfo::staffGroup(clefType()) != st->group()) {
if (tick > Fraction(0,1) && !generated()) // if clef is not generated, hide it
show = false;
else // if generated, replace with initial clef type
// TODO : instead of initial staff clef (which is assumed to be compatible)
// use the last compatible clef previously found in staff
_clefTypes = staff()->clefType(0);
_clefTypes = staff()->clefType(Fraction(0,1));
}
Measure* meas = clefSeg->measure();
@ -158,12 +158,12 @@ void Clef::layout()
if (!show) {
setbbox(QRectF());
qDebug("Clef::layout(): invisible clef at tick %d(%d) staff %d",
segment()->tick(), segment()->tick()/1920, staffIdx());
segment()->tick().ticks(), segment()->tick().ticks()/1920, staffIdx());
return;
}
lines = staffType->lines(); // init values from staff type
lineDist = staffType->lineDistance().val();
stepOffset = staffType->stepOffset();
lines = st->lines(); // init values from staff type
lineDist = st->lineDistance().val();
stepOffset = st->stepOffset();
}
else {
lines = 5;
@ -321,15 +321,6 @@ void Clef::write(XmlWriter& xml) const
xml.etag();
}
//---------------------------------------------------------
// tick
//---------------------------------------------------------
int Clef::tick() const
{
return segment() ? segment()->tick() : 0;
}
//---------------------------------------------------------
// setClefType
//---------------------------------------------------------
@ -441,12 +432,12 @@ Clef* Clef::otherClef()
if (!parent() || !parent()->isSegment())
return nullptr;
Segment* segm = toSegment(parent());
int segmTick = segm->tick();
if (!segm->parent() || !segm->parent()->isMeasure())
return nullptr;
return 0;
Measure* meas = toMeasure(segm->parent());
Measure* otherMeas = nullptr;
Segment* otherSegm = nullptr;
Fraction segmTick = segm->tick();
if (segmTick == meas->tick()) // if clef segm is measure-initial
otherMeas = meas->prevMeasure(); // look for a previous measure
else if (segmTick == meas->tick() + meas->ticks()) // if clef segm is measure-final

View file

@ -152,13 +152,11 @@ class Clef final : public Element {
virtual void read(XmlReader&);
virtual void write(XmlWriter&) const;
virtual bool isEditable() const { return false; }
virtual bool isEditable() const { return false; }
bool small() const { return _small; }
void setSmall(bool val);
int tick() const;
bool showCourtesy() const { return _showCourtesy; }
void setShowCourtesy(bool v) { _showCourtesy = v; }
void undoSetShowCourtesy(bool v);

View file

@ -85,19 +85,19 @@ void CmdState::reset()
{
layoutFlags = LayoutFlag::NO_FLAGS;
_updateMode = UpdateMode::DoNothing;
_startTick = -1;
_endTick = -1;
_startTick = Fraction(-1,1);
_endTick = Fraction(-1,1);
}
//---------------------------------------------------------
// setTick
//---------------------------------------------------------
void CmdState::setTick(int t)
void CmdState::setTick(const Fraction& t)
{
if (_startTick == -1 || t < _startTick)
if (_startTick == Fraction(-1,1) || t < _startTick)
_startTick = t;
if (_endTick == -1 || t > _endTick)
if (_endTick == Fraction(-1,1) || t > _endTick)
_endTick = t;
setUpdateMode(UpdateMode::Layout);
}
@ -197,7 +197,7 @@ void Score::endCmd(bool rollback)
void CmdState::dump()
{
qDebug("CmdState: mode %d %d-%d", int(_updateMode), _startTick, _endTick);
qDebug("CmdState: mode %d %d-%d", int(_updateMode), _startTick.ticks(), _endTick.ticks());
// bool _excerptsChanged { false };
// bool _instrumentsChanged { false };
@ -298,8 +298,8 @@ void Score::cmdAddSpanner(Spanner* spanner, const QPointF& pos)
if (spanner->anchor() == Spanner::Anchor::SEGMENT) {
spanner->setTick(segment->tick());
int lastTick = lastMeasure()->tick() + lastMeasure()->ticks();
int tick2 = qMin(segment->measure()->tick() + segment->measure()->ticks(), lastTick);
Fraction lastTick = lastMeasure()->tick() + lastMeasure()->ticks();
Fraction tick2 = qMin(segment->measure()->tick() + segment->measure()->ticks(), lastTick);
spanner->setTick2(tick2);
}
else { // Anchor::MEASURE, Anchor::CHORD, Anchor::NOTE
@ -330,7 +330,7 @@ void Score::cmdAddSpanner(Spanner* spanner, int staffIdx, Segment* startSegment,
for (auto ss : spanner->spannerSegments())
ss->setTrack(track);
spanner->setTick(startSegment->tick());
int tick2;
Fraction tick2;
if (!endSegment)
tick2 = lastSegment()->tick();
else if (endSegment == startSegment)
@ -392,7 +392,7 @@ void Score::expandVoice(Segment* s, int track)
}
if (ps) {
ChordRest* cr = toChordRest(ps->element(track));
int tick = cr->tick() + cr->actualTicks();
Fraction tick = cr->tick() + cr->actualTicks();
if (tick > s->tick()) {
// previous cr extends past current segment
qDebug("expandVoice: cannot insert element here");
@ -411,10 +411,10 @@ void Score::expandVoice(Segment* s, int track)
// fill up to s->tick() with rests
//
Measure* m = s->measure();
int stick = ps ? ps->tick() : m->tick();
int ticks = s->tick() - stick;
if (ticks)
setRest(stick, track, Fraction::fromTicks(ticks), false, 0);
Fraction stick = ps ? ps->tick() : m->tick();
Fraction ticks = s->tick() - stick;
if (ticks.isNotZero())
setRest(stick, track, ticks, false, 0);
//
// fill from s->tick() until next chord/rest in measure
@ -428,7 +428,7 @@ void Score::expandVoice(Segment* s, int track)
if (ticks == m->ticks())
addRest(s, track, TDuration(TDuration::DurationType::V_MEASURE), 0);
else
setRest(s->tick(), track, Fraction::fromTicks(ticks), false, 0);
setRest(s->tick(), track, ticks, false, 0);
}
void Score::expandVoice()
@ -457,7 +457,7 @@ void Score::cmdAddInterval(int val, const std::vector<Note*>& nl)
int ntpc2;
if (abs(valTmp) != 7) {
int line = on->line() - valTmp;
int tick = chord->tick();
Fraction tick = chord->tick();
Staff* estaff = staff(on->staffIdx() + chord->staffMove());
ClefType clef = estaff->clef(tick);
Key key = estaff->key(tick);
@ -543,7 +543,7 @@ Note* Score::setGraceNote(Chord* ch, int pitch, NoteType type, int len)
TDuration d;
d.setVal(len);
chord->setDurationType(d);
chord->setDuration(d.fraction());
chord->setTicks(d.fraction());
chord->setNoteType(type);
chord->setMag(ch->staff()->mag(chord->tick()) * styleD(Sid::graceNoteMag));
@ -563,14 +563,15 @@ Note* Score::setGraceNote(Chord* ch, int pitch, NoteType type, int len)
// tick start position in measure
//---------------------------------------------------------
void Score::createCRSequence(Fraction f, ChordRest* cr, int tick)
void Score::createCRSequence(const Fraction& f, ChordRest* cr, const Fraction& t)
{
Fraction tick(t);
Measure* measure = cr->measure();
ChordRest* ocr = 0;
for (TDuration d : toDurationList(f, true)) {
ChordRest* ncr = toChordRest(cr->clone());
ncr->setDurationType(d);
ncr->setDuration(d.fraction());
ncr->setTicks(d.fraction());
if (cr->isChord() && ocr) {
Chord* nc = toChord(ncr);
@ -604,7 +605,7 @@ Segment* Score::setNoteRest(Segment* segment, int track, NoteVal nval, Fraction
Q_ASSERT(segment->segmentType() == SegmentType::ChordRest);
bool isRest = nval.pitch == -1;
int tick = segment->tick();
Fraction tick = segment->tick();
Element* nr = 0;
Tie* tie = 0;
ChordRest* cr = toChordRest(segment->element(track));
@ -618,7 +619,7 @@ Segment* Score::setNoteRest(Segment* segment, int track, NoteVal nval, Fraction
Fraction dd = makeGap(segment, track, sd, cr ? cr->tuplet() : 0);
if (dd.isZero()) {
qDebug("cannot get gap at %d type: %d/%d", tick, sd.numerator(),
qDebug("cannot get gap at %d type: %d/%d", tick.ticks(), sd.numerator(),
sd.denominator());
break;
}
@ -639,7 +640,7 @@ Segment* Score::setNoteRest(Segment* segment, int track, NoteVal nval, Fraction
nr = ncr = new Rest(this);
nr->setTrack(track);
ncr->setDurationType(d);
ncr->setDuration(d == TDuration::DurationType::V_MEASURE ? measure->len() : d.fraction());
ncr->setTicks(d == TDuration::DurationType::V_MEASURE ? measure->ticks() : d.fraction());
}
else {
nr = note = new Note(this);
@ -652,7 +653,7 @@ Segment* Score::setNoteRest(Segment* segment, int track, NoteVal nval, Fraction
Chord* chord = new Chord(this);
chord->setTrack(track);
chord->setDurationType(d);
chord->setDuration(d.fraction());
chord->setTicks(d.fraction());
chord->setStemDirection(stemDirection);
chord->add(note);
note->setNval(nval, tick);
@ -754,7 +755,7 @@ Fraction Score::makeGap(Segment* segment, int track, const Fraction& _sd, Tuplet
// not be deleted (it may contain other elements we want to preserve)
//
Segment* firstSegment = segment;
int nextTick = segment->tick();
Fraction nextTick = segment->tick();
for (Segment* seg = firstSegment; seg; seg = seg->next(SegmentType::ChordRest)) {
//
@ -765,9 +766,9 @@ Fraction Score::makeGap(Segment* segment, int track, const Fraction& _sd, Tuplet
if (seg->tick() < nextTick)
continue;
Segment* seg1 = seg->next(SegmentType::ChordRest);
int tick2 = seg1 ? seg1->tick() : seg->measure()->tick() + seg->measure()->ticks();
Fraction tick2 = seg1 ? seg1->tick() : seg->measure()->tick() + seg->measure()->ticks();
segment = seg;
Fraction td(Fraction::fromTicks(tick2 - seg->tick()));
Fraction td(tick2 - seg->tick());
if (td > sd)
td = sd;
akkumulated += td;
@ -779,7 +780,7 @@ Fraction Score::makeGap(Segment* segment, int track, const Fraction& _sd, Tuplet
}
if (seg->tick() > nextTick) {
// there was a gap
Fraction td(Fraction::fromTicks(seg->tick() - nextTick));
Fraction td(seg->tick() - nextTick);
if (td > sd)
td = sd;
akkumulated += td;
@ -803,7 +804,7 @@ Fraction Score::makeGap(Segment* segment, int track, const Fraction& _sd, Tuplet
if (tupletEnd)
return akkumulated;
}
Fraction td(cr->duration());
Fraction td(cr->ticks());
// remove tremolo between 2 notes, if present
if (cr->isChord()) {
@ -831,7 +832,7 @@ Fraction Score::makeGap(Segment* segment, int track, const Fraction& _sd, Tuplet
seg = toChordRest(t->elements().back())->segment();
// now delete the full tuplet
td = ltuplet->duration();
td = ltuplet->ticks();
cmdDeleteTuplet(ltuplet, false);
tuplet = 0;
}
@ -841,7 +842,7 @@ Fraction Score::makeGap(Segment* segment, int track, const Fraction& _sd, Tuplet
// even if there was a tuplet, we didn't remove it
ltuplet = 0;
}
nextTick += td.ticks();
nextTick += td;
if (sd < td) {
//
// we removed too much
@ -856,9 +857,9 @@ Fraction Score::makeGap(Segment* segment, int track, const Fraction& _sd, Tuplet
Fraction f = sd / cr->staff()->timeStretch(cr->tick());
for (Tuplet* t = tuplet; t; t = t->tuplet())
f /= t->ratio();
int tick = cr->tick() + f.ticks();
Fraction tick = cr->tick() + f;
if ((tuplet == 0) && (((measure->tick() - tick) % dList[0].ticks()) == 0)) {
if ((tuplet == 0) && (((measure->tick() - tick).ticks() % dList[0].ticks().ticks()) == 0)) {
for (TDuration d : dList) {
if (ltuplet) {
// take care not to recreate tuplet we just deleted
@ -889,7 +890,7 @@ Fraction Score::makeGap(Segment* segment, int track, const Fraction& _sd, Tuplet
if (sd.isZero())
return akkumulated;
}
// int ticks = measure->tick() + measure->ticks() - segment->tick();
// Fraction ticks = measure->tick() + measure->ticks() - segment->tick();
// Fraction td = Fraction::fromTicks(ticks);
// NEEDS REVIEW !!
// once the statement below is removed, these two lines do nothing
@ -911,18 +912,18 @@ Fraction Score::makeGap(Segment* segment, int track, const Fraction& _sd, Tuplet
// - do not stop at measure end
//---------------------------------------------------------
bool Score::makeGap1(int baseTick, int staffIdx, Fraction len, int voiceOffset[VOICES])
bool Score::makeGap1(const Fraction& baseTick, int staffIdx, const Fraction& len, int voiceOffset[VOICES])
{
Segment* seg = tick2segment(baseTick, true, SegmentType::ChordRest);
if (!seg) {
qDebug("no segment to paste at tick %d", baseTick);
qDebug("no segment to paste at tick %d", baseTick.ticks());
return false;
}
int strack = staffIdx * VOICES;
for (int track = strack; track < strack + VOICES; track++) {
if (voiceOffset[track-strack] == -1)
continue;
int tick = baseTick + voiceOffset[track-strack];
Fraction tick = baseTick + Fraction::fromTicks(voiceOffset[track-strack]);
Measure* m = tick2measure(tick);
if ((track % VOICES) && !m->hasVoices(staffIdx))
continue;
@ -937,7 +938,7 @@ bool Score::makeGap1(int baseTick, int staffIdx, Fraction len, int voiceOffset[V
return true;
}
bool Score::makeGapVoice(Segment* seg, int track, Fraction len, int tick)
bool Score::makeGapVoice(Segment* seg, int track, Fraction len, const Fraction& tick)
{
ChordRest* cr = 0;
cr = toChordRest(seg->element(track));
@ -947,7 +948,7 @@ bool Score::makeGapVoice(Segment* seg, int track, Fraction len, int tick)
for (;;) {
if (seg1 == 0) {
if (!(track % VOICES))
qDebug("no segment before tick %d", tick);
qDebug("no segment before tick %d", tick.ticks());
// this happens only for voices other than voice 1
expandVoice(seg, track);
return makeGapVoice(seg,track,len,tick);
@ -957,13 +958,13 @@ bool Score::makeGapVoice(Segment* seg, int track, Fraction len, int tick)
seg1 = seg1->prev(SegmentType::ChordRest);
}
ChordRest* cr1 = toChordRest(seg1->element(track));
Fraction srcF = cr1->duration();
Fraction dstF = Fraction::fromTicks(tick - cr1->tick());
Fraction srcF = cr1->ticks();
Fraction dstF = tick - cr1->tick();
std::vector<TDuration> dList = toDurationList(dstF, true);
size_t n = dList.size();
undoChangeChordRestLen(cr1, TDuration(dList[0]));
if (n > 1) {
int crtick = cr1->tick() + cr1->actualTicks();
Fraction crtick = cr1->tick() + cr1->actualTicks();
Measure* measure = tick2measure(crtick);
if (cr1->type() == ElementType::CHORD) {
// split Chord
@ -982,7 +983,7 @@ bool Score::makeGapVoice(Segment* seg, int track, Fraction len, int tick)
for (size_t i = 1; i < n; ++i) {
TDuration d = dList[i];
Rest* r2 = toRest(r->clone());
r2->setDuration(d.fraction());
r2->setTicks(d.fraction());
r2->setDurationType(d);
undoAddCR(r2, measure, crtick);
seg1 = r2->segment();
@ -1058,7 +1059,7 @@ QList<Fraction> Score::splitGapToMeasureBoundaries(ChordRest* cr, Fraction gap)
for (DurationElement* de : tuplet->elements()) {
if (de == cr)
break;
rest -= de->duration();
rest -= de->ticks();
}
if (rest < gap)
qDebug("does not fit in tuplet");
@ -1068,10 +1069,10 @@ QList<Fraction> Score::splitGapToMeasureBoundaries(ChordRest* cr, Fraction gap)
}
Segment* s = cr->segment();
while (gap > Fraction(0)) {
while (gap > Fraction(0,1)) {
Measure* m = s->measure();
Fraction timeStretch = cr->staff()->timeStretch(s->tick());
Fraction rest = (m->len() - s->rfrac()) * timeStretch;
Fraction rest = (m->ticks() - s->rtick()) * timeStretch;
if (rest >= gap) {
flist.append(gap);
return flist;
@ -1107,7 +1108,7 @@ void Score::changeCRlen(ChordRest* cr, const Fraction& dstF, bool fillWithRest)
// operation mean for measure repeats.
return;
}
Fraction srcF(cr->duration());
Fraction srcF(cr->ticks());
if (srcF == dstF)
return;
@ -1139,7 +1140,7 @@ void Score::changeCRlen(ChordRest* cr, const Fraction& dstF, bool fillWithRest)
}
std::vector<TDuration> dList = toDurationList(dstF, true);
undoChangeChordRestLen(cr, dList[0]);
int tick2 = cr->tick();
Fraction tick2 = cr->tick();
for (unsigned i = 1; i < dList.size(); ++i) {
tick2 += dList[i-1].ticks();
TDuration d = dList[i];
@ -1163,7 +1164,7 @@ void Score::changeCRlen(ChordRest* cr, const Fraction& dstF, bool fillWithRest)
deselectAll();
int tick = cr->tick();
Fraction tick = cr->tick();
Fraction f = dstF;
ChordRest* cr1 = cr;
Chord* oc = 0;
@ -1179,7 +1180,7 @@ void Score::changeCRlen(ChordRest* cr, const Fraction& dstF, bool fillWithRest)
if (first) {
std::vector<TDuration> dList = toDurationList(f2, true);
undoChangeChordRestLen(cr, dList[0]);
int tick2 = cr->tick();
Fraction tick2 = cr->tick();
for (unsigned i = 1; i < dList.size(); ++i) {
tick2 += dList[i-1].ticks();
TDuration d = dList[i];
@ -1193,14 +1194,14 @@ void Score::changeCRlen(ChordRest* cr, const Fraction& dstF, bool fillWithRest)
select(r, SelectType::SINGLE, 0);
first = false;
}
tick += f2.ticks() * timeStretch.numerator() / timeStretch.denominator();
tick += f2 * timeStretch;
}
else {
std::vector<TDuration> dList = toDurationList(f2, true);
Measure* measure = tick2measure(tick);
int etick = measure->tick();
Fraction etick = measure->tick();
if (((tick - etick) % dList[0].ticks()) == 0) {
if (((tick - etick).ticks() % dList[0].ticks().ticks()) == 0) {
for (TDuration du : dList) {
bool genTie;
Chord* cc;
@ -1330,7 +1331,7 @@ void Score::upDown(bool up, UpDownMode mode, bool updateSelection)
QList<Note*> el = selection().uniqueNotes();
for (Note* oNote : el) {
int tick = oNote->chord()->tick();
Fraction tick = oNote->chord()->tick();
Staff* staff = oNote->staff();
Part* part = staff->part();
Key key = staff->key(tick);
@ -1631,7 +1632,7 @@ void Score::changeAccidental(Note* note, AccidentalType accidental)
Measure* measure = segment->measure();
if (!measure)
return;
int tick = segment->tick();
Fraction tick = segment->tick();
Staff* estaff = staff(chord->staffIdx() + chord->staffMove());
if (!estaff)
return;
@ -1811,8 +1812,8 @@ void Score::cmdAddStretch(qreal val)
{
if (!selection().isRange())
return;
int startTick = selection().tickStart();
int endTick = selection().tickEnd();
Fraction startTick = selection().tickStart();
Fraction endTick = selection().tickEnd();
for (Measure* m = firstMeasureMM(); m; m = m->nextMeasureMM()) {
if (m->tick() < startTick)
continue;
@ -1840,7 +1841,7 @@ void Score::cmdResetBeamMode()
return;
}
int endTick = selection().tickEnd();
Fraction endTick = selection().tickEnd();
for (Segment* seg = selection().firstChordRestSegment(); seg && seg->tick() < endTick; seg = seg->next1(SegmentType::ChordRest)) {
for (int track = selection().staffStart() * VOICES; track < selection().staffEnd() * VOICES; ++track) {
@ -1885,8 +1886,8 @@ void Score::cmdResetNoteAndRestGroupings()
}
// save selection values because selection changes during grouping
int sTick = selection().tickStart();
int eTick = selection().tickEnd();
Fraction sTick = selection().tickStart();
Fraction eTick = selection().tickEnd();
int sStaff = selection().staffStart();
int eStaff = selection().staffEnd();
@ -2331,20 +2332,20 @@ void Score::cmdIncDecDuration(int nSteps, bool stepDotted)
Element* el = selection().element();
if (el == 0)
return;
if (el->type() == ElementType::NOTE)
if (el->isNote())
el = el->parent();
if (!el->isChordRest())
return;
ChordRest* cr = toChordRest(el);
// if measure rest is selected as input, then the correct initialDuration will be the duration of the measure's time signature, else is just the input state's duration
// if measure rest is selected as input, then the correct initialDuration will be the
// duration of the measure's time signature, else is just the input state's duration
TDuration initialDuration = (cr->durationType() == TDuration::DurationType::V_MEASURE) ? TDuration(cr->measure()->timesig()) : _is.duration();
TDuration d = initialDuration.shiftRetainDots(nSteps, stepDotted);
if (!d.isValid())
return;
if (cr->type() == ElementType::CHORD && (toChord(cr)->noteType() != NoteType::NORMAL)) {
if (cr->isChord() && (toChord(cr)->noteType() != NoteType::NORMAL)) {
//
// handle appoggiatura and acciaccatura
//
@ -2465,7 +2466,7 @@ void Score::cmdExplode()
Measure* startMeasure = startSegment->measure();
Measure* endMeasure = endSegment ? endSegment->measure() : lastMeasure();
int lTick = endMeasure->endTick();
Fraction lTick = endMeasure->endTick();
bool voice = false;
for (Measure* m = startMeasure; m && m->tick() != lTick; m = m->nextMeasure()) {
@ -2610,8 +2611,8 @@ void Score::cmdImplode()
Segment* endSegment = selection().endSegment();
Measure* startMeasure = startSegment->measure();
Measure* endMeasure = endSegment ? endSegment->measure() : lastMeasure();
int startTick = startSegment->tick();
int endTick = endSegment ? endSegment->tick() : lastMeasure()->endTick();
Fraction startTick = startSegment->tick();
Fraction endTick = endSegment ? endSegment->tick() : lastMeasure()->endTick();
Q_ASSERT(startMeasure && endMeasure);
// if single staff selected, combine voices
@ -2640,7 +2641,7 @@ void Score::cmdImplode()
if (src && src->isChord()) {
Chord* srcChord = toChord(src);
// when combining voices, skip if not same duration
if (srcChord->duration() != dstChord->duration())
if (srcChord->ticks() != dstChord->ticks())
continue;
// add notes
for (Note* n : srcChord->notes()) {
@ -2733,7 +2734,7 @@ void Score::cmdSlashFill()
return;
Segment* endSegment = selection().endSegment();
int endTick = endSegment ? endSegment->tick() : lastSegment()->tick() + 1;
Fraction endTick = endSegment ? endSegment->tick() : lastSegment()->tick() + Fraction::fromTicks(1);
Chord* firstSlash = 0;
Chord* lastSlash = 0;
@ -2750,10 +2751,10 @@ void Score::cmdSlashFill()
int n = (d > 4 && s->measure()->timesig().numerator() % 3 == 0) ? 3 : 1;
Fraction f(n, d);
// skip over any leading segments before next (first) beat
if (s->rtick() % f.ticks())
if (s->rtick().ticks() % f.ticks())
continue;
// determine voice to use - first available voice for this measure / staff
if (voice == -1 || s->rtick() == 0) {
if (voice == -1 || s->rtick().isZero()) {
bool needGap[VOICES];
for (voice = 0; voice < VOICES; ++voice) {
needGap[voice] = false;
@ -3082,46 +3083,6 @@ void Score::cmdPitchDownOctave()
upDown(false, UpDownMode::OCTAVE);
}
/*//---------------------------------------------------------
// cmdnextElement
//---------------------------------------------------------
void Score::cmdNextElement()
{
Element* el = selection().element();
if (!el && !selection().elements().isEmpty() )
el = selection().elements().first();
if (el){
Element* next = nextElement();
int staffId = el->staffIdx();
selectSingle(next, staffId);
}
else
selectSingle(score()->firstElement(), 0); // check staffId
}
//---------------------------------------------------------
// cmdprevElement
//---------------------------------------------------------
void Score::cmdPrevElement()
{
Element* el = selection().element();
if (!el && !selection().elements().isEmpty() )
el = selection().elements().last();
if (el){
Element* prev = prevElement();
int staffId = el->staffIdx();
selectSingle(prev, staffId);
}
else
selectSingle(score()->lastElement(), 0); // check staffId
}
*/
//---------------------------------------------------------
// cmdPadNoteInclreaseTAB
//---------------------------------------------------------
@ -3418,8 +3379,8 @@ void Score::cmdAddPitch(const EditData& ed, int note, bool addFlag, bool insert)
if (p && p->isClef()) {
Clef* clef = toClef(p);
// check if it's an actual change or just a courtesy
ClefType ctb = staff->clef(clef->tick() - 1);
if (ctb != clef->clefType() || clef->tick() == 0) {
ClefType ctb = staff->clef(clef->tick() - Fraction::fromTicks(1));
if (ctb != clef->clefType() || clef->tick().isZero()) {
curPitch = line2pitch(4, clef->clefType(), Key::C); // C 72 for treble clef
break;
}

View file

@ -34,7 +34,7 @@ ConnectorInfo::ConnectorInfo(const Element* current, int track, Fraction frac)
// it may be corrected later.
if (track >= 0)
_currentLoc.setTrack(track);
if (frac >= 0)
if (frac >= Fraction(0,1))
_currentLoc.setFrac(frac);
}
@ -59,11 +59,12 @@ void ConnectorInfo::updateLocation(const Element* e, Location& l, bool clipboard
// ConnectorInfo::updateCurrentInfo
//---------------------------------------------------------
void ConnectorInfo::updateCurrentInfo(bool clipboardmode) {
void ConnectorInfo::updateCurrentInfo(bool clipboardmode)
{
if (!currentUpdated() && _current)
updateLocation(_current, _currentLoc, clipboardmode);
setCurrentUpdated(true);
}
}
//---------------------------------------------------------
// ConnectorInfo::connect

View file

@ -62,7 +62,7 @@ class ConnectorInfo {
const ConnectorInfo* findLast() const;
public:
ConnectorInfo(const Element* current, int track = -1, Fraction frac = -1);
ConnectorInfo(const Element* current, int track = -1, Fraction = { -1, 1});
ConnectorInfo(const Location& currentLocation);
ConnectorInfo* prev() const { return _prev; }
@ -135,7 +135,7 @@ class ConnectorInfoWriter : public ConnectorInfo {
virtual const char* tagName() const = 0;
public:
ConnectorInfoWriter(XmlWriter& xml, const Element* current, const Element* connector, int track = -1, Fraction frac = -1);
ConnectorInfoWriter(XmlWriter& xml, const Element* current, const Element* connector, int track = -1, Fraction = { -1, 1});
ConnectorInfoWriter* prev() const { return static_cast<ConnectorInfoWriter*>(_prev); }
ConnectorInfoWriter* next() const { return static_cast<ConnectorInfoWriter*>(_next); }

View file

@ -42,14 +42,6 @@ DurationElement::DurationElement(const DurationElement& e)
_duration = e._duration;
}
//---------------------------------------------------------
// DurationElement
//---------------------------------------------------------
DurationElement::~DurationElement()
{
}
//---------------------------------------------------------
// topTuplet
//---------------------------------------------------------
@ -65,10 +57,10 @@ Tuplet* DurationElement::topTuplet() const
}
//---------------------------------------------------------
// globalDuration
// globalTicks
//---------------------------------------------------------
Fraction DurationElement::globalDuration() const
Fraction DurationElement::globalTicks() const
{
Fraction f(_duration);
for (Tuplet* t = tuplet(); t; t = t->tuplet())
@ -77,55 +69,12 @@ Fraction DurationElement::globalDuration() const
}
//---------------------------------------------------------
// actualTicks
// actualTicks
//---------------------------------------------------------
int DurationElement::actualTicks() const
Fraction DurationElement::actualTicks() const
{
return actualFraction().ticks();
}
//---------------------------------------------------------
// actualFraction
//---------------------------------------------------------
Fraction DurationElement::actualFraction() const
{
return globalDuration() / staff()->timeStretch(tick());
}
//---------------------------------------------------------
// afrac
// Absolute position of element in fractions.
//---------------------------------------------------------
Fraction DurationElement::afrac() const
{
Tuplet* t = tuplet();
if (t) {
Fraction f = t->afrac();
for (DurationElement* de : t->elements()) {
if (de == this)
break;
f += de->actualFraction();
}
return f.reduced();
}
else
return Fraction::fromTicks(tick());
}
//---------------------------------------------------------
// rfrac
//---------------------------------------------------------
Fraction DurationElement::rfrac() const
{
if (tuplet()) {
if (Measure* m = measure())
return afrac() - m->afrac();
}
return Fraction::fromTicks(rtick());
return globalTicks() / staff()->timeStretch(tick());
}
//---------------------------------------------------------
@ -134,11 +83,9 @@ Fraction DurationElement::rfrac() const
void DurationElement::readAddTuplet(Tuplet* t)
{
if (t) {
setTuplet(t);
if (!score()->undoStack()->active()) // HACK, also added in Undo::AddElement()
t->add(this);
}
setTuplet(t);
if (!score()->undoStack()->active()) // HACK, also added in Undo::AddElement()
t->add(this);
}
//---------------------------------------------------------
@ -188,7 +135,7 @@ bool DurationElement::setProperty(Pid propertyId, const QVariant& v)
switch (propertyId) {
case Pid::DURATION: {
Fraction f(v.value<Fraction>());
setDuration(f);
setTicks(f);
// TODO: do we really need to re-layout all here?
score()->setLayoutAll();
}

View file

@ -44,7 +44,6 @@ class DurationElement : public Element {
public:
DurationElement(Score* = 0, ElementFlags = ElementFlag::MOVABLE | ElementFlag::ON_STAFF);
DurationElement(const DurationElement& e);
~DurationElement();
virtual Measure* measure() const { return (Measure*)(parent()); }
@ -56,14 +55,12 @@ class DurationElement : public Element {
Tuplet* tuplet() const { return _tuplet; }
Tuplet* topTuplet() const;
virtual Beam* beam() const { return 0; }
int actualTicks() const;
Fraction actualFraction() const;
Fraction afrac() const override;
Fraction rfrac() const override;
virtual Fraction duration() const { return _duration; }
Fraction globalDuration() const;
void setDuration(const Fraction& f) { _duration = f; }
Fraction actualTicks() const;
virtual Fraction ticks() const { return _duration; }
Fraction globalTicks() const;
void setTicks(const Fraction& f) { _duration = f; }
virtual QVariant getProperty(Pid propertyId) const override;
virtual bool setProperty(Pid propertyId, const QVariant&) override;

View file

@ -71,7 +71,7 @@ void TDuration::setVal(int ticks)
TDuration dt;
for (int i = 0; i < int(TDuration::DurationType::V_ZERO); ++i) {
dt.setType(TDuration::DurationType(i));
int t = dt.ticks();
int t = dt.ticks().ticks();
if (ticks / t) {
int remain = ticks % t;
if ((t - remain) < (t/4)) {
@ -92,34 +92,36 @@ void TDuration::setVal(int ticks)
// ticks
//---------------------------------------------------------
int TDuration::ticks() const
Fraction TDuration::ticks() const
{
int t;
Fraction t;
switch(_val) {
case DurationType::V_QUARTER: t = MScore::division; break;
case DurationType::V_1024TH: t = MScore::division / 256; break;
case DurationType::V_512TH: t = MScore::division / 128; break;
case DurationType::V_256TH: t = MScore::division / 64; break;
case DurationType::V_128TH: t = MScore::division / 32; break;
case DurationType::V_64TH: t = MScore::division / 16; break;
case DurationType::V_32ND: t = MScore::division / 8; break;
case DurationType::V_16TH: t = MScore::division / 4; break;
case DurationType::V_EIGHTH: t = MScore::division / 2; break;
case DurationType::V_HALF: t = MScore::division * 2; break;
case DurationType::V_WHOLE: t = MScore::division * 4; break;
case DurationType::V_BREVE: t = MScore::division * 8; break;
case DurationType::V_LONG: t = MScore::division * 16; break;
case DurationType::V_QUARTER: t = Fraction(1, 4); break;
case DurationType::V_1024TH: t = Fraction(1, 1024); break;
case DurationType::V_512TH: t = Fraction(1, 512); break;
case DurationType::V_256TH: t = Fraction(1, 256); break;
case DurationType::V_128TH: t = Fraction(1, 128); break;
case DurationType::V_64TH: t = Fraction(1, 64); break;
case DurationType::V_32ND: t = Fraction(1, 32); break;
case DurationType::V_16TH: t = Fraction(1, 16); break;
case DurationType::V_EIGHTH: t = Fraction(1, 8); break;
case DurationType::V_HALF: t = Fraction(1, 2); break;
case DurationType::V_WHOLE: t = Fraction(1, 1); break;
case DurationType::V_BREVE: t = Fraction(2, 1); break;
case DurationType::V_LONG: t = Fraction(4, 1); break;
case DurationType::V_ZERO:
case DurationType::V_MEASURE:
return 0;
return Fraction(0,1);
default:
case DurationType::V_INVALID:
return -1;
return Fraction(-1,1);
}
int tmp = t;
for (int i = 0; i < _dots; ++i)
tmp += (t >> (i+1));
return tmp;
Fraction tmp = t;
for (int i = 0; i < _dots; ++i) {
tmp *= Fraction(1,2);
t += tmp;
}
return t;
}
//---------------------------------------------------------
@ -286,8 +288,12 @@ void TDuration::setType(const QString& s)
//---------------------------------------------------------
// shiftType
// if stepDotted = false, duration type will inc/dec by nSteps with _dots remaining same
// if stepDotted = true, duration will round toward zero to next single-dotted or undotted duration and then will included dotted durations when stepping
// If stepDotted = false, duration type will inc/dec by
// nSteps with _dots remaining same.
//
// If stepDotted = true, duration will round toward zero
// to next single-dotted or undotted duration and then
// will included dotted durations when stepping
//---------------------------------------------------------
void TDuration::shiftType(int nSteps, bool stepDotted)
@ -303,7 +309,7 @@ void TDuration::shiftType(int nSteps, bool stepDotted)
int newValAsNumSingleDotSteps = int(_val) * 2 + roundDownSingleDots + nSteps;
// convert that new duration back into terms of DurationType integer value and number of dots
newDots = newValAsNumSingleDotSteps % 2; // odd means there is a dot
newDots = newValAsNumSingleDotSteps % 2; // odd means there is a dot
newValue = newValAsNumSingleDotSteps / 2 + newDots; // if new duration has a dot, then that
}
else {
@ -517,14 +523,14 @@ std::vector<TDuration> toDurationList(Fraction l, bool useDots, int maxDots, boo
// toRhythmicDurationList
//---------------------------------------------------------
std::vector<TDuration> toRhythmicDurationList(const Fraction& l, bool isRest, int rtickStart, const TimeSigFrac& nominal, Measure* msr, int maxDots)
std::vector<TDuration> toRhythmicDurationList(const Fraction& l, bool isRest, Fraction rtickStart, const TimeSigFrac& nominal, Measure* msr, int maxDots)
{
std::vector<TDuration> dList;
dList.reserve(8);
if (msr->isAnacrusis())
rtickStart = nominal.ticksPerMeasure() - rtickStart;
else if (isRest && l == msr->len()) {
rtickStart = Fraction::fromTicks(nominal.ticksPerMeasure()) - rtickStart;
else if (isRest && l == msr->ticks()) {
TDuration d = TDuration(TDuration::DurationType::V_MEASURE);
dList.push_back(d);
return dList;
@ -542,18 +548,18 @@ std::vector<TDuration> toRhythmicDurationList(const Fraction& l, bool isRest, in
// populateRhythmicList
//---------------------------------------------------------
void populateRhythmicList(std::vector<TDuration>* dList, const Fraction& l, bool isRest, int rtickStart, const TimeSigFrac& nominal, int maxDots)
void populateRhythmicList(std::vector<TDuration>* dList, const Fraction& l, bool isRest, const Fraction& rtickStart, const TimeSigFrac& nominal, int maxDots)
{
int rtickEnd = rtickStart + l.ticks();
Fraction rtickEnd = rtickStart + l;
bool needToSplit = false; // do we need to split?
int rtickSplit = 0; // tick to split on if we need to
// CHECK AT SUBBEAT LEVEL
int startLevel = nominal.rtick2subbeatLevel(rtickStart);
int endLevel = nominal.rtick2subbeatLevel(rtickEnd);
int strongestLevelCrossed = nominal.strongestSubbeatLevelInRange(rtickStart, rtickEnd, &rtickSplit); // sets rtickSplit
int startLevel = nominal.rtick2subbeatLevel(rtickStart.ticks());
int endLevel = nominal.rtick2subbeatLevel(rtickEnd.ticks());
int strongestLevelCrossed = nominal.strongestSubbeatLevelInRange(rtickStart.ticks(), rtickEnd.ticks(), &rtickSplit); // sets rtickSplit
if ((startLevel < 0) || (endLevel < 0) || (strongestLevelCrossed < 0)) {
// Beyond maximum subbeat level so just split into largest possible durations.
@ -571,21 +577,21 @@ void populateRhythmicList(std::vector<TDuration>* dList, const Fraction& l, bool
// nor for the next simplest case of level 2 syncopation (allow sixteenth-note, eighth, eighth... to cross unstressed beats)
if (startLevel == endLevel && strongestLevelCrossed == startLevel - 2) {
// but disallow sixteenth-note, quarter, quarter...
int ticksToNext = nominal.ticksToNextSubbeat(rtickStart, startLevel - 1);
int ticksPastPrev = nominal.ticksPastSubbeat(rtickStart, startLevel - 1);
int ticksToNext = nominal.ticksToNextSubbeat(rtickStart.ticks(), startLevel - 1);
int ticksPastPrev = nominal.ticksPastSubbeat(rtickStart.ticks(), startLevel - 1);
needToSplit = ticksToNext != ticksPastPrev;
}
if (!needToSplit && strongestLevelCrossed == 0) {
// NOW CHECK AT DENOMINATOR UNIT LEVEL AND BEAT LEVEL
BeatType startBeat = nominal.rtick2beatType(rtickStart);
BeatType endBeat = nominal.rtick2beatType(rtickEnd);
BeatType startBeat = nominal.rtick2beatType(rtickStart.ticks());
BeatType endBeat = nominal.rtick2beatType(rtickEnd.ticks());
int dUnitsCrossed = 0; // number of timeSig denominator units the note/rest crosses
// if there is a choice of which beat to split on, should we use the first or last?
bool useLast = startBeat <= BeatType::SIMPLE_UNSTRESSED; // split on the later beat if starting on a beat
BeatType strongestBeatCrossed = nominal.strongestBeatInRange(rtickStart, rtickEnd, &dUnitsCrossed, &rtickSplit, useLast);
BeatType strongestBeatCrossed = nominal.strongestBeatInRange(rtickStart.ticks(), rtickEnd.ticks(), &dUnitsCrossed, &rtickSplit, useLast);
needToSplit = forceRhythmicSplit(isRest, startBeat, endBeat, dUnitsCrossed, strongestBeatCrossed, nominal);
}
@ -603,12 +609,12 @@ void populateRhythmicList(std::vector<TDuration>* dList, const Fraction& l, bool
}
// Split on the strongest beat or subbeat crossed
Fraction leftSplit = Fraction::fromTicks(rtickSplit - rtickStart);
Fraction leftSplit = Fraction::fromTicks(rtickSplit) - rtickStart;
Fraction rightSplit = l - leftSplit;
// Recurse to see if we need to split further before adding to list
populateRhythmicList(dList, leftSplit, isRest, rtickStart, nominal, maxDots);
populateRhythmicList(dList, rightSplit, isRest, rtickSplit , nominal, maxDots);
populateRhythmicList(dList, rightSplit, isRest, Fraction::fromTicks(rtickSplit) , nominal, maxDots);
}
//---------------------------------------------------------
@ -616,37 +622,38 @@ void populateRhythmicList(std::vector<TDuration>* dList, const Fraction& l, bool
// Split compound notes/rests where they enter a compound beat.
//---------------------------------------------------------
void splitCompoundBeatsForList(std::vector<TDuration>* dList, const Fraction& l, bool isRest, int rtickStart, const TimeSigFrac& nominal, int maxDots)
void splitCompoundBeatsForList(std::vector<TDuration>* dList, const Fraction& l, bool isRest,
const Fraction& rtickStart, const TimeSigFrac& nominal, int maxDots)
{
int rtickEnd = rtickStart + l.ticks();
Fraction rtickEnd = rtickStart + l;
BeatType startBeat = nominal.rtick2beatType(rtickStart);
BeatType endBeat = nominal.rtick2beatType(rtickEnd);
BeatType startBeat = nominal.rtick2beatType(rtickStart.ticks());
BeatType endBeat = nominal.rtick2beatType(rtickEnd.ticks());
if (startBeat > BeatType::COMPOUND_UNSTRESSED) {
// Not starting on a compound beat so mustn't extend into next compound beat
int splitTicks = nominal.ticksToNextBeat(rtickStart);
int splitTicks = nominal.ticksToNextBeat(rtickStart.ticks());
if (rtickEnd - rtickStart > splitTicks) {
if ((rtickEnd - rtickStart).ticks() > splitTicks) {
// Duration extends into next beat so must split
Fraction leftSplit = Fraction::fromTicks(splitTicks);
Fraction rightSplit = l - leftSplit;
populateRhythmicList(dList, leftSplit, isRest, rtickStart, nominal, maxDots); // this side is ok to proceed
splitCompoundBeatsForList(dList, rightSplit, isRest, rtickStart + splitTicks, nominal, maxDots); // not checked yet
splitCompoundBeatsForList(dList, rightSplit, isRest, rtickStart + Fraction::fromTicks(splitTicks), nominal, maxDots); // not checked yet
return;
}
}
if (endBeat > BeatType::COMPOUND_UNSTRESSED) {
// Not ending on a compound beat so mustn't extend into previous compound beat
int splitTicks = nominal.ticksPastBeat(rtickEnd);
int splitTicks = nominal.ticksPastBeat(rtickEnd.ticks());
if (rtickEnd - rtickStart > splitTicks) {
if ((rtickEnd - rtickStart).ticks() > splitTicks) {
// Duration extends into previous beat so must split
Fraction rightSplit = Fraction::fromTicks(splitTicks);
Fraction leftSplit = l - rightSplit;
populateRhythmicList(dList, leftSplit, isRest, rtickStart, nominal, maxDots); // must add leftSplit to list first
populateRhythmicList(dList, rightSplit, isRest, rtickEnd - splitTicks, nominal, maxDots);
populateRhythmicList(dList, rightSplit, isRest, rtickEnd - Fraction::fromTicks(splitTicks), nominal, maxDots);
return;
}
}
@ -678,7 +685,9 @@ void splitCompoundBeatsForList(std::vector<TDuration>* dList, const Fraction& l,
// all compound and simple full beats, and not any subbeats.
//---------------------------------------------------------
bool forceRhythmicSplit(bool isRest, BeatType startBeat, BeatType endBeat, int dUnitsCrossed, BeatType strongestBeatCrossed, const TimeSigFrac& nominal) {
bool forceRhythmicSplit(bool isRest, BeatType startBeat, BeatType endBeat,
int dUnitsCrossed, BeatType strongestBeatCrossed, const TimeSigFrac& nominal) {
// Assumption: Notes were split at measure boundary before this function was
// called. (Necessary because timeSig might be different in next measure.)
Q_ASSERT(strongestBeatCrossed != BeatType::DOWNBEAT);

View file

@ -53,7 +53,7 @@ class TDuration {
void setType(DurationType t);
void setType(const QString&);
int ticks() const;
Fraction ticks() const;
bool operator==(const TDuration& t) const { return t._val == _val && t._dots == _dots; }
bool operator==(const DurationType& t) const { return t == _val; }
bool operator!=(const TDuration& t) const { return t._val != _val || t._dots != _dots; }
@ -71,7 +71,12 @@ class TDuration {
int hooks() const;
bool hasStem() const;
TDuration shift(int nSteps) const { TDuration d(type()); d.shiftType(nSteps); return d; } // dots are not retained
TDuration shiftRetainDots(int nSteps, bool stepDotted = false) { TDuration d(type()); d.setDots(_dots); d.shiftType(nSteps, stepDotted); return d; }
TDuration shiftRetainDots(int nSteps, bool stepDotted = false) {
TDuration d(type());
d.setDots(_dots);
d.shiftType(nSteps, stepDotted);
return d;
}
int dots() const { return _dots; }
void setDots(int v);
Fraction fraction() const;
@ -80,14 +85,14 @@ class TDuration {
};
std::vector<TDuration> toDurationList(Fraction l, bool useDots, int maxDots = 4, bool printRestRemains = true);
std::vector<TDuration> toRhythmicDurationList(const Fraction& l, bool isRest, int rtickStart, const TimeSigFrac& nominal, Measure* msr, int maxDots);
std::vector<TDuration> toRhythmicDurationList(const Fraction& l, bool isRest, Fraction rtickStart, const TimeSigFrac& nominal, Measure* msr, int maxDots);
bool forceRhythmicSplit(bool isRest, BeatType startBeat, BeatType endBeat, int beatsCrossed, BeatType strongestBeatCrossed, const TimeSigFrac& nominal);
bool forceRhythmicSplitSimple(bool isRest, BeatType startBeat, BeatType endBeat, int beatsCrossed, BeatType strongestBeatCrossed);
bool forceRhythmicSplitCompound(bool isRest, BeatType startBeat, BeatType endBeat, int beatsCrossed, BeatType strongestBeatCrossed);
void populateRhythmicList(std::vector<TDuration>* dList, const Fraction& l, bool isRest, int rtickStart, const TimeSigFrac& nominal, int maxDots);
void splitCompoundBeatsForList(std::vector<TDuration>* dList, const Fraction& l, bool isRest, int rtickStart, const TimeSigFrac& nominal, int maxDots);
void populateRhythmicList(std::vector<TDuration>* dList, const Fraction& l, bool isRest, const Fraction& rtickStart, const TimeSigFrac& nominal, int maxDots);
void splitCompoundBeatsForList(std::vector<TDuration>* dList, const Fraction& l, bool isRest, const Fraction& rtickStart, const TimeSigFrac& nominal, int maxDots);
} // namespace Ms
Q_DECLARE_METATYPE(Ms::TDuration);

File diff suppressed because it is too large Load diff

View file

@ -245,6 +245,16 @@ Staff* Element::staff() const
return score()->staff(_track >> 2);
}
//---------------------------------------------------------
// staffType
//---------------------------------------------------------
StaffType* Element::staffType() const
{
Staff* s = staff();
return s ? s->staffType(tick()) : 0;
}
//---------------------------------------------------------
// z
//---------------------------------------------------------
@ -256,6 +266,36 @@ int Element::z() const
return _z;
}
//---------------------------------------------------------
// tick
//---------------------------------------------------------
Fraction Element::tick() const
{
const Element* e = this;
while (e->parent()) {
if (e->parent()->isSegment())
return toSegment(e->parent())->tick();
e = e->parent();
}
return Fraction(0, 1);
}
//---------------------------------------------------------
// rtick
//---------------------------------------------------------
Fraction Element::rtick() const
{
const Element* e = this;
while (e->parent()) {
if (e->parent()->isSegment())
return toSegment(e->parent())->rtick();
e = e->parent();
}
return Fraction(0, 1);
}
//---------------------------------------------------------
// part
//---------------------------------------------------------
@ -510,7 +550,7 @@ void Element::writeProperties(XmlWriter& xml) const
xml.tag("track", t);
}
if (xml.writePosition())
xml.tag(Pid::POSITION, rfrac());
xml.tag(Pid::POSITION, rtick());
if (_tag != 0x1) {
for (int i = 1; i < MAX_TAGS; i++) {
if (_tag == ((unsigned)1 << i)) {
@ -634,7 +674,7 @@ bool Element::readProperties(XmlReader& e)
else if (tag == "tick") {
int val = e.readInt();
if (val >= 0)
e.initTick(score()->fileDivision(val));
e.setTick(Fraction::fromTicks(score()->fileDivision(val))); // obsolete
}
else if (tag == "pos") // obsolete
readProperty(e, Pid::OFFSET);
@ -843,7 +883,7 @@ QByteArray Element::mimeData(const QPointF& dragOffset) const
xml.setClipboardmode(true);
xml.stag("Element");
if (isNote())
xml.tag("duration", toNote(this)->chord()->duration());
xml.tag("duration", toNote(this)->chord()->ticks());
if (!dragOffset.isNull())
xml.tag("dragOffset", dragOffset);
write(xml);
@ -1067,7 +1107,7 @@ QVariant Element::getProperty(Pid propertyId) const
case Pid::VOICE:
return voice();
case Pid::POSITION:
return rfrac();
return rtick();
case Pid::GENERATED:
return generated();
case Pid::COLOR:
@ -1670,67 +1710,6 @@ bool Element::isUserModified() const
return !visible() || !offset().isNull() || (color() != MScore::defaultColor);
}
//---------------------------------------------------------
// tick
// utility, searches for segment / segment parent
//---------------------------------------------------------
int Element::tick() const
{
const Element* e = this;
while (e) {
if (e->isSegment())
return toSegment(e)->tick();
else if (e->isMeasureBase())
return toMeasureBase(e)->tick();
e = e->parent();
}
return -1;
}
//---------------------------------------------------------
// rtick
// utility, searches for segment / segment parent
//---------------------------------------------------------
int Element::rtick() const
{
const Element* e = this;
while (e) {
if (e->isSegment())
return toSegment(e)->rtick();
e = e->parent();
}
return -1;
}
//---------------------------------------------------------
// rfrac
// Position of element in fractions relative to a
// measure start.
//---------------------------------------------------------
Fraction Element::rfrac() const
{
if (parent())
return parent()->rfrac();
else
return -1;
}
//---------------------------------------------------------
// afrac
// Absolute position of element in fractions.
//---------------------------------------------------------
Fraction Element::afrac() const
{
if (parent())
return parent()->afrac();
else
return -1;
}
//---------------------------------------------------------
// triggerLayout
//---------------------------------------------------------

View file

@ -36,6 +36,7 @@ class XmlWriter;
enum class SymId;
enum class Pid;
enum class OffsetType : char;
class StaffType;
//---------------------------------------------------------
// Grip
@ -223,12 +224,15 @@ class Element : public ScoreElement {
qreal pageX() const;
qreal canvasX() const;
const QPointF& offset() const { return _offset; }
virtual void setOffset(const QPointF& o) { _offset = o; }
void setOffset(qreal x, qreal y) { _offset.rx() = x, _offset.ry() = y; }
QPointF& roffset() { return _offset; }
qreal& rxoffset() { return _offset.rx(); }
qreal& ryoffset() { return _offset.ry(); }
const QPointF& offset() const { return _offset; }
virtual void setOffset(const QPointF& o) { _offset = o; }
void setOffset(qreal x, qreal y) { _offset.rx() = x, _offset.ry() = y; }
QPointF& roffset() { return _offset; }
qreal& rxoffset() { return _offset.rx(); }
qreal& ryoffset() { return _offset.ry(); }
virtual Fraction tick() const;
virtual Fraction rtick() const;
bool isNudged() const { return !_offset.isNull(); }
@ -296,6 +300,7 @@ class Element : public ScoreElement {
int voice() const { return _track & 3; }
void setVoice(int v) { _track = (_track / VOICES) * VOICES + v; }
Staff* staff() const;
StaffType* staffType() const;
Part* part() const;
virtual void add(Element*);
@ -364,11 +369,6 @@ class Element : public ScoreElement {
bool isPrintable() const;
qreal point(const Spatium sp) const { return sp.val() * spatium(); }
virtual int tick() const; // utility, searches for segment / segment parent
virtual int rtick() const; // utility, searches for segment / segment parent
virtual Fraction rfrac() const; // utility, searches for segment / segment parent
virtual Fraction afrac() const; // utility, searches for segment / segment parent
//
// check element for consistency; return false if element
// is not valid

View file

@ -213,7 +213,7 @@ void Excerpt::createExcerpt(Excerpt* excerpt)
// handle transposing instruments
if (oscore->styleB(Sid::concertPitch) != score->styleB(Sid::concertPitch)) {
for (const Staff* staff : score->staves()) {
if (staff->staffType(0)->group() == StaffGroup::PERCUSSION)
if (staff->staffType(Fraction(0,1))->group() == StaffGroup::PERCUSSION)
continue;
// if this staff has no transposition, and no instrument changes, we can skip it
@ -230,10 +230,10 @@ void Excerpt::createExcerpt(Excerpt* excerpt)
int startTrack = staffIdx * VOICES;
int endTrack = startTrack + VOICES;
int endTick = 0;
Fraction endTick = Fraction(0,1);
if (score->lastSegment())
endTick = score->lastSegment()->tick();
score->transposeKeys(staffIdx, staffIdx+1, 0, endTick, interval, true, flip);
score->transposeKeys(staffIdx, staffIdx+1, Fraction(0,1), endTick, interval, true, flip);
for (auto segment = score->firstSegmentMM(SegmentType::ChordRest); segment; segment = segment->next1MM(SegmentType::ChordRest)) {
interval = staff->part()->instrument(segment->tick())->transpose();
@ -441,7 +441,7 @@ void Excerpt::cloneStaves(Score* oscore, Score* score, const QList<int>& map, QM
Measure* nm = new Measure(score);
nmb = nm;
nm->setTick(m->tick());
nm->setLen(m->len());
nm->setTicks(m->ticks());
nm->setTimesig(m->timesig());
nm->setRepeatCount(m->repeatCount());
@ -504,7 +504,7 @@ void Excerpt::cloneStaves(Score* oscore, Score* score, const QList<int>& map, QM
for (int track : t) {
//Clone KeySig TimeSig and Clefs if voice 1 of source staff is not mapped to a track
Element* oef = oseg->element(srcTrack & ~3);
if (oef && (oef->isTimeSig() || oef->isKeySig()) && oef->tick() == 0
if (oef && (oef->isTimeSig() || oef->isKeySig()) && oef->tick().isZero()
&& !(trackList.size() == (score->excerpt()->parts().size() * VOICES))) {
Element* ne = oef->linkedClone();
ne->setTrack(track & ~3);
@ -666,8 +666,8 @@ void Excerpt::cloneStaves(Score* oscore, Score* score, const QList<int>& map, QM
Segment* tst = nm->segments().firstCRSegment();
if (srcTrack % VOICES && !(track % VOICES) && (!tst || (!tst->element(track)))) {
Rest* rest = new Rest(score);
rest->setDuration(nm->len());
rest->setDurationType(nm->len().ticks());
rest->setTicks(nm->ticks());
rest->setDurationType(nm->ticks());
rest->setTrack(track);
Segment* segment = nm->getSegment(SegmentType::ChordRest, nm->tick());
segment->add(rest);
@ -830,8 +830,8 @@ void Excerpt::cloneStaff(Staff* srcStaff, Staff* dstStaff)
if (oe->isClef()) {
// only clone clef if it matches staff group and does not exists yet
Clef* clef = toClef(oe);
int tick = seg->tick();
if (ClefInfo::staffGroup(clef->concertClef()) == dstStaff->constStaffType(0)->group()
Fraction tick = seg->tick();
if (ClefInfo::staffGroup(clef->concertClef()) == dstStaff->constStaffType(Fraction(0,1))->group()
&& dstStaff->clefType(tick) != clef->clefTypeList()) {
ne = oe->clone();
}
@ -982,7 +982,7 @@ void Excerpt::cloneStaff(Staff* srcStaff, Staff* dstStaff)
// staves are potentially in different scores
//---------------------------------------------------------
void Excerpt::cloneStaff2(Staff* srcStaff, Staff* dstStaff, int stick, int etick)
void Excerpt::cloneStaff2(Staff* srcStaff, Staff* dstStaff, const Fraction& stick, const Fraction& etick)
{
Score* oscore = srcStaff->score();
Score* score = dstStaff->score();

View file

@ -13,6 +13,8 @@
#ifndef __EXCERPT_H__
#define __EXCERPT_H__
#include "fraction.h"
namespace Ms {
class MasterScore;
@ -67,7 +69,7 @@ class Excerpt : public QObject {
static void createExcerpt(Excerpt*);
static void cloneStaves(Score* oscore, Score* score, const QList<int>& map, QMultiMap<int, int>& allTracks);
static void cloneStaff(Staff* ostaff, Staff* nstaff);
static void cloneStaff2(Staff* ostaff, Staff* nstaff, int stick, int etick);
static void cloneStaff2(Staff* ostaff, Staff* nstaff, const Fraction& stick, const Fraction& etick);
};
} // namespace Ms

View file

@ -222,9 +222,9 @@ void Fermata::layout()
Element* e = s->element(track());
if (e) {
if (e->isChord())
rxpos() += score()->noteHeadWidth() * staff()->mag(0) * .5;
rxpos() += score()->noteHeadWidth() * staff()->mag(Fraction(0, 1)) * .5;
else
rxpos() += e->x() + e->width() * staff()->mag(0) * .5;
rxpos() += e->x() + e->width() * staff()->mag(Fraction(0, 1)) * .5;
}
QString name = Sym::id2name(_symId);

View file

@ -983,7 +983,7 @@ FiguredBass::FiguredBass(Score* s)
st.setSizeIsSpatiumDependent(true);
setElementStyle(st);
#endif
setTicks(0);
setTicks(Fraction(0,1));
qDeleteAll(items);
items.clear();
}
@ -1018,7 +1018,7 @@ void FiguredBass::write(XmlWriter& xml) const
xml.stag(this);
if(!onNote())
xml.tag("onNote", onNote());
if (ticks() > 0)
if (ticks().isNotZero())
xml.tag("ticks", ticks());
// if unparseable items, write full text data
if (items.size() < 1)
@ -1045,7 +1045,7 @@ void FiguredBass::read(XmlReader& e)
while (e.readNextStartElement()) {
const QStringRef& tag(e.name());
if (tag == "ticks")
setTicks(e.readInt());
setTicks(Fraction::fromTicks(e.readInt()));
else if (tag == "onNote")
setOnNote(e.readInt() != 0l);
else if (tag == "FiguredBassItem") {
@ -1115,15 +1115,15 @@ void FiguredBass::layout()
void FiguredBass::layoutLines()
{
if (_ticks <= 0 || !segment()) {
if (_ticks <= Fraction(0,1) || !segment()) {
_lineLengths.resize(1); // be sure to always have
_lineLengths[0] = 0; // at least 1 item in array
return;
}
ChordRest* lastCR = nullptr; // the last ChordRest of this
Segment * nextSegm = nullptr; // the Segment beyond this' segment
int nextTick = segment()->tick() + _ticks; // the tick beyond this' duration
ChordRest* lastCR = nullptr; // the last ChordRest of this
Segment* nextSegm = nullptr; // the Segment beyond this' segment
Fraction nextTick = segment()->tick() + _ticks; // the tick beyond this' duration
// locate the measure containing the last tick of this; it is either:
// the same measure containing nextTick, if nextTick is not the first tick of a measure
@ -1131,7 +1131,7 @@ void FiguredBass::layoutLines()
// or the previous measure, if nextTick is the first tick of a measure
// (and line should stop before any measure terminal segment (bar, clef, ...) )
Measure* m = score()->tick2measure(nextTick-1);
Measure* m = score()->tick2measure(nextTick-Fraction::fromTicks(1));
if (m) {
// locate the first segment (of ANY type) right after this' last tick
for (nextSegm = m->first(SegmentType::All); nextSegm; nextSegm = nextSegm->next()) {
@ -1143,7 +1143,7 @@ void FiguredBass::layoutLines()
lastCR = nextSegm->prev1()->nextChordRest(track(), true);
}
if (!m || !nextSegm) {
qDebug("FiguredBass layout: no segment found for tick %d", nextTick);
qDebug("FiguredBass layout: no segment found for tick %d", nextTick.ticks());
_lineLengths.resize(1); // be sure to always have
_lineLengths[0] = 0; // at least 1 item in array
return;
@ -1326,10 +1326,10 @@ void FiguredBass::setVisible(bool flag)
FiguredBass* FiguredBass::nextFiguredBass() const
{
if (_ticks <= 0) // if _ticks unset, no clear idea of when 'this' ends
if (_ticks <= Fraction(0,1)) // if _ticks unset, no clear idea of when 'this' ends
return 0;
Segment * nextSegm; // the Segment beyond this' segment
int nextTick = segment()->tick() + _ticks; // the tick beyond this' duration
Segment* nextSegm; // the Segment beyond this' segment
Fraction nextTick = segment()->tick() + _ticks; // the tick beyond this' duration
// locate the ChordRest segment right after this' end
nextSegm = score()->tick2segment(nextTick, true, SegmentType::ChordRest);
@ -1420,10 +1420,10 @@ FiguredBassItem * FiguredBass::addItem()
// FiguredBass elements are created and looked for only in the first track of the staff.
//---------------------------------------------------------
FiguredBass * FiguredBass::addFiguredBassToSegment(Segment * seg, int track, int extTicks, bool * pNew)
FiguredBass* FiguredBass::addFiguredBassToSegment(Segment * seg, int track, const Fraction& extTicks, bool * pNew)
{
int endTick; // where this FB is initially assumed to end
int staff = track / VOICES; // convert track to staff
Fraction endTick; // where this FB is initially assumed to end
int staff = track / VOICES; // convert track to staff
track = staff * VOICES; // first track for this staff
// scan segment annotations for an existing FB element in the same staff
@ -1443,14 +1443,14 @@ FiguredBass * FiguredBass::addFiguredBassToSegment(Segment * seg, int track, int
fb->setParent(seg);
// locate next SegChordRest in the same staff to estimate presumed duration of element
endTick = INT_MAX;
endTick = Fraction(INT_MAX,1);
Segment * nextSegm;
for (int iVoice = 0; iVoice < VOICES; iVoice++) {
nextSegm = seg->nextCR(track + iVoice);
if(nextSegm && nextSegm->tick() < endTick)
endTick = nextSegm->tick();
}
if(endTick == INT_MAX) { // no next segment: set up to score end
if(endTick == Fraction(INT_MAX,1)) { // no next segment: set up to score end
Measure * meas = seg->score()->lastMeasure();
endTick = meas->tick() + meas->ticks();
}
@ -1467,7 +1467,7 @@ FiguredBass * FiguredBass::addFiguredBassToSegment(Segment * seg, int track, int
}
// if we are extending a previous FB
if(extTicks > 0) {
if (extTicks > Fraction(0,1)) {
// locate previous FB for same staff
Segment * prevSegm;
FiguredBass* prevFB = 0;
@ -1480,8 +1480,8 @@ FiguredBass * FiguredBass::addFiguredBassToSegment(Segment * seg, int track, int
}
if(prevFB) {
// if previous FB did not stop more than extTicks before this FB...
int delta = seg->tick() - prevFB->segment()->tick();
if(prevFB->ticks() + extTicks >= delta)
Fraction delta = seg->tick() - prevFB->segment()->tick();
if (prevFB->ticks() + extTicks >= delta)
prevFB->setTicks(delta); // update prev FB ticks to last up to this FB
break;
}
@ -1649,7 +1649,7 @@ QList<QString> FiguredBass::fontNames()
bool FiguredBass::fontData(int nIdx, QString * pFamily, QString * pDisplayName,
qreal * pSize, qreal * pLineHeight)
{
{
if(nIdx >= 0 && nIdx < g_FBFonts.size()) {
FiguredBassFont f = g_FBFonts.at(nIdx);
if(pFamily) *pFamily = f.family;
@ -1659,66 +1659,7 @@ bool FiguredBass::fontData(int nIdx, QString * pFamily, QString * pDisplayName,
return true;
}
return false;
}
//---------------------------------------------------------
//
// MusicXML I/O
//
//---------------------------------------------------------
//---------------------------------------------------------
// Read MusicXML
//
// Set the FiguredBass state based on the MusicXML <figured-bass> node de.
// Note that onNote and ticks must be set by the MusicXML importer,
// as the required context is not present in the items DOM tree.
// Exception: if a <duration> element is present, tick can be set.
// Return true if valid, non-empty figure(s) are found
//---------------------------------------------------------
#if 0
bool FiguredBass::readMusicXML(XmlReader& e, int divisions)
{
bool parentheses = e.attribute("parentheses") == "yes";
QString normalizedText;
int idx = 0;
while (e.readNextStartElement()) {
const QStringRef& tag(e.name());
if (tag == "duration") {
QString val(e.readElementText());
bool ok = true;
int duration = val.toInt(&ok);
if (ok) {
duration *= MScore::division;
duration /= divisions;
setTicks(duration);
}
else
qDebug("MusicXml-Import: bad duration value: <%s>",
qPrintable(val));
}
else if (tag == "figure") {
FiguredBassItem * pItem = new FiguredBassItem(score(), idx++);
pItem->setTrack(track());
pItem->setParent(this);
pItem->readMusicXML(e, parentheses);
items.append(*pItem);
// add item normalized text
if (!normalizedText.empty())
normalizedText.append('\n');
normalizedText.append(pItem->normalizedText());
}
else {
e.unknown();
return false;
}
}
setText(normalizedText); // this is the text to show while editing
bool res = !normalizedText.empty();
return res;
}
#endif
//---------------------------------------------------------
// hasParentheses
@ -1728,7 +1669,7 @@ bool FiguredBass::readMusicXML(XmlReader& e, int divisions)
bool FiguredBass::hasParentheses() const
{
for(FiguredBassItem* item : items)
for (FiguredBassItem* item : items)
if (item->startsWithParenthesis())
return true;
return false;
@ -1747,7 +1688,7 @@ void FiguredBass::writeMusicXML(XmlWriter& xml, bool isOriginalFigure, int crEnd
for(FiguredBassItem* item : items)
item->writeMusicXML(xml, isOriginalFigure, crEndTick, fbEndTick);
if (writeDuration)
xml.tag("duration", ticks() / divisions);
xml.tag("duration", ticks().ticks() / divisions);
xml.etag();
}
@ -1778,7 +1719,7 @@ FiguredBass* Score::addFiguredBass()
bool bNew;
if (el->isNote()) {
ChordRest * cr = toNote(el)->chord();
fb = FiguredBass::addFiguredBassToSegment(cr->segment(), cr->staffIdx() * VOICES, 0, &bNew);
fb = FiguredBass::addFiguredBassToSegment(cr->segment(), cr->staffIdx() * VOICES, Fraction(0,1), &bNew);
}
else if (el->isFiguredBass()) {
fb = toFiguredBass(el);

View file

@ -233,7 +233,7 @@ class FiguredBass final : public TextBase {
std::vector<FiguredBassItem*> items; // the individual lines of the F.B.
QVector<qreal> _lineLengths; // lengths of duration indicator lines (in raster units)
bool _onNote; // true if this element is on a staff note | false if it is betweee notes
int _ticks; // the duration (used for cont. lines and for multiple F.B.
Fraction _ticks; // the duration (used for cont. lines and for multiple F.B.
// under the same note)
qreal _printedLineLength; // the length of lines actually printed (i.e. continuation lines)
void layoutLines();
@ -245,7 +245,7 @@ class FiguredBass final : public TextBase {
~FiguredBass();
// a convenience static function to create/retrieve a new FiguredBass into/from its intended parent
static FiguredBass * addFiguredBassToSegment(Segment *seg, int track, int extTicks, bool *pNew);
static FiguredBass* addFiguredBassToSegment(Segment* seg, int track, const Fraction& extTicks, bool *pNew);
// static functions for font config files
static bool readConfigFile(const QString& fileName);
@ -290,8 +290,8 @@ class FiguredBass final : public TextBase {
size_t numOfItems() const { return items.size(); }
void setOnNote(bool val) { _onNote = val; }
Segment * segment() const { return (Segment*)(parent()); }
int ticks() const { return _ticks; }
void setTicks(int val) { _ticks = val; }
Fraction ticks() const { return _ticks; }
void setTicks(const Fraction& v) { _ticks = v; }
qreal additionalContLineX(qreal pagePosY) const;// returns the X coord (in page coord) of cont. line at pagePosY, if any
FiguredBass * nextFiguredBass() const; // returns next *adjacent* f.b. item, if any

View file

@ -89,10 +89,9 @@ void Fingering::calculatePlacement()
void Fingering::layout()
{
if (parent()) {
const int tick = parent()->tick();
Fraction tick = parent()->tick();
const Staff* st = staff();
if (st && st->isTabStaff(tick)
&& !st->staffType(tick)->showTabFingering()) {
if (st && st->isTabStaff(tick) && !st->staffType(tick)->showTabFingering()) {
setbbox(QRectF());
return;
}

View file

@ -159,11 +159,13 @@ Fraction& Fraction::operator/=(const Fraction& val)
return *this;
}
#if 0
Fraction& Fraction::operator/=(int val)
{
_denominator *= val;
return *this;
}
#endif
//---------------------------------------------------------
// fromTicks
@ -171,6 +173,8 @@ Fraction& Fraction::operator/=(int val)
Fraction Fraction::fromTicks(int ticks)
{
if (ticks == -1)
return Fraction(-1,1); // HACK
return Fraction(ticks, MScore::division * 4).reduced();
}
@ -180,7 +184,10 @@ Fraction Fraction::fromTicks(int ticks)
int Fraction::ticks() const
{
// MScore::division - ticks per quarter note
if (_numerator == -1 && _denominator == 1) // HACK
return -1;
// MScore::division - ticks per quarter note
// MScore::division * 4 - ticks per whole note
// result: rounded (MScore::division * 4 * _numerator * 1.0 / _denominator) value
const auto result = (static_cast<int_least64_t>(_numerator) * MScore::division * 4 + (_denominator/2)) / _denominator;

View file

@ -22,11 +22,19 @@ namespace Ms {
//---------------------------------------------------------
class Fraction {
int _numerator;
int _denominator;
int _numerator { 0 };
int _denominator { 1 };
public:
constexpr Fraction(int z = 0, int n = 1) : _numerator(z), _denominator(n) {}
#if 0
// implicit conversion from int to Fraction: this is convenient but may hide some potential bugs
constexpr Fraction(int z=0, int n=1) : _numerator(z), _denominator(n) {}
#else
// no implicit conversion from int to Fraction:
constexpr Fraction() {}
constexpr Fraction(int z, int n) : _numerator(z), _denominator(n) {}
#endif
int numerator() const { return _numerator; }
int denominator() const { return _denominator; }
int& rnumerator() { return _numerator; }
@ -37,6 +45,7 @@ class Fraction {
void set(int z, int n) { _numerator = z; _denominator = n; }
bool isZero() const { return _numerator == 0; }
bool isNotZero() const { return _numerator != 0; }
bool isValid() const { return _denominator != 0; }
void reduce();
@ -58,13 +67,14 @@ class Fraction {
Fraction& operator*=(const Fraction&);
Fraction& operator*=(int);
Fraction& operator/=(const Fraction&);
Fraction& operator/=(int);
// Fraction& operator/=(int);
Fraction operator+(const Fraction& v) const { return Fraction(*this) += v; }
Fraction operator-(const Fraction& v) const { return Fraction(*this) -= v; }
Fraction operator-() const { return Fraction(-_numerator, _denominator); }
Fraction operator*(const Fraction& v) const { return Fraction(*this) *= v; }
Fraction operator/(const Fraction& v) const { return Fraction(*this) /= v; }
Fraction operator/(int v) const { return Fraction(*this) /= v; }
// Fraction operator/(int v) const { return Fraction(*this) /= v; }
bool operator<(const Fraction&) const;
bool operator<=(const Fraction&) const;
@ -73,8 +83,8 @@ class Fraction {
bool operator==(const Fraction&) const;
bool operator!=(const Fraction&) const;
QString print() const { return QString("%1/%2").arg(_numerator).arg(_denominator); }
QString toString() const { return print(); }
QString print() const { return QString("%1/%2").arg(_numerator).arg(_denominator); }
QString toString() const { return print(); }
operator QVariant() const { return QVariant::fromValue(*this); }
};

View file

@ -274,7 +274,7 @@ void Glissando::layout()
// FINAL SYSTEM-INITIAL NOTE
// if the last gliss. segment attaches to a system-initial note, some extra width has to be added
if (cr2->segment()->measure() == cr2->segment()->system()->firstMeasure() && cr2->rtick() == 0
if (cr2->segment()->measure() == cr2->segment()->system()->firstMeasure() && cr2->rtick().isZero()
// but ignore graces after, as they are not the first note of the system,
// even if their segment is the first segment of the system
&& !(cr2->noteType() == NoteType::GRACE8_AFTER

View file

@ -75,21 +75,21 @@ Beam::Mode Groups::endBeam(ChordRest* cr, ChordRest* prev)
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();
Fraction tick = cr->rtick() * stretch;
Beam::Mode val = g.beamMode(tick, d.type());
Beam::Mode val = g.beamMode(tick.ticks(), d.type());
// context-dependent checks
if (val == Beam::Mode::AUTO && tick) {
if (val == Beam::Mode::AUTO && tick.isNotZero()) {
// 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);
val = g.beamMode(tick.ticks(), TDuration::DurationType::V_16TH);
else if (d == TDuration::DurationType::V_16TH)
val = g.beamMode(tick, TDuration::DurationType::V_32ND);
val = g.beamMode(tick.ticks(), TDuration::DurationType::V_32ND);
else
val = g.beamMode(tick, TDuration::DurationType::V_64TH);
val = g.beamMode(tick.ticks(), 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

View file

@ -209,7 +209,7 @@ void Harmony::write(XmlWriter& xml) const
if (staff()) {
// parent can be a fret diagram
Segment* segment = parent()->isSegment() ? toSegment(parent()) : toSegment(parent()->parent());
int tick = segment ? segment->tick() : -1;
Fraction tick = segment ? segment->tick() : Fraction(-1,1);
const Interval& interval = part()->instrument(tick)->transpose();
if (xml.clipboardmode() && !score()->styleB(Sid::concertPitch) && interval.chromatic) {
rRootTpc = transposeTpc(_rootTpc, interval, true);
@ -762,7 +762,7 @@ void Harmony::endEdit(EditData& ed)
if (score()->styleB(Sid::concertPitch) != h->score()->styleB(Sid::concertPitch)) {
Part* partDest = h->part();
Segment* segment = toSegment(parent());
int tick = segment ? segment->tick() : -1;
Fraction tick = segment ? segment->tick() : Fraction(-1,1);
Interval interval = partDest->instrument(tick)->transpose();
if (!interval.isZero()) {
if (!h->score()->styleB(Sid::concertPitch))

View file

@ -49,9 +49,9 @@ StaffGroup InputState::staffGroup() const
// tick
//---------------------------------------------------------
int InputState::tick() const
Fraction InputState::tick() const
{
return _segment ? _segment->tick() : 0;
return _segment ? _segment->tick() : Fraction(0,1);
}
//---------------------------------------------------------

View file

@ -62,12 +62,12 @@ class InputState {
ChordRest* cr() const;
int tick() const;
Fraction tick() const;
void setDuration(const TDuration& d) { _duration = d; }
TDuration duration() const { return _duration; }
void setDots(int n) { _duration.setDots(n); }
int ticks() const { return _duration.ticks(); }
Fraction ticks() const { return _duration.ticks(); }
Segment* segment() const { return _segment; }
void setSegment(Segment* s);

View file

@ -34,10 +34,10 @@ void Score::cmdJoinMeasure(Measure* m1, Measure* m2)
ScoreRange range;
range.read(m1->first(), m2->last());
int tick1 = m1->tick();
int tick2 = m2->endTick();
Fraction tick1 = m1->tick();
Fraction tick2 = m2->endTick();
auto spanners = _spanner.findContained(tick1, tick2);
auto spanners = _spanner.findContained(tick1.ticks(), tick2.ticks());
for (auto i : spanners)
undo(new RemoveElement(i.value));
@ -55,7 +55,7 @@ void Score::cmdJoinMeasure(Measure* m1, Measure* m2)
const Fraction newTimesig = m1->timesig();
Fraction newLen;
for (Measure* mm = m1; mm; mm = mm->nextMeasure()) {
newLen += mm->len();
newLen += mm->ticks();
if (mm == m2)
break;
}

View file

@ -116,7 +116,7 @@ void KeySig::layout()
clef = c->clefType();
else
// no clef found, so get the clef type from the clefs list, using the previous tick
clef = staff()->clef(tick() - 1);
clef = staff()->clef(tick() - Fraction::fromTicks(1));
}
int accidentals = 0, naturals = 0;
@ -146,7 +146,7 @@ void KeySig::layout()
// If we're not force hiding naturals (Continuous panel), use score style settings
if (!_hideNaturals) {
const bool newSection = (!segment()
|| (segment()->rtick() == 0 && (!prevMeasure || prevMeasure->sectionBreak()))
|| (segment()->rtick().isZero() && (!prevMeasure || prevMeasure->sectionBreak()))
);
naturalsOn = !newSection && (score()->styleI(Sid::keySigNaturals) != int(KeySigNatural::NONE) || (t1 == 0));
}
@ -164,7 +164,7 @@ void KeySig::layout()
Key t2 = Key::C;
if (naturalsOn) {
if (staff())
t2 = staff()->key(tick() - 1);
t2 = staff()->key(tick() - Fraction(1, 480*4));
if (t2 == Key::C)
naturalsOn = false;
else {
@ -527,15 +527,6 @@ void KeySig::changeKeySigEvent(const KeySigEvent& t)
setKeySigEvent(t);
}
//---------------------------------------------------------
// tick
//---------------------------------------------------------
int KeySig::tick() const
{
return segment() ? segment()->tick() : 0;
}
//---------------------------------------------------------
// undoSetShowCourtesy
//---------------------------------------------------------

View file

@ -61,7 +61,6 @@ class KeySig final : public Element {
bool operator==(const KeySig&) const;
void changeKeySigEvent(const KeySigEvent&);
void setKeySigEvent(const KeySigEvent& e) { _sig = e; }
int tick() const;
bool showCourtesy() const { return _showCourtesy; }
void setShowCourtesy(bool v) { _showCourtesy = v; }

View file

@ -780,7 +780,7 @@ void Score::layoutChords3(std::vector<Note*>& notes, const Staff* staff, Segment
// track columns of octave-separated accidentals
int columnBottom[7] = { -1, -1, -1, -1, -1, -1, -1 };
int tick = notes.front()->tick();
Fraction tick = notes.front()->chord()->segment()->tick();
qreal sp = staff->spatium(tick);
qreal stepDistance = sp * staff->lineDistance(tick) * .5;
int stepOffset = staff->staffType(tick)->stepOffset();
@ -1352,7 +1352,7 @@ void Score::connectTies(bool silent)
nnote = searchTieNote(n);
if (nnote == 0) {
if (!silent) {
qDebug("next note at %d track %d for tie not found (version %d)", s->tick(), i, _mscVersion);
qDebug("next note at %d track %d for tie not found (version %d)", s->tick().ticks(), i, _mscVersion);
delete tie;
n->setTieFor(0);
}
@ -1623,7 +1623,7 @@ void Score::respace(std::vector<ChordRest*>* elements)
ChordRest* cr = (*elements)[i];
ChordRest* ncr = (*elements)[i+1];
width[i] = cr->shape().minHorizontalDistance(ncr->shape());
ticksList[i] = cr->duration().ticks();
ticksList[i] = cr->ticks().ticks();
minTick = qMin(ticksList[i], minTick);
}
@ -1755,16 +1755,16 @@ void Score::createMMRest(Measure* m, Measure* lm, const Fraction& len)
Measure* mmr = m->mmRest();
if (mmr) {
if (mmr->len() != len) {
if (mmr->ticks() != len) {
Segment* s = mmr->findSegmentR(SegmentType::EndBarLine, mmr->ticks());
mmr->setLen(len);
mmr->setTicks(len);
if (s)
s->setTick(mmr->endTick());
s->setRtick(mmr->ticks());
}
}
else {
mmr = new Measure(this);
mmr->setLen(len);
mmr->setTicks(len);
mmr->setTick(m->tick());
mmr->setPageBreak(lm->pageBreak());
mmr->setLineBreak(lm->lineBreak());
@ -1847,13 +1847,13 @@ void Score::createMMRest(Measure* m, Measure* lm, const Fraction& len)
}
for (Element* e : oldList)
delete e;
Segment* s = mmr->undoGetSegmentR(SegmentType::ChordRest, 0);
Segment* s = mmr->undoGetSegmentR(SegmentType::ChordRest, Fraction(0,1));
for (int staffIdx = 0; staffIdx < _staves.size(); ++staffIdx) {
int track = staffIdx * VOICES;
if (s->element(track) == 0) {
Rest* r = new Rest(this);
r->setDurationType(TDuration::DurationType::V_MEASURE);
r->setDuration(mmr->len());
r->setTicks(mmr->ticks());
r->setTrack(track);
r->setParent(s);
undo(new AddElement(r));
@ -1886,11 +1886,11 @@ void Score::createMMRest(Measure* m, Measure* lm, const Fraction& len)
//
// check for time signature
//
cs = m->findSegmentR(SegmentType::TimeSig, 0);
cs = m->findSegmentR(SegmentType::TimeSig, Fraction(0,1));
ns = mmr->findSegment(SegmentType::TimeSig, m->tick());
if (cs) {
if (ns == 0)
ns = mmr->undoGetSegmentR(SegmentType::TimeSig, 0);
ns = mmr->undoGetSegmentR(SegmentType::TimeSig, Fraction(0,1));
for (int staffIdx = 0; staffIdx < _staves.size(); ++staffIdx) {
int track = staffIdx * VOICES;
TimeSig* ts = toTimeSig(cs->element(track));
@ -1914,11 +1914,11 @@ void Score::createMMRest(Measure* m, Measure* lm, const Fraction& len)
//
// check for ambitus
//
cs = m->findSegmentR(SegmentType::Ambitus, 0);
cs = m->findSegmentR(SegmentType::Ambitus, Fraction(0,1));
ns = mmr->findSegment(SegmentType::Ambitus, m->tick());
if (cs) {
if (ns == 0)
ns = mmr->undoGetSegmentR(SegmentType::Ambitus, 0);
ns = mmr->undoGetSegmentR(SegmentType::Ambitus, Fraction(0,1));
for (int staffIdx = 0; staffIdx < _staves.size(); ++staffIdx) {
int track = staffIdx * VOICES;
Ambitus* a = toAmbitus(cs->element(track));
@ -1942,11 +1942,11 @@ void Score::createMMRest(Measure* m, Measure* lm, const Fraction& len)
//
// check for key signature
//
cs = m->findSegmentR(SegmentType::KeySig, 0);
ns = mmr->findSegmentR(SegmentType::KeySig, 0);
cs = m->findSegmentR(SegmentType::KeySig, Fraction(0,1));
ns = mmr->findSegmentR(SegmentType::KeySig, Fraction(0,1));
if (cs) {
if (ns == 0)
ns = mmr->undoGetSegmentR(SegmentType::KeySig, 0);
ns = mmr->undoGetSegmentR(SegmentType::KeySig, Fraction(0,1));
for (int staffIdx = 0; staffIdx < _staves.size(); ++staffIdx) {
int track = staffIdx * VOICES;
KeySig* ts = toKeySig(cs->element(track));
@ -1971,7 +1971,7 @@ void Score::createMMRest(Measure* m, Measure* lm, const Fraction& len)
//
// check for rehearsal mark etc.
//
cs = m->findSegmentR(SegmentType::ChordRest, 0);
cs = m->findSegmentR(SegmentType::ChordRest, Fraction(0,1));
if (cs) {
for (Element* e : cs->annotations()) {
if (!(e->isRehearsalMark() || e->isTempoText() || e->isHarmony() || e->isStaffText() || e->isSystemText()))
@ -2074,7 +2074,7 @@ static bool breakMultiMeasureRest(Measure* m)
|| (m->prevMeasure() && (m->prevMeasure()->sectionBreak())))
return true;
auto sl = m->score()->spannerMap().findOverlapping(m->tick(), m->endTick());
auto sl = m->score()->spannerMap().findOverlapping(m->tick().ticks(), m->endTick().ticks());
for (auto i : sl) {
Spanner* s = i.value;
if (s->isVolta() && (s->tick() == m->tick() || s->tick2() == m->tick()))
@ -2105,7 +2105,7 @@ static bool breakMultiMeasureRest(Measure* m)
}
// break for end of volta
auto l = m->score()->spannerMap().findOverlapping(m->tick(), m->endTick());
auto l = m->score()->spannerMap().findOverlapping(m->tick().ticks(), m->endTick().ticks());
for (auto isp : l) {
Spanner* s = isp.value;
if (s->isVolta() && (s->tick2() == m->endTick()))
@ -2129,10 +2129,10 @@ static bool breakMultiMeasureRest(Measure* m)
continue;
if (s->isStartRepeatBarLineType())
return true;
if (s->isType(SegmentType::KeySig | SegmentType::TimeSig) && m->tick())
if (s->isType(SegmentType::KeySig | SegmentType::TimeSig) && m->tick().isNotZero())
return true;
if (s->isClefType()) {
if (s->tick() != m->endTick() && m->tick())
if (s->tick() != m->endTick() && m->tick().isNotZero())
return true;
}
}
@ -2194,7 +2194,7 @@ void Score::createBeams(Measure* measure)
Beam::Mode bm = Beam::Mode::AUTO;
ChordRest* prev = 0;
bool checkBeats = false;
Fraction stretch = 1;
Fraction stretch = Fraction(1,1);
QHash<int, TDuration> beatSubdivision;
// if this measure is simple meter (actually X/4),
@ -2203,7 +2203,7 @@ void Score::createBeams(Measure* measure)
beatSubdivision.clear();
TimeSig* ts = stf->timeSig(measure->tick());
checkBeats = false;
stretch = ts ? ts->stretch() : 1;
stretch = ts ? ts->stretch() : Fraction(1,1);
const SegmentType st = SegmentType::ChordRest;
if (ts && ts->denominator() == 4) {
@ -2212,7 +2212,7 @@ void Score::createBeams(Measure* measure)
ChordRest* mcr = toChordRest(s->element(track));
if (mcr == 0)
continue;
int beat = ((mcr->rtick() * stretch.numerator()) / stretch.denominator()) / MScore::division;
int beat = (mcr->rtick() * stretch).ticks() / MScore::division;
if (beatSubdivision.contains(beat))
beatSubdivision[beat] = qMin(beatSubdivision[beat], mcr->durationType());
else
@ -2230,7 +2230,7 @@ void Score::createBeams(Measure* measure)
// Handle cross-measure beams
Beam::Mode mode = cr->beamMode();
if (mode == Beam::Mode::MID || mode == Beam::Mode::END) {
ChordRest* prevCR = findCR(measure->tick() - 1, track);
ChordRest* prevCR = findCR(measure->tick() - Fraction::fromTicks(1), track);
if (prevCR) {
const Measure* pm = prevCR->measure();
if (!beamNoContinue(prevCR->beamMode())
@ -2265,11 +2265,11 @@ void Score::createBeams(Measure* measure)
// perform additional context-dependent checks
if (bm == Beam::Mode::AUTO) {
// check if we need to break beams according to minimum duration in current / previous beat
if (checkBeats && cr->rtick()) {
int tick = (cr->rtick() * stretch.numerator()) / stretch.denominator();
if (checkBeats && cr->rtick().isNotZero()) {
Fraction tick = cr->rtick() * stretch;
// check if on the beat
if (tick % MScore::division == 0) {
int beat = tick / MScore::division;
if ((tick.ticks() % MScore::division) == 0) {
int beat = tick.ticks() / MScore::division;
// get minimum duration for this & previous beat
TDuration minDuration = qMin(beatSubdivision[beat], beatSubdivision[beat - 1]);
// re-calculate beam as if this were the duration of current chordrest
@ -2526,7 +2526,7 @@ void Score::getNextMeasure(LayoutContext& lc)
break;
lc.adjustMeasureNo(nm);
++n;
len += nm->len();
len += nm->ticks();
lm = nm;
if (!(mb && mb->isMeasure()))
break;
@ -2578,7 +2578,7 @@ void Score::getNextMeasure(LayoutContext& lc)
KeySig* ks = toKeySig(segment.element(staffIdx * VOICES));
if (!ks)
continue;
int tick = segment.tick();
Fraction tick = segment.tick();
as.init(staff->keySigEvent(tick), staff->clef(tick));
ks->layout();
}
@ -2660,7 +2660,7 @@ void Score::getNextMeasure(LayoutContext& lc)
if (isMaster()) {
// Reset tempo to set correct time stretch for fermata.
const int startTick = measure->tick();
const Fraction& startTick = measure->tick();
resetTempoRange(startTick, measure->endTick());
// Implement section break rest
@ -2686,7 +2686,7 @@ void Score::getNextMeasure(LayoutContext& lc)
for (Segment& segment : measure->segments()) {
if (segment.isBreathType()) {
qreal length = 0.0;
int tick = segment.tick();
Fraction tick = segment.tick();
// find longest pause
for (int i = 0, n = ntracks(); i < n; ++i) {
Element* e = segment.element(i);
@ -2742,11 +2742,11 @@ void Score::getNextMeasure(LayoutContext& lc)
}
}
if (stretch != 0.0 && stretch != 1.0) {
qreal otempo = tempomap()->tempo(segment.tick());
qreal otempo = tempomap()->tempo(segment.tick().ticks());
qreal ntempo = otempo / stretch;
setTempo(segment.tick(), ntempo);
int etick = segment.tick() + segment.ticks() - 1;
auto e = tempomap()->find(etick);
Fraction etick = segment.tick() + segment.ticks() - Fraction(1, 480*4);
auto e = tempomap()->find(etick.ticks());
if (e == tempomap()->end())
setTempo(etick, otempo);
}
@ -2758,22 +2758,22 @@ void Score::getNextMeasure(LayoutContext& lc)
// even if they are equivalent 4/4 vs 2/2
// also check if nominal time signature has changed
if (isMaster() && ((!measure->len().identical(lc.sig)
&& measure->len() != lc.sig * measure->mmRestCount())
if (isMaster() && ((!measure->ticks().identical(lc.sig)
&& measure->ticks() != lc.sig * measure->mmRestCount())
|| (lc.prevMeasure && lc.prevMeasure->isMeasure()
&& !measure->timesig().identical(toMeasure(lc.prevMeasure)->timesig()))))
{
if (measure->isMMRest())
lc.sig = measure->mmRestFirst()->len();
lc.sig = measure->mmRestFirst()->ticks();
else
lc.sig = measure->len();
sigmap()->add(lc.tick, SigEvent(lc.sig, measure->timesig(), measure->no()));
lc.sig = measure->ticks();
sigmap()->add(lc.tick.ticks(), SigEvent(lc.sig, measure->timesig(), measure->no()));
}
Segment* seg = measure->findSegmentR(SegmentType::StartRepeatBarLine, 0);
Segment* seg = measure->findSegmentR(SegmentType::StartRepeatBarLine, Fraction(0,1));
if (measure->repeatStart()) {
if (!seg)
seg = measure->getSegmentR(SegmentType::StartRepeatBarLine, 0);
seg = measure->getSegmentR(SegmentType::StartRepeatBarLine, Fraction(0,1));
measure->barLinesSetSpan(seg); // this also creates necessary barlines
for (int staffIdx = 0; staffIdx < nstaves(); ++staffIdx) {
BarLine* b = toBarLine(seg->element(staffIdx * VOICES));
@ -3121,7 +3121,7 @@ void Score::layoutLyrics(System* system)
// layoutTies
//---------------------------------------------------------
void layoutTies(Chord* ch, System* system, int stick)
void layoutTies(Chord* ch, System* system, const Fraction& stick)
{
for (Note* note : ch->notes()) {
Tie* t = note->tieFor();
@ -3203,7 +3203,7 @@ System* Score::collectSystem(LayoutContext& lc)
lc.startWithLongNames = lc.firstSystem && measure->sectionBreakElement()->startWithLongNames();
}
System* system = getNextSystem(lc);
int lcmTick = lc.curMeasure ? lc.curMeasure->tick() : 0;
Fraction lcmTick = lc.curMeasure ? lc.curMeasure->tick() : Fraction(0,1);
system->setInstrumentNames(lc.startWithLongNames, lcmTick);
qreal minWidth = 0;
@ -3226,7 +3226,7 @@ System* Score::collectSystem(LayoutContext& lc)
system->layoutSystem(minWidth);
minWidth += system->leftMargin();
if (m->repeatStart()) {
Segment* s = m->findSegmentR(SegmentType::StartRepeatBarLine, 0);
Segment* s = m->findSegmentR(SegmentType::StartRepeatBarLine, Fraction(0,1));
if (!s->enabled())
s->setEnabled(true);
}
@ -3304,7 +3304,7 @@ System* Score::collectSystem(LayoutContext& lc)
if (lc.curMeasure->isMeasure()) {
Measure* m1 = toMeasure(lc.curMeasure);
if (m1->repeatStart()) {
Segment* s = m1->findSegmentR(SegmentType::StartRepeatBarLine, 0);
Segment* s = m1->findSegmentR(SegmentType::StartRepeatBarLine, Fraction(0,1));
if (!s->enabled()) {
s->setEnabled(true);
m1->computeMinWidth();
@ -3410,13 +3410,13 @@ System* Score::collectSystem(LayoutContext& lc)
else if (mb->isMeasure()) {
Measure* m = toMeasure(mb);
mw += m->width(); // measures are stretched already with basicStretch()
totalWeight += m->ticks() * m->basicStretch();
totalWeight += m->ticks().ticks() * m->basicStretch();
}
}
#ifndef NDEBUG
if (!qFuzzyCompare(mw, minWidth))
qDebug("==layoutSystem %6d old %.1f new %.1f", system->measures().front()->tick(), minWidth, mw);
qDebug("==layoutSystem %6d old %.1f new %.1f", system->measures().front()->tick().ticks(), minWidth, mw);
#endif
rest = systemWidth - minWidth;
//
@ -3443,7 +3443,7 @@ System* Score::collectSystem(LayoutContext& lc)
mb->setPos(pos);
Measure* m = toMeasure(mb);
qreal stretch = m->basicStretch();
ww += rest * m->ticks() * stretch;
ww += rest * m->ticks().ticks() * stretch;
m->stretchMeasure(ww);
m->layoutStaffLines();
}
@ -3645,9 +3645,9 @@ void Score::layoutSystemElements(System* system, LayoutContext& lc)
// layout slurs
//-------------------------------------------------------------
int stick = system->measures().front()->tick();
int etick = system->measures().back()->endTick();
auto spanners = score()->spannerMap().findOverlapping(stick, etick);
Fraction stick = system->measures().front()->tick();
Fraction etick = system->measures().back()->endTick();
auto spanners = score()->spannerMap().findOverlapping(stick.ticks(), etick.ticks());
std::vector<Spanner*> spanner;
for (auto interval : spanners) {
@ -3999,7 +3999,7 @@ void LayoutContext::collectPage()
measureNo = 0;
startWithLongNames = true;
firstSystem = true;
tick = 0;
tick = Fraction(0,1);
prevMeasure = 0;
curMeasure = 0;
nextMeasure = ms->measures()->first();
@ -4043,7 +4043,7 @@ void LayoutContext::collectPage()
}
qreal height = 0;
int stick = -1;
Fraction stick = Fraction(-1,1);
for (System* s : page->systems()) {
Score* currentScore = s->score();
height += s->rypos();
@ -4051,7 +4051,7 @@ void LayoutContext::collectPage()
if (!mb->isMeasure())
continue;
Measure* m = toMeasure(mb);
if (stick == -1)
if (stick == Fraction(-1,1))
stick = m->tick();
for (int track = 0; track < currentScore->ntracks(); ++track) {
@ -4124,17 +4124,19 @@ void LayoutContext::collectPage()
void Score::doLayout()
{
doLayoutRange(0, -1);
doLayoutRange(Fraction(0,1), Fraction(-1,1));
}
//---------------------------------------------------------
// doLayoutRange
//---------------------------------------------------------
void Score::doLayoutRange(int stick, int etick)
void Score::doLayoutRange(const Fraction& st, const Fraction& et)
{
if (stick == -1 && etick == -1)
abort();
Fraction stick(st);
Fraction etick(et);
Q_ASSERT(!(stick == Fraction(-1,1) && etick == Fraction(-1,1)));
if (!last() || (lineMode() && !firstMeasure())) {
qDebug("empty score");
qDeleteAll(_systems);
@ -4145,11 +4147,10 @@ void Score::doLayoutRange(int stick, int etick)
}
// if (!_systems.isEmpty())
// return;
qDebug("%p %d-%d %s systems %d", this, stick, etick, isMaster() ? "Master" : "Part", int(_systems.size()));
bool layoutAll = stick <= 0 && (etick < 0 || etick >= last()->endTick());
if (stick < 0)
stick = 0;
if (etick < 0)
bool layoutAll = stick <= Fraction(0,1) && (etick < Fraction(0,1) || etick >= last()->endTick());
if (stick < Fraction(0,1))
stick = Fraction(0,1);
if (etick < Fraction(0,1))
etick = last()->endTick();
LayoutContext lc;
@ -4217,7 +4218,7 @@ void Score::doLayoutRange(int stick, int etick)
_systems.erase(_systems.begin() + systemIndex, _systems.end());
if (!lc.nextMeasure->prevMeasure()) {
lc.measureNo = 0;
lc.tick = 0;
lc.tick = Fraction(0,1);
}
else {
if (lc.nextMeasure->prevMeasure()->sectionBreak())

View file

@ -29,7 +29,7 @@ struct LayoutContext {
bool firstSystem { true };
Page* page { 0 };
int curPage { 0 }; // index in Score->page()s
int tick { 0 };
Fraction tick { 0, 1 };
Fraction sig;
QList<System*> systemList; // reusable systems
@ -45,7 +45,7 @@ struct LayoutContext {
MeasureBase* curMeasure { 0 };
MeasureBase* nextMeasure { 0 };
int measureNo { 0 };
int endTick;
Fraction endTick;
LayoutContext() = default;
LayoutContext(const LayoutContext&) = delete;

View file

@ -41,7 +41,7 @@
namespace Ms {
extern void layoutTies(Chord* ch, System* system, int stick);
extern void layoutTies(Chord* ch, System* system, const Fraction& stick);
extern void layoutDrumsetChord(Chord* c, const Drumset* drumset, const StaffType* st, qreal spatium);
//---------------------------------------------------------
@ -152,7 +152,7 @@ void Score::resetSystems(bool /*layoutAll*/, LayoutContext& lc)
if (firstMeasure) {
system->layoutSystem(0.0);
if (m->repeatStart()) {
Segment* s = m->findSegmentR(SegmentType::StartRepeatBarLine, 0);
Segment* s = m->findSegmentR(SegmentType::StartRepeatBarLine, Fraction(0,1));
if (!s->enabled())
s->setEnabled(true);
}
@ -538,7 +538,7 @@ void LayoutContext::layoutMeasureLinear(MeasureBase* mb)
KeySig* ks = toKeySig(segment.element(staffIdx * VOICES));
if (!ks)
continue;
int t = segment.tick();
Fraction t = segment.tick();
as.init(staff->keySigEvent(t), staff->clef(t));
ks->layout();
}
@ -617,7 +617,7 @@ void LayoutContext::layoutMeasureLinear(MeasureBase* mb)
for (Segment& segment : measure->segments()) {
if (segment.isBreathType()) {
qreal length = 0.0;
int t = segment.tick();
Fraction t = segment.tick();
// find longest pause
for (int i = 0, n = score->ntracks(); i < n; ++i) {
Element* e = segment.element(i);
@ -659,11 +659,11 @@ void LayoutContext::layoutMeasureLinear(MeasureBase* mb)
stretch = qMax(stretch, toFermata(e)->timeStretch());
}
if (stretch != 0.0 && stretch != 1.0) {
qreal otempo = score->tempomap()->tempo(segment.tick());
qreal otempo = score->tempomap()->tempo(segment.tick().ticks());
qreal ntempo = otempo / stretch;
score->setTempo(segment.tick(), ntempo);
int etick = segment.tick() + segment.ticks() - 1;
auto e = score->tempomap()->find(etick);
Fraction etick = segment.tick() + segment.ticks() - Fraction(1, 480*4);
auto e = score->tempomap()->find(etick.ticks());
if (e == score->tempomap()->end())
score->setTempo(etick, otempo);
}
@ -682,21 +682,21 @@ void LayoutContext::layoutMeasureLinear(MeasureBase* mb)
// even if they are equivalent 4/4 vs 2/2
// also check if nominal time signature has changed
if (score->isMaster() && ((!measure->len().identical(sig) && measure->len() != sig * measure->mmRestCount())
if (score->isMaster() && ((!measure->ticks().identical(sig) && measure->ticks() != sig * measure->mmRestCount())
|| (prevMeasure && prevMeasure->isMeasure()
&& !measure->timesig().identical(toMeasure(prevMeasure)->timesig()))))
{
if (measure->isMMRest())
sig = measure->mmRestFirst()->len();
sig = measure->mmRestFirst()->ticks();
else
sig = measure->len();
score->sigmap()->add(tick, SigEvent(sig, measure->timesig(), measure->no()));
sig = measure->ticks();
score->sigmap()->add(tick.ticks(), SigEvent(sig, measure->timesig(), measure->no()));
}
Segment* seg = measure->findSegmentR(SegmentType::StartRepeatBarLine, 0);
Segment* seg = measure->findSegmentR(SegmentType::StartRepeatBarLine, Fraction(0,1));
if (measure->repeatStart()) {
if (!seg)
seg = measure->getSegmentR(SegmentType::StartRepeatBarLine, 0);
seg = measure->getSegmentR(SegmentType::StartRepeatBarLine, Fraction(0,1));
measure->barLinesSetSpan(seg); // this also creates necessary barlines
for (int staffIdx = 0; staffIdx < score->nstaves(); ++staffIdx) {
BarLine* b = toBarLine(seg->element(staffIdx * VOICES));

View file

@ -244,7 +244,7 @@ QPointF LetRing::linePos(Grip grip, System** sys) const
x -= c->x();
}
if (!s) {
int t = tick2();
Fraction t = tick2();
Measure* m = score()->tick2measure(t);
s = m->system();
x = m->tick2pos(t);

View file

@ -534,12 +534,12 @@ QPointF SLine::linePos(Grip grip, System** sys) const
}
}
}
else if (isLyricsLine() && toLyrics(parent())->ticks() > 0) {
else if (isLyricsLine() && toLyrics(parent())->ticks() > Fraction(0,1)) {
// melisma line
// it is possible CR won't be in correct track
// prefer element in current track if available
if (!cr)
qDebug("no end for lyricsline segment - start %d, ticks %d", tick(), ticks());
qDebug("no end for lyricsline segment - start %d, ticks %d", tick().ticks(), ticks().ticks());
else if (cr->track() != track()) {
Element* e = cr->segment()->element(track());
if (e)
@ -610,7 +610,7 @@ QPointF SLine::linePos(Grip grip, System** sys) const
}
}
int t = grip == Grip::START ? tick() : tick2();
Fraction t = grip == Grip::START ? tick() : tick2();
Measure* m = cr ? cr->measure() : score()->tick2measure(t);
if (m) {
@ -737,8 +737,8 @@ QPointF SLine::linePos(Grip grip, System** sys) const
SpannerSegment* SLine::layoutSystem(System* system)
{
int stick = system->firstMeasure()->tick();
int etick = system->lastMeasure()->endTick();
Fraction stick = system->firstMeasure()->tick();
Fraction etick = system->lastMeasure()->endTick();
LineSegment* lineSegm = toLineSegment(getNextLayoutSystemSegment(system, [this]() { return createLineSegment(); }));
@ -825,7 +825,7 @@ SpannerSegment* SLine::layoutSystem(System* system)
void SLine::layout()
{
if (score() == gscore || tick() == -1 || tick2() == 1) {
if (score() == gscore || (tick() == Fraction(-1,1)) || (ticks() == Fraction(0,1))) {
//
// when used in a palette or while dragging from palette,
// SLine has no parent and
@ -1009,14 +1009,14 @@ bool SLine::readProperties(XmlReader& e)
const QStringRef& tag(e.name());
if (tag == "tick2") { // obsolete
if (tick() == -1) // not necessarily set (for first note of score?) #30151
if (tick() == Fraction(-1,1)) // not necessarily set (for first note of score?) #30151
setTick(e.tick());
setTick2(e.readInt());
setTick2(Fraction::fromTicks(e.readInt()));
}
else if (tag == "tick") // obsolete
setTick(e.readInt());
setTick(Fraction::fromTicks(e.readInt()));
else if (tag == "ticks")
setTicks(e.readInt());
setTicks(Fraction::fromTicks(e.readInt()));
else if (tag == "Segment") {
LineSegment* ls = createLineSegment();
ls->setTrack(track()); // needed in read to get the right staff mag

View file

@ -138,7 +138,7 @@ void Location::fillPositionForElement(const Element* e, bool absfrac)
if (track() == absDefaults.track())
setTrack(track(e));
if (frac() == absDefaults.frac())
setFrac(absfrac ? e->afrac() : e->rfrac());
setFrac(absfrac ? e->tick() : e->rtick());
if (measure() == absDefaults.measure())
setMeasure(absfrac ? 0 : measure(e));
}
@ -265,7 +265,7 @@ QVariant Location::getLocationProperty(Pid pid, const Element* start, const Elem
case Pid::LOCATION_MEASURES:
return measure(end) - measure(start);
case Pid::LOCATION_FRACTIONS:
return end->rfrac() - start->rfrac();
return end->rtick() - start->rtick();
case Pid::LOCATION_GRACE:
return graceIndex(end) - graceIndex(end);
case Pid::LOCATION_NOTE:

View file

@ -25,6 +25,10 @@ class XmlWriter;
enum class Pid;
//---------------------------------------------------------
// Location
//---------------------------------------------------------
class Location {
int _staff;
int _voice;
@ -43,8 +47,8 @@ class Location {
constexpr Location(int staff, int voice, int measure, Fraction frac, int graceIndex, int note, bool rel)
: _staff(staff), _voice(voice), _measure(measure), _frac(frac), _graceIndex(graceIndex), _note(note), _rel(rel) {}
static constexpr Location absolute() { return Location(INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, false); }
static constexpr Location relative() { return Location(0, 0, 0, 0, INT_MIN, 0, true); }
static constexpr Location absolute() { return Location(INT_MIN, INT_MIN, INT_MIN, Fraction(INT_MIN,1), INT_MIN, INT_MIN, false); }
static constexpr Location relative() { return Location(0, 0, 0, Fraction(0, 1), INT_MIN, 0, true); }
void toAbsolute(const Location& ref);
void toRelative(const Location& ref);

View file

@ -43,7 +43,7 @@ Lyrics::Lyrics(Score* s)
_even = false;
initElementStyle(&lyricsElementStyle);
_no = 0;
_ticks = 0;
_ticks = Fraction(0,1);
_syllabic = Syllabic::SINGLE;
_separator = 0;
}
@ -134,8 +134,8 @@ bool Lyrics::readProperties(XmlReader& e)
else
qDebug("bad syllabic property");
}
else if (tag == "ticks")
_ticks = e.readInt();
else if (tag == "ticks") // obsolete
_ticks = e.readFraction();
else if (readProperty(tag, e, Pid::PLACEMENT))
;
else if (!TextBase::readProperties(e))
@ -186,7 +186,7 @@ void Lyrics::remove(Element* el)
bool Lyrics::isMelisma() const
{
// entered as melisma using underscore?
if (_ticks > 0)
if (_ticks > Fraction(0,1))
return true;
// hyphenated?
@ -300,7 +300,7 @@ void Lyrics::layout()
rxpos() = x;
if (_ticks > 0 || _syllabic == Syllabic::BEGIN || _syllabic == Syllabic::MIDDLE) {
if (_ticks > Fraction(0,1) || _syllabic == Syllabic::BEGIN || _syllabic == Syllabic::MIDDLE) {
if (!_separator) {
_separator = new LyricsLine(score());
_separator->setTick(cr->tick());
@ -311,7 +311,7 @@ void Lyrics::layout()
// HACK separator should have non-zero length to get its layout
// always triggered. A proper ticks length will be set later on the
// separator layout.
_separator->setTicks(1);
_separator->setTicks(Fraction::fromTicks(1));
_separator->setTrack(track());
_separator->setTrack2(track());
// bbox().setWidth(bbox().width()); // ??
@ -421,7 +421,7 @@ void Lyrics::paste(EditData& ed)
// endTick
//---------------------------------------------------------
int Lyrics::endTick() const
Fraction Lyrics::endTick() const
{
return segment()->tick() + ticks();
}
@ -512,7 +512,7 @@ bool Lyrics::setProperty(Pid propertyId, const QVariant& v)
_syllabic = Syllabic(v.toInt());
break;
case Pid::LYRIC_TICKS:
_ticks = v.toInt();
_ticks = v.value<Fraction>();
break;
case Pid::VERSE:
_no = v.toInt();
@ -540,6 +540,7 @@ QVariant Lyrics::propertyDefault(Pid id) const
case Pid::SYLLABIC:
return int(Syllabic::SINGLE);
case Pid::LYRIC_TICKS:
return Fraction(0,1);
case Pid::VERSE:
return 0;
case Pid::ALIGN:

View file

@ -42,7 +42,7 @@ class Lyrics final : public TextBase {
// static constexpr qreal LYRICS_WORD_MIN_DISTANCE = 0.33; // min. distance between lyrics from different words
private:
int _ticks; ///< if > 0 then draw an underline to tick() + _ticks
Fraction _ticks; ///< if > 0 then draw an underline to tick() + _ticks
///< (melisma)
Syllabic _syllabic;
LyricsLine* _separator;
@ -85,9 +85,9 @@ class Lyrics final : public TextBase {
virtual void remove(Element*) override;
virtual void endEdit(EditData&) override;
int ticks() const { return _ticks; }
void setTicks(int tick) { _ticks = tick; }
int endTick() const;
Fraction ticks() const { return _ticks; }
void setTicks(const Fraction& tick) { _ticks = tick; }
Fraction endTick() const;
void removeFromScore();
using ScoreElement::undoChangeProperty;

View file

@ -90,20 +90,20 @@ void LyricsLine::styleChanged()
void LyricsLine::layout()
{
bool tempMelismaTicks = (lyrics()->ticks() == Lyrics::TEMP_MELISMA_TICKS);
if (lyrics()->ticks()) { // melisma
bool tempMelismaTicks = (lyrics()->ticks() == Fraction::fromTicks(Lyrics::TEMP_MELISMA_TICKS));
if (lyrics()->ticks().isNotZero()) { // melisma
setLineWidth(score()->styleP(Sid::lyricsLineThickness));
// if lyrics has a temporary one-chord melisma, set to 0 ticks (just its own chord)
if (tempMelismaTicks)
lyrics()->setTicks(0);
lyrics()->setTicks(Fraction(0,1));
// Lyrics::_ticks points to the beginning of the last spanned segment,
// but the line shall include it:
// include the duration of this last segment in the melisma duration
Segment* lyricsSegment = lyrics()->segment();
int lyricsStartTick = lyricsSegment->tick();
int lyricsEndTick = lyrics()->endTick();
int lyricsTrack = lyrics()->track();
Segment* lyricsSegment = lyrics()->segment();
Fraction lyricsStartTick = lyricsSegment->tick();
Fraction lyricsEndTick = lyrics()->endTick();
int lyricsTrack = lyrics()->track();
// find segment with tick >= endTick
Segment* s = lyricsSegment;
@ -113,7 +113,7 @@ void LyricsLine::layout()
// user probably deleted measures at end of score, leaving this melisma too long
// set s to last segment and reset lyricsEndTick to trigger FIXUP code below
s = score()->lastSegment();
lyricsEndTick = -1;
lyricsEndTick = Fraction(-1,1);
}
Element* se = s->element(lyricsTrack);
// everything is OK if we have reached a chord at right tick on right track
@ -149,7 +149,7 @@ void LyricsLine::layout()
// nothing to do but set ticks to 0
// this will result in melisma being deleted later
lyrics()->undoChangeProperty(Pid::LYRIC_TICKS, 0);
setTicks(0);
setTicks(Fraction(0,1));
return;
}
}
@ -161,10 +161,10 @@ void LyricsLine::layout()
_nextLyrics = searchNextLyrics(lyrics()->segment(), staffIdx(), lyrics()->no(), lyrics()->placement());
setTick2(_nextLyrics ? _nextLyrics->segment()->tick() : tick());
}
if (ticks()) { // only do layout if some time span
if (ticks().isNotZero()) { // only do layout if some time span
// do layout with non-0 duration
if (tempMelismaTicks)
lyrics()->setTicks(Lyrics::TEMP_MELISMA_TICKS);
lyrics()->setTicks(Fraction::fromTicks(Lyrics::TEMP_MELISMA_TICKS));
}
}
@ -174,17 +174,15 @@ void LyricsLine::layout()
SpannerSegment* LyricsLine::layoutSystem(System* system)
{
int stick = system->firstMeasure()->tick();
int etick = system->lastMeasure()->endTick();
// qDebug("%s %p %d-%d %d-%d", name(), this, stick, etick, tick(), tick2());
Fraction stick = system->firstMeasure()->tick();
Fraction etick = system->lastMeasure()->endTick();
LyricsLineSegment* lineSegm = toLyricsLineSegment(getNextLayoutSystemSegment(system, [this]() { return createLineSegment(); }));
SpannerSegmentType sst;
if (tick() >= stick) {
layout();
if (!ticks()) // only do layout if some time span
if (ticks().isZero()) // only do layout if some time span
return 0;
SLine::layout();
//
@ -260,7 +258,7 @@ SpannerSegment* LyricsLine::layoutSystem(System* system)
// if temp melisma extend the first line segment to be
// after the lyrics syllable (otherwise the melisma segment
// will be too short).
const bool tempMelismaTicks = (lyrics()->ticks() == Lyrics::TEMP_MELISMA_TICKS);
const bool tempMelismaTicks = (lyrics()->ticks() == Fraction::fromTicks(Lyrics::TEMP_MELISMA_TICKS));
if (tempMelismaTicks && spannerSegments().size() > 0 && spannerSegments().front() == lineSegm)
lineSegm->rxpos2() += lyrics()->width();
return lineSegm;
@ -301,11 +299,11 @@ bool LyricsLine::setProperty(Pid propertyId, const QVariant& v)
{
// if parent lyrics has a melisma, change its length too
if (parent() && parent()->type() == ElementType::LYRICS
&& toLyrics(parent())->ticks() > 0) {
int newTicks = toLyrics(parent())->ticks() + v.toInt() - ticks();
&& toLyrics(parent())->ticks() > Fraction(0,1)) {
Fraction newTicks = toLyrics(parent())->ticks() + v.value<Fraction>() - ticks();
parent()->undoChangeProperty(Pid::LYRIC_TICKS, newTicks);
}
setTicks(v.toInt());
setTicks(v.value<Fraction>());
}
break;
default:
@ -336,7 +334,7 @@ void LyricsLineSegment::layout()
ryoffset() = 0.0;
bool endOfSystem = false;
bool isEndMelisma = lyricsLine()->lyrics()->ticks() > 0;
bool isEndMelisma = lyricsLine()->lyrics()->ticks() > Fraction(0,1);
Lyrics* lyr = 0;
Lyrics* nextLyr = 0;
qreal fromX = 0;
@ -344,7 +342,7 @@ void LyricsLineSegment::layout()
qreal sp = spatium();
System* sys;
if (lyricsLine()->ticks() <= 0) { // if no span,
if (lyricsLine()->ticks() <= Fraction(0,1)) { // if no span,
_numOfDashes = 0; // nothing to draw
return; // and do nothing
}
@ -461,7 +459,7 @@ void LyricsLineSegment::draw(QPainter* painter) const
pen.setWidthF(lyricsLine()->lineWidth());
pen.setCapStyle(Qt::FlatCap);
painter->setPen(pen);
if (lyricsLine()->lyrics()->ticks() > 0) // melisma
if (lyricsLine()->lyrics()->ticks() > Fraction(0,1)) // melisma
painter->drawLine(QPointF(), pos2());
else { // dash(es)
qreal step = pos2().x() / _numOfDashes;

View file

@ -35,7 +35,7 @@ extern MScore* mscore;
MCursor::MCursor(MasterScore* s)
{
_score = s;
move(0, 0);
move(0, Fraction(0,1));
}
//---------------------------------------------------------
@ -46,7 +46,7 @@ void MCursor::createMeasures()
{
Measure* measure;
for (;;) {
int tick = 0;
Fraction tick = Fraction(0,1);
measure = _score->lastMeasure();
if (measure) {
tick = measure->tick() + measure->ticks();
@ -56,7 +56,7 @@ void MCursor::createMeasures()
measure = new Measure(_score);
measure->setTick(tick);
measure->setTimesig(_sig);
measure->setLen(_sig);
measure->setTicks(_sig);
_score->measures()->add(measure);
}
}
@ -75,7 +75,7 @@ Chord* MCursor::addChord(int pitch, const TDuration& duration)
chord = new Chord(_score);
chord->setTrack(_track);
chord->setDurationType(duration);
chord->setDuration(duration.fraction());
chord->setTicks(duration.fraction());
segment->add(chord);
}
Note* note = new Note(_score);
@ -120,7 +120,7 @@ TimeSig* MCursor::addTimeSig(const Fraction& f)
ts->setTrack(i * VOICES);
segment->add(ts);
}
_score->sigmap()->add(_tick, SigEvent(f));
_score->sigmap()->add(_tick.ticks(), SigEvent(f));
return ts;
}
@ -133,14 +133,14 @@ void MCursor::createScore(const QString& name)
delete _score;
_score = new MasterScore(mscore->baseStyle());
_score->setName(name);
move(0, 0);
move(0, Fraction(0,1));
}
//---------------------------------------------------------
// move
//---------------------------------------------------------
void MCursor::move(int t, int tick)
void MCursor::move(int t, const Fraction& tick)
{
_track = t;
_tick = tick;

View file

@ -31,7 +31,7 @@ enum class Key;
class MCursor {
MasterScore* _score;
int _tick;
Fraction _tick;
int _track;
Fraction _sig;
@ -47,10 +47,10 @@ class MCursor {
void addKeySig(Key);
TimeSig* addTimeSig(const Fraction&);
void move(int track, int tick);
void move(int track, const Fraction& tick);
MasterScore* score() const { return _score; }
void setScore(MasterScore* s) { _score = s; }
void setTimeSig(Fraction f) { _sig = f; }
void setTimeSig(Fraction f) { _sig = f; }
};

View file

@ -193,8 +193,9 @@ void MStaff::setTrack(int track)
//---------------------------------------------------------
Measure::Measure(Score* s)
: MeasureBase(s), _timesig(4,4), _len(4,4)
: MeasureBase(s), _timesig(4,4)
{
setTicks(Fraction(4,4));
_repeatCount = 2;
int n = score()->nstaves();
@ -432,21 +433,21 @@ AccidentalVal Measure::findAccidental(Segment* s, int staffIdx, int line, bool &
// return x position for tick relative to System
//---------------------------------------------------------
qreal Measure::tick2pos(int tck) const
qreal Measure::tick2pos(Fraction tck) const
{
tck -= ticks();
if (isMMRest()) {
Segment* s = first(SegmentType::ChordRest);
qreal x1 = s->x();
qreal w = width() - x1;
return x1 + (tck * w) / (ticks() * mmRestCount());
return x1 + (tck.ticks() * w) / (ticks().ticks() * mmRestCount());
}
Segment* s;
qreal x1 = 0;
qreal x2 = 0;
int tick1 = 0;
int tick2 = 0;
Fraction tick1 = Fraction(0,1);
Fraction tick2 = Fraction(0,1);
for (s = first(SegmentType::ChordRest); s; s = s->next(SegmentType::ChordRest)) {
x2 = s->x();
tick2 = s->rtick();
@ -462,8 +463,8 @@ qreal Measure::tick2pos(int tck) const
tick2 = ticks();
}
qreal dx = x2 - x1;
int dt = tick2 - tick1;
x1 += (dt == 0) ? 0.0 : (dx * (tck - tick1) / dt);
Fraction dt = tick2 - tick1;
x1 += dt.isZero() ? 0.0 : (dx * (tck.ticks() - tick1.ticks()) / dt.ticks());
return x1 + pos().x();
}
@ -671,7 +672,7 @@ void Measure::layout2()
/// Search for chord at position \a tick in \a track
//---------------------------------------------------------
Chord* Measure::findChord(int t, int track)
Chord* Measure::findChord(Fraction t, int track)
{
t -= tick();
for (Segment* seg = last(); seg; seg = seg->prev()) {
@ -691,7 +692,7 @@ Chord* Measure::findChord(int t, int track)
/// Search for chord or rest at position \a tick at \a staff in \a voice.
//---------------------------------------------------------
ChordRest* Measure::findChordRest(int t, int track)
ChordRest* Measure::findChordRest(Fraction t, int track)
{
t -= tick();
for (const Segment& seg : _segments) {
@ -710,9 +711,9 @@ ChordRest* Measure::findChordRest(int t, int track)
// tick2segment
//---------------------------------------------------------
Segment* Measure::tick2segment(int t, SegmentType st)
Segment* Measure::tick2segment(const Fraction& _t, SegmentType st)
{
t -= tick();
Fraction t = _t - tick();
for (Segment& s : _segments) {
if (s.rtick() == t) {
if (s.segmentType() & st)
@ -724,55 +725,16 @@ Segment* Measure::tick2segment(int t, SegmentType st)
return 0;
}
//---------------------------------------------------------
// findSegment
/// Search for a segment of type \a st at position \a t.
//---------------------------------------------------------
Segment* Measure::findSegment(SegmentType st, int t) const
{
t -= tick();
Segment* s;
if (t > ticks()/2) {
// search backwards
for (s = last(); s && s->rtick() > t; s = s->prev())
;
while (s && s->prev() && s->prev()->rtick() == t)
s = s->prev();
}
else {
// search forwards
for (s = first(); s && s->rtick() < t; s = s->next())
;
}
for (; s && s->rtick() == t; s = s->next()) {
if (s->segmentType() & st)
return s;
}
return 0;
}
//---------------------------------------------------------
// getSegment
/// Get a segment of type \a st at tick position \a t.
/// If the segment does not exist, it is created.
//---------------------------------------------------------
Segment* Measure::getSegment(SegmentType st, int t)
{
return getSegmentR(st, t - tick());
}
//---------------------------------------------------------
// findSegmentR
// Search for a segment of type st at relative
// Search for a segment of type st at measure relative
// position t.
//---------------------------------------------------------
Segment* Measure::findSegmentR(SegmentType st, int t) const
Segment* Measure::findSegmentR(SegmentType st, const Fraction& t) const
{
Segment* s;
if (t > ticks()/2) {
if (t > (ticks() * Fraction(1,2))) {
// search backwards
for (s = last(); s && s->rtick() > t; s = s->prev())
;
@ -792,12 +754,26 @@ Segment* Measure::findSegmentR(SegmentType st, int t) const
}
//---------------------------------------------------------
// findFirst
// undoGetSegmentR
//---------------------------------------------------------
Segment* Measure::undoGetSegmentR(SegmentType type, const Fraction& t)
{
Segment* s = findSegmentR(type, t);
if (s == 0) {
s = new Segment(this, type, t);
score()->undoAddElement(s);
}
return s;
}
//---------------------------------------------------------
// findFirstR
// return first segment of type st at relative
// position t.
//---------------------------------------------------------
Segment* Measure::findFirst(SegmentType st, int t) const
Segment* Measure::findFirstR(SegmentType st, const Fraction& t) const
{
Segment* s;
// search forwards
@ -810,11 +786,11 @@ Segment* Measure::findFirst(SegmentType st, int t) const
//---------------------------------------------------------
// getSegmentR
/// Get a segment of type \a st at relative tick position \a t.
/// Get a segment of type st at relative tick position t.
/// If the segment does not exist, it is created.
//---------------------------------------------------------
Segment* Measure::getSegmentR(SegmentType st, int t)
Segment* Measure::getSegmentR(SegmentType st, const Fraction& t)
{
Segment* s = findSegmentR(st, t);
if (!s) {
@ -824,29 +800,6 @@ Segment* Measure::getSegmentR(SegmentType st, int t)
return s;
}
//---------------------------------------------------------
// undoGetSegment
//---------------------------------------------------------
Segment* Measure::undoGetSegment(SegmentType type, int t)
{
return undoGetSegmentR(type, t-tick());
}
//---------------------------------------------------------
// undoGetSegmentR
//---------------------------------------------------------
Segment* Measure::undoGetSegmentR(SegmentType type, int t)
{
Segment* s = findSegmentR(type, t);
if (s == 0) {
s = new Segment(this, type, t);
score()->undoAddElement(s);
}
return s;
}
//---------------------------------------------------------
// add
/// Add new Element \a el to Measure.
@ -860,8 +813,8 @@ void Measure::add(Element* e)
switch (type) {
case ElementType::SEGMENT:
{
Segment* seg = toSegment(e);
int t = seg->rtick();
Segment* seg = toSegment(e);
Fraction t = seg->rtick();
SegmentType st = seg->segmentType();
Segment* s;
@ -1042,25 +995,25 @@ void Measure::spatiumChanged(qreal /*oldValue*/, qreal /*newValue*/)
// diff == 0 cannot be optimized away
//-------------------------------------------------------------------
void Measure::moveTicks(int diff)
void Measure::moveTicks(const Fraction& diff)
{
std::set<Tuplet*> tuplets;
setTick(tick() + diff);
for (Segment* segment = last(); segment; segment = segment->prev()) {
if (segment->segmentType() & (SegmentType::EndBarLine | SegmentType::TimeSigAnnounce))
segment->setTick(tick() + ticks());
else if (segment->isChordRestType())
segment->setRtick(ticks());
else if (segment->isChordRestType()) {
// Tuplet ticks are stored as absolute ticks, so they must be adjusted.
// But each tuplet must only be adjusted once.
for (Element* e : segment->elist())
for (Element* e : segment->elist()) {
if (e) {
ChordRest* cr = toChordRest(e);
Tuplet* tuplet = cr->tuplet();
if (tuplet && tuplets.count(tuplet) == 0) {
tuplet->setTick(tuplet->tick() + diff);
if (tuplet && tuplets.count(tuplet) == 0)
tuplets.insert(tuplet);
}
}
}
}
}
tuplets.clear();
}
@ -1201,7 +1154,7 @@ void Measure::cmdAddStaves(int sStaff, int eStaff, bool createRest)
for (int staffIdx : sl) {
if (createRest)
score()->setRest(tick(), staffIdx * VOICES, len(), false, 0, _timesig == len());
score()->setRest(tick(), staffIdx * VOICES, ticks(), false, 0, _timesig == ticks());
// replicate time signature
if (ts) {
@ -1456,8 +1409,7 @@ Element* Measure::drop(EditData& data)
}
case ElementType::TIMESIG:
score()->cmdAddTimeSig(this, staffIdx, toTimeSig(e),
data.modifiers & Qt::ControlModifier);
score()->cmdAddTimeSig(this, staffIdx, toTimeSig(e), data.modifiers & Qt::ControlModifier);
return 0;
case ElementType::LAYOUT_BREAK: {
@ -1663,7 +1615,7 @@ RepeatMeasure* Measure::cmdInsertRepeatMeasure(int staffIdx)
rm->setTrack(staffIdx * VOICES);
rm->setParent(seg);
rm->setDurationType(TDuration::DurationType::V_MEASURE);
rm->setDuration(stretchedLen(score()->staff(staffIdx)));
rm->setTicks(stretchedLen(score()->staff(staffIdx)));
score()->undoAddCR(rm, this, tick());
for (Element* e : el()) {
if (e->isSlur() && e->staffIdx() == staffIdx)
@ -1680,12 +1632,12 @@ RepeatMeasure* Measure::cmdInsertRepeatMeasure(int staffIdx)
void Measure::adjustToLen(Fraction nf, bool appendRestsIfNecessary)
{
int ol = len().ticks();
int nl = nf.ticks();
int diff = nl - ol;
Fraction ol = ticks();
Fraction nl = nf;
Fraction diff = nl - ol;
int startTick = endTick();
if (diff < 0)
Fraction startTick = endTick();
if (diff < Fraction(0,1))
startTick += diff;
score()->undoInsertTime(startTick, diff);
@ -1698,7 +1650,7 @@ void Measure::adjustToLen(Fraction nf, bool appendRestsIfNecessary)
// move EndBarLine, TimeSigAnnounce, KeySigAnnounce
for (Segment* seg = m->first(); seg; seg = seg->next()) {
if (seg->segmentType() & (SegmentType::EndBarLine|SegmentType::TimeSigAnnounce|SegmentType::KeySigAnnounce)) {
seg->setTick(tick() + nl);
seg->setRtick(nl);
}
}
}
@ -1750,11 +1702,11 @@ void Measure::adjustToLen(Fraction nf, bool appendRestsIfNecessary)
}
// add rests for any other duration list value
int tickOffset = tick() + rest->actualTicks();
Fraction tickOffset = tick() + rest->actualTicks();
for (unsigned i = 1; i < durList.size(); i++) {
Rest* newRest = new Rest(s);
newRest->setDurationType(durList.at(i));
newRest->setDuration(durList.at(i).fraction());
newRest->setTicks(durList.at(i).fraction());
newRest->setTrack(rest->track());
score()->undoAddCR(newRest, this, tickOffset);
tickOffset += newRest->actualTicks();
@ -1768,9 +1720,9 @@ void Measure::adjustToLen(Fraction nf, bool appendRestsIfNecessary)
int etrack = strack + VOICES;
for (int trk = strack; trk < etrack; ++trk) {
int n = diff;
Fraction n = diff;
bool rFlag = false;
if (n < 0) {
if (n < Fraction(0,1)) {
for (Segment* segment = m->last(); segment;) {
Segment* pseg = segment->prev();
if (segment->segmentType() == SegmentType::ChordRest) {
@ -1781,14 +1733,14 @@ void Measure::adjustToLen(Fraction nf, bool appendRestsIfNecessary)
if (e && e->isChordRest()) {
ChordRest* cr = toChordRest(e);
if (cr->durationType() == TDuration::DurationType::V_MEASURE) {
int actualTicks = cr->actualTicks();
Fraction actualTicks = cr->actualTicks();
n += actualTicks;
cr->setDurationType(TDuration(Fraction::fromTicks(actualTicks)));
cr->setDurationType(TDuration(actualTicks));
}
else
n += cr->actualTicks();
s->undoRemoveElement(e);
if (n >= 0)
if (n >= Fraction(0,1))
break;
}
}
@ -1802,15 +1754,15 @@ void Measure::adjustToLen(Fraction nf, bool appendRestsIfNecessary)
rFlag = true;
}
int voice = trk % VOICES;
if (appendRestsIfNecessary && (n > 0) && (rFlag || voice == 0)) {
if (appendRestsIfNecessary && (n > Fraction(0,1)) && (rFlag || voice == 0)) {
// add rest to measure
int rtick = tick() + nl - n;
Fraction rtick = tick() + nl - n;
int track = staffIdx * VOICES + voice;
s->setRest(rtick, track, Fraction::fromTicks(n) * stretch, false, 0, false);
s->setRest(rtick, track, n * stretch, false, 0, false);
}
}
}
if (diff < 0) {
if (diff < Fraction(0,1)) {
//
// CHECK: do not remove all slurs
//
@ -1887,15 +1839,6 @@ void Measure::write(XmlWriter& xml, int staff, bool writeSystemElements, bool fo
xml.etag();
}
//---------------------------------------------------------
// ticks
//---------------------------------------------------------
int Measure::ticks() const
{
return _len.ticks();
}
//---------------------------------------------------------
// Measure::read
//---------------------------------------------------------
@ -1925,8 +1868,8 @@ void Measure::read(XmlReader& e, int staffIdx)
else
qDebug("illegal measure size <%s>", qPrintable(e.attribute("len")));
irregular = true;
score()->sigmap()->add(tick(), SigEvent(_len, _timesig));
score()->sigmap()->add(tick() + ticks(), SigEvent(_timesig));
score()->sigmap()->add(tick().ticks(), SigEvent(_len, _timesig));
score()->sigmap()->add((tick() + ticks()).ticks(), SigEvent(_timesig));
}
else
irregular = false;
@ -1936,7 +1879,7 @@ void Measure::read(XmlReader& e, int staffIdx)
if (tag == "voice") {
e.setTrack(nextTrack++);
e.initTick(tick());
e.setTick(tick());
readVoice(e, staffIdx, irregular);
}
else if (tag == "Marker" || tag == "Jump") {
@ -2007,7 +1950,7 @@ void Measure::read(XmlReader& e, int staffIdx)
_mmRestCount = e.readInt();
// set tick to previous measure
setTick(e.lastMeasure()->tick());
e.initTick(e.lastMeasure()->tick());
e.setTick(e.lastMeasure()->tick());
}
else if (tag == "MeasureNumber") {
MeasureNumber* noText = new MeasureNumber(score());
@ -2023,7 +1966,7 @@ void Measure::read(XmlReader& e, int staffIdx)
e.checkConnectors();
if (isMMRest()) {
Measure* lm = e.lastMeasure();
e.initTick(lm->tick() + lm->ticks());
e.setTick(lm->tick() + lm->ticks());
}
e.setCurrentMeasure(nullptr);
}
@ -2051,8 +1994,9 @@ void Measure::readVoice(XmlReader& e, int staffIdx, bool irregular)
loc.read(e);
e.setLocation(loc);
}
else if (tag == "tick") {
e.initTick(score()->fileDivision(e.readInt()));
else if (tag == "tick") { // obsolete?
qDebug("read midi tick");
e.setTick(Fraction::fromTicks(score()->fileDivision(e.readInt())));
}
else if (tag == "BarLine") {
BarLine* barLine = new BarLine(score());
@ -2065,17 +2009,17 @@ void Measure::readVoice(XmlReader& e, int staffIdx, bool irregular)
// BeginBarLine: first segment of a measure, systemic barline
SegmentType st = SegmentType::Invalid;
int t = e.tick() - tick();
if (t && (t != ticks()))
Fraction t = e.tick() - tick();
if (t.isNotZero() && (t != ticks()))
st = SegmentType::BarLine;
else if (barLine->barLineType() == BarLineType::START_REPEAT && t == 0)
else if (barLine->barLineType() == BarLineType::START_REPEAT && t.isZero())
st = SegmentType::StartRepeatBarLine;
else if (barLine->barLineType() == BarLineType::START_REPEAT && t == ticks()) {
// old version, ignore
delete barLine;
barLine = 0;
}
else if (t == 0 && segment == 0)
else if (t.isZero() && segment == 0)
st = SegmentType::BeginBarLine;
else
st = SegmentType::EndBarLine;
@ -2097,8 +2041,8 @@ void Measure::readVoice(XmlReader& e, int staffIdx, bool irregular)
startingBeam->add(chord); // also calls chord->setBeam(startingBeam)
startingBeam = nullptr;
}
if (tuplet && !chord->isGrace())
chord->readAddTuplet(tuplet);
// if (tuplet && !chord->isGrace())
// chord->readAddTuplet(tuplet);
segment = getSegment(SegmentType::ChordRest, e.tick());
if (chord->noteType() != NoteType::NORMAL)
graceNotes.push_back(chord);
@ -2110,8 +2054,9 @@ void Measure::readVoice(XmlReader& e, int staffIdx, bool irregular)
chord->add(gc);
}
graceNotes.clear();
int crticks = chord->actualTicks();
e.incTick(crticks);
if (tuplet)
tuplet->add(chord);
e.incTick(chord->actualTicks());
}
if (fermata) {
segment->add(fermata);
@ -2121,15 +2066,13 @@ void Measure::readVoice(XmlReader& e, int staffIdx, bool irregular)
else if (tag == "Rest") {
Rest* rest = new Rest(score());
rest->setDurationType(TDuration::DurationType::V_MEASURE);
rest->setDuration(timesig()/timeStretch);
rest->setTicks(timesig()/timeStretch);
rest->setTrack(e.track());
rest->read(e);
if (startingBeam) {
startingBeam->add(rest); // also calls rest->setBeam(startingBeam)
startingBeam = nullptr;
}
if (tuplet)
rest->readAddTuplet(tuplet);
segment = getSegment(SegmentType::ChordRest, e.tick());
segment->add(rest);
if (fermata) {
@ -2137,17 +2080,18 @@ void Measure::readVoice(XmlReader& e, int staffIdx, bool irregular)
fermata = nullptr;
}
if (!rest->duration().isValid()) // hack
rest->setDuration(timesig()/timeStretch);
if (!rest->ticks().isValid()) // hack
rest->setTicks(timesig()/timeStretch);
if (tuplet)
tuplet->add(rest);
e.incTick(rest->actualTicks());
}
else if (tag == "Breath") {
Breath* breath = new Breath(score());
breath->setTrack(e.track());
int tick = e.tick();
breath->read(e);
segment = getSegment(SegmentType::Breath, tick);
segment = getSegment(SegmentType::Breath, e.tick());
segment->add(breath);
}
else if (tag == "Spanner")
@ -2176,7 +2120,7 @@ void Measure::readVoice(XmlReader& e, int staffIdx, bool irregular)
header = true;
else {
header = true;
for (Segment* s = _segments.first(); s && !s->rtick(); s = s->next()) {
for (Segment* s = _segments.first(); s && s->rtick().isZero(); s = s->next()) {
if (s->isKeySigType() || s->isTimeSigType()) {
// hack: there may be other segment types which should
// generate a clef at current position
@ -2193,7 +2137,7 @@ void Measure::readVoice(XmlReader& e, int staffIdx, bool irregular)
ts->setTrack(e.track());
ts->read(e);
// if time sig not at beginning of measure => courtesy time sig
int currTick = e.tick();
Fraction currTick = e.tick();
bool courtesySig = (currTick > tick());
if (courtesySig) {
// if courtesy sig., just add it without map processing
@ -2209,12 +2153,12 @@ void Measure::readVoice(XmlReader& e, int staffIdx, bool irregular)
_timesig = ts->sig() / timeStretch;
if (irregular) {
score()->sigmap()->add(tick(), SigEvent(_len, _timesig));
score()->sigmap()->add(tick() + ticks(), SigEvent(_timesig));
score()->sigmap()->add(tick().ticks(), SigEvent(_len, _timesig));
score()->sigmap()->add((tick() + ticks()).ticks(), SigEvent(_timesig));
}
else {
_len = _timesig;
score()->sigmap()->add(tick(), SigEvent(_timesig));
score()->sigmap()->add(tick().ticks(), SigEvent(_timesig));
}
}
}
@ -2222,14 +2166,13 @@ void Measure::readVoice(XmlReader& e, int staffIdx, bool irregular)
KeySig* ks = new KeySig(score());
ks->setTrack(e.track());
ks->read(e);
int curTick = e.tick();
if (!ks->isCustom() && !ks->isAtonal() && ks->key() == Key::C && curTick == 0) {
Fraction curTick = e.tick();
if (!ks->isCustom() && !ks->isAtonal() && ks->key() == Key::C && curTick.isZero()) {
// ignore empty key signature
qDebug("remove keysig c at tick 0");
}
else {
// if key sig not at beginning of measure => courtesy key sig
// bool courtesySig = (curTick > tick());
bool courtesySig = (curTick == endTick());
segment = getSegment(courtesySig ? SegmentType::KeySigAnnounce : SegmentType::KeySig, curTick);
segment->add(ks);
@ -2307,7 +2250,7 @@ void Measure::readVoice(XmlReader& e, int staffIdx, bool irregular)
tuplet->setParent(this);
tuplet->read(e);
if (oldTuplet)
tuplet->readAddTuplet(oldTuplet);
oldTuplet->add(tuplet);
}
else if (tag == "endTuplet") {
if (!tuplet) {
@ -2389,8 +2332,8 @@ void Measure::readAddConnector(ConnectorInfoReader* info, bool pasteMode)
{
Spanner* sp = toSpanner(info->connector());
const Location& l = info->location();
const int lTick = l.frac().ticks();
const int spTick = pasteMode ? lTick : (tick() + lTick);
Fraction lTick = l.frac();
Fraction spTick = pasteMode ? lTick : (tick() + lTick);
if (info->isStart()) {
sp->setTrack(l.track());
sp->setTick(spTick);
@ -2461,8 +2404,8 @@ bool Measure::isFinalMeasureOfSection() const
bool Measure::isAnacrusis() const
{
TimeSigFrac timeSig = score()->sigmap()->timesig(tick()).nominal();
return irregular() && ticks() < timeSig.ticksPerMeasure();
TimeSigFrac timeSig = score()->sigmap()->timesig(tick().ticks()).nominal();
return irregular() && ticks() < Fraction::fromTicks(timeSig.ticksPerMeasure());
}
//---------------------------------------------------------
@ -2508,7 +2451,7 @@ void Measure::createVoice(int track)
if (s->segmentType() != SegmentType::ChordRest)
continue;
if (s->element(track) == 0)
score()->setRest(s->tick(), track, len(), true, 0);
score()->setRest(s->tick(), track, ticks(), true, 0);
break;
}
}
@ -2549,14 +2492,14 @@ void Measure::exchangeVoice(int strack, int dtrack, int staffIdx)
s->swapElements(strack, dtrack);
}
auto spanners = score()->spannerMap().findOverlapping(tick(), endTick()-1);
int start = tick();
int end = start + ticks();
auto spanners = score()->spannerMap().findOverlapping(tick().ticks(), endTick().ticks()-1);
Fraction start = tick();
Fraction end = start + ticks();
for (auto i = spanners.begin(); i < spanners.end(); i++) {
Spanner* sp = i->value;
int spStart = sp->tick();
int spEnd = spStart + sp->ticks();
qDebug("Start %d End %d Diff %d \n Measure Start %d End %d", spStart, spEnd, spEnd-spStart, start, end);
Fraction spStart = sp->tick();
Fraction spEnd = spStart + sp->ticks();
qDebug("Start %d End %d Diff %d \n Measure Start %d End %d", spStart.ticks(), spEnd.ticks(), (spEnd-spStart).ticks(), start.ticks(), end.ticks());
if (sp->isSlur() && (spStart >= start || spEnd < end)) {
if (sp->track() == strack && spStart >= start){
sp->setTrack(dtrack);
@ -2785,7 +2728,7 @@ bool Measure::isOnlyDeletedRests(int track) const
Fraction Measure::stretchedLen(Staff* staff) const
{
return len() * staff->timeStretch(tick());
return ticks() * staff->timeStretch(tick());
}
//---------------------------------------------------------
@ -2892,10 +2835,10 @@ Measure* Measure::cloneMeasure(Score* sc, TieMap* tieMap)
}
//---------------------------------------------------------
// pos2sel
// snap
//---------------------------------------------------------
int Measure::snap(int tick, const QPointF p) const
Fraction Measure::snap(const Fraction& tick, const QPointF p) const
{
Segment* s = first();
for (; s->next(); s = s->next()) {
@ -2917,7 +2860,7 @@ int Measure::snap(int tick, const QPointF p) const
// snapNote
//---------------------------------------------------------
int Measure::snapNote(int /*tick*/, const QPointF p, int staff) const
Fraction Measure::snapNote(const Fraction& /*tick*/, const QPointF p, int staff) const
{
Segment* s = first();
for (;;) {
@ -3141,7 +3084,7 @@ void Measure::stretchMeasure(qreal targetWidth)
{
bbox().setWidth(targetWidth);
int minTick = computeTicks();
Fraction minTick = computeTicks();
//---------------------------------------------------
// compute stretch
@ -3156,9 +3099,9 @@ void Measure::stretchMeasure(qreal targetWidth)
for (Segment& s : _segments) {
if (!s.enabled())
continue;
int t = s.ticks();
if (t) {
qreal str = 1.0 + 0.865617 * log(qreal(t) / qreal(minTick)); // .6 * log(t / minTick) / log(2);
Fraction t = s.ticks();
if (t.isNotZero()) {
qreal str = 1.0 + 0.865617 * log(qreal(t.ticks()) / qreal(minTick.ticks())); // .6 * log(t / minTick.ticks()) / log(2);
qreal d = s.width() / str;
s.setStretch(str);
springs.insert(std::pair<qreal, Segment*>(d, &s));
@ -3281,12 +3224,13 @@ void Measure::stretchMeasure(qreal targetWidth)
// return minTick
//---------------------------------------------------
int Measure::computeTicks() {
int minTick = ticks();
if (minTick <= 0) {
qDebug("=====minTick %d measure %p", minTick, this);
Fraction Measure::computeTicks()
{
Fraction minTick = ticks();
if (minTick <= Fraction(0,1)) {
qDebug("=====minTick %d measure %p", minTick.ticks(), this);
}
Q_ASSERT(minTick > 0);
Q_ASSERT(minTick > Fraction(0,1));
Segment* ns = first();
while (ns && !ns->enabled())
@ -3294,16 +3238,15 @@ int Measure::computeTicks() {
while (ns) {
Segment* s = ns;
ns = s->nextEnabled();
int nticks = (ns ? ns->rtick() : ticks()) - s->rtick();
if (nticks) {
Fraction nticks = (ns ? ns->rtick() : ticks()) - s->rtick();
if (nticks.isNotZero()) {
if (nticks < minTick)
minTick = nticks;
}
s->setTicks(nticks);
}
return minTick;
}
}
//---------------------------------------------------------
// endBarLine
@ -3457,10 +3400,10 @@ qreal Measure::createEndBarLines(bool isLastMeasureInSystem)
setHasCourtesyKeySig(false);
if (isLastMeasureInSystem && show) {
int tick = endTick();
Fraction tick = endTick();
for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) {
Staff* staff = score()->staff(staffIdx);
KeySigEvent key1 = staff->keySigEvent(tick - 1);
KeySigEvent key1 = staff->keySigEvent(tick - Fraction::fromTicks(1));
KeySigEvent key2 = staff->keySigEvent(tick);
if (!(key1 == key2)) {
// locate a key sig. in next measure and, if found,
@ -3582,8 +3525,8 @@ qreal Measure::basicWidth() const
void Measure::addSystemHeader(bool isFirstSystem)
{
int staffIdx = 0;
Segment* kSegment = findFirst(SegmentType::KeySig, 0);
Segment* cSegment = findFirst(SegmentType::HeaderClef, 0);
Segment* kSegment = findFirstR(SegmentType::KeySig, Fraction(0,1));
Segment* cSegment = findFirstR(SegmentType::HeaderClef, Fraction(0,1));
for (const Staff* staff : score()->staves()) {
const int track = staffIdx * VOICES;
@ -3619,7 +3562,7 @@ void Measure::addSystemHeader(bool isFirstSystem)
if (needKeysig) {
KeySig* keysig;
if (!kSegment) {
kSegment = new Segment(this, SegmentType::KeySig, 0);
kSegment = new Segment(this, SegmentType::KeySig, Fraction(0,1));
kSegment->setHeader(true);
add(kSegment);
keysig = 0;
@ -3674,7 +3617,7 @@ void Measure::addSystemHeader(bool isFirstSystem)
if (isFirstSystem || score()->styleB(Sid::genClef)) {
// find the clef type at the previous tick
ClefTypeList cl = staff->clefType(tick() - 1);
ClefTypeList cl = staff->clefType(tick() - Fraction::fromTicks(1));
// look for a clef change at the end of the previous measure
if (prevMeasure()) {
Segment* s = prevMeasure()->findSegment(SegmentType::Clef, tick());
@ -3686,7 +3629,7 @@ void Measure::addSystemHeader(bool isFirstSystem)
}
Clef* clef;
if (!cSegment) {
cSegment = new Segment(this, SegmentType::HeaderClef, 0);
cSegment = new Segment(this, SegmentType::HeaderClef, Fraction(0,1));
cSegment->setHeader(true);
add(cSegment);
clef = 0;
@ -3729,7 +3672,7 @@ void Measure::addSystemHeader(bool isFirstSystem)
int n = score()->nstaves();
if ((n > 1 && score()->styleB(Sid::startBarlineMultiple)) || (n == 1 && score()->styleB(Sid::startBarlineSingle))) {
if (!s) {
s = new Segment(this, SegmentType::BeginBarLine, 0);
s = new Segment(this, SegmentType::BeginBarLine, Fraction(0,1));
add(s);
}
for (int track = 0; track < score()->ntracks(); track += VOICES) {
@ -3761,7 +3704,7 @@ void Measure::addSystemHeader(bool isFirstSystem)
void Measure::addSystemTrailer(Measure* nm)
{
int _rtick = ticks();
Fraction _rtick = ticks();
bool isFinalMeasure = isFinalMeasureOfSection();
// locate a time sig. in the next measure and, if found,
@ -3770,7 +3713,7 @@ void Measure::addSystemTrailer(Measure* nm)
bool showCourtesySig = false;
Segment* s = findSegmentR(SegmentType::TimeSigAnnounce, _rtick);
if (score()->genCourtesyTimesig() && !isFinalMeasure && !score()->floatMode()) {
Segment* tss = nm->findSegmentR(SegmentType::TimeSig, 0);
Segment* tss = nm->findSegmentR(SegmentType::TimeSig, Fraction(0,1));
if (tss) {
ts = toTimeSig(tss->element(0));
if (ts && ts->showCourtesySig()) {
@ -3943,7 +3886,7 @@ void Measure::setStretchedWidth(qreal w)
continue;
stretchableWidth += s->width();
}
w += stretchableWidth * (basicStretch()-1.0) * ticks() / 1920.0;
w += stretchableWidth * (basicStretch()-1.0) * ticks().ticks() / 1920.0;
}
setWidth(w);
}
@ -3967,20 +3910,6 @@ static bool hasAccidental(Segment* s)
return false;
}
//---------------------------------------------------------
// dumpMeasure
//---------------------------------------------------------
#if 0
static void dumpMeasure(Measure* m)
{
printf("Measure tick %d width %f\n", m->tick(), m->width());
for (Segment* s = m->first(); s; s = s->next()) {
printf(" %04d %16s %f %f\n", s->rtick(), s->subTypeName(), s->x(), s->width());
}
}
#endif
//---------------------------------------------------------
// computeMinWidth
// sets the minimum stretched width of segment list s
@ -3995,7 +3924,7 @@ void Measure::computeMinWidth(Segment* s, qreal x, bool isSystemHeader)
if (isMMRest()) {
// Reset MM rest to initial size and position
Segment* seg = findSegmentR(SegmentType::ChordRest, 0);
Segment* seg = findSegmentR(SegmentType::ChordRest, Fraction(0,1));
const int nstaves = score()->nstaves();
for (int st = 0; st < nstaves; ++st) {
Rest* mmRest = toRest(seg->element(staff2track(st)));

View file

@ -70,7 +70,6 @@ class Measure final : public MeasureBase {
qreal _userStretch;
Fraction _timesig;
Fraction _len; ///< actual length of measure
int _mmRestCount; // > 0 if this is a multi measure rest
// 0 if this is the start of a mm rest (_mmRest != 0)
@ -137,47 +136,45 @@ class Measure final : public MeasureBase {
Fraction timesig() const { return _timesig; }
void setTimesig(const Fraction& f) { _timesig = f; }
Fraction len() const { return _len; }
Fraction stretchedLen(Staff*) const;
void setLen(const Fraction& f) { _len = f; }
virtual int ticks() const override; // actual length of measure in ticks
bool isIrregular() const { return _timesig != _len; }
int size() const { return _segments.size(); }
Ms::Segment* first() const { return _segments.first(); }
Segment* first(SegmentType t) const { return _segments.first(t); }
Segment* firstEnabled() const { return _segments.first(ElementFlag::ENABLED); }
int size() const { return _segments.size(); }
Ms::Segment* first() const { return _segments.first(); }
Segment* first(SegmentType t) const { return _segments.first(t); }
Segment* firstEnabled() const { return _segments.first(ElementFlag::ENABLED); }
Ms::Segment* last() const { return _segments.last(); }
SegmentList& segments() { return _segments; }
const SegmentList& segments() const { return _segments; }
Ms::Segment* last() const { return _segments.last(); }
SegmentList& segments() { return _segments; }
const SegmentList& segments() const { return _segments; }
qreal userStretch() const;
void setUserStretch(qreal v) { _userStretch = v; }
void setUserStretch(qreal v) { _userStretch = v; }
void stretchMeasure(qreal stretch);
int computeTicks();
Fraction computeTicks();
void layout2();
void layoutMeasureNumber();
Chord* findChord(int tick, int track);
ChordRest* findChordRest(int tick, int track);
int snap(int tick, const QPointF p) const;
int snapNote(int tick, const QPointF p, int staff) const;
Chord* findChord(Fraction tick, int track);
ChordRest* findChordRest(Fraction tick, int track);
Fraction snap(const Fraction& tick, const QPointF p) const;
Fraction snapNote(const Fraction& tick, const QPointF p, int staff) const;
void insertStaff(Staff*, int staff);
void insertMStaff(MStaff* staff, int idx);
void removeMStaff(MStaff* staff, int idx);
virtual void moveTicks(int diff);
virtual void moveTicks(const Fraction& diff) override;
void cmdRemoveStaves(int s, int e);
void cmdAddStaves(int s, int e, bool createRest);
void removeStaves(int s, int e);
void insertStaves(int s, int e);
qreal tick2pos(int) const;
Segment* tick2segment(int tick, SegmentType st = SegmentType::ChordRest);
qreal tick2pos(Fraction) const;
Segment* tick2segment(const Fraction& tick, SegmentType st = SegmentType::ChordRest);
void sortStaves(QList<int>& dst);
@ -187,19 +184,16 @@ class Measure final : public MeasureBase {
int repeatCount() const { return _repeatCount; }
void setRepeatCount(int val) { _repeatCount = val; }
Segment* undoGetSegment(SegmentType st, int tick); // deprecated
Segment* getSegment(SegmentType st, int tick); // deprecated
Segment* findSegment(SegmentType st, int tick) const; // deprecated
Segment* findSegmentR(SegmentType st, const Fraction&) const;
Segment* undoGetSegmentR(SegmentType st, const Fraction& f);
Segment* getSegmentR(SegmentType st, const Fraction& f);
Segment* findFirstR(SegmentType st, const Fraction& rtick) const;
Segment* undoGetSegmentR(SegmentType st, int rtick);
Segment* getSegmentR(SegmentType st, int rtick);
Segment* findSegmentR(SegmentType st, int rtick) const;
// segment routines with absolute tick values
Segment* findSegment(SegmentType st, const Fraction& f) const { return findSegmentR(st, f - tick()); }
Segment* undoGetSegment(SegmentType st, const Fraction& f) { return undoGetSegmentR(st, f - tick()); }
Segment* getSegment(SegmentType st, const Fraction& f) { return getSegmentR(st, f - tick()); }
// preferred:
Segment* undoGetSegment(SegmentType st, const Fraction& f) { return undoGetSegmentR(st, f.ticks()); }
Segment* getSegment(SegmentType st, const Fraction& f) { return getSegmentR(st, f.ticks()); }
Segment* findFirst(SegmentType st, int rtick) const;
qreal createEndBarLines(bool);
void barLinesSetSpan(Segment*);

View file

@ -542,15 +542,6 @@ bool MeasureBase::readProperties(XmlReader& e)
return true;
}
//---------------------------------------------------------
// afrac
//---------------------------------------------------------
Fraction MeasureBase::afrac() const
{
return Fraction::fromTicks(_tick);
}
//---------------------------------------------------------
// index
//---------------------------------------------------------

View file

@ -64,11 +64,12 @@ class MeasureBase : public Element {
ElementList _el; ///< Measure(/tick) relative -elements: with defined start time
///< but outside the staff
int _tick { 0 };
Fraction _tick { Fraction(0, 1) };
int _no { 0 }; ///< Measure number, counting from zero
int _noOffset { 0 }; ///< Offset to measure number
protected:
Fraction _len { Fraction(0, 1) }; ///< actual length of measure
void cleanupLayoutBreaks(bool undo);
public:
@ -111,20 +112,20 @@ class MeasureBase : public Element {
void undoSetSectionBreak(bool v) { undoSetBreak(v, LayoutBreak::SECTION);}
void undoSetNoBreak(bool v) { undoSetBreak(v, LayoutBreak::NOBREAK);}
virtual void moveTicks(int diff) { setTick(tick() + diff); }
virtual void moveTicks(const Fraction& diff) { setTick(tick() + diff); }
virtual void add(Element*) override;
virtual void remove(Element*) override;
virtual void writeProperties(XmlWriter&) const override;
virtual bool readProperties(XmlReader&) override;
virtual int tick() const override { return _tick; }
virtual int ticks() const { return 0; }
int endTick() const { return tick() + ticks(); }
void setTick(int t) { _tick = t; }
Fraction tick() const { return _tick; }
void setTick(const Fraction& f) { _tick = f; }
Fraction rfrac() const override { return 0; }
Fraction afrac() const override;
Fraction ticks() const { return _len; }
void setTicks(const Fraction& f) { _len = f; }
Fraction endTick() const { return _tick + _len; }
qreal pause() const;

View file

@ -150,7 +150,7 @@ void MasterScore::rebuildExcerptsMidiMapping()
for (const auto& item : *masterPart->instruments()) {
const Instrument* iMaster = item.second;
const int tick = item.first;
Instrument* iLocal = p->instrument(tick);
Instrument* iLocal = p->instrument(Fraction::fromTicks(tick));
Q_ASSERT(iLocal->channel().size() == iMaster->channel().size());
const int nchannels = iLocal->channel().size();
for (int c = 0; c < nchannels; ++c) {

View file

@ -87,7 +87,7 @@ ChordRest* nextChordRest(ChordRest* cr, bool skipGrace)
}
}
int track = cr->track();
int track = cr->track();
SegmentType st = SegmentType::ChordRest;
for (Segment* seg = cr->segment()->next1MM(st); seg; seg = seg->next1MM(st)) {
@ -437,7 +437,7 @@ ChordRest* Score::nextMeasure(ChordRest* element, bool selectBehavior, bool mmRe
if (!measure)
return 0;
int endTick = element->measure()->last()->nextChordRest(element->track(), true)->tick();
Fraction endTick = element->measure()->last()->nextChordRest(element->track(), true)->tick();
bool last = false;
if (selection().isRange()) {
@ -486,7 +486,7 @@ ChordRest* Score::prevMeasure(ChordRest* element, bool mmRest)
else
measure = element->measure()->prevMeasure();
int startTick = element->measure()->first()->nextChordRest(element->track())->tick();
Fraction startTick = element->measure()->first()->nextChordRest(element->track())->tick();
bool last = false;
if (selection().isRange() && selection().isEndActive() && selection().startSegment()->tick() <= startTick)

View file

@ -658,7 +658,7 @@ int Note::tpc1default(int p) const
{
Key key = Key::C;
if (staff() && chord()) {
int tick = chord()->tick();
Fraction tick = chord()->tick();
key = staff()->key(tick);
if (!concertPitch()) {
Interval interval = part()->instrument(tick)->transpose();
@ -679,7 +679,7 @@ int Note::tpc2default(int p) const
{
Key key = Key::C;
if (staff() && chord()) {
int tick = chord()->tick();
Fraction tick = chord()->tick();
key = staff()->key(tick);
if (concertPitch()) {
Interval interval = part()->instrument(tick)->transpose();
@ -697,7 +697,7 @@ int Note::tpc2default(int p) const
void Note::setTpcFromPitch()
{
// works best if note is already added to score, otherwise we can't determine transposition or key
int tick = chord() ? chord()->tick() : -1;
Fraction tick = chord() ? chord()->tick() : Fraction(-1,1);
Interval v = staff() ? part()->instrument(tick)->transpose() : Interval();
Key key = (staff() && chord()) ? staff()->key(chord()->tick()) : Key::C;
// convert key to concert pitch
@ -773,7 +773,7 @@ QString Note::tpcUserName(bool explicitAccidental) const
int Note::transposeTpc(int tpc)
{
int tick = chord() ? chord()->tick() : -1;
Fraction tick = chord() ? chord()->tick() : Fraction(-1,1);
Interval v = part()->instrument(tick)->transpose();
if (v.isZero())
return tpc;
@ -818,8 +818,8 @@ SymId Note::noteHead() const
Key key = Key::C;
NoteHeadScheme scheme = NoteHeadScheme::HEAD_NORMAL;
if (chord() && chord()->staff()){
int tick = chord()->tick();
if (tick >= 0) {
Fraction tick = chord()->tick();
if (tick >= Fraction(0,1)) {
const Staff* st = chord()->staff();
key = st->key(tick);
scheme = st->staffType(tick)->noteHeadScheme();
@ -952,9 +952,9 @@ QPointF Note::stemUpSE() const
int Note::playTicks() const
{
int stick = firstTiedNote()->chord()->tick();
Fraction stick = firstTiedNote()->chord()->tick();
const Note* note = lastTiedNote();
return note->chord()->tick() + note->chord()->actualTicks() - stick;
return (note->chord()->tick() + note->chord()->actualTicks() - stick).ticks();
}
//---------------------------------------------------------
@ -1240,7 +1240,7 @@ void Note::read(XmlReader& e)
_tpc[1] = tpc;
}
if (!(tpcIsValid(_tpc[0]) && tpcIsValid(_tpc[1]))) {
int tick = chord() ? chord()->tick() : -1;
Fraction tick = chord() ? chord()->tick() : Fraction(-1,1);
Interval v = staff() ? part()->instrument(tick)->transpose() : Interval();
if (tpcIsValid(_tpc[0])) {
v.flip();
@ -1479,7 +1479,7 @@ void Note::readAddConnector(ConnectorInfoReader* info, bool pasteMode)
int Note::transposition() const
{
int tick = chord() ? chord()->tick() : -1;
Fraction tick = chord() ? chord()->tick() : Fraction(-1,1);
return staff() ? part()->instrument(tick)->transpose().chromatic : 0;
}
@ -1518,7 +1518,7 @@ void Note::startDrag(EditData& ed)
QRectF Note::drag(EditData& ed)
{
int _tick = chord()->tick();
Fraction _tick = chord()->tick();
const Staff* stf = staff();
const StaffType* st = stf->staffType(_tick);
if (st->isDrumStaff())
@ -2468,7 +2468,7 @@ void Note::updateLine()
// set note properties from NoteVal
//---------------------------------------------------------
void Note::setNval(const NoteVal& nval, int tick)
void Note::setNval(const NoteVal& nval, Fraction tick)
{
setPitch(nval.pitch);
_fret = nval.fret;
@ -2477,7 +2477,7 @@ void Note::setNval(const NoteVal& nval, int tick)
_tpc[0] = nval.tpc1;
_tpc[1] = nval.tpc2;
if (tick == -1 && chord())
if (tick == Fraction(-1,1) && chord())
tick = chord()->tick();
Interval v = part()->instrument(tick)->transpose();
if (nval.tpc1 == Tpc::TPC_INVALID) {

View file

@ -434,7 +434,7 @@ class Note final : public Element {
int qmlDotsCount();
void updateAccidental(AccidentalState*);
void updateLine();
void setNval(const NoteVal&, int tick = -1);
void setNval(const NoteVal&, Fraction = { -1, 1} );
NoteEventList& playEvents() { return _playEvents; }
const NoteEventList& playEvents() const { return _playEvents; }
NoteEvent* noteEvent(int idx) { return &_playEvents[idx]; }

View file

@ -38,7 +38,7 @@ void NoteDot::draw(QPainter* p) const
{
if (note() && note()->dotsHidden()) // don't draw dot if note is hidden
return;
int tick = note() ? note()->chord()->tick() : rest()->tick();
Fraction tick = note() ? note()->chord()->tick() : rest()->tick();
if (!staff()->isTabStaff(tick) || staff()->staffType(tick)->stemThrough()) {
p->setPen(curColor());
drawSymbol(SymId::augmentationDot, p);

View file

@ -37,7 +37,7 @@ NoteVal Score::noteValForPosition(Position pos, bool &error)
error = false;
Segment* s = pos.segment;
int line = pos.line;
int tick = s->tick();
Fraction tick = s->tick();
int staffIdx = pos.staffIdx;
Staff* st = staff(staffIdx);
ClefType clef = st->clef(tick);
@ -154,15 +154,15 @@ Note* Score::addPitch(NoteVal& nval, bool addFlag)
return 0;
Fraction duration;
if (_is.usingNoteEntryMethod(NoteEntryMethod::REPITCH)) {
duration = _is.cr()->duration();
duration = _is.cr()->ticks();
}
else if (_is.usingNoteEntryMethod(NoteEntryMethod::REALTIME_AUTO) || _is.usingNoteEntryMethod(NoteEntryMethod::REALTIME_MANUAL)) {
// FIXME: truncate duration at barline in real-time modes.
// The user might try to enter a duration that is too long to fit in the remaining space in the measure.
// We could split the duration at the barline and continue into the next bar, but this would create extra
// notes, extra ties, and extra pain. Instead, we simply truncate the duration at the barline.
int ticks2measureEnd = _is.segment()->measure()->ticks() - _is.segment()->rtick();
duration = _is.duration().ticks() > ticks2measureEnd ? Fraction::fromTicks(ticks2measureEnd) : _is.duration().fraction();
Fraction ticks2measureEnd = _is.segment()->measure()->ticks() - _is.segment()->rtick();
duration = _is.duration() > ticks2measureEnd ? ticks2measureEnd : _is.duration().fraction();
}
else {
duration = _is.duration().fraction();
@ -243,7 +243,7 @@ Note* Score::addPitch(NoteVal& nval, bool addFlag)
//
ChordRest* e = searchNote(_is.tick(), _is.track());
if (e) {
int stick = 0;
Fraction stick = Fraction(0, 1);
Element* ee = _is.slur()->startElement();
if (ee->isChordRest())
stick = toChordRest(ee)->tick();
@ -409,7 +409,7 @@ void Score::putNote(const Position& p, bool replace)
void Score::repitchNote(const Position& p, bool replace)
{
Segment* s = p.segment;
int tick = s->tick();
Fraction tick = s->tick();
Staff* st = staff(p.staffIdx);
ClefType clef = st->clef(tick);
@ -492,7 +492,7 @@ void Score::repitchNote(const Position& p, bool replace)
// the new note will be added below
while (!chord->notes().empty())
undoRemoveElement(chord->notes().front());
}
}
// add new note to chord
undoAddElement(note);
setPlayNote(true);
@ -548,11 +548,11 @@ void Score::localInsertChord(const Position& pos)
{
const TDuration duration = _is.duration();
const Fraction fraction = duration.fraction();
const int len = fraction.ticks();
const Fraction len = fraction;
Segment* seg = pos.segment;
const int tick = seg->tick();
Fraction tick = seg->tick();
Measure* measure = seg->measure()->isMMRest() ? seg->measure()->mmRestFirst() : seg->measure();
const Fraction targetMeasureLen = measure->len() + fraction;
const Fraction targetMeasureLen = measure->ticks() + fraction;
// Shift spanners, enlarge the measure.
// The approach is similar to that in Measure::adjustToLen() but does
@ -585,8 +585,8 @@ void Score::localInsertChord(const Position& pos)
Rest* measureRest = toRest(maybeRest);
// If measure rest is situated at measure start we will fill
// the whole measure with rests.
measureIsFull = (measureRest->rtick() == 0);
const Fraction fillLen = measureIsFull ? targetMeasureLen : measureRest->duration();
measureIsFull = measureRest->rtick().isZero();
const Fraction fillLen = measureIsFull ? targetMeasureLen : measureRest->ticks();
ms->setRest(measureRest->tick(), track, fillLen, /* useDots */ false, /* tuplet */ nullptr, /* useFullMeasureRest */ false);
}
@ -595,20 +595,20 @@ void Score::localInsertChord(const Position& pos)
ChordRest* cr = ms->findCR(tick, track);
if (cr && cr->tick() < tick && (cr->tick() + cr->actualTicks()) > tick) {
if (cr->isRest()) {
const Fraction fillLen = cr->duration() + fraction;
const Fraction fillLen = cr->ticks() + fraction;
ms->undoRemoveElement(cr);
ms->setRest(cr->tick(), track, fillLen, /* useDots */ false, /* tuplet */ nullptr, /* useFullMeasureRest */ false);
}
else if (cr->isChord()) {
Chord* chord = toChord(cr);
std::vector<TDuration> durations = toDurationList(chord->duration() + fraction, /* useDots */ true);
Fraction p = chord->afrac();
std::vector<TDuration> durations = toDurationList(chord->ticks() + fraction, /* useDots */ true);
Fraction p = chord->tick();
ms->undoRemoveElement(chord);
Chord* prevChord = nullptr;
for (const TDuration& dur : durations) {
Chord* prototype = prevChord ? prevChord : chord;
const bool genTie = bool(prevChord);
prevChord = ms->addChord(p.ticks(), dur, prototype, genTie, /* tuplet */ nullptr);
prevChord = ms->addChord(p, dur, prototype, genTie, /* tuplet */ nullptr);
p += dur.fraction();
}
// TODO: reconnect ties if this chord was tied to other
@ -648,20 +648,20 @@ void Score::globalInsertChord(const Position& pos)
int strack = 0; // for now for all tracks
int etrack = nstaves() * VOICES;
int stick = s1->tick();
int etick = s2->tick();
int ticks = fraction.ticks();
Fraction stick = s1->tick();
Fraction etick = s2->tick();
Fraction ticks = fraction;
Fraction len = r.ticks();
Fraction len = r.duration();
if (!r.truncate(fraction))
appendMeasures(1);
putNote(pos, true);
int dtick = s1->tick() + ticks;
Fraction dtick = s1->tick() + ticks;
int voiceOffsets[VOICES] { 0, 0, 0, 0 };
len = r.duration();
len = r.ticks();
for (int staffIdx = 0; staffIdx < nstaves(); ++staffIdx)
makeGap1(dtick, staffIdx, r.duration(), voiceOffsets);
makeGap1(dtick, staffIdx, r.ticks(), voiceOffsets);
r.write(this, dtick);
for (auto i : spanner()) {

View file

@ -357,12 +357,12 @@ bool Ottava::setProperty(Pid propertyId, const QVariant& val)
break;
case Pid::SPANNER_TICKS:
setTicks(val.toInt());
setTicks(val.value<Fraction>());
staff()->updateOttava();
break;
case Pid::SPANNER_TICK:
setTick(val.toInt());
setTick(val.value<Fraction>());
staff()->updateOttava();
break;

View file

@ -511,9 +511,9 @@ QRectF Page::tbbox()
// endTick
//---------------------------------------------------------
int Page::endTick() const
Fraction Page::endTick() const
{
return _systems.empty() ? -1 : _systems.back()->measures().back()->endTick();
return _systems.empty() ? Fraction(-1,1) : _systems.back()->measures().back()->endTick();
}
}

View file

@ -74,7 +74,7 @@ class Page final : public Element {
QPointF pagePos() const { return QPointF(); } ///< position in page coordinates
QList<Element*> elements(); ///< list of visible elements
QRectF tbbox(); // tight bounding box, excluding white space
int endTick() const;
Fraction endTick() const;
};

View file

@ -231,7 +231,7 @@ QPointF PalmMute::linePos(Grip grip, System** sys) const
x -= c->x();
}
if (!s) {
int t = tick2();
Fraction t = tick2();
Measure* m = score()->tick2measure(t);
s = m->system();
x = m->tick2pos(t);

View file

@ -109,7 +109,7 @@ bool Part::readProperties(XmlReader& e)
else if (tag == "Instrument") {
Instrument* instr = new Instrument;
instr->read(e, this);
setInstrument(instr, -1);
setInstrument(instr, Fraction(-1,1));
}
else if (tag == "name")
instrument()->setLongName(e.readElementText());
@ -162,12 +162,12 @@ void Part::write(XmlWriter& xml) const
// setLongNames
//---------------------------------------------------------
void Part::setLongNames(QList<StaffName>& name, int tick)
void Part::setLongNames(QList<StaffName>& name, const Fraction& tick)
{
instrument(tick)->longNames() = name;
}
void Part::setShortNames(QList<StaffName>& name, int tick)
void Part::setShortNames(QList<StaffName>& name, const Fraction& tick)
{
instrument(tick)->shortNames() = name;
}
@ -273,7 +273,7 @@ int Part::midiPort() const
// setMidiChannel(channel, port) to set both
//---------------------------------------------------------
void Part::setMidiChannel(int ch, int port, int tick)
void Part::setMidiChannel(int ch, int port, const Fraction& tick)
{
Channel* channel = instrument(tick)->channel(0);
if (channel->channel() == -1)
@ -286,29 +286,30 @@ void Part::setMidiChannel(int ch, int port, int tick)
// setInstrument
//---------------------------------------------------------
void Part::setInstrument(Instrument* i, int tick)
void Part::setInstrument(Instrument* i, Fraction tick)
{
_instruments.setInstrument(i, tick);
_instruments.setInstrument(i, tick.ticks());
}
void Part::setInstrument(const Instrument&& i, int tick)
void Part::setInstrument(const Instrument&& i, Fraction tick)
{
_instruments.setInstrument(new Instrument(i), tick);
_instruments.setInstrument(new Instrument(i), tick.ticks());
}
void Part::setInstrument(const Instrument& i, int tick)
void Part::setInstrument(const Instrument& i, Fraction tick)
{
_instruments.setInstrument(new Instrument(i), tick);
_instruments.setInstrument(new Instrument(i), tick.ticks());
}
//---------------------------------------------------------
// removeInstrument
//---------------------------------------------------------
void Part::removeInstrument(int tick)
void Part::removeInstrument(const Fraction& tick)
{
auto i = _instruments.find(tick);
auto i = _instruments.find(tick.ticks());
if (i == _instruments.end()) {
qDebug("Part::removeInstrument: not found at tick %d", tick);
qDebug("Part::removeInstrument: not found at tick %d", tick.ticks());
return;
}
_instruments.erase(i);
@ -318,18 +319,18 @@ void Part::removeInstrument(int tick)
// instrument
//---------------------------------------------------------
Instrument* Part::instrument(int tick)
Instrument* Part::instrument(Fraction tick)
{
return _instruments.instrument(tick);
return _instruments.instrument(tick.ticks());
}
//---------------------------------------------------------
// instrument
//---------------------------------------------------------
const Instrument* Part::instrument(int tick) const
const Instrument* Part::instrument(Fraction tick) const
{
return _instruments.instrument(tick);
return _instruments.instrument(tick.ticks());
}
//---------------------------------------------------------
@ -345,7 +346,7 @@ const InstrumentList* Part::instruments() const
// instrumentId
//---------------------------------------------------------
QString Part::instrumentId(int tick) const
QString Part::instrumentId(const Fraction& tick) const
{
return instrument(tick)->instrumentId();
}
@ -354,7 +355,7 @@ QString Part::instrumentId(int tick) const
// longName
//---------------------------------------------------------
QString Part::longName(int tick) const
QString Part::longName(const Fraction& tick) const
{
const QList<StaffName>& nl = longNames(tick);
return nl.empty() ? "" : nl[0].name();
@ -364,7 +365,7 @@ QString Part::longName(int tick) const
// instrumentName
//---------------------------------------------------------
QString Part::instrumentName(int tick) const
QString Part::instrumentName(const Fraction& tick) const
{
return instrument(tick)->trackName();
}
@ -373,7 +374,7 @@ QString Part::instrumentName(int tick) const
// shortName
//---------------------------------------------------------
QString Part::shortName(int tick) const
QString Part::shortName(const Fraction& tick) const
{
const QList<StaffName>& nl = shortNames(tick);
return nl.empty() ? "" : nl[0].name();
@ -474,28 +475,28 @@ int Part::endTrack() const
// insertTime
//---------------------------------------------------------
void Part::insertTime(int tick, int len)
void Part::insertTime(const Fraction& tick, const Fraction& len)
{
if (len == 0)
if (len.isZero())
return;
// move all instruments
if (len < 0) {
if (len < Fraction(0,1)) {
// remove instruments between tickpos >= tick and tickpos < (tick+len)
// ownership goes back to class InstrumentChange()
auto si = _instruments.lower_bound(tick);
auto ei = _instruments.lower_bound(tick-len);
auto si = _instruments.lower_bound(tick.ticks());
auto ei = _instruments.lower_bound((tick-len).ticks());
_instruments.erase(si, ei);
}
InstrumentList il;
for (auto i = _instruments.lower_bound(tick); i != _instruments.end();) {
for (auto i = _instruments.lower_bound(tick.ticks()); i != _instruments.end();) {
Instrument* instrument = i->second;
int t = i->first;
_instruments.erase(i++);
_instruments[t + len] = instrument;
_instruments[t + len.ticks()] = instrument;
}
_instruments.insert(il.begin(), il.end());
}
@ -548,7 +549,7 @@ bool Part::hasPitchedStaff()
if (!staves())
return false;
for (Staff* s : *staves()) {
if (s && s->isPitchedStaff(0))
if (s && s->isPitchedStaff(Fraction(0,1)))
return true;
}
return false;
@ -563,7 +564,7 @@ bool Part::hasTabStaff()
if (!staves())
return false;
for (Staff* s : *staves()) {
if (s && s->isTabStaff(0))
if (s && s->isTabStaff(Fraction(0,1)))
return true;
}
return false;
@ -578,7 +579,7 @@ bool Part::hasDrumStaff()
if (!staves())
return false;
for (Staff* s : *staves()) {
if (s && s->isDrumStaff(0))
if (s && s->isDrumStaff(Fraction(0,1)))
return true;
}
return false;

View file

@ -73,16 +73,16 @@ class Part final : public ScoreElement {
int startTrack() const;
int endTrack() const;
QString longName(int tick = -1) const;
QString shortName(int tick = -1) const;
QString instrumentName(int tick = -1) const;
QString instrumentId(int tick = -1) const;
QString longName(const Fraction& tick = { -1, 1 } ) const;
QString shortName(const Fraction& tick = { -1, 1 } ) const;
QString instrumentName(const Fraction& tick = { -1, 1 } ) const;
QString instrumentId(const Fraction& tick = { -1, 1 } ) const;
const QList<StaffName>& longNames(int tick = -1) const { return instrument(tick)->longNames(); }
const QList<StaffName>& shortNames(int tick = -1) const { return instrument(tick)->shortNames(); }
const QList<StaffName>& longNames(const Fraction& tick = { -1, 1 } ) const { return instrument(tick)->longNames(); }
const QList<StaffName>& shortNames(const Fraction& tick = { -1, 1 } ) const { return instrument(tick)->shortNames(); }
void setLongNames(QList<StaffName>& s, int tick = -1);
void setShortNames(QList<StaffName>& s, int tick = -1);
void setLongNames(QList<StaffName>& s, const Fraction& tick = { -1, 1 } );
void setShortNames(QList<StaffName>& s, const Fraction& tick = { -1, 1 } );
void setLongName(const QString& s);
void setShortName(const QString& s);
@ -97,22 +97,22 @@ class Part final : public ScoreElement {
int midiChannel() const;
int midiPort() const;
void setMidiChannel(int ch, int port = -1, int tick = -1); // tick != -1 for InstrumentChange
void setMidiChannel(int ch, int port = -1, const Fraction& tick = {-1,1}); // tick != -1 for InstrumentChange
void insertStaff(Staff*, int idx);
void removeStaff(Staff*);
bool show() const { return _show; }
void setShow(bool val) { _show = val; }
Instrument* instrument(int tick = -1);
const Instrument* instrument(int tick = -1) const;
void setInstrument(Instrument*, int tick = -1); // transfer ownership
void setInstrument(const Instrument&&, int tick = -1);
void setInstrument(const Instrument&, int tick = -1);
void removeInstrument(int tick);
Instrument* instrument(Fraction = { -1, 1 } );
const Instrument* instrument(Fraction = { -1, 1 }) const;
void setInstrument(Instrument*, Fraction = { -1, 1} ); // transfer ownership
void setInstrument(const Instrument&&, Fraction = { -1, 1 });
void setInstrument(const Instrument&, Fraction = { -1, 1 });
void removeInstrument(const Fraction&);
const InstrumentList* instruments() const;
void insertTime(int tick, int len);
void insertTime(const Fraction& tick, const Fraction& len);
QString partName() const { return _partName; }
void setPartName(const QString& s) { _partName = s; }

View file

@ -42,7 +42,7 @@ namespace Ms {
// transposeChord
//---------------------------------------------------------
static void transposeChord(Chord* c, Interval srcTranspose, int tick)
static void transposeChord(Chord* c, Interval srcTranspose, const Fraction& tick)
{
// set note track
// check if staffMove moves a note to a
@ -84,9 +84,9 @@ bool Score::pasteStaff(XmlReader& e, Segment* dst, int dstStaff)
QList<Chord*> graceNotes;
Beam* startingBeam = nullptr;
Tuplet* tuplet = nullptr;
int dstTick = dst->tick();
Fraction dstTick = dst->tick();
bool pasted = false;
int tickLen = 0;
Fraction tickLen = Fraction(0,1);
int staves = 0;
bool done = false;
while (e.readNextStartElement()) {
@ -103,13 +103,13 @@ bool Score::pasteStaff(XmlReader& e, Segment* dst, int dstStaff)
break;
}
}
int tickStart = e.intAttribute("tick", 0);
tickLen = e.intAttribute("len", 0);
Fraction tickStart = Fraction::fromTicks(e.intAttribute("tick", 0));
tickLen = Fraction::fromTicks(e.intAttribute("len", 0));
int staffStart = e.intAttribute("staff", 0);
staves = e.intAttribute("staves", 0);
e.setTickOffset(dstTick - tickStart);
e.initTick(0);
e.setTick(Fraction(0,1));
while (e.readNextStartElement()) {
if (done)
@ -150,8 +150,8 @@ bool Score::pasteStaff(XmlReader& e, Segment* dst, int dstStaff)
voiceOffset[voiceId] = e.readInt();
}
e.readNext();
if (!makeGap1(dstTick, dstStaffIdx, Fraction::fromTicks(tickLen), voiceOffset)) {
qDebug("cannot make gap in staff %d at tick %d", dstStaffIdx, dstTick);
if (!makeGap1(dstTick, dstStaffIdx, tickLen, voiceOffset)) {
qDebug("cannot make gap in staff %d at tick %d", dstStaffIdx, dstTick.ticks());
done = true; // break main loop, cannot make gap
break;
}
@ -163,7 +163,7 @@ bool Score::pasteStaff(XmlReader& e, Segment* dst, int dstStaff)
}
else if (tag == "Tuplet") {
Tuplet* oldTuplet = tuplet;
int tick = e.tick();
Fraction tick = e.tick();
// no paste into local time signature
if (staff(dstStaffIdx)->isLocalTimeSignature(tick)) {
MScore::setError(DEST_LOCAL_TIME_SIGNATURE);
@ -178,7 +178,7 @@ bool Score::pasteStaff(XmlReader& e, Segment* dst, int dstStaff)
tuplet->setParent(measure);
tuplet->setTick(tick);
tuplet->setTuplet(oldTuplet);
if (tuplet->rfrac() + tuplet->actualFraction() > measure->len()) {
if (tuplet->rtick() + tuplet->actualTicks() > measure->ticks()) {
delete tuplet;
if (oldTuplet && oldTuplet->elements().empty())
delete oldTuplet;
@ -211,7 +211,7 @@ bool Score::pasteStaff(XmlReader& e, Segment* dst, int dstStaff)
cr->setTrack(e.track());
cr->read(e);
cr->setSelected(false);
int tick = e.tick();
Fraction tick = e.tick();
// no paste into local time signature
if (staff(dstStaffIdx)->isLocalTimeSignature(tick)) {
MScore::setError(DEST_LOCAL_TIME_SIGNATURE);
@ -221,11 +221,11 @@ bool Score::pasteStaff(XmlReader& e, Segment* dst, int dstStaff)
startingBeam->add(cr); // also calls cr->setBeam(startingBeam)
startingBeam = nullptr;
}
if (tuplet)
cr->readAddTuplet(tuplet);
if (cr->isGrace())
graceNotes.push_back(toChord(cr));
else {
if (tuplet)
cr->readAddTuplet(tuplet);
e.incTick(cr->actualTicks());
if (cr->isChord()) {
Chord* chord = toChord(cr);
@ -234,8 +234,8 @@ bool Score::pasteStaff(XmlReader& e, Segment* dst, int dstStaff)
// but these will be removed later
if (chord->tremolo() && chord->tremolo()->twoNotes()) {
Measure* m = tick2measure(tick);
int ticks = cr->actualTicks();
int rticks = m->endTick() - tick;
Fraction ticks = cr->actualTicks();
Fraction rticks = m->endTick() - tick;
if (rticks < ticks || (rticks != ticks && rticks < ticks * 2)) {
MScore::setError(DEST_TREMOLO);
return false;
@ -264,11 +264,11 @@ bool Score::pasteStaff(XmlReader& e, Segment* dst, int dstStaff)
}
// shorten last cr to fit in the space made by makeGap
if ((tick - dstTick) + cr->actualTicks() > tickLen) {
int newLength = tickLen - (tick - dstTick);
Fraction newLength = tickLen - (tick - dstTick);
// check previous CR on same track, if it has tremolo, delete the tremolo
// we don't want a tremolo and two different chord durations
if (cr->isChord()) {
Segment* s = tick2leftSegment(tick - 1);
Segment* s = tick2leftSegment(tick - Fraction::fromTicks(1));
if (s) {
ChordRest* crt = toChordRest(s->element(cr->track()));
if (!crt)
@ -284,11 +284,11 @@ bool Score::pasteStaff(XmlReader& e, Segment* dst, int dstStaff)
}
}
}
if (!cr->tuplet()/*|| cr->actualTicks() - newLength > (cr->tuplet()->ratio().numerator() + 1 ) / 2*/) {
if (!cr->tuplet()) {
// shorten duration
// exempt notes in tuplets, since we don't allow copy of partial tuplet anyhow
// TODO: figure out a reasonable fudge factor to make sure shorten tuplets appropriately if we do ever copy a partial tuplet
cr->setDuration(Fraction::fromTicks(newLength));
cr->setTicks(newLength);
cr->setDurationType(newLength);
}
}
@ -312,7 +312,7 @@ bool Score::pasteStaff(XmlReader& e, Segment* dst, int dstStaff)
undoTransposeHarmony(harmony, rootTpc, baseTpc);
}
int tick = e.tick();
Fraction tick = e.tick();
Measure* m = tick2measure(tick);
Segment* seg = m->undoGetSegment(SegmentType::ChordRest, tick);
for (Element* el : seg->findAnnotations(ElementType::HARMONY, e.track(), e.track()))
@ -354,9 +354,9 @@ bool Score::pasteStaff(XmlReader& e, Segment* dst, int dstStaff)
Clef* clef = new Clef(this);
clef->read(e);
clef->setTrack(e.track());
int tick = e.tick();
Fraction tick = e.tick();
Measure* m = tick2measure(tick);
if (m->tick() && m->tick() == tick)
if (m->tick().isNotZero() && m->tick() == tick)
m = m->prevMeasure();
Segment* segment = m->undoGetSegment(SegmentType::Clef, tick);
clef->setParent(segment);
@ -366,7 +366,7 @@ bool Score::pasteStaff(XmlReader& e, Segment* dst, int dstStaff)
Breath* breath = new Breath(this);
breath->read(e);
breath->setTrack(e.track());
int tick = e.tick();
Fraction tick = e.tick();
Measure* m = tick2measure(tick);
Segment* segment = m->undoGetSegment(SegmentType::Breath, tick);
breath->setParent(segment);
@ -477,10 +477,10 @@ void Score::readAddConnector(ConnectorInfoReader* info, bool pasteMode)
sp->setAnchor(Spanner::Anchor::SEGMENT);
sp->setTrack(l.track());
sp->setTrack2(l.track());
sp->setTick(l.frac().ticks());
sp->setTick(l.frac());
}
else if (info->isEnd()) {
sp->setTick2(l.frac().ticks());
sp->setTick2(l.frac());
undoAddElement(sp);
if (sp->isOttava())
sp->staff()->updateOttava();
@ -496,9 +496,10 @@ void Score::readAddConnector(ConnectorInfoReader* info, bool pasteMode)
// pasteChordRest
//---------------------------------------------------------
void Score::pasteChordRest(ChordRest* cr, int tick, const Interval& srcTranspose)
void Score::pasteChordRest(ChordRest* cr, const Fraction& t, const Interval& srcTranspose)
{
// qDebug("pasteChordRest %s at %d, len %d/%d", cr->name(), tick, cr->duration().numerator(), cr->duration().denominator() );
Fraction tick(t);
// qDebug("pasteChordRest %s at %d, len %d/%d", cr->name(), tick, cr->ticks().numerator(), cr->ticks().denominator() );
if (cr->isChord())
transposeChord(toChord(cr), srcTranspose, tick);
@ -511,9 +512,9 @@ void Score::pasteChordRest(ChordRest* cr, int tick, const Interval& srcTranspose
// otherwise, we need to convert to duration rest(s)
// and potentially split the rest up (eg, 5/4 => whole + quarter)
bool convertMeasureRest = cr->isRest() && cr->durationType().type() == TDuration::DurationType::V_MEASURE
&& (tick != measure->tick() || cr->duration() != measure->len());
&& (tick != measure->tick() || cr->ticks() != measure->ticks());
int measureEnd = measure->endTick();
Fraction measureEnd = measure->endTick();
bool isGrace = cr->isChord() && toChord(cr)->noteType() != NoteType::NORMAL;
// if note is too long to fit in measure, split it up with a tie across the barline
@ -525,19 +526,19 @@ void Score::pasteChordRest(ChordRest* cr, int tick, const Interval& srcTranspose
if (cr->isChord()) {
// split Chord
Chord* c = toChord(cr);
int rest = c->actualTicks();
Fraction rest = c->actualTicks();
bool firstpart = true;
while (rest) {
while (rest.isNotZero()) {
measure = tick2measure(tick);
Chord* c2 = firstpart ? c : toChord(c->clone());
if (!firstpart)
c2->removeMarkings(true);
int mlen = measure->tick() + measure->ticks() - tick;
int len = mlen > rest ? rest : mlen;
std::vector<TDuration> dl = toRhythmicDurationList(Fraction::fromTicks(len), false, tick - measure->tick(), sigmap()->timesig(tick).nominal(), measure, MAX_DOTS);
Fraction mlen = measure->tick() + measure->ticks() - tick;
Fraction len = mlen > rest ? rest : mlen;
std::vector<TDuration> dl = toRhythmicDurationList(len, false, tick - measure->tick(), sigmap()->timesig(tick).nominal(), measure, MAX_DOTS);
TDuration d = dl[0];
c2->setDurationType(d);
c2->setDuration(d.fraction());
c2->setTicks(d.fraction());
rest -= c2->actualTicks();
undoAddCR(c2, measure, tick);
@ -566,39 +567,39 @@ void Score::pasteChordRest(ChordRest* cr, int tick, const Interval& srcTranspose
else if (cr->isRest()) {
// split Rest
Rest* r = toRest(cr);
Fraction rest = r->duration();
Fraction rest = r->ticks();
bool firstpart = true;
while (!rest.isZero()) {
Rest* r2 = firstpart ? r : toRest(r->clone());
measure = tick2measure(tick);
Fraction mlen = Fraction::fromTicks(measure->tick() + measure->ticks() - tick);
Fraction mlen = measure->tick() + measure->ticks() - tick;
Fraction len = rest > mlen ? mlen : rest;
std::vector<TDuration> dl = toRhythmicDurationList(len, true, tick - measure->tick(), sigmap()->timesig(tick).nominal(), measure, MAX_DOTS);
TDuration d = dl[0];
r2->setDurationType(d);
r2->setDuration(d.isMeasure() ? measure->len() : d.fraction());
r2->setTicks(d.isMeasure() ? measure->ticks() : d.fraction());
undoAddCR(r2, measure, tick);
rest -= r2->duration();
rest -= r2->ticks();
tick += r2->actualTicks();
firstpart = false;
}
}
else if (cr->isRepeatMeasure()) {
RepeatMeasure* rm = toRepeatMeasure(cr);
std::vector<TDuration> list = toDurationList(rm->actualDuration(), true);
std::vector<TDuration> list = toDurationList(rm->actualTicks(), true);
for (auto dur : list) {
Rest* r = new Rest(this, dur);
r->setTrack(cr->track());
Fraction rest = r->duration();
Fraction rest = r->ticks();
while (!rest.isZero()) {
Rest* r2 = toRest(r->clone());
measure = tick2measure(tick);
Fraction mlen = Fraction::fromTicks(measure->tick() + measure->ticks() - tick);
Fraction mlen = measure->tick() + measure->ticks() - tick;
Fraction len = rest > mlen ? mlen : rest;
std::vector<TDuration> dl = toDurationList(len, false);
TDuration d = dl[0];
r2->setDuration(d.fraction());
r2->setTicks(d.fraction());
r2->setDurationType(d);
undoAddCR(r2, measure, tick);
rest -= d.fraction();
@ -626,15 +627,15 @@ void Score::pasteChordRest(ChordRest* cr, int tick, const Interval& srcTranspose
void Score::pasteSymbols(XmlReader& e, ChordRest* dst)
{
Segment* currSegm = dst->segment();
int destTick = 0; // the tick and track to place the pasted element at
Fraction destTick = Fraction(0,1); // the tick and track to place the pasted element at
int destTrack = 0;
bool done = false;
int segDelta = 0;
Segment* startSegm= currSegm;
int startTick = dst->tick(); // the initial tick and track where to start pasting
Fraction startTick = dst->tick(); // the initial tick and track where to start pasting
int startTrack = dst->track();
int maxTrack = ntracks();
int lastTick = lastSegment()->tick();
Fraction lastTick = lastSegment()->tick();
while (e.readNextStartElement()) {
if (done)
@ -657,7 +658,7 @@ void Score::pasteSymbols(XmlReader& e, ChordRest* dst)
currSegm = startSegm;
}
else if (tag == "tickOffset")
destTick = startTick + e.readInt();
destTick = startTick + Fraction::fromTicks(e.readInt());
else if (tag == "segDelta")
segDelta = e.readInt();
else {
@ -744,7 +745,7 @@ void Score::pasteSymbols(XmlReader& e, ChordRest* dst)
else if (tag == "FiguredBass") {
// FiguredBass always belongs to first staff voice
destTrack = trackZeroVoice(destTrack);
int ticks;
Fraction ticks;
FiguredBass* el = new FiguredBass(this);
el->setTrack(destTrack);
el->read(e);
@ -783,11 +784,11 @@ void Score::pasteSymbols(XmlReader& e, ChordRest* dst)
continue;
}
// by default, split on-note duration in half: half on-note and half off-note
int totTicks = currSegm->tick() - prevSegm->tick();
int destTick1 = prevSegm->tick() + totTicks / 2;
ticks = totTicks / 2;
Fraction totTicks = currSegm->tick() - prevSegm->tick();
Fraction destTick1 = prevSegm->tick() + (totTicks * Fraction(1,2));
ticks = totTicks * Fraction(1, 2);
if (onNoteFB)
onNoteFB->setTicks(totTicks / 2);
onNoteFB->setTicks(totTicks * Fraction(1,2));
// look for a segment at this tick; if none, create one
Segment * nextSegm = prevSegm;
while (nextSegm && nextSegm->tick() < destTick1)
@ -805,7 +806,7 @@ void Score::pasteSymbols(XmlReader& e, ChordRest* dst)
}
else
// by default, assign to FiguredBass element the duration of the chord it refers to
ticks = toChordRest(currSegm->element(destTrack))->duration().ticks();
ticks = toChordRest(currSegm->element(destTrack))->ticks();
// in both cases, look for an existing f.b. element in segment and remove it, if found
FiguredBass* oldFB = nullptr;
foreach (Element* a, currSegm->annotations()) {

View file

@ -251,7 +251,7 @@ QPointF Pedal::linePos(Grip grip, System** sys) const
x -= c->x();
}
if (!s) {
int t = tick2();
Fraction t = tick2();
Measure* m = score()->tick2measure(t);
s = m->system();
x = m->tick2pos(t);

View file

@ -565,11 +565,11 @@ int computeWindow(const std::vector<Note*>& notes, int start, int end)
int k = 0;
while (i < end) {
pitch[k] = notes[i]->pitch() % 12;
int tick = notes[i]->chord()->tick();
Fraction tick = notes[i]->chord()->tick();
key[k] = int(notes[i]->staff()->key(tick)) + 7;
if (key[k] < 0 || key[k] > 14) {
qDebug("illegal key at tick %d: %d, window %d-%d",
tick, key[k] - 7, start, end);
tick.ticks(), key[k] - 7, start, end);
return 0;
// abort();
}
@ -633,7 +633,7 @@ int computeWindow(const std::vector<Note*>& notes, int start, int end)
void changeAllTpcs(Note* n, int tpc1)
{
Interval v;
int tick = n && n->chord() ? n->chord()->tick() : -1;
Fraction tick = n && n->chord() ? n->chord()->tick() : Fraction(-1,1);
if (n && n->part() && n->part()->instrument()) {
v = n->part()->instrument(tick)->transpose();
v.flip();

View file

@ -19,7 +19,6 @@ namespace Ms {
class MidiNote;
class Note;
class Event;
enum class Key;
const int INVALID_PITCH = -1;

View file

@ -178,8 +178,8 @@ static constexpr PropertyMetaData propertyList[] = {
{ Pid::TIMESIG_GLOBAL, false, 0, P_TYPE::FRACTION, DUMMY_QT_TRANSLATE_NOOP("propertyName", "global time signature") },
{ Pid::TIMESIG_STRETCH, false, 0, P_TYPE::FRACTION, DUMMY_QT_TRANSLATE_NOOP("propertyName", "time signature stretch") },
{ Pid::TIMESIG_TYPE, true, "subtype", P_TYPE::INT, DUMMY_QT_TRANSLATE_NOOP("propertyName", "subtype") },
{ Pid::SPANNER_TICK, true, "tick", P_TYPE::INT, DUMMY_QT_TRANSLATE_NOOP("propertyName", "tick") },
{ Pid::SPANNER_TICKS, true, "ticks", P_TYPE::INT, DUMMY_QT_TRANSLATE_NOOP("propertyName", "ticks") },
{ Pid::SPANNER_TICK, true, "tick", P_TYPE::FRACTION, DUMMY_QT_TRANSLATE_NOOP("propertyName", "tick") },
{ Pid::SPANNER_TICKS, true, "ticks", P_TYPE::FRACTION, DUMMY_QT_TRANSLATE_NOOP("propertyName", "ticks") },
{ Pid::SPANNER_TRACK2, false, "track2", P_TYPE::INT, DUMMY_QT_TRANSLATE_NOOP("propertyName", "track2") },
{ Pid::OFFSET2, false, "userOff2", P_TYPE::POINT_SP, DUMMY_QT_TRANSLATE_NOOP("propertyName", "offset2") },
{ Pid::BREAK_MMR, false, "breakMultiMeasureRest", P_TYPE::BOOL, DUMMY_QT_TRANSLATE_NOOP("propertyName", "breaking multimeasure rest")},
@ -197,7 +197,7 @@ static constexpr PropertyMetaData propertyList[] = {
{ Pid::VERSE, true, "no", P_TYPE::ZERO_INT, DUMMY_QT_TRANSLATE_NOOP("propertyName", "verse") },
{ Pid::SYLLABIC, true, "syllabic", P_TYPE::INT, DUMMY_QT_TRANSLATE_NOOP("propertyName", "syllabic") },
{ Pid::LYRIC_TICKS, true, "ticks", P_TYPE::INT, DUMMY_QT_TRANSLATE_NOOP("propertyName", "ticks") },
{ Pid::LYRIC_TICKS, true, "ticks", P_TYPE::FRACTION, DUMMY_QT_TRANSLATE_NOOP("propertyName", "ticks") },
{ Pid::VOLTA_ENDING, true, "endings", P_TYPE::INT_LIST, DUMMY_QT_TRANSLATE_NOOP("propertyName", "endings") },
{ Pid::LINE_VISIBLE, true, "lineVisible", P_TYPE::BOOL, DUMMY_QT_TRANSLATE_NOOP("propertyName", "visible line") },
{ Pid::MAG, false, "mag", P_TYPE::REAL, DUMMY_QT_TRANSLATE_NOOP("propertyName", "mag") },
@ -219,7 +219,7 @@ static constexpr PropertyMetaData propertyList[] = {
{ Pid::AUTOPLACE, false, "autoplace", P_TYPE::BOOL, DUMMY_QT_TRANSLATE_NOOP("propertyName", "autoplace") },
{ Pid::DASH_LINE_LEN, false, "dashLineLength", P_TYPE::REAL, DUMMY_QT_TRANSLATE_NOOP("propertyName", "dash line length") },
{ Pid::DASH_GAP_LEN, false, "dashGapLength", P_TYPE::REAL, DUMMY_QT_TRANSLATE_NOOP("propertyName", "dash gap length") },
{ Pid::TICK, false, 0, P_TYPE::INT, DUMMY_QT_TRANSLATE_NOOP("propertyName", "tick") },
{ Pid::TICK, false, 0, P_TYPE::FRACTION, DUMMY_QT_TRANSLATE_NOOP("propertyName", "tick") },
{ Pid::PLAYBACK_VOICE1, false, "playbackVoice1", P_TYPE::BOOL, DUMMY_QT_TRANSLATE_NOOP("propertyName", "playback voice 1") },
{ Pid::PLAYBACK_VOICE2, false, "playbackVoice2", P_TYPE::BOOL, DUMMY_QT_TRANSLATE_NOOP("propertyName", "playback voice 2") },
{ Pid::PLAYBACK_VOICE3, false, "playbackVoice3", P_TYPE::BOOL, DUMMY_QT_TRANSLATE_NOOP("propertyName", "playback voice 3") },

View file

@ -82,7 +82,7 @@ void TrackList::appendTuplet(Tuplet* srcTuplet, Tuplet* dstTuplet)
void TrackList::combineTuplet(Tuplet* dst, Tuplet* src)
{
dst->setDuration(dst->duration() * 2);
dst->setTicks(dst->ticks() * 2);
dst->setBaseLen(dst->baseLen().shift(-1));
// try to combine tie'd notes
@ -98,7 +98,7 @@ void TrackList::combineTuplet(Tuplet* dst, Tuplet* src)
}
if (akkumulateChord) {
Chord* bc = toChord(dst->elements().back());
bc->setDuration(bc->duration() + chord->duration());
bc->setTicks(bc->ticks() + chord->ticks());
// forward ties
int i = 0;
@ -129,7 +129,7 @@ void TrackList::combineTuplet(Tuplet* dst, Tuplet* src)
void TrackList::append(Element* e)
{
if (e->isDurationElement()) {
_duration += toDurationElement(e)->duration();
_duration += toDurationElement(e)->ticks();
bool accumulateRest = e->isRest() && !empty() && back()->isRest();
Segment* s = accumulateRest ? toRest(e)->segment() : 0;
@ -137,9 +137,9 @@ void TrackList::append(Element* e)
if (s && !s->score()->isSpannerStartEnd(s->tick(), e->track()) && !s->annotations().size()) {
// akkumulate rests
Rest* rest = toRest(back());
Fraction du = rest->duration();
du += toRest(e)->duration();
rest->setDuration(du);
Fraction du = rest->ticks();
du += toRest(e)->ticks();
rest->setTicks(du);
}
else {
Element* element = 0;
@ -174,8 +174,8 @@ void TrackList::append(Element* e)
}
if (akkumulateChord && !empty() && back()->isChord()) {
Chord* bc = toChord(back());
const Fraction du = bc->duration() + chord->duration();
bc->setDuration(du);
const Fraction du = bc->ticks() + chord->ticks();
bc->setTicks(du);
// forward ties
int idx = 0;
@ -212,14 +212,14 @@ void TrackList::appendGap(const Fraction& du)
Element* e = empty() ? 0 : back();
if (e && e->isRest()) {
Rest* rest = toRest(back());
Fraction dd = rest->duration();
Fraction dd = rest->ticks();
dd += du;
_duration += du;
rest->setDuration(dd);
rest->setTicks(dd);
}
else {
Rest* rest = new Rest(0);
rest->setDuration(du);
rest->setTicks(du);
QList<Element*>::append(rest);
_duration += du;
}
@ -238,14 +238,14 @@ bool TrackList::truncate(const Fraction& f)
if (!e->isRest())
return false;
Rest* r = toRest(e);
if (r->duration() < f)
if (r->ticks() < f)
return false;
if (r->duration() == f) {
if (r->ticks() == f) {
removeLast();
delete r;
}
else
r->setDuration(r->duration() - f);
r->setTicks(r->ticks() - f);
_duration -= f;
return true;
}
@ -256,8 +256,7 @@ bool TrackList::truncate(const Fraction& f)
void TrackList::read(const Segment* fs, const Segment* es)
{
int tick = fs->tick();
int gap = 0;
Fraction tick = fs->tick();
const Segment* s;
for (s = fs; s && (s != es); s = s->next1()) {
@ -276,22 +275,23 @@ void TrackList::read(const Segment* fs, const Segment* es)
RepeatMeasure* rm = toRepeatMeasure(e);
Rest r(*rm);
append(&r);
tick += r.duration().ticks();
tick += r.ticks();
}
else if (e->isChordRest()) {
DurationElement* de = toDurationElement(e);
gap = s->tick() - tick;
Fraction gap = s->tick() - tick;
if (de->tuplet()) {
Tuplet* t = de->topTuplet();
s = skipTuplet(t); // continue with first chord/rest after tuplet
de = t;
}
if (gap) {
appendGap(Fraction::fromTicks(gap));
Q_ASSERT(gap >= Fraction(0,1));
if (gap.isNotZero()) {
appendGap(gap);
tick += gap;
}
append(de);
tick += de->duration().ticks();
tick += de->ticks();
}
else if (e->isBarLine()) {
BarLine* bl = toBarLine(e);
@ -301,9 +301,9 @@ void TrackList::read(const Segment* fs, const Segment* es)
else
append(e);
}
gap = es->tick() - tick;
if (gap)
appendGap(Fraction::fromTicks(gap));
Fraction gap = es->tick() - tick;
if (gap.isNotZero())
appendGap(gap);
//
// connect ties
@ -340,6 +340,23 @@ void TrackList::read(const Segment* fs, const Segment* es)
}
}
//---------------------------------------------------------
// checkRest
//---------------------------------------------------------
static void checkRest(Fraction& rest, Measure*& m, const Fraction& d)
{
if (rest.isZero()) {
if (m->nextMeasure()) {
m = m->nextMeasure();
rest = m->ticks();
}
else {
qFatal("premature end of measure list, rest %d/%d", d.numerator(), d.denominator());
}
}
}
//---------------------------------------------------------
// writeTuplet
// measure - current measure
@ -351,17 +368,17 @@ Tuplet* TrackList::writeTuplet(Tuplet* parent, Tuplet* tuplet, Measure*& measure
Score* score = measure->score();
Tuplet* dt = tuplet->clone();
dt->setParent(measure);
Fraction du = tuplet->duration();
Fraction du = tuplet->ticks();
if (du > rest) {
// we must split the tuplet
dt->setDuration(du * Fraction(1, 2));
dt->setTicks(du * Fraction(1, 2));
dt->setBaseLen(tuplet->baseLen().shift(1));
}
if (parent)
parent->add(dt);
for (DurationElement* e : tuplet->elements()) {
Fraction duration = e->globalDuration();
Fraction duration = e->globalTicks();
Tuplet* tt = dt;
Fraction ratio = Fraction(1, 1);
while (tt) {
@ -370,11 +387,11 @@ Tuplet* TrackList::writeTuplet(Tuplet* parent, Tuplet* tuplet, Measure*& measure
}
bool firstpart = true;
while (duration > 0) {
while (duration > Fraction(0,1)) {
if (rest.isZero()) {
if (measure->nextMeasure()) {
measure = measure->nextMeasure();
rest = measure->len();
rest = measure->ticks();
if (e != tuplet->elements().back()) {
// create second part of split tuplet
dt = dt->clone();
@ -400,7 +417,7 @@ Tuplet* TrackList::writeTuplet(Tuplet* parent, Tuplet* tuplet, Measure*& measure
Fraction dd = qMin(rest, duration) * ratio;
std::vector<TDuration> dl = toDurationList(dd, false);
for (const TDuration& k : dl) {
Segment* segment = measure->undoGetSegment(SegmentType::ChordRest, measure->len() - rest);
Segment* segment = measure->undoGetSegmentR(SegmentType::ChordRest, measure->ticks() - rest);
Fraction gd = k.fraction() / ratio;
ChordRest* cr = toChordRest(e->clone());
if (!firstpart)
@ -408,7 +425,7 @@ Tuplet* TrackList::writeTuplet(Tuplet* parent, Tuplet* tuplet, Measure*& measure
cr->setScore(score);
cr->setTrack(_track);
segment->add(cr);
cr->setDuration(k.fraction());
cr->setTicks(k.fraction());
cr->setDurationType(k);
rest -= gd;
duration -= gd;
@ -439,40 +456,23 @@ Tuplet* TrackList::writeTuplet(Tuplet* parent, Tuplet* tuplet, Measure*& measure
return dt;
}
//---------------------------------------------------------
// checkRest
//---------------------------------------------------------
static void checkRest(Fraction& rest, Measure*& m, const Fraction& d)
{
if (rest.isZero()) {
if (m->nextMeasure()) {
m = m->nextMeasure();
rest = m->len();
}
else {
qFatal("premature end of measure list, rest %d/%d", d.numerator(), d.denominator());
}
}
}
//---------------------------------------------------------
// write
// rewrite notes into measure list measure
//---------------------------------------------------------
bool TrackList::write(Score* score, int tick) const
bool TrackList::write(Score* score, const Fraction& tick) const
{
if ((_track % VOICES) && size() == 1 && at(0)->isRest()) // dont write rests in voice > 0
return true;
Measure* measure = score->tick2measure(tick);
Measure* m = measure;
Fraction remains = Fraction::fromTicks(m->endTick() - tick);
Fraction remains = m->endTick() - tick;
Segment* segment = 0;
for (Element* e : *this) {
if (e->isDurationElement()) {
Fraction duration = toDurationElement(e)->duration();
Fraction duration = toDurationElement(e)->ticks();
checkRest(remains, m, duration); // go to next measure, if necessary
if (duration > remains && e->isTuplet()) {
// experimental: allow tuplet split in the middle
@ -482,12 +482,12 @@ bool TrackList::write(Score* score, int tick) const
}
}
bool firstpart = true;
while (duration > 0) {
if ((e->isRest() || e->isRepeatMeasure()) && (duration >= remains || e == back()) && (remains == m->len())) {
while (duration > Fraction(0,1)) {
if ((e->isRest() || e->isRepeatMeasure()) && (duration >= remains || e == back()) && (remains == m->ticks())) {
//
// handle full measure rest
//
Segment* seg = m->getSegment(SegmentType::ChordRest, m->len() - remains);
Segment* seg = m->getSegmentR(SegmentType::ChordRest, m->ticks() - remains);
if ((_track % VOICES) == 0) {
// write only for voice 1
Rest* r = new Rest(score, TDuration::DurationType::V_MEASURE);
@ -495,35 +495,32 @@ bool TrackList::write(Score* score, int tick) const
// but this is not valid during rewrite when adding time signatures
// since the time signature has not been added yet
//Fraction stretchedLen = m->stretchedLen(staff);
//r->setDuration(stretchedLen);
r->setDuration(m->len());
//r->setTicks(stretchedLen);
r->setTicks(m->ticks());
r->setTrack(_track);
seg->add(r);
}
duration -= m->len();
duration -= m->ticks();
remains.set(0, 1);
}
else if (e->isChordRest()) {
Fraction du = qMin(remains, duration);
Fraction du = qMin(remains, duration);
std::vector<TDuration> dl = toDurationList(du, e->isChord());
if (dl.empty())
qDebug("duration d %d/%d", du.numerator(), du.denominator());
Q_ASSERT(!dl.empty());
for (const TDuration& k : dl) {
segment = m->undoGetSegment(SegmentType::ChordRest, m->len() - remains);
segment = m->undoGetSegmentR(SegmentType::ChordRest, m->ticks() - remains);
ChordRest* cr = toChordRest(e->clone());
if (!firstpart)
cr->removeMarkings(true);
cr->setTrack(_track);
cr->setScore(score);
Fraction gd = k.fraction();
cr->setDuration(gd);
cr->setTicks(gd);
cr->setDurationType(k);
segment->add(cr);
duration -= gd;
remains -= gd;
remains -= gd;
if (cr->isChord()) {
for (Note* note : toChord(cr)->notes()) {
@ -541,7 +538,7 @@ bool TrackList::write(Score* score, int tick) const
duration = Fraction();
}
firstpart = false;
if (duration > 0)
if (duration > Fraction(0,1))
checkRest(remains, m, duration); // go to next measure, if necessary
}
}
@ -555,14 +552,14 @@ bool TrackList::write(Score* score, int tick) const
}
else if (e->isClef()) {
Segment* seg;
if (remains == m->len() && m->tick() > 0) {
if (remains == m->ticks() && m->tick() > Fraction(0,1)) {
Measure* pm = m->prevMeasure();
seg = pm->getSegment(SegmentType::Clef, pm->len());
seg = pm->getSegmentR(SegmentType::Clef, pm->ticks());
}
else if (remains != m->len())
seg = m->getSegment(SegmentType::Clef, m->len() - remains);
else if (remains != m->ticks())
seg = m->getSegmentR(SegmentType::Clef, m->ticks() - remains);
else
seg = m->getSegmentR(SegmentType::HeaderClef, 0);
seg = m->getSegmentR(SegmentType::HeaderClef, Fraction(0,1));
Element* ne = e->clone();
ne->setScore(score);
ne->setTrack(_track);
@ -574,7 +571,7 @@ bool TrackList::write(Score* score, int tick) const
// add the element in its own segment;
// but KeySig has to be at start of (current) measure
Segment* seg = m->getSegment(Segment::segmentType(e->type()), e->isKeySig() ? Fraction() : m->len() - remains);
Segment* seg = m->getSegmentR(Segment::segmentType(e->type()), e->isKeySig() ? Fraction() : m->ticks() - remains);
Element* ne = e->clone();
ne->setScore(score);
ne->setTrack(_track);
@ -621,19 +618,19 @@ ScoreRange::~ScoreRange()
void ScoreRange::read(Segment* first, Segment* last, bool readSpanner)
{
_first = first;
_last = last;
_first = first;
_last = last;
Score* score = first->score();
QList<int> sl = score->uniqueStaves();
int startTrack = 0;
int endTrack = score->nstaves() * VOICES;
int endTrack = score->nstaves() * VOICES;
spanner.clear();
if (readSpanner) {
int stick = first->tick();
int etick = last->tick();
Fraction stick = first->tick();
Fraction etick = last->tick();
for (auto i : first->score()->spanner()) {
Spanner* s = i.second;
if (s->tick() >= stick && s->tick() < etick && s->track() >= startTrack && s->track() < endTrack) {
@ -662,7 +659,7 @@ void ScoreRange::read(Segment* first, Segment* last, bool readSpanner)
// write
//---------------------------------------------------------
bool ScoreRange::write(Score* score, int tick) const
bool ScoreRange::write(Score* score, const Fraction& tick) const
{
for (TrackList* dl : tracks) {
int track = dl->track();
@ -678,7 +675,7 @@ bool ScoreRange::write(Score* score, int tick) const
Staff* nstaff = toStaff(le);
if (nstaff == ostaff)
continue;
Excerpt::cloneStaff2(ostaff, nstaff, tick, tick + dl->duration().ticks());
Excerpt::cloneStaff2(ostaff, nstaff, tick, (tick + dl->ticks()));
}
}
}
@ -725,12 +722,12 @@ bool ScoreRange::write(Score* score, int tick) const
void ScoreRange::fill(const Fraction& f)
{
const Fraction oldDuration = duration();
const int oldEndTick = _first->tick() + oldDuration.ticks();
const Fraction oldDuration = ticks();
Fraction oldEndTick = _first->tick() + oldDuration;
for (auto t : tracks)
t->appendGap(f);
const int diff = (duration() - oldDuration).ticks();
Fraction diff = ticks() - oldDuration;
for (Spanner* sp : spanner) {
if (sp->tick2() >= oldEndTick && sp->tick() < oldEndTick)
sp->setTicks(sp->ticks() + diff);
@ -751,7 +748,7 @@ bool ScoreRange::truncate(const Fraction& f)
if (!e->isRest())
return false;
Rest* r = toRest(e);
if (r->duration() < f)
if (r->ticks() < f)
return false;
}
for (TrackList* dl : tracks)
@ -760,12 +757,12 @@ bool ScoreRange::truncate(const Fraction& f)
}
//---------------------------------------------------------
// duration
// ticks
//---------------------------------------------------------
Fraction ScoreRange::duration() const
Fraction ScoreRange::ticks() const
{
return tracks.empty() ? Fraction() : tracks[0]->duration();
return tracks.empty() ? Fraction() : tracks[0]->ticks();
}
//---------------------------------------------------------
@ -777,7 +774,7 @@ void TrackList::dump() const
qDebug("elements %d, duration %d/%d", size(), _duration.numerator(), _duration.denominator());
for (Element* e : *this) {
if (e->isDurationElement()) {
Fraction du = toDurationElement(e)->duration();
Fraction du = toDurationElement(e)->ticks();
qDebug(" %s %d/%d", e->name(), du.numerator(), du.denominator());
}
else

View file

@ -45,14 +45,14 @@ class TrackList : public QList<Element*>
TrackList(ScoreRange* r) { _range = r; }
~TrackList();
Fraction duration() const { return _duration; }
Fraction ticks() const { return _duration; }
ScoreRange* range() const { return _range; }
int track() const { return _track; }
void setTrack(int val) { _track = val; }
void read(const Segment* fs, const Segment* ls);
bool write(Score*, int tick) const;
bool write(Score*, const Fraction&) const;
void appendGap(const Fraction&);
bool truncate(const Fraction&);
@ -64,7 +64,7 @@ class TrackList : public QList<Element*>
//---------------------------------------------------------
struct Annotation {
int tick;
Fraction tick;
Element* e;
};
@ -85,8 +85,8 @@ class ScoreRange {
ScoreRange() {}
~ScoreRange();
void read(Segment* first, Segment* last, bool readSpanner = true);
bool write(Score*, int tick) const;
Fraction duration() const;
bool write(Score*, const Fraction&) const;
Fraction ticks() const;
Segment* first() const { return _first; }
Segment* last() const { return _last; }
void fill(const Fraction&);

View file

@ -744,13 +744,13 @@ static void readNote(Note* note, XmlReader& e)
}
else if (tag == "onTimeOffset") {
if (note->onTimeType() == 1)
note->setOnTimeOffset(e.readInt() * 1000 / note->chord()->actualTicks());
note->setOnTimeOffset(e.readInt() * 1000 / note->chord()->actualTicks().ticks());
else
note->setOnTimeOffset(e.readInt() * 10);
}
else if (tag == "offTimeOffset") {
if (note->offTimeType() == 1)
note->setOffTimeOffset(1000 + (e.readInt() * 1000 / note->chord()->actualTicks()));
note->setOffTimeOffset(1000 + (e.readInt() * 1000 / note->chord()->actualTicks().ticks()));
else
note->setOffTimeOffset(1000 + (e.readInt() * 10));
}
@ -865,7 +865,7 @@ static void readNote(Note* note, XmlReader& e)
note->setTpc2(tpc);
}
if (!(tpcIsValid(note->tpc1()) && tpcIsValid(note->tpc2()))) {
int tick = note->chord() ? note->chord()->tick() : -1;
Fraction tick = note->chord() ? note->chord()->tick() : Fraction(-1,1);
Interval v = note->staff() ? note->part()->instrument(tick)->transpose() : Interval();
if (tpcIsValid(note->tpc1())) {
v.flip();
@ -985,21 +985,21 @@ static void readTuplet(Tuplet* tuplet, XmlReader& e)
else if (tag == "baseLen") // obsolete even in 1.3
bl = e.readInt();
else if (tag == "tick")
tuplet->setTick(e.readInt());
tuplet->setTick(Fraction::fromTicks(e.readInt()));
else if (!readTupletProperties206(e, tuplet))
e.unknown();
}
Fraction r = (tuplet->ratio() == 1) ? tuplet->ratio() : tuplet->ratio().reduced();
Fraction r = (tuplet->ratio() == Fraction(1,1)) ? tuplet->ratio() : tuplet->ratio().reduced();
// this may be wrong, but at this stage it is kept for compatibility. It will be corrected afterwards
// during "sanitize" step
Fraction f(r.denominator(), tuplet->baseLen().fraction().denominator());
tuplet->setDuration(f.reduced());
tuplet->setTicks(f.reduced());
if (bl != -1) { // obsolete, even in 1.3
TDuration d;
d.setVal(bl);
tuplet->setBaseLen(d);
d.setVal(bl * tuplet->ratio().denominator());
tuplet->setDuration(d.fraction());
tuplet->setTicks(d.fraction());
}
}
@ -1524,16 +1524,16 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
// tick is obsolete
if (e.hasAttribute("tick"))
e.initTick(m->score()->fileDivision(e.intAttribute("tick")));
e.setTick(Fraction::fromTicks(m->score()->fileDivision(e.intAttribute("tick"))));
if (e.hasAttribute("len")) {
QStringList sl = e.attribute("len").split('/');
if (sl.size() == 2)
m->setLen(Fraction(sl[0].toInt(), sl[1].toInt()));
m->setTicks(Fraction(sl[0].toInt(), sl[1].toInt()));
else
qDebug("illegal measure size <%s>", qPrintable(e.attribute("len")));
m->score()->sigmap()->add(m->tick(), SigEvent(m->len(), m->timesig()));
m->score()->sigmap()->add(m->endTick(), SigEvent(m->timesig()));
m->score()->sigmap()->add(m->tick().ticks(), SigEvent(m->ticks(), m->timesig()));
m->score()->sigmap()->add(m->endTick().ticks(), SigEvent(m->timesig()));
}
Staff* staff = m->score()->staff(staffIdx);
@ -1542,15 +1542,15 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
// keep track of tick of previous element
// this allows markings that need to apply to previous element to do so
// even though we may have already advanced to next tick position
int lastTick = e.tick();
Fraction lastTick = e.tick();
while (e.readNextStartElement()) {
const QStringRef& tag(e.name());
if (tag == "move")
e.initTick(e.readFraction().ticks() + m->tick());
e.setTick(e.readFraction() + m->tick());
else if (tag == "tick") {
e.initTick(m->score()->fileDivision(e.readInt()));
e.setTick(Fraction::fromTicks(m->score()->fileDivision(e.readInt())));
lastTick = e.tick();
}
else if (tag == "BarLine") {
@ -1632,7 +1632,7 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
chord->add(gc);
}
graceNotes.clear();
int crticks = chord->actualTicks();
Fraction crticks = chord->actualTicks();
if (chord->tremolo()) {
Tremolo* tremolo = chord->tremolo();
@ -1656,15 +1656,14 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
pch->setTremolo(tremolo);
chord->setTremolo(0);
// force duration to half
Fraction pts(timeStretch * pch->globalDuration());
int pcrticks = pts.ticks();
pch->setDuration(Fraction::fromTicks(pcrticks / 2));
chord->setDuration(Fraction::fromTicks(crticks / 2));
Fraction pts(timeStretch * pch->globalTicks());
pch->setTicks(pts * Fraction(1,2));
chord->setTicks(crticks * Fraction(1,2));
}
else {
qDebug("tremolo: first note not found");
}
crticks /= 2;
crticks = crticks * Fraction(1,2);
}
else {
tremolo->setParent(chord);
@ -1677,7 +1676,7 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
else if (tag == "Rest") {
Rest* rest = new Rest(m->score());
rest->setDurationType(TDuration::DurationType::V_MEASURE);
rest->setDuration(m->timesig()/timeStretch);
rest->setTicks(m->timesig()/timeStretch);
rest->setTrack(e.track());
readRest(m, rest, e);
if (!rest->segment())
@ -1685,8 +1684,8 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
segment = rest->segment();
segment->add(rest);
if (!rest->duration().isValid()) // hack
rest->setDuration(m->timesig()/timeStretch);
if (!rest->ticks().isValid()) // hack
rest->setTicks(m->timesig()/timeStretch);
lastTick = e.tick();
e.incTick(rest->actualTicks());
@ -1694,13 +1693,13 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
else if (tag == "Breath") {
Breath* breath = new Breath(m->score());
breath->setTrack(e.track());
int tick = e.tick();
Fraction tick = e.tick();
breath->read(e);
// older scores placed the breath segment right after the chord to which it applies
// rather than before the next chordrest segment with an element for the staff
// result would be layout too far left if there are other segments due to notes in other staves
// we need to find tick of chord to which this applies, and add its duration
int prevTick;
Fraction prevTick;
if (e.tick() < tick)
prevTick = e.tick(); // use our own tick if we explicitly reset to earlier position
else
@ -1783,9 +1782,8 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
readRest(m, rm, e);
segment = m->getSegment(SegmentType::ChordRest, e.tick());
segment->add(rm);
if (rm->actualDuration().isZero()) { // might happen with 1.3 scores
rm->setDuration(m->len());
}
if (rm->actualTicks().isZero()) // might happen with 1.3 scores
rm->setTicks(m->ticks());
lastTick = e.tick();
e.incTick(m->ticks());
}
@ -1802,8 +1800,8 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
|| (clef->clefType() == ClefType::PERC && !isDrumStaff)
|| (clef->clefType() != ClefType::PERC && isDrumStaff)) {
clef->setClefType(ClefType::G);
staff->clefList().erase(e.tick());
staff->clefList().insert(std::pair<int,ClefType>(e.tick(), ClefType::G));
staff->clefList().erase(e.tick().ticks());
staff->clefList().insert(std::pair<int,ClefType>(e.tick().ticks(), ClefType::G));
}
// there may be more than one clef segment for same tick position
@ -1816,7 +1814,7 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
header = true;
else {
header = true;
for (Segment* s = m->segments().first(); s && !s->rtick(); s = s->next()) {
for (Segment* s = m->segments().first(); s && s->rtick().isZero(); s = s->next()) {
if (s->isKeySigType() || s->isTimeSigType()) {
// hack: there may be other segment types which should
// generate a clef at current position
@ -1833,7 +1831,7 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
ts->setTrack(e.track());
ts->read(e);
// if time sig not at beginning of measure => courtesy time sig
int currTick = e.tick();
Fraction currTick = e.tick();
bool courtesySig = (currTick > m->tick());
if (courtesySig) {
// if courtesy sig., just add it without map processing
@ -1853,8 +1851,8 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
KeySig* ks = new KeySig(m->score());
ks->setTrack(e.track());
ks->read(e);
int curTick = e.tick();
if (!ks->isCustom() && !ks->isAtonal() && ks->key() == Key::C && curTick == 0) {
Fraction curTick = e.tick();
if (!ks->isCustom() && !ks->isAtonal() && ks->key() == Key::C && curTick.isZero()) {
// ignore empty key signature
qDebug("remove keysig c at tick 0");
if (ks->links()) {
@ -1875,7 +1873,7 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
Lyrics* l = new Lyrics(m->score());
l->setTrack(e.track());
int iEndTick = 0; // used for backward compatibility
int iEndTick = 0; // used for backward compatibility
Text* _verseNumber = 0;
while (e.readNextStartElement()) {
@ -1901,7 +1899,7 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
iEndTick = e.readInt();
}
else if (t == "ticks")
l->setTicks(e.readInt());
l->setTicks(Fraction::fromTicks(e.readInt()));
else if (t == "Number") { // obsolete
_verseNumber = new Text(l->score());
readText114(e, _verseNumber, l);
@ -1912,7 +1910,7 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
}
// if any endTick, make it relative to current tick
if (iEndTick) {
l->setTicks(iEndTick - e.tick());
l->setTicks(Fraction::fromTicks(iEndTick - e.tick().ticks()));
// qDebug("Lyrics::endTick: %d ticks %d", iEndTick, _ticks);
}
if (_verseNumber) {
@ -2138,7 +2136,7 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
m->setMMRestCount(e.readInt());
// set tick to previous measure
m->setTick(e.lastMeasure()->tick());
e.initTick(e.lastMeasure()->tick());
e.setTick(e.lastMeasure()->tick());
}
else if (m->MeasureBase::readProperties(e))
;
@ -2148,13 +2146,15 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
// For nested tuplets created with MuseScore 1.3 tuplet dialog (i.e. "Other..." dialog),
// the parent tuplet was not set. Try to infere if the tuplet was actually a nested tuplet
for (Tuplet* tuplet : e.tuplets()) {
int tupletTick = tuplet->tick();
int tupletDuration = tuplet->actualTicks() - 1;
Fraction tupletTick = tuplet->tick();
Fraction tupletDuration = tuplet->actualTicks() - Fraction::fromTicks(1);
std::vector<DurationElement*> tElements = tuplet->elements();
for (Tuplet* tuplet2 : e.tuplets()) {
if ((tuplet2->tuplet()) || (tuplet2->voice() != tuplet->voice())) // already a nested tuplet or in a different voice
continue;
int possibleDuration = tuplet2->duration().ticks() * tuplet->ratio().denominator() / tuplet->ratio().numerator() - 1;
// int possibleDuration = tuplet2->duration().ticks() * tuplet->ratio().denominator() / tuplet->ratio().numerator() - 1;
Fraction possibleDuration = tuplet2->ticks() * Fraction(tuplet->ratio().denominator(), (tuplet->ratio().numerator()-1));
if ((tuplet2 != tuplet) && (tuplet2->tick() >= tupletTick) && (tuplet2->tick() < tupletTick + tupletDuration) && (tuplet2->tick() + possibleDuration < tupletTick + tupletDuration)) {
bool found = false;
for (DurationElement* de : tElements) {
@ -2286,7 +2286,7 @@ static void readBox(XmlReader& e, Box* b)
static void readStaffContent(Score* score, XmlReader& e)
{
int staff = e.intAttribute("id", 1) - 1;
e.initTick(0);
e.setTick(Fraction(0,1));
e.setTrack(staff * VOICES);
Measure* measure = score->firstMeasure();
@ -2298,7 +2298,7 @@ static void readStaffContent(Score* score, XmlReader& e)
measure = new Measure(score);
measure->setTick(e.tick());
const SigEvent& ev = score->sigmap()->timesig(measure->tick());
measure->setLen(ev.timesig());
measure->setTicks(ev.timesig());
measure->setTimesig(ev.nominal());
readMeasure(measure, staff, e);
@ -2307,7 +2307,7 @@ static void readStaffContent(Score* score, XmlReader& e)
if (!measure->isMMRest()) {
score->measures()->add(measure);
e.setLastMeasure(measure);
e.initTick(measure->tick() + measure->ticks());
e.setTick(measure->tick() + measure->ticks());
}
else {
// this is a multi measure rest
@ -2327,7 +2327,7 @@ static void readStaffContent(Score* score, XmlReader& e)
measure->setTick(e.tick());
score->measures()->add(measure);
}
e.initTick(measure->tick());
e.setTick(measure->tick());
readMeasure(measure, staff, e);
measure->checkMeasure(staff);
@ -2350,7 +2350,7 @@ static void readStaffContent(Score* score, XmlReader& e)
score->measures()->add(mb);
}
else if (tag == "tick")
e.initTick(score->fileDivision(e.readInt()));
e.setTick(Fraction::fromTicks(score->fileDivision(e.readInt())));
else
e.unknown();
}
@ -2367,14 +2367,14 @@ static void readStaff(Staff* staff, XmlReader& e)
const QStringRef& tag(e.name());
if (tag == "lines") {
int lines = e.readInt();
staff->setLines(0, lines);
staff->setLines(Fraction(0,1), lines);
if (lines != 5) {
staff->setBarLineFrom(lines == 1 ? BARLINE_SPAN_1LINESTAFF_FROM : 0);
staff->setBarLineTo(lines == 1 ? BARLINE_SPAN_1LINESTAFF_TO : (lines - 1) * 2);
}
}
else if (tag == "small")
staff->setSmall(0, e.readInt());
staff->setSmall(Fraction(0,1), e.readInt());
else if (tag == "invisible")
staff->setInvisible(e.readInt());
else if (tag == "slashStyle")
@ -2507,7 +2507,7 @@ static void readPart(Part* part, XmlReader& e)
if (tag == "Staff") {
Staff* staff = new Staff(_score);
staff->setPart(part);
staff->setStaffType(0, StaffType()); // will reset later if needed
staff->setStaffType(Fraction(0,1), StaffType()); // will reset later if needed
_score->staves().push_back(staff);
part->staves()->push_back(staff);
readStaff(staff, e);
@ -2533,9 +2533,9 @@ static void readPart(Part* part, XmlReader& e)
}
Drumset* d = i->drumset();
Staff* st = part->staff(0);
if (d && st && st->lines(0) != 5) {
if (d && st && st->lines(Fraction(0,1)) != 5) {
int n = 0;
if (st->lines(0) == 1)
if (st->lines(Fraction(0,1)) == 1)
n = 4;
for (int j = 0; j < DRUM_INSTRUMENTS; ++j)
d->drum(j).line -= n;
@ -2565,17 +2565,17 @@ static void readPart(Part* part, XmlReader& e)
if (part->instrument()->useDrumset()) {
for (Staff* staff : *part->staves()) {
int lines = staff->lines(0);
int lines = staff->lines(Fraction(0,1));
int bf = staff->barLineFrom();
int bt = staff->barLineTo();
staff->setStaffType(0, *StaffType::getDefaultPreset(StaffGroup::PERCUSSION));
staff->setStaffType(Fraction(0,1), *StaffType::getDefaultPreset(StaffGroup::PERCUSSION));
// this allows 2/3-line percussion staves to keep the double spacing they had in 1.3
if (lines == 2 || lines == 3)
((StaffType*)(staff->staffType(0)))->setLineDistance(Spatium(2.0));
((StaffType*)(staff->staffType(Fraction(0,1))))->setLineDistance(Spatium(2.0));
staff->setLines(0, lines); // this also sets stepOffset
staff->setLines(Fraction(0,1), lines); // this also sets stepOffset
staff->setBarLineFrom(bf);
staff->setBarLineTo(bt);
}
@ -2970,14 +2970,14 @@ Score::FileError MasterScore::read114(XmlReader& e)
s->setTrack(e.track());
else
e.setTrack(s->track()); // update current track
if (s->tick() == -1)
if (s->tick() == Fraction(-1,1))
s->setTick(e.tick());
else
e.initTick(s->tick()); // update current tick
e.setTick(s->tick()); // update current tick
if (s->track2() == -1)
s->setTrack2(s->track());
if (s->ticks() == 0) {
qDebug("zero spanner %s ticks: %d", s->name(), s->ticks());
if (s->ticks().isZero()) {
qDebug("zero spanner %s ticks: %d", s->name(), s->ticks().ticks());
delete s;
}
else {
@ -3021,9 +3021,9 @@ Score::FileError MasterScore::read114(XmlReader& e)
s->setBarLineSpan(nstaves() - idx);
}
for (auto i : s->clefList()) {
int tick = i.first;
Fraction tick = Fraction::fromTicks(i.first);
ClefType clefId = i.second._concertClef;
Measure* m = tick2measure(tick);
Measure* m = tick2measure(tick);
if (!m)
continue;
SegmentType st = SegmentType::Clef;
@ -3049,12 +3049,12 @@ Score::FileError MasterScore::read114(XmlReader& e)
// create missing KeySig
KeyList* km = s->keyList();
for (auto i = km->begin(); i != km->end(); ++i) {
int tick = i->first;
if (tick < 0) {
qDebug("read114: Key tick %d", tick);
Fraction tick = Fraction::fromTicks(i->first);
if (tick < Fraction(0,1)) {
qDebug("read114: Key tick %d", tick.ticks());
continue;
}
if (tick == 0 && i->second.key() == Key::C)
if (tick.isZero() && i->second.key() == Key::C)
continue;
Measure* m = tick2measure(tick);
if (!m) //empty score
@ -3208,9 +3208,9 @@ Score::FileError MasterScore::read114(XmlReader& e)
// some 1.3 scores have tempolist but no tempo text
fixTicks();
for (auto i : tm) {
int tick = i.first;
qreal tempo = i.second.tempo;
if (tempomap()->tempo(tick) != tempo) {
Fraction tick = Fraction::fromTicks(i.first);
qreal tempo = i.second.tempo;
if (tempomap()->tempo(tick.ticks()) != tempo) {
TempoText* tt = new TempoText(this);
tt->setXmlText(QString("<sym>metNoteQuarterUp</sym> = %1").arg(qRound(tempo*60)));
tt->setTempo(tempo);

View file

@ -1085,7 +1085,7 @@ void readPart206(Part* part, XmlReader& e)
readInstrument(i, part, e);
Drumset* ds = i->drumset();
Staff* s = part->staff(0);
int lld = s ? qRound(s->lineDistance(0)) : 1;
int lld = s ? qRound(s->lineDistance(Fraction(0,1))) : 1;
if (ds && s && lld > 1) {
for (int j = 0; j < DRUM_INSTRUMENTS; ++j)
ds->drum(j).line /= lld;
@ -1168,7 +1168,7 @@ static void readNote(Note* note, XmlReader& e)
note->setTpc2(tpc);
}
if (!(tpcIsValid(note->tpc1()) && tpcIsValid(note->tpc2()))) {
int tick = note->chord() ? note->chord()->tick() : -1;
Fraction tick = note->chord() ? note->chord()->tick() : Fraction(-1,1);
Interval v = note->staff() ? note->part()->instrument(tick)->transpose() : Interval();
if (tpcIsValid(note->tpc1())) {
v.flip();
@ -1460,7 +1460,7 @@ bool readNoteProperties206(Note* note, XmlReader& e)
placeholder->setAnchor(Spanner::Anchor::NOTE);
placeholder->setEndElement(note);
placeholder->setTrack2(note->track());
placeholder->setTick(0);
placeholder->setTick(Fraction(0,1));
placeholder->setTick2(e.tick());
e.addSpanner(id1, placeholder);
}
@ -1751,9 +1751,9 @@ static void readTuplet(Tuplet* tuplet, XmlReader& e)
else if (!readTupletProperties206(e, tuplet))
e.unknown();
}
Fraction r = (tuplet->ratio() == 1) ? tuplet->ratio() : tuplet->ratio().reduced();
Fraction r = (tuplet->ratio() == Fraction(1,1)) ? tuplet->ratio() : tuplet->ratio().reduced();
Fraction f(r.denominator(), tuplet->baseLen().fraction().denominator());
tuplet->setDuration(f.reduced());
tuplet->setTicks(f.reduced());
}
//---------------------------------------------------------
@ -1785,7 +1785,7 @@ static void readLyrics(Lyrics* lyrics, XmlReader& e)
// if any endTick, make it relative to current tick
if (iEndTick)
lyrics->setTicks(iEndTick - e.tick());
lyrics->setTicks(Fraction::fromTicks(iEndTick) - e.tick());
if (_verseNumber) {
// TODO: add text to main text
delete _verseNumber;
@ -1882,21 +1882,21 @@ bool readChordRestProperties206(XmlReader& e, ChordRest* ch)
// OTOH, freshly created (un-initialized) rests have numerator == 0 (< 4/4)
// (see Fraction() constructor in fraction.h; this happens for instance
// when pasting selection from clipboard): they should not be converted
ch->duration().numerator() != 0 &&
ch->ticks().numerator() != 0 &&
// rest durations are initialized to full measure duration when
// created upon reading the <Rest> tag (see Measure::read() )
// so a V_WHOLE rest in a measure of 4/4 or less => V_MEASURE
(ch->actualDurationType()==TDuration::DurationType::V_WHOLE && ch->duration() <= Fraction(4, 4)) ) {
(ch->actualDurationType()==TDuration::DurationType::V_WHOLE && ch->ticks() <= Fraction(4, 4)) ) {
// old pre 2.0 scores: convert
ch->setDurationType(TDuration::DurationType::V_MEASURE);
}
else // not from old score: set duration fraction from duration type
ch->setDuration(ch->actualDurationType().fraction());
ch->setTicks(ch->actualDurationType().fraction());
}
else {
if (ch->score()->mscVersion() <= 114) {
SigEvent event = ch->score()->sigmap()->timesig(e.tick());
ch->setDuration(event.timesig());
ch->setTicks(event.timesig());
}
}
}
@ -1943,7 +1943,7 @@ bool readChordRestProperties206(XmlReader& e, ChordRest* ch)
else if (tag == "small")
ch->setSmall(e.readInt());
else if (tag == "duration")
ch->setDuration(e.readFraction());
ch->setTicks(e.readFraction());
else if (tag == "ticklen") { // obsolete (version < 1.12)
int mticks = ch->score()->sigmap()->timesig(e.tick()).timesig().ticks();
int i = e.readInt();
@ -1951,11 +1951,11 @@ bool readChordRestProperties206(XmlReader& e, ChordRest* ch)
i = mticks;
if ((ch->type() == ElementType::REST) && (mticks == i)) {
ch->setDurationType(TDuration::DurationType::V_MEASURE);
ch->setDuration(Fraction::fromTicks(i));
ch->setTicks(Fraction::fromTicks(i));
}
else {
Fraction f = Fraction::fromTicks(i);
ch->setDuration(f);
ch->setTicks(f);
ch->setDurationType(TDuration(f));
}
}
@ -1983,8 +1983,8 @@ bool readChordRestProperties206(XmlReader& e, ChordRest* ch)
}
else {
if (atype == "start") {
if (spanner->ticks() > 0 && spanner->tick() == -1) // stop has been read first
spanner->setTicks(spanner->ticks() - e.tick() - 1);
if (spanner->ticks() > Fraction(0,1) && spanner->tick() == Fraction(-1,1)) // stop has been read first
spanner->setTicks(spanner->ticks() - e.tick() - Fraction::fromTicks(1));
spanner->setTick(e.tick());
spanner->setTrack(ch->track());
if (spanner->type() == ElementType::SLUR)
@ -2742,18 +2742,18 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
// tick is obsolete
if (e.hasAttribute("tick"))
e.initTick(score->fileDivision(e.intAttribute("tick")));
e.setTick(Fraction::fromTicks(score->fileDivision(e.intAttribute("tick"))));
bool irregular;
if (e.hasAttribute("len")) {
QStringList sl = e.attribute("len").split('/');
if (sl.size() == 2)
m->setLen(Fraction(sl[0].toInt(), sl[1].toInt()));
m->setTicks(Fraction(sl[0].toInt(), sl[1].toInt()));
else
qDebug("illegal measure size <%s>", qPrintable(e.attribute("len")));
irregular = true;
score->sigmap()->add(m->tick(), SigEvent(m->len(), m->timesig()));
score->sigmap()->add(m->endTick(), SigEvent(m->timesig()));
score->sigmap()->add(m->tick().ticks(), SigEvent(m->ticks(), m->timesig()));
score->sigmap()->add(m->endTick().ticks(), SigEvent(m->timesig()));
}
else
irregular = false;
@ -2764,15 +2764,15 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
// keep track of tick of previous element
// this allows markings that need to apply to previous element to do so
// even though we may have already advanced to next tick position
int lastTick = e.tick();
Fraction lastTick = e.tick();
while (e.readNextStartElement()) {
const QStringRef& tag(e.name());
if (tag == "move")
e.initTick(e.readFraction().ticks() + m->tick());
e.setTick(e.readFraction() + m->tick());
else if (tag == "tick") {
e.initTick(score->fileDivision(e.readInt()));
e.setTick(Fraction::fromTicks(score->fileDivision(e.readInt())));
lastTick = e.tick();
}
else if (tag == "BarLine") {
@ -2853,23 +2853,23 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
chord->add(gc);
}
graceNotes.clear();
int crticks = chord->actualTicks();
lastTick = e.tick();
Fraction crticks = chord->actualTicks();
lastTick = e.tick();
e.incTick(crticks);
}
}
else if (tag == "Rest") {
Rest* rest = new Rest(score);
rest->setDurationType(TDuration::DurationType::V_MEASURE);
rest->setDuration(m->timesig()/timeStretch);
rest->setTicks(m->timesig()/timeStretch);
rest->setTrack(e.track());
segment = m->getSegment(SegmentType::ChordRest, e.tick());
rest->setParent(segment);
readRest(rest, e);
segment->add(rest);
if (!rest->duration().isValid()) // hack
rest->setDuration(m->timesig()/timeStretch);
if (!rest->ticks().isValid()) // hack
rest->setTicks(m->timesig()/timeStretch);
lastTick = e.tick();
e.incTick(rest->actualTicks());
@ -2877,13 +2877,13 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
else if (tag == "Breath") {
Breath* breath = new Breath(score);
breath->setTrack(e.track());
int tick = e.tick();
Fraction tick = e.tick();
breath->read(e);
// older scores placed the breath segment right after the chord to which it applies
// rather than before the next chordrest segment with an element for the staff
// result would be layout too far left if there are other segments due to notes in other staves
// we need to find tick of chord to which this applies, and add its duration
int prevTick;
Fraction prevTick;
if (e.tick() < tick)
prevTick = e.tick(); // use our own tick if we explicitly reset to earlier position
else
@ -2984,8 +2984,8 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
clef->setTrack(e.track());
clef->read(e);
clef->setGenerated(false);
if (e.tick() == 0) {
if (score->staff(staffIdx)->clef(0) != clef->clefType())
if (e.tick().isZero()) {
if (score->staff(staffIdx)->clef(Fraction(0,1)) != clef->clefType())
score->staff(staffIdx)->setDefaultClefType(clef->clefType());
if (clef->links() && clef->links()->size() == 1) {
e.linkIds().remove(clef->links()->lid());
@ -3045,7 +3045,7 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
ts->setTrack(e.track());
ts->read(e);
// if time sig not at beginning of measure => courtesy time sig
int currTick = e.tick();
Fraction currTick = e.tick();
bool courtesySig = (currTick > m->tick());
if (courtesySig) {
// if courtesy sig., just add it without map processing
@ -3061,12 +3061,12 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
m->setTimesig(ts->sig() / timeStretch);
if (irregular) {
score->sigmap()->add(m->tick(), SigEvent(m->len(), m->timesig()));
score->sigmap()->add(m->endTick(), SigEvent(m->timesig()));
score->sigmap()->add(m->tick().ticks(), SigEvent(m->ticks(), m->timesig()));
score->sigmap()->add(m->endTick().ticks(), SigEvent(m->timesig()));
}
else {
m->setLen(m->timesig());
score->sigmap()->add(m->tick(), SigEvent(m->timesig()));
m->setTicks(m->timesig());
score->sigmap()->add(m->tick().ticks(), SigEvent(m->timesig()));
}
}
}
@ -3074,8 +3074,8 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
KeySig* ks = new KeySig(score);
ks->setTrack(e.track());
ks->read(e);
int curTick = e.tick();
if (!ks->isCustom() && !ks->isAtonal() && ks->key() == Key::C && curTick == 0) {
Fraction curTick = e.tick();
if (!ks->isCustom() && !ks->isAtonal() && ks->key() == Key::C && curTick.isZero()) {
// ignore empty key signature
qDebug("remove keysig c at tick 0");
if (ks->links()) {
@ -3338,7 +3338,7 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
m->setMMRestCount(e.readInt());
// set tick to previous measure
m->setTick(e.lastMeasure()->tick());
e.initTick(e.lastMeasure()->tick());
e.setTick(e.lastMeasure()->tick());
}
else if (m->MeasureBase::readProperties(e))
;
@ -3417,7 +3417,7 @@ static void readBox(Box* b, XmlReader& e)
static void readStaffContent(Score* score, XmlReader& e)
{
int staff = e.intAttribute("id", 1) - 1;
e.initTick(0);
e.setTick(Fraction(0,1));
e.setTrack(staff * VOICES);
Box* lastReadBox = nullptr;
bool readMeasureLast = false;
@ -3441,7 +3441,7 @@ static void readStaffContent(Score* score, XmlReader& e)
//
Measure* m = e.lastMeasure(); // measure->prevMeasure();
Fraction f(m ? m->timesig() : Fraction(4,4));
measure->setLen(f);
measure->setTicks(f);
measure->setTimesig(f);
readMeasure(measure, staff, e);
@ -3449,7 +3449,7 @@ static void readStaffContent(Score* score, XmlReader& e)
if (!measure->isMMRest()) {
score->measures()->add(measure);
e.setLastMeasure(measure);
e.initTick(measure->tick() + measure->ticks());
e.setTick(measure->endTick());
}
else {
// this is a multi measure rest
@ -3473,7 +3473,7 @@ static void readStaffContent(Score* score, XmlReader& e)
readMeasureLast = false;
}
else if (tag == "tick")
e.initTick(score->fileDivision(e.readInt()));
e.setTick(Fraction::fromTicks(score->fileDivision(e.readInt())));
else
e.unknown();
}
@ -3490,7 +3490,7 @@ static void readStaffContent(Score* score, XmlReader& e)
measure->setTick(e.tick());
score->measures()->add(measure);
}
e.initTick(measure->tick());
e.setTick(measure->tick());
readMeasure(measure, staff, e);
measure->checkMeasure(staff);
if (measure->isMMRest())
@ -3504,7 +3504,7 @@ static void readStaffContent(Score* score, XmlReader& e)
}
}
else if (tag == "tick")
e.initTick(score->fileDivision(e.readInt()));
e.setTick(Fraction::fromTicks(score->fileDivision(e.readInt())));
else
e.unknown();
}

View file

@ -47,7 +47,7 @@ void RehearsalMark::layout()
Segment* s = segment();
if (s) {
if (!s->rtick()) {
if (s->rtick().isZero()) {
// first CR of measure, decide whether to align to barline
if (!s->prev() && align() & Align::CENTER) {
// measure with no clef / keysig / timesig

View file

@ -171,7 +171,7 @@ void MasterScore::updateChannel()
}
}
}
for (auto it = spanner().cbegin(); it != spanner().cend(); ++it) {
Spanner* spanner = (*it).second;
if (!spanner->isVolta())
@ -245,11 +245,11 @@ static void collectNote(EventMap* events, int channel, const Note* note, int vel
if (chord->isGrace()) {
Q_ASSERT( !graceNotesMerged(chord)); // this function should not be called on a grace note if grace notes are merged
chord = toChord(chord->parent());
ticks = chord->actualTicks(); // ticks of the parent note
ticks = chord->actualTicks().ticks(); // ticks of the parent note
tieLen = 0;
}
else {
ticks = chord->actualTicks(); // ticks of the actual note
ticks = chord->actualTicks().ticks(); // ticks of the actual note
// calculate additional length due to ties forward
// taking NoteEvent length adjustments into account
// but stopping at any note with multiple NoteEvents
@ -262,7 +262,7 @@ static void collectNote(EventMap* events, int channel, const Note* note, int vel
// add value of this note to main note
// if we wish to suppress first note of ornament,
// then do this regardless of number of NoteEvents
tieLen += (n->chord()->actualTicks() * (nel[0].len())) / 1000;
tieLen += (n->chord()->actualTicks().ticks() * (nel[0].len())) / 1000;
}
else {
// recurse
@ -277,8 +277,8 @@ static void collectNote(EventMap* events, int channel, const Note* note, int vel
}
}
int tick1 = chord->tick() + tickOffset;
bool tieFor = note->tieFor();
int tick1 = chord->tick().ticks() + tickOffset;
bool tieFor = note->tieFor();
bool tieBack = note->tieBack();
NoteEventList nel = note->playEvents();
@ -403,7 +403,7 @@ static void collectMeasureEvents(EventMap* events, Measure* m, Staff* staff, int
int etrack = nextStaffIdx * VOICES;
for (Segment* seg = m->first(st); seg; seg = seg->next(st)) {
int tick = seg->tick();
int tick = seg->tick().ticks();
for (int track = strack; track < etrack; ++track) {
// skip linked staves, except primary
if (!m->score()->staff(track / VOICES)->primaryStaff()) {
@ -417,8 +417,8 @@ static void collectMeasureEvents(EventMap* events, Measure* m, Staff* staff, int
Chord* chord = toChord(cr);
Staff* st1 = chord->staff();
int staffIdx = st1->idx();
int velocity = st1->velocities().velo(seg->tick());
Instrument* instr = chord->part()->instrument(tick);
int velocity = st1->velocities().velo(seg->tick().ticks());
Instrument* instr = chord->part()->instrument(Fraction::fromTicks(tick));
int channel = instr->channel(chord->upNote()->subchannel())->channel();
events->registerChannel(channel);
@ -449,7 +449,7 @@ static void collectMeasureEvents(EventMap* events, Measure* m, Staff* staff, int
if (!e->isStaffTextBase() || e->staffIdx() < firstStaffIdx || e->staffIdx() >= nextStaffIdx)
continue;
const StaffTextBase* st1 = toStaffTextBase(e);
int tick = s->tick() + tickOffset;
Fraction tick = s->tick() + Fraction::fromTicks(tickOffset);
Instrument* instr = e->part()->instrument(tick);
for (const ChannelActions& ca : *st1->channelActions()) {
@ -463,9 +463,9 @@ static void collectMeasureEvents(EventMap* events, Measure* m, Staff* staff, int
NPlayEvent e1(event);
e1.setOriginatingStaff(firstStaffIdx);
if (e1.dataA() == CTRL_PROGRAM)
events->insert(std::pair<int, NPlayEvent>(tick-1, e1));
events->insert(std::pair<int, NPlayEvent>(tick.ticks()-1, e1));
else
events->insert(std::pair<int, NPlayEvent>(tick, e1));
events->insert(std::pair<int, NPlayEvent>(tick.ticks(), e1));
}
}
}
@ -477,7 +477,7 @@ static void collectMeasureEvents(EventMap* events, Measure* m, Staff* staff, int
for (int i = 0; i < 4; ++i) {
static int num[4] = { 12, 13, 16, 16 };
for (int k = 0; k < num[i]; ++k)
aeolusSetStop(tick, channel, i, k, st1->getAeolusStop(i, k), events);
aeolusSetStop(tick.ticks(), channel, i, k, st1->getAeolusStop(i, k), events);
}
}
}
@ -523,10 +523,10 @@ void Score::updateRepeatList(bool expandRepeats)
void Score::updateHairpin(Hairpin* h)
{
Staff* st = h->staff();
int tick = h->tick();
int velo = st->velocities().velo(tick);
Fraction tick = h->tick();
int velo = st->velocities().velo(tick.ticks());
int incr = h->veloChange();
int tick2 = h->tick2();
Fraction tick2 = h->tick2();
//
// If velocity increase/decrease is zero, then assume
@ -536,14 +536,14 @@ void Score::updateHairpin(Hairpin* h)
int endVelo = velo;
if (h->hairpinType() == HairpinType::CRESC_HAIRPIN || h->hairpinType() == HairpinType::CRESC_LINE) {
if (incr == 0 && velo < st->velocities().nextVelo(tick2-1))
endVelo = st->velocities().nextVelo(tick2-1);
if (incr == 0 && velo < st->velocities().nextVelo(tick2.ticks()-1))
endVelo = st->velocities().nextVelo(tick2.ticks()-1);
else
endVelo += incr;
}
else {
if (incr == 0 && velo > st->velocities().nextVelo(tick2-1))
endVelo = st->velocities().nextVelo(tick2-1);
if (incr == 0 && velo > st->velocities().nextVelo(tick2.ticks()-1))
endVelo = st->velocities().nextVelo(tick2.ticks()-1);
else
endVelo -= incr;
}
@ -555,19 +555,19 @@ void Score::updateHairpin(Hairpin* h)
switch (h->dynRange()) {
case Dynamic::Range::STAFF:
st->velocities().setVelo(tick, VeloEvent(VeloType::RAMP, velo));
st->velocities().setVelo(tick2-1, VeloEvent(VeloType::FIX, endVelo));
st->velocities().setVelo(tick.ticks(), VeloEvent(VeloType::RAMP, velo));
st->velocities().setVelo(tick2.ticks()-1, VeloEvent(VeloType::FIX, endVelo));
break;
case Dynamic::Range::PART:
for (Staff* s : *st->part()->staves()) {
s->velocities().setVelo(tick, VeloEvent(VeloType::RAMP, velo));
s->velocities().setVelo(tick2-1, VeloEvent(VeloType::FIX, endVelo));
s->velocities().setVelo(tick.ticks(), VeloEvent(VeloType::RAMP, velo));
s->velocities().setVelo(tick2.ticks()-1, VeloEvent(VeloType::FIX, endVelo));
}
break;
case Dynamic::Range::SYSTEM:
for (Staff* s : _staves) {
s->velocities().setVelo(tick, VeloEvent(VeloType::RAMP, velo));
s->velocities().setVelo(tick2-1, VeloEvent(VeloType::FIX, endVelo));
s->velocities().setVelo(tick.ticks(), VeloEvent(VeloType::RAMP, velo));
s->velocities().setVelo(tick2.ticks()-1, VeloEvent(VeloType::FIX, endVelo));
}
break;
}
@ -580,10 +580,10 @@ void Score::updateHairpin(Hairpin* h)
void Score::removeHairpin(Hairpin* h)
{
Staff* st = h->staff();
int tick = h->tick();
int tick2 = h->tick2() - 1;
int tick = h->tick().ticks();
int tick2 = h->tick2().ticks() - 1;
switch(h->dynRange()) {
switch (h->dynRange()) {
case Dynamic::Range::STAFF:
st->velocities().remove(tick);
st->velocities().remove(tick2);
@ -629,7 +629,7 @@ void Score::updateVelo()
int partStaff = Score::staffIdx(prt);
for (Segment* s = firstMeasure()->first(); s; s = s->next1()) {
int tick = s->tick();
Fraction tick = s->tick();
for (const Element* e : s->annotations()) {
if (e->staffIdx() != staffIdx)
continue;
@ -643,17 +643,17 @@ void Score::updateVelo()
switch(d->dynRange()) {
case Dynamic::Range::STAFF:
if (dStaffIdx == staffIdx)
velo.setVelo(tick, v);
velo.setVelo(tick.ticks(), v);
break;
case Dynamic::Range::PART:
if (dStaffIdx >= partStaff && dStaffIdx < partStaff+partStaves) {
for (int i = partStaff; i < partStaff+partStaves; ++i)
staff(i)->velocities().setVelo(tick, v);
staff(i)->velocities().setVelo(tick.ticks(), v);
}
break;
case Dynamic::Range::SYSTEM:
for (int i = 0; i < nstaves(); ++i)
staff(i)->velocities().setVelo(tick, v);
staff(i)->velocities().setVelo(tick.ticks(), v);
break;
}
}
@ -666,7 +666,7 @@ void Score::updateVelo()
updateHairpin(h);
}
}
for (auto it = spanner().cbegin(); it != spanner().cend(); ++it) {
Spanner* spanner = (*it).second;
if (!spanner->isVolta())
@ -684,12 +684,12 @@ void Score::renderStaff(EventMap* events, Staff* staff)
{
Measure* lastMeasure = 0;
for (const RepeatSegment* rs : *repeatList()) {
int startTick = rs->tick;
int endTick = startTick + rs->len();
Fraction startTick = Fraction::fromTicks(rs->tick);
Fraction endTick = startTick + Fraction::fromTicks(rs->len());
int tickOffset = rs->utick - rs->tick;
for (Measure* m = tick2measure(startTick); m; m = m->nextMeasure()) {
if (lastMeasure && m->isRepeatMeasure(staff)) {
int offset = m->tick() - lastMeasure->tick();
int offset = (m->tick() - lastMeasure->tick()).ticks();
collectMeasureEvents(events, lastMeasure, staff, tickOffset + offset);
}
else {
@ -731,24 +731,26 @@ void Score::renderSpanners(EventMap* events)
else
lastEvent = std::pair<int, std::pair<bool, int>>(0, std::pair<bool, int>(true, staff));
if (s->tick() >= tick1 && s->tick() < tick2) {
int st = s->tick().ticks();
if (st >= tick1 && st < tick2) {
// Handle "overlapping" pedal segments (usual case for connected pedal line)
if (lastEvent.second.first == false && lastEvent.first >= (s->tick() + tickOffset + 2)) {
if (lastEvent.second.first == false && lastEvent.first >= (st + tickOffset + 2)) {
channelPedalEvents.at(channel).pop_back();
channelPedalEvents.at(channel).push_back(std::pair<int, std::pair<bool, int>>(s->tick() + tickOffset + 1, std::pair<bool, int>(false, staff)));
channelPedalEvents.at(channel).push_back(std::pair<int, std::pair<bool, int>>(st + tickOffset + 1, std::pair<bool, int>(false, staff)));
}
channelPedalEvents.at(channel).push_back(std::pair<int, std::pair<bool, int>>(s->tick() + tickOffset + 2, std::pair<bool, int>(true, staff)));
int a = st + tickOffset + 2;
channelPedalEvents.at(channel).push_back(std::pair<int, std::pair<bool, int>>(a, std::pair<bool, int>(true, staff)));
}
if (s->tick2() >= tick1 && s->tick2() <= tick2) {
int t = s->tick2() + tickOffset + 1;
if (s->tick2().ticks() >= tick1 && s->tick2().ticks() <= tick2) {
int t = s->tick2().ticks() + tickOffset + 1;
if (t > repeatList()->last()->utick + repeatList()->last()->len())
t = repeatList()->last()->utick + repeatList()->last()->len();
channelPedalEvents.at(channel).push_back(std::pair<int, std::pair<bool, int>>(t, std::pair<bool, int>(false, staff)));
}
}
else if (s->isVibrato()) {
int stick = s->tick();
int etick = s->tick2();
int stick = s->tick().ticks();
int etick = s->tick2().ticks();
if (stick >= tick2 || etick < tick1)
continue;
@ -825,7 +827,7 @@ void Score::renderSpanners(EventMap* events)
void Score::swingAdjustParams(Chord* chord, int& gateTime, int& ontime, int swingUnit, int swingRatio)
{
int tick = chord->rtick();
Fraction tick = chord->rtick();
// adjust for anacrusis
Measure* cm = chord->measure();
MeasureBase* pm = cm->prev();
@ -833,25 +835,25 @@ void Score::swingAdjustParams(Chord* chord, int& gateTime, int& ontime, int swin
if (!pm || pm->lineBreak() || pm->pageBreak() || pm->sectionBreak()
|| pt == ElementType::VBOX || pt == ElementType::HBOX
|| pt == ElementType::FBOX || pt == ElementType::TBOX) {
int offset = (cm->timesig() - cm->len()).ticks();
if (offset > 0) {
Fraction offset = cm->timesig() - cm->ticks();
if (offset > Fraction(0,1)) {
tick += offset;
}
}
int swingBeat = swingUnit * 2;
qreal ticksDuration = (qreal)chord->actualTicks();
qreal ticksDuration = (qreal)chord->actualTicks().ticks();
qreal swingTickAdjust = ((qreal)swingBeat) * (((qreal)(swingRatio-50))/100.0);
qreal swingActualAdjust = (swingTickAdjust/ticksDuration) * 1000.0;
ChordRest *ncr = nextChordRest(chord);
//Check the position of the chord to apply changes accordingly
if (tick % swingBeat == swingUnit) {
if (tick.ticks() % swingBeat == swingUnit) {
if (!isSubdivided(chord,swingUnit)) {
ontime = ontime + swingActualAdjust;
}
}
int endTick = tick + ticksDuration;
int endTick = tick.ticks() + ticksDuration;
if ((endTick % swingBeat == swingUnit) && (!isSubdivided(ncr,swingUnit))) {
gateTime = gateTime + (swingActualAdjust/10);
}
@ -867,7 +869,7 @@ bool Score::isSubdivided(ChordRest* chord, int swingUnit)
if (!chord)
return false;
ChordRest* prev = prevChordRest(chord);
if (chord->actualTicks() < swingUnit || (prev && prev->actualTicks() < swingUnit))
if (chord->actualTicks().ticks() < swingUnit || (prev && prev->actualTicks().ticks() < swingUnit))
return true;
else
return false;
@ -930,7 +932,7 @@ void renderTremolo(Chord* chord, QList<NoteEventList>& ell)
if (c2->type() == ElementType::CHORD) {
int notes2 = int(c2->notes().size());
int tnotes = qMax(notes, notes2);
int tticks = chord->actualTicks() * 2; // use twice the size
int tticks = chord->actualTicks().ticks() * 2; // use twice the size
int n = tticks / t;
n /= 2;
int l = 2000 * t / tticks;
@ -984,7 +986,7 @@ void renderTremolo(Chord* chord, QList<NoteEventList>& ell)
int t = MScore::division / (1 << (tremolo->lines() + chord->durationType().hooks()));
if (t == 0) // avoid crash on very short tremolo
t = 1;
int n = chord->duration().ticks() / t;
int n = chord->ticks().ticks() / t;
int l = 1000 / n;
for (int k = 0; k < notes; ++k) {
NoteEventList* events = &(ell)[k];
@ -1022,8 +1024,8 @@ void renderArpeggio(Chord *chord, QList<NoteEventList> & ell)
NoteEventList* events = &(ell)[i];
events->clear();
auto tempoRatio = chord->score()->tempomap()->tempo(chord->tick()) / Score::defaultTempo();
int ot = (l * j * 1000) / chord->upNote()->playTicks() *
auto tempoRatio = chord->score()->tempomap()->tempo(chord->tick().ticks()) / Score::defaultTempo();
int ot = (l * j * 1000) / chord->upNote()->playTicks() *
tempoRatio * chord->arpeggio()->Stretch();
events->append(NoteEvent(0, ot, 1000 - ot));
@ -1092,7 +1094,7 @@ int articulationExcursion(Note *noteL, Note *noteR, int deltastep)
Chord *chordL = noteL->chord();
Chord *chordR = noteR->chord();
int epitchL = noteL->epitch();
int tickL = chordL->tick();
Fraction tickL = chordL->tick();
// we canot use staffL = chord->staff() because that won't correspond to the noteL->line()
// in the case the user has pressed Shift-Cmd->Up or Shift-Cmd-Down.
// Therefore we have to take staffMove() into account using vStaffIdx().
@ -1154,16 +1156,16 @@ int articulationExcursion(Note *noteL, Note *noteR, int deltastep)
// return the total of the actualTicks of the given note plus
// the chain of zero or more notes tied to it to the right.
//---------------------------------------------------------
int totalTiedNoteTicks(Note* note)
{
int total = note->chord()->actualTicks();
Fraction total = note->chord()->actualTicks();
while (note->tieFor() && note->tieFor()->endNote() && (note->chord()->tick() < note->tieFor()->endNote()->chord()->tick())) {
note = note->tieFor()->endNote();
total += note->chord()->actualTicks();
}
return total;
};
return total.ticks();
}
//---------------------------------------------------------
// renderNoteArticulation
@ -1199,7 +1201,7 @@ bool renderNoteArticulation(NoteEventList* events, Note* note, bool chromatic, i
if (gnb + p + b + s + gna <= 0 )
return false;
int tick = chord->tick();
Fraction tick = chord->tick();
qreal tempo = chord->score()->tempo(tick);
int ticksPerSecond = tempo * MScore::division;
@ -1269,8 +1271,8 @@ bool renderNoteArticulation(NoteEventList* events, Note* note, bool chromatic, i
// RETURNS the new ontime value. The caller is expected to assign this value.
auto makeEvent = [note,chord,chromatic,events] (int pitch, int ontime, int duration) {
events->append( NoteEvent(chromatic ? pitch : articulationExcursion(note,note,pitch),
ontime/chord->actualTicks(),
duration/chord->actualTicks()));
ontime/chord->actualTicks().ticks(),
duration/chord->actualTicks().ticks()));
return ontime + duration;
};
@ -1289,8 +1291,8 @@ bool renderNoteArticulation(NoteEventList* events, Note* note, bool chromatic, i
// The pitch is relative to the pitch of the note, the event is rendering
if (n->play())
events->append( NoteEvent(n->pitch() - notePitch,
ontime/chord->actualTicks(),
millespernote/chord->actualTicks()));
ontime/chord->actualTicks().ticks(),
millespernote/chord->actualTicks().ticks()));
}
ontime += millespernote;
}
@ -1534,8 +1536,10 @@ void renderGlissando(NoteEventList* events, Note *notestart)
// which overlaps this chord and is of type ElementType::TRILL
//---------------------------------------------------------
Trill* findFirstTrill(Chord *chord) {
auto spanners = chord->score()->spannerMap().findOverlapping(1+chord->tick(), chord->tick() + chord->actualTicks() - 1);
Trill* findFirstTrill(Chord *chord)
{
auto spanners = chord->score()->spannerMap().findOverlapping(1+chord->tick().ticks(),
chord->tick().ticks() + chord->actualTicks().ticks() - 1);
for (auto i : spanners) {
if (i.value->type() != ElementType::TRILL)
continue;
@ -1674,7 +1678,7 @@ static QList<NoteEventList> renderChord(Chord* chord, int gateTime, int ontime,
// to effect the on/off time of the main note
//---------------------------------------------------------
void Score::createGraceNotesPlayEvents(int tick, Chord* chord, int &ontime, int &trailtime)
void Score::createGraceNotesPlayEvents(const Fraction& tick, Chord* chord, int& ontime, int& trailtime)
{
QVector<Chord*> gnb = chord->graceNotesBefore();
QVector<Chord*> gna = chord->graceNotesAfter();
@ -1700,7 +1704,7 @@ void Score::createGraceNotesPlayEvents(int tick, Chord* chord, int &ontime, int
int graceDuration = 0;
bool drumset = (getDrumset(chord) != nullptr);
const qreal ticksPerSecond = tempo(tick) * MScore::division;
const qreal chordTimeMS = (chord->actualTicks() / ticksPerSecond) * 1000;
const qreal chordTimeMS = (chord->actualTicks().ticks() / ticksPerSecond) * 1000;
if (drumset) {
int flamDuration = 15; //ms
graceDuration = flamDuration / chordTimeMS * 1000; //ratio 1/1000 from the main note length
@ -1791,10 +1795,10 @@ void Score::createPlayEvents(Chord* chord)
{
int gateTime = 100;
int tick = chord->tick();
Fraction tick = chord->tick();
Slur* slur = 0;
for (auto sp : _spanner.map()) {
if (sp.second->type() != ElementType::SLUR || sp.second->staffIdx() != chord->staffIdx())
if (!sp.second->isSlur() || sp.second->staffIdx() != chord->staffIdx())
continue;
Slur* s = toSlur(sp.second);
if (tick >= s->tick() && tick < s->tick2()) {
@ -1857,28 +1861,27 @@ void Score::createPlayEvents()
// renderMetronome
//---------------------------------------------------------
void Score::renderMetronome(EventMap* events, Measure* m, int tickOffset)
void Score::renderMetronome(EventMap* events, Measure* m, const Fraction& tickOffset)
{
int msrTick = m->tick();
qreal tempo = tempomap()->tempo(msrTick);
int msrTick = m->tick().ticks();
qreal tempo = tempomap()->tempo(msrTick);
TimeSigFrac timeSig = sigmap()->timesig(msrTick).nominal();
int clickTicks = timeSig.isBeatedCompound(tempo) ? timeSig.beatTicks() : timeSig.dUnitTicks();
int endTick = m->endTick();
int clickTicks = timeSig.isBeatedCompound(tempo) ? timeSig.beatTicks() : timeSig.dUnitTicks();
int endTick = m->endTick().ticks();
int rtick;
if (m->isAnacrusis()) {
int rem = m->ticks() % clickTicks;
int rem = m->ticks().ticks() % clickTicks;
msrTick += rem;
rtick = rem + timeSig.ticksPerMeasure() - m->ticks();
rtick = rem + timeSig.ticksPerMeasure() - m->ticks().ticks();
}
else
rtick = 0;
for (int tick = msrTick; tick < endTick; tick += clickTicks, rtick+=clickTicks)
events->insert(std::pair<int,NPlayEvent>(tick + tickOffset, NPlayEvent(timeSig.rtick2beatType(rtick))));
for (int tick = msrTick; tick < endTick; tick += clickTicks, rtick += clickTicks)
events->insert(std::pair<int,NPlayEvent>(tick + tickOffset.ticks(), NPlayEvent(timeSig.rtick2beatType(rtick))));
}
//---------------------------------------------------------
@ -1920,9 +1923,9 @@ void Score::renderMidi(EventMap* events, bool metronome, bool expandRepeats)
//
// add metronome tick events
//
for (Measure* m = tick2measure(startTick); m; m = m->nextMeasure()) {
renderMetronome(events, m, tickOffset);
if (m->tick() + m->ticks() >= endTick)
for (Measure* m = tick2measure(Fraction::fromTicks(startTick)); m; m = m->nextMeasure()) {
renderMetronome(events, m, Fraction::fromTicks(tickOffset));
if (m->endTick().ticks() >= endTick)
break;
}
}

View file

@ -71,10 +71,10 @@ void RepeatMeasure::layout()
}
//---------------------------------------------------------
// duration
// ticks
//---------------------------------------------------------
Fraction RepeatMeasure::duration() const
Fraction RepeatMeasure::ticks() const
{
if (measure())
return measure()->stretchedLen(staff());

View file

@ -36,8 +36,8 @@ class RepeatMeasure final : public Rest {
virtual ElementType type() const override { return ElementType::REPEAT_MEASURE; }
virtual void draw(QPainter*) const override;
virtual void layout() override;
virtual Fraction duration() const override;
Fraction actualDuration() const { return Rest::duration(); }
virtual Fraction ticks() const override;
Fraction actualTicks() const { return Rest::ticks(); }
virtual QString accessibleInfo() const override;
};

View file

@ -99,14 +99,14 @@ RepeatSegment::RepeatSegment(RepeatSegment * const rs, Measure * const fromMeasu
++it;
}
if (!measureList.empty()) {
tick = measureList.cbegin()->first->tick();
tick = measureList.cbegin()->first->tick().ticks();
}
}
void RepeatSegment::addMeasure(Measure * const m)
{
if (measureList.empty()) {
tick = m->tick();
tick = m->tick().ticks();
}
measureList.push_back(std::make_pair(m, m->playbackCount()));
}
@ -123,7 +123,7 @@ bool RepeatSegment::containsMeasure(Measure const * const m) const
int RepeatSegment::len() const
{
return (measureList.empty()) ? 0 : (measureList.last().first->endTick() - tick);
return (measureList.empty()) ? 0 : (measureList.last().first->endTick().ticks() - tick);
}
//---------------------------------------------------------
@ -616,7 +616,7 @@ void RepeatList::unwindSection(Measure* const sectionStartMeasure, Measure* cons
// this is the most recent playthrough of this measure -> copy it
if (nullptr == rs) {
rs = new RepeatSegment();
rs->tick = referenceIt->first->tick();
rs->tick = referenceIt->first->tick().ticks();
}
rs->measureList.push_back(std::make_pair(referenceIt->first, referenceIt->second));
}

View file

@ -50,7 +50,7 @@ Rest::Rest(Score* s, const TDuration& d)
_sym = SymId::restQuarter;
setDurationType(d);
if (d.fraction().isValid())
setDuration(d.fraction());
setTicks(d.fraction());
}
Rest::Rest(const Rest& r, bool link)
@ -233,7 +233,7 @@ Element* Rest::drop(EditData& data)
NoteVal nval;
nval.pitch = n->pitch();
nval.headGroup = n->headGroup();
Fraction d = score()->inputState().duration().fraction();
Fraction d = score()->inputState().ticks();
if (!d.isZero()) {
Segment* seg = score()->setNoteRest(segment(), track(), nval, d, dir);
if (seg) {
@ -277,7 +277,7 @@ SymId Rest::getSymbol(TDuration::DurationType type, int line, int lines, int* yo
case TDuration::DurationType::V_BREVE:
return SymId::restDoubleWhole;
case TDuration::DurationType::V_MEASURE:
if (duration() >= Fraction(2, 1))
if (ticks() >= Fraction(2, 1))
return SymId::restDoubleWhole;
// fall through
case TDuration::DurationType::V_WHOLE:
@ -355,10 +355,10 @@ void Rest::layout()
int dots = durationType().dots();
// if rest is whole measure, convert into actual type and dot values
if (type == TDuration::DurationType::V_MEASURE) {
int ticks = measure()->ticks();
TDuration dur = TDuration(Fraction::fromTicks(ticks)).type();
type = dur.type();
dots = dur.dots();
Fraction ticks = measure()->ticks();
TDuration dur = TDuration(ticks).type();
type = dur.type();
dots = dur.dots();
}
// symbol needed; if not exist, create, if exists, update duration
if (!_tabDur)
@ -483,7 +483,7 @@ int Rest::computeLineOffset(int lines)
Element* e = s->element(track() + 1);
if (e && e->isRest() && (!e->visible() || toRest(e)->isGap())) {
Rest* r = toRest(e);
if (r->globalDuration() == globalDuration()) {
if (r->globalTicks() == globalTicks()) {
offsetVoices = false;
}
}
@ -542,7 +542,7 @@ int Rest::computeLineOffset(int lines)
lineOffset = up ? -3 : 5;
break;
case TDuration::DurationType::V_MEASURE:
if (duration() >= Fraction(2, 1)) // breve symbol
if (ticks() >= Fraction(2, 1)) // breve symbol
lineOffset = up ? -3 : 5;
else
lineOffset = up ? -4 : 6; // whole symbol

View file

@ -254,9 +254,9 @@ Score::Score()
_scoreFont = ScoreFont::fontFactory("emmentaler");
_pos[int(POS::CURRENT)] = 0;
_pos[int(POS::LEFT)] = 0;
_pos[int(POS::RIGHT)] = 0;
_pos[int(POS::CURRENT)] = Fraction(0,1);
_pos[int(POS::LEFT)] = Fraction(0,1);
_pos[int(POS::RIGHT)] = Fraction(0,1);
_fileDivision = MScore::division;
_style = MScore::defaultStyle();
// accInfo = tr("No selection"); // ??
@ -404,7 +404,7 @@ void Score::addMeasure(MeasureBase* m, MeasureBase* pos)
void Score::fixTicks()
{
int tick = 0;
Fraction tick = Fraction(0,1);
Measure* fm = firstMeasure();
if (fm == 0)
return;
@ -412,13 +412,13 @@ void Score::fixTicks()
for (Staff* staff : _staves)
staff->clearTimeSig();
Fraction sig(fm->len());
Fraction sig(fm->ticks());
Fraction nomSig(fm->timesig());
if (isMaster()) {
tempomap()->clear();
sigmap()->clear();
sigmap()->add(0, SigEvent(fm->len(), fm->timesig(), 0));
sigmap()->add(0, SigEvent(fm->ticks(), fm->timesig(), 0));
}
for (MeasureBase* mb = first(); mb; mb = mb->next()) {
@ -426,10 +426,10 @@ void Score::fixTicks()
mb->setTick(tick);
continue;
}
Measure* m = toMeasure(mb);
int mtick = m->tick();
int diff = tick - mtick;
int measureTicks = m->ticks();
Measure* m = toMeasure(mb);
Fraction mtick = m->tick();
Fraction diff = tick - mtick;
Fraction measureTicks = m->ticks();
m->moveTicks(diff);
if (m->mmRest())
m->mmRest()->moveTicks(diff);
@ -447,7 +447,7 @@ void Score::fixTicks()
for (Segment* s = m->first(); s; s = s->next()) {
if (isMaster() && s->segmentType() == SegmentType::Breath) {
qreal length = 0.0;
int tick1 = s->tick();
Fraction tick1 = s->tick();
// find longest pause
for (int i = 0, n = ntracks(); i < n; ++i) {
Element* e = s->element(i);
@ -506,10 +506,10 @@ void Score::fixTicks()
// even if they are equivalent 4/4 vs 2/2
// also check if nominal time signature has changed
if (isMaster() && (!sig.identical(m->len()) || !nomSig.identical(m->timesig()))) {
sig = m->len();
if (isMaster() && (!sig.identical(m->ticks()) || !nomSig.identical(m->timesig()))) {
sig = m->ticks();
nomSig = m->timesig();
sigmap()->add(tick, SigEvent(sig, nomSig, m->no()));
sigmap()->add(tick.ticks(), SigEvent(sig, nomSig, m->no()));
}
tick += measureTicks;
@ -597,7 +597,7 @@ Measure* Score::pos2measure(const QPointF& p, int* rst, int* pitch, Segment** se
*rst = i;
if (pitch) {
Staff* s1 = _staves[i];
int tick = segment->tick();
Fraction tick = segment->tick();
ClefType clef = s1->clef(tick);
*pitch = y2pitch(pppp.y() - sstaff->bbox().y(), clef, s1->spatium(tick));
}
@ -1023,7 +1023,7 @@ static Segment* getNextValidInputSegment(Segment* s, int track, int voice)
if (cr1)
break;
}
int nextTick = (cr1 == nullptr) ? s->measure()->tick() : cr1->tick() + cr1->actualTicks();
Fraction nextTick = (cr1 == nullptr) ? s->measure()->tick() : cr1->tick() + cr1->actualTicks();
static const SegmentType st { SegmentType::ChordRest };
while (s) {
@ -1167,9 +1167,9 @@ bool Score::getPosition(Position* pos, const QPointF& p, int voice) const
//
// TODO: restrict to reasonable values (pitch 0-127)
//
Staff* s = staff(pos->staffIdx);
qreal mag = s->mag(segment->tick());
int tick = segment->tick();
Staff* s = staff(pos->staffIdx);
qreal mag = s->mag(segment->tick());
Fraction tick = segment->tick();
// in TABs, step from one string to another; in other staves, step on and between lines
qreal lineDist = s->staffType(tick)->lineDistance().val() * (s->isTabStaff(measure->tick()) ? 1 : .5) * mag * spatium();
@ -1282,20 +1282,19 @@ void Score::styleChanged()
// this tick
//---------------------------------------------------------
Measure* Score::getCreateMeasure(int tick)
Measure* Score::getCreateMeasure(const Fraction& tick)
{
Measure* last = lastMeasure();
if (last == 0 || ((last->tick() + last->ticks()) <= tick)) {
int lastTick = last ? (last->tick()+last->ticks()) : 0;
Fraction lastTick = last ? (last->tick()+last->ticks()) : Fraction(0,1);
while (tick >= lastTick) {
Measure* m = new Measure(this);
Fraction ts = sigmap()->timesig(lastTick).timesig();
// qDebug("getCreateMeasure %d %d/%d", tick, ts.numerator(), ts.denominator());
m->setTick(lastTick);
m->setTimesig(ts);
m->setLen(ts);
m->setTicks(ts);
measures()->add(toMeasureBase(m));
lastTick += ts.ticks();
lastTick += Fraction::fromTicks(ts.ticks());
}
}
return tick2measure(tick);
@ -1558,8 +1557,8 @@ void Score::removeElement(Element* element)
case ElementType::TEMPO_TEXT:
{
TempoText* tt = toTempoText(element);
int tick = tt->segment()->tick();
tempomap()->delTempo(tick);
Fraction tick = tt->segment()->tick();
tempomap()->delTempo(tick.ticks());
}
break;
case ElementType::INSTRUMENT_CHANGE: {
@ -1702,10 +1701,10 @@ Measure* Score::lastMeasureMM() const
// endTick
//---------------------------------------------------------
int Score::endTick() const
Fraction Score::endTick() const
{
Measure* m = lastMeasure();
return m ? m->endTick() : 0;
return m ? m->endTick() : Fraction(0,1);
}
//---------------------------------------------------------
@ -1774,7 +1773,7 @@ int Score::utime2utick(qreal utime) const
// inputPos
//---------------------------------------------------------
int Score::inputPos() const
Fraction Score::inputPos() const
{
return _is.tick();
}
@ -1995,7 +1994,7 @@ bool Score::appendScore(Score* score, bool addPageBreak, bool addSectionBreak)
}
TieMap tieMap;
int tickOfAppend = last()->endTick();
Fraction tickOfAppend = last()->endTick();
// apply Page/Section Breaks if desired
if (addPageBreak) {
@ -2016,7 +2015,7 @@ bool Score::appendScore(Score* score, bool addPageBreak, bool addSectionBreak)
// convert any "generated" initial clefs into real "non-generated" clefs if clef type changes
Measure* fm = score->firstMeasure();
if (fm) {
Segment* seg = fm->findSegmentR(SegmentType::HeaderClef, 0);
Segment* seg = fm->findSegmentR(SegmentType::HeaderClef, Fraction(0,1));
if (seg) {
for (int staffIdx = 0; staffIdx < score->nstaves(); ++staffIdx) {
int track = staffIdx * VOICES;
@ -2060,7 +2059,7 @@ bool Score::appendScore(Score* score, bool addPageBreak, bool addSectionBreak)
ChordRest* cr = toChordRest(s->element(staffIdx * VOICES + v));
if (cr == 0)
continue;
f += cr->actualFraction();
f += cr->actualTicks();
}
}
if (f.isZero())
@ -2078,7 +2077,7 @@ bool Score::appendScore(Score* score, bool addPageBreak, bool addSectionBreak)
if (!seg->element(staffIdx * VOICES)) {
// no need to create new initial "C" key sig
// if staff already ends in that key
if (joinedStaff->key(tickOfAppend - 1) == Key::C)
if (joinedStaff->key(tickOfAppend - Fraction::fromTicks(1)) == Key::C)
continue;
Key key = Key::C;
KeySig* ks = new KeySig(this);
@ -2089,7 +2088,7 @@ bool Score::appendScore(Score* score, bool addPageBreak, bool addSectionBreak)
}
// other key signatures (initial other than "C", non-initial)
for (auto k : *(st->keyList())) {
int tick = k.first;
Fraction tick = Fraction::fromTicks(k.first);
KeySigEvent key = k.second;
joinedStaff->setKey(tick + tickOfAppend, key);
}
@ -2148,12 +2147,12 @@ void Score::splitStaff(int staffIdx, int splitPoint)
Clef* clef = new Clef(this);
clef->setClefType(ClefType::F);
clef->setTrack((staffIdx+1) * VOICES);
Segment* seg = firstMeasure()->getSegment(SegmentType::HeaderClef, 0);
Segment* seg = firstMeasure()->getSegment(SegmentType::HeaderClef, Fraction(0,1));
clef->setParent(seg);
undoAddElement(clef);
clef->layout();
undoChangeKeySig(ns, 0, st->keySigEvent(0));
undoChangeKeySig(ns, Fraction(0,1), st->keySigEvent(Fraction(0,1)));
masterScore()->rebuildMidiMapping();
cmdState()._instrumentsChanged = true;
@ -2224,54 +2223,54 @@ void Score::splitStaff(int staffIdx, int splitPoint)
// make sure that the timeline for dtrack
// has no gaps
//
int ctick = 0;
Fraction ctick = Fraction(0,1);
for (Measure* m = firstMeasure(); m; m = m->nextMeasure()) {
for (Segment* s = m->first(SegmentType::ChordRest); s; s = s->next1(SegmentType::ChordRest)) {
ChordRest* cr = toChordRest(s->element(dtrack));
if (cr == 0)
continue;
int rest = s->tick() - ctick;
if (rest) {
Fraction rest = s->tick() - ctick;
if (rest.isNotZero()) {
// insert Rest
Segment* s1 = tick2segment(ctick);
if (s1 == 0) {
qDebug("no segment at %d", ctick);
qDebug("no segment at %d", ctick.ticks());
continue;
}
setRest(ctick, dtrack, Fraction::fromTicks(rest), false, 0);
setRest(ctick, dtrack, rest, false, 0);
}
ctick = s->tick() + cr->actualTicks();
}
int rest = m->tick() + m->ticks() - ctick;
if (rest) {
setRest(ctick, dtrack, Fraction::fromTicks(rest), false, 0);
Fraction rest = m->tick() + m->ticks() - ctick;
if (rest.isNotZero()) {
setRest(ctick, dtrack, rest, false, 0);
ctick += rest;
}
}
//
// same for strack
//
ctick = 0;
ctick = Fraction(0,1);
for (Measure* m = firstMeasure(); m; m = m->nextMeasure()) {
for (Segment* s = m->first(SegmentType::ChordRest); s; s = s->next1(SegmentType::ChordRest)) {
ChordRest* cr = toChordRest(s->element(strack));
if (cr == 0)
continue;
int rest = s->tick() - ctick;
if (rest) {
Fraction rest = s->tick() - ctick;
if (rest.isNotZero()) {
// insert Rest
Segment* s1 = tick2segment(ctick);
if (s1 == 0) {
qDebug("no segment at %d", ctick);
qDebug("no segment at %d", ctick.ticks());
continue;
}
setRest(ctick, strack, Fraction::fromTicks(rest), false, 0);
setRest(ctick, strack, rest, false, 0);
}
ctick = s->tick() + cr->actualTicks();
}
int rest = m->tick() + m->ticks() - ctick;
if (rest) {
setRest(ctick, strack, Fraction::fromTicks(rest), false, 0);
Fraction rest = m->tick() + m->ticks() - ctick;
if (rest.isNotZero()) {
setRest(ctick, strack, rest, false, 0);
ctick += rest;
}
}
@ -2463,7 +2462,7 @@ void Score::adjustKeySigs(int sidx, int eidx, KeyList km)
for (int staffIdx = sidx; staffIdx < eidx; ++staffIdx) {
Staff* staff = _staves[staffIdx];
for (auto i = km.begin(); i != km.end(); ++i) {
int tick = i->first;
Fraction tick = Fraction::fromTicks(i->first);
Measure* measure = tick2measure(tick);
if (!measure)
continue;
@ -2576,7 +2575,7 @@ void Score::cmdConcertPitchChanged(bool flag, bool /*useDoubleSharpsFlats*/)
undoChangeStyleVal(Sid::concertPitch, flag); // change style flag
for (Staff* staff : _staves) {
if (staff->staffType(0)->group() == StaffGroup::PERCUSSION) // TODO
if (staff->staffType(Fraction(0,1))->group() == StaffGroup::PERCUSSION) // TODO
continue;
// if this staff has no transposition, and no instrument changes, we can skip it
Interval interval = staff->part()->instrument()->transpose();
@ -2589,7 +2588,7 @@ void Score::cmdConcertPitchChanged(bool flag, bool /*useDoubleSharpsFlats*/)
int startTrack = staffIdx * VOICES;
int endTrack = startTrack + VOICES;
transposeKeys(staffIdx, staffIdx + 1, 0, lastSegment()->tick(), interval, true, !flag);
transposeKeys(staffIdx, staffIdx + 1, Fraction(0,1), lastSegment()->tick(), interval, true, !flag);
for (Segment* segment = firstSegment(SegmentType::ChordRest); segment; segment = segment->next1(SegmentType::ChordRest)) {
interval = staff->part()->instrument(segment->tick())->transpose();
@ -2721,7 +2720,7 @@ void Score::padToggle(Pad n)
else {
// Enter a note on the middle staff line
Staff* s = staff(_is.track() / VOICES);
int tick = _is.tick();
Fraction tick = _is.tick();
ClefType clef = s->clef(tick);
Key key = s->key(tick);
nval = NoteVal(line2pitch(4, clef, key));
@ -2750,7 +2749,7 @@ void Score::padToggle(Pad n)
if (cr && cr->isRest() && cr->measure()->isMMRest()) {
Measure* m = cr->measure()->mmRestFirst();
if (m)
cr = m->findChordRest(0, 0);
cr = m->findChordRest(Fraction(0,1), 0);
}
if (!cr)
@ -2789,7 +2788,7 @@ void Score::select(Element* e, SelectType type, int staffIdx)
Element* ee = e;
if (ee->isNote())
ee = ee->parent();
int tick = toChordRest(ee)->segment()->tick();
Fraction tick = toChordRest(ee)->segment()->tick();
if (masterScore()->playPos() != tick)
masterScore()->setPlayPos(tick);
}
@ -2874,7 +2873,7 @@ void Score::selectAdd(Element* e)
if (e->isMeasure()) {
Measure* m = toMeasure(e);
int tick = m->tick();
Fraction tick = m->tick();
if (_selection.isNone()) {
_selection.setRange(m->tick2segment(tick),
m == lastMeasure() ? 0 : m->last(),
@ -2906,8 +2905,8 @@ void Score::selectRange(Element* e, int staffIdx)
bool endRangeSelected = selection().isRange() && selection().endSegment() == nullptr;
if (e->isMeasure()) {
Measure* m = toMeasure(e);
int tick = m->tick();
int etick = tick + m->ticks();
Fraction tick = m->tick();
Fraction etick = tick + m->ticks();
activeTrack = staffIdx * VOICES;
Segment* s1 = m->tick2segment(tick);
if (!s1) // m is corrupted!
@ -2926,7 +2925,7 @@ void Score::selectRange(Element* e, int staffIdx)
if (oe->isNote())
oe = oe->parent();
ChordRest* cr = toChordRest(oe);
int oetick = cr->segment()->tick();
Fraction oetick = cr->segment()->tick();
Segment* startSegment = cr->segment();
Segment* endSegment = m->last();
if (tick < oetick) {
@ -3006,7 +3005,7 @@ void Score::selectRange(Element* e, int staffIdx)
// doing this in note entry mode can clear selection
if (_selection.startSegment() && !noteEntryMode()) {
int tick = _selection.startSegment()->tick();
Fraction tick = _selection.startSegment()->tick();
if (masterScore()->playPos() != tick)
masterScore()->setPlayPos(tick);
}
@ -3054,7 +3053,7 @@ void Score::collectMatch(void* data, Element* e)
} while (ee);
}
if (e->isRest() && p->durationTicks != -1) {
if (e->isRest() && p->durationTicks != Fraction(-1,1)) {
const Rest* r = toRest(e);
if (p->durationTicks != r->actualTicks())
return;
@ -3119,7 +3118,7 @@ void Score::selectSimilar(Element* e, bool sameStaff)
pattern.staffEnd = sameStaff ? e->staffIdx() + 1 : -1;
pattern.voice = -1;
pattern.system = 0;
pattern.durationTicks = -1;
pattern.durationTicks = Fraction(-1,1);
score->scanElements(&pattern, collectMatch);
@ -3152,7 +3151,7 @@ void Score::selectSimilarInRange(Element* e)
pattern.staffEnd = selection().staffEnd();
pattern.voice = -1;
pattern.system = 0;
pattern.durationTicks = -1;
pattern.durationTicks = Fraction(-1,1);
score->scanElementsInRange(&pattern, collectMatch);
@ -3243,7 +3242,7 @@ void Score::lassoSelectEnd()
// addLyrics
//---------------------------------------------------------
void Score::addLyrics(int tick, int staffIdx, const QString& txt)
void Score::addLyrics(const Fraction& tick, int staffIdx, const QString& txt)
{
if (txt.trimmed().isEmpty())
return;
@ -3251,7 +3250,7 @@ void Score::addLyrics(int tick, int staffIdx, const QString& txt)
Segment* seg = measure->findSegment(SegmentType::ChordRest, tick);
if (seg == 0) {
qDebug("no segment found for lyrics<%s> at tick %d",
qPrintable(txt), tick);
qPrintable(txt), tick.ticks());
return;
}
@ -3270,7 +3269,7 @@ void Score::addLyrics(int tick, int staffIdx, const QString& txt)
}
if (!lyricsAdded) {
qDebug("no chord/rest for lyrics<%s> at tick %d, staff %d",
qPrintable(txt), tick, staffIdx);
qPrintable(txt), tick.ticks(), staffIdx);
}
}
@ -3284,9 +3283,9 @@ void Score::setTempo(Segment* segment, qreal tempo)
setTempo(segment->tick(), tempo);
}
void Score::setTempo(int tick, qreal tempo)
void Score::setTempo(const Fraction& tick, qreal tempo)
{
tempomap()->setTempo(tick, tempo);
tempomap()->setTempo(tick.ticks(), tempo);
_playlistDirty = true;
}
@ -3294,9 +3293,9 @@ void Score::setTempo(int tick, qreal tempo)
// removeTempo
//---------------------------------------------------------
void Score::removeTempo(int tick)
void Score::removeTempo(const Fraction& tick)
{
tempomap()->delTempo(tick);
tempomap()->delTempo(tick.ticks());
_playlistDirty = true;
}
@ -3306,7 +3305,7 @@ void Score::removeTempo(int tick)
void Score::resetTempo()
{
resetTempoRange(0, std::numeric_limits<int>::max());
resetTempoRange(Fraction(0,1), Fraction(std::numeric_limits<int>::max(), 1));
}
//---------------------------------------------------------
@ -3315,17 +3314,17 @@ void Score::resetTempo()
// Start tick included, end tick excluded.
//---------------------------------------------------------
void Score::resetTempoRange(int tick1, int tick2)
void Score::resetTempoRange(const Fraction& tick1, const Fraction& tick2)
{
const bool zeroInRange = (tick1 <= 0 && tick2 > 0);
tempomap()->clearRange(tick1, tick2);
const bool zeroInRange = (tick1 <= Fraction(0,1) && tick2 > Fraction(0,1));
tempomap()->clearRange(tick1.ticks(), tick2.ticks());
if (zeroInRange)
tempomap()->setTempo(0, _defaultTempo);
sigmap()->clearRange(tick1, tick2);
sigmap()->clearRange(tick1.ticks(), tick2.ticks());
if (zeroInRange) {
Measure* m = firstMeasure();
if (m)
sigmap()->add(0, SigEvent(m->len(), m->timesig(), 0));
sigmap()->add(0, SigEvent(m->ticks(), m->timesig(), 0));
}
}
@ -3333,9 +3332,9 @@ void Score::resetTempoRange(int tick1, int tick2)
// setPause
//---------------------------------------------------------
void Score::setPause(int tick, qreal seconds)
void Score::setPause(const Fraction& tick, qreal seconds)
{
tempomap()->setPause(tick, seconds);
tempomap()->setPause(tick.ticks(), seconds);
_playlistDirty = true;
}
@ -3343,9 +3342,9 @@ void Score::setPause(int tick, qreal seconds)
// tempo
//---------------------------------------------------------
qreal Score::tempo(int tick) const
qreal Score::tempo(const Fraction& tick) const
{
return tempomap()->tempo(tick);
return tempomap()->tempo(tick.ticks());
}
//---------------------------------------------------------
@ -3508,8 +3507,8 @@ void Score::appendPart(const QString& name)
for (int i = 0; i < t->nstaves(); ++i) {
Staff* staff = new Staff(this);
staff->setPart(part);
staff->setLines(0, t->staffLines[i]);
staff->setSmall(0, t->smallStaff[i]);
staff->setLines(Fraction(0,1), t->staffLines[i]);
staff->setSmall(Fraction(0,1), t->smallStaff[i]);
if (i == 0) {
staff->setBracketType(0, t->bracket[0]);
staff->setBracketSpan(0, t->nstaves());
@ -3556,7 +3555,7 @@ void Score::removeSpanner(Spanner* s)
// for track ?
//---------------------------------------------------------
bool Score::isSpannerStartEnd(int tick, int track) const
bool Score::isSpannerStartEnd(const Fraction& tick, int track) const
{
for (auto i : _spanner.map()) {
if (i.second->track() != track)
@ -3567,7 +3566,7 @@ bool Score::isSpannerStartEnd(int tick, int track) const
return false;
}
void Score::insertTime(int tick, int len)
void Score::insertTime(const Fraction& tick, const Fraction& len)
{
for (Staff* staff : staves())
staff->insertTime(tick, len);
@ -3597,16 +3596,17 @@ void Score::removeUnmanagedSpanner(Spanner* s)
// setPos
//---------------------------------------------------------
void Score::setPos(POS pos, int tick)
void Score::setPos(POS pos, Fraction tick)
{
if (tick < 0)
tick = 0;
if (tick != _pos[int(pos)])
_pos[int(pos)] = tick;
if (tick < Fraction(0,1))
tick = Fraction(0,1);
Q_ASSERT(tick <= lastMeasure()->endTick());
_pos[int(pos)] = tick;
// even though tick position might not have changed, layout might have
// so we should update cursor here
// however, we must be careful not to call setPos() again while handling posChanged, or recursion results
emit posChanged(pos, unsigned(tick));
emit posChanged(pos, unsigned(tick.ticks()));
}
//---------------------------------------------------------
@ -3640,11 +3640,11 @@ QList<int> Score::uniqueStaves() const
// find chord/rest <= tick in track
//---------------------------------------------------------
ChordRest* Score::findCR(int tick, int track) const
ChordRest* Score::findCR(Fraction tick, int track) const
{
Measure* m = tick2measureMM(tick);
if (!m) {
qDebug("findCR: no measure for tick %d", tick);
qDebug("findCR: no measure for tick %d", tick.ticks());
return nullptr;
}
// attach to first rest all spanner when mmRest
@ -3673,23 +3673,24 @@ ChordRest* Score::findCR(int tick, int track) const
// find last chord/rest on staff that ends before tick
//---------------------------------------------------------
ChordRest* Score::findCRinStaff(int tick, int staffIdx) const
ChordRest* Score::findCRinStaff(const Fraction& tick, int staffIdx) const
{
int ptick = tick - 1;
Fraction ptick = tick - Fraction::fromTicks(1);
Measure* m = tick2measureMM(ptick);
if (!m) {
qDebug("findCRinStaff: no measure for tick %d", ptick);
return nullptr;
qDebug("findCRinStaff: no measure for tick %d", ptick.ticks());
return 0;
}
// attach to first rest all spanner when mmRest
if (m->isMMRest())
ptick = m->tick();
Segment* s = m->first(SegmentType::ChordRest);
int strack = staffIdx * VOICES;
int etrack = strack + VOICES;
Segment* s = m->first(SegmentType::ChordRest);
int strack = staffIdx * VOICES;
int etrack = strack + VOICES;
int actualTrack = strack;
int lastTick = -1;
Fraction lastTick = Fraction(-1,1);
for (Segment* ns = s; ; ns = ns->next(SegmentType::ChordRest)) {
if (ns == 0 || ns->tick() > ptick)
break;
@ -3697,11 +3698,8 @@ ChordRest* Score::findCRinStaff(int tick, int staffIdx) const
for (int t = strack; t < etrack; ++t) {
ChordRest* cr = toChordRest(ns->element(t));
if (cr) {
int endTick = cr->tick() + cr->actualTicks();
// allow fudge factor for tuplets
// TODO: replace with fraction-based calculation
int fudge = cr->tuplet() ? 5 : 0;
if (endTick + fudge >= lastTick && endTick - fudge <= tick) {
Fraction endTick = cr->tick() + cr->actualTicks();
if (endTick >= lastTick && endTick <= tick) {
s = ns;
actualTrack = t;
lastTick = endTick;
@ -3711,7 +3709,7 @@ ChordRest* Score::findCRinStaff(int tick, int staffIdx) const
}
if (s)
return toChordRest(s->element(actualTrack));
return nullptr;
return 0;
}
//---------------------------------------------------------
@ -3842,8 +3840,8 @@ QString Score::extractLyrics()
}
// follow the repeat segments
for (const RepeatSegment* rs : *repeatList()) {
int startTick = rs->tick;
int endTick = startTick + rs->len();
Fraction startTick = Fraction::fromTicks(rs->tick);
Fraction endTick = startTick + Fraction::fromTicks(rs->len());
for (Measure* m = tick2measure(startTick); m; m = m->nextMeasure()) {
int playCount = m->playbackCount();
for (Segment* seg = m->first(st); seg; seg = seg->next(st)) {
@ -3866,7 +3864,7 @@ QString Score::extractLyrics()
result += lyric;
}
m->setPlaybackCount(m->playbackCount() + 1);
if (m->tick() + m->ticks() >= endTick)
if (m->endTick() >= endTick)
break;
}
}
@ -3912,8 +3910,9 @@ int Score::keysig()
Key result = Key::C;
for (int staffIdx = 0; staffIdx < nstaves(); ++staffIdx) {
Staff* st = staff(staffIdx);
Key key = st->key(0);
if (st->staffType(0)->group() == StaffGroup::PERCUSSION || st->keySigEvent(0).custom() || st->keySigEvent(0).isAtonal()) // ignore percussion and custom / atonal key
constexpr Fraction t(0,1);
Key key = st->key(t);
if (st->staffType(t)->group() == StaffGroup::PERCUSSION || st->keySigEvent(t).custom() || st->keySigEvent(t).isAtonal()) // ignore percussion and custom / atonal key
continue;
result = key;
int diff = st->part()->instrument()->transpose().chromatic;
@ -3944,7 +3943,7 @@ int Score::duration()
QString Score::createRehearsalMarkText(RehearsalMark* current) const
{
int tick = current->segment()->tick();
Fraction tick = current->segment()->tick();
RehearsalMark* before = 0;
RehearsalMark* after = 0;
for (Segment* s = firstSegment(SegmentType::All); s; s = s->next1()) {
@ -4083,20 +4082,20 @@ void Score::changeVoice(int voice)
// set up destination chord
if (dstCR && dstCR->type() == ElementType::CHORD && dstCR->globalDuration() == chord->globalDuration()) {
if (dstCR && dstCR->type() == ElementType::CHORD && dstCR->globalTicks() == chord->globalTicks()) {
// existing chord in destination with correct duration;
// can simply move note in
dstChord = toChord(dstCR);
}
else if (dstCR && dstCR->type() == ElementType::REST && dstCR->globalDuration() == chord->globalDuration()) {
else if (dstCR && dstCR->type() == ElementType::REST && dstCR->globalTicks() == chord->globalTicks()) {
// existing rest in destination with correct duration;
// replace with chord, then move note in
// this case allows for tuplets, unlike the more general case below
dstChord = new Chord(this);
dstChord->setTrack(dstTrack);
dstChord->setDurationType(chord->durationType());
dstChord->setDuration(chord->duration());
dstChord->setTicks(chord->ticks());
dstChord->setTuplet(dstCR->tuplet());
dstChord->setParent(s);
undoRemoveElement(dstCR);
@ -4123,19 +4122,19 @@ void Score::changeVoice(int voice)
break;
}
}
int gapStart = pcr ? pcr->tick() + pcr->actualTicks() : m->tick();
int gapEnd = ncr ? ncr->tick() : m->tick() + m->ticks();
Fraction gapStart = pcr ? pcr->tick() + pcr->actualTicks() : m->tick();
Fraction gapEnd = ncr ? ncr->tick() : m->tick() + m->ticks();
if (gapStart <= s->tick() && gapEnd >= s->tick() + chord->actualTicks()) {
// big enough gap found
dstChord = new Chord(this);
dstChord->setTrack(dstTrack);
dstChord->setDurationType(chord->durationType());
dstChord->setDuration(chord->duration());
dstChord->setTicks(chord->ticks());
dstChord->setParent(s);
// makeGapVoice will not back-fill an empty voice
if (voice && !dstCR)
expandVoice(s, /*m->first(SegmentType::ChordRest,*/ dstTrack);
makeGapVoice(s, dstTrack, chord->actualFraction(), s->tick());
makeGapVoice(s, dstTrack, chord->actualTicks(), s->tick());
}
}
@ -4159,7 +4158,7 @@ void Score::changeVoice(int voice)
Rest* r = new Rest(this);
r->setTrack(chord->track());
r->setDurationType(chord->durationType());
r->setDuration(chord->duration());
r->setTicks(chord->ticks());
r->setTuplet(chord->tuplet());
r->setParent(s);
// if there were grace notes, move them
@ -4441,8 +4440,8 @@ void MasterScore::setUpdateAll()
void MasterScore::setLayoutAll()
{
_cmdState.setTick(0);
_cmdState.setTick(measures()->last() ? measures()->last()->endTick() : 0);
_cmdState.setTick(Fraction(0,1));
_cmdState.setTick(measures()->last() ? measures()->last()->endTick() : Fraction(0,1));
}
//---------------------------------------------------------
@ -4480,9 +4479,9 @@ void MasterScore::setPlaybackScore(Score* score)
// setLayout
//---------------------------------------------------------
void MasterScore::setLayout(int t)
void MasterScore::setLayout(const Fraction& t)
{
if (t >= 0)
if (t >= Fraction(0,1))
_cmdState.setTick(t);
}

View file

@ -256,8 +256,8 @@ enum class UpdateMode {
class CmdState {
UpdateMode _updateMode { UpdateMode::DoNothing };
int _startTick {-1}; // start tick for mode LayoutTick
int _endTick {-1}; // end tick for mode LayoutTick
Fraction _startTick {-1, 1}; // start tick for mode LayoutTick
Fraction _endTick {-1, 1}; // end tick for mode LayoutTick
public:
LayoutFlags layoutFlags;
@ -272,9 +272,9 @@ class CmdState {
bool layoutRange() const { return _updateMode == UpdateMode::Layout; }
bool updateAll() const { return int(_updateMode) >= int(UpdateMode::UpdateAll); }
bool updateRange() const { return _updateMode == UpdateMode::Update; }
void setTick(int t);
int startTick() const { return _startTick; }
int endTick() const { return _endTick; }
void setTick(const Fraction& t);
Fraction startTick() const { return _startTick; }
Fraction endTick() const { return _endTick; }
#ifndef NDEBUG
void dump();
#endif
@ -436,7 +436,7 @@ class Score : public QObject, public ScoreElement {
bool _defaultsRead { false }; ///< defaults were read at MusicXML import, allow export of defaults in convertermode
bool _isPalette { false };
int _pos[3]; ///< 0 - current, 1 - left loop, 2 - right loop
Fraction _pos[3]; ///< 0 - current, 1 - left loop, 2 - right loop
int _mscVersion { MSCVERSION }; ///< version of current loading *.msc file
@ -498,7 +498,7 @@ class Score : public QObject, public ScoreElement {
bool isSubdivided(ChordRest*, int);
void addAudioTrack();
QList<Fraction> splitGapToMeasureBoundaries(ChordRest*, Fraction);
void pasteChordRest(ChordRest* cr, int tick, const Interval&);
void pasteChordRest(ChordRest* cr, const Fraction& tick, const Interval&);
void selectSingle(Element* e, int staffIdx);
void selectAdd(Element* e);
@ -513,11 +513,11 @@ class Score : public QObject, public ScoreElement {
void resetSystems(bool layoutAll, LayoutContext& lc);
void collectLinearSystem(LayoutContext& lc);
void resetTempo();
void resetTempoRange(int tick1, int tick2);
void resetTempoRange(const Fraction& tick1, const Fraction& tick2);
void renderStaff(EventMap* events, Staff*);
void renderSpanners(EventMap* events);
void renderMetronome(EventMap* events, Measure* m, int tickOffset);
void renderMetronome(EventMap* events, Measure* m, const Fraction& tickOffset);
void updateVelo();
protected:
@ -526,7 +526,7 @@ class Score : public QObject, public ScoreElement {
SynthesizerState _synthesizerState;
void createPlayEvents(Chord*);
void createGraceNotesPlayEvents(int tick, Chord* chord, int& ontime, int& trailtime);
void createGraceNotesPlayEvents(const Fraction& tick, Chord* chord, int& ontime, int& trailtime);
void cmdPitchUp();
void cmdPitchDown();
void cmdPitchUpOctave();
@ -587,16 +587,16 @@ class Score : public QObject, public ScoreElement {
void cmdAddStretch(qreal);
void cmdResetNoteAndRestGroupings();
void cmdResetAllPositions();
void cmdDoubleDuration() { cmdIncDecDuration(-1, 0); }
void cmdHalfDuration() { cmdIncDecDuration( 1, 0); }
void cmdIncDurationDotted() { cmdIncDecDuration(-1, 1); }
void cmdDecDurationDotted() { cmdIncDecDuration( 1, 1); }
void cmdDoubleDuration() { cmdIncDecDuration(-1, false); }
void cmdHalfDuration() { cmdIncDecDuration( 1, false); }
void cmdIncDurationDotted() { cmdIncDecDuration(-1, true); }
void cmdDecDurationDotted() { cmdIncDecDuration( 1, true); }
void cmdToggleLayoutBreak(LayoutBreak::Type);
void addRemoveBreaks(int interval, bool lock);
bool transpose(Note* n, Interval, bool useSharpsFlats);
void transposeKeys(int staffStart, int staffEnd, int tickStart, int tickEnd, const Interval&, bool useInstrument = false, bool flip = false);
void transposeKeys(int staffStart, int staffEnd, const Fraction& tickStart, const Fraction& tickEnd, const Interval&, bool useInstrument = false, bool flip = false);
bool transpose(TransposeMode mode, TransposeDirection, Key transposeKey, int transposeInterval,
bool trKeys, bool transposeChordNames, bool useDoubleSharpsFlats);
@ -617,7 +617,7 @@ class Score : public QObject, public ScoreElement {
void dragPosition(const QPointF&, int* staffIdx, Segment**) const;
void undoAddElement(Element* element);
void undoAddCR(ChordRest* element, Measure*, int tick);
void undoAddCR(ChordRest* element, Measure*, const Fraction& tick);
void undoRemoveElement(Element* element);
void undoChangeElement(Element* oldElement, Element* newElement);
void undoChangePitch(Note* note, int pitch, int tpc1, int tpc2);
@ -634,16 +634,16 @@ class Score : public QObject, public ScoreElement {
void undoChangeInvisible(Element*, bool);
void undoChangeTuning(Note*, qreal);
void undoChangeUserMirror(Note*, MScore::DirectionH);
void undoChangeKeySig(Staff* ostaff, int tick, KeySigEvent);
void undoChangeClef(Staff* ostaff, Element* e, ClefType ct);
bool undoPropertyChanged(Element*, Pid, const QVariant& v, PropertyFlags ps = PropertyFlags::NOSTYLE);
void undoChangeKeySig(Staff* ostaff, const Fraction& tick, KeySigEvent);
void undoChangeClef(Staff* ostaff, Element*, ClefType st);
bool undoPropertyChanged(Element* e, Pid t, const QVariant& st, PropertyFlags ps = PropertyFlags::NOSTYLE);
void undoPropertyChanged(ScoreElement*, Pid, const QVariant& v, PropertyFlags ps = PropertyFlags::NOSTYLE);
inline virtual UndoStack* undoStack() const;
void undo(UndoCommand*, EditData* = 0) const;
void undoRemoveMeasures(Measure*, Measure*);
void undoAddBracket(Staff* staff, int level, BracketType type, int span);
void undoRemoveBracket(Bracket*);
void undoInsertTime(int tick, int len);
void undoInsertTime(const Fraction& tick, const Fraction& len);
void undoChangeStyleVal(Sid idx, const QVariant& v);
void undoChangePageNumberOffset(int po);
@ -652,22 +652,22 @@ class Score : public QObject, public ScoreElement {
Segment* setNoteRest(Segment*, int track, NoteVal nval, Fraction, Direction stemDirection = Direction::AUTO, bool rhythmic = false);
void changeCRlen(ChordRest* cr, const TDuration&);
void changeCRlen(ChordRest* cr, const Fraction&, bool fillWithRest=true);
void createCRSequence(Fraction f, ChordRest* cr, int tick);
void createCRSequence(const Fraction& f, ChordRest* cr, const Fraction& tick);
Fraction makeGap(Segment*, int track, const Fraction&, Tuplet*, bool keepChord = false);
bool makeGap1(int baseTick, int staffIdx, Fraction len, int voiceOffset[VOICES]);
bool makeGapVoice(Segment* seg, int track, Fraction len, int tick);
bool makeGap1(const Fraction& baseTick, int staffIdx, const Fraction& len, int voiceOffset[VOICES]);
bool makeGapVoice(Segment* seg, int track, Fraction len, const Fraction& tick);
Rest* addRest(int tick, int track, TDuration, Tuplet*);
Rest* addRest(const Fraction& tick, int track, TDuration, Tuplet*);
Rest* addRest(Segment* seg, int track, TDuration d, Tuplet*);
Chord* addChord(int tick, TDuration d, Chord* oc, bool genTie, Tuplet* tuplet);
Chord* addChord(const Fraction& tick, TDuration d, Chord* oc, bool genTie, Tuplet* tuplet);
ChordRest* addClone(ChordRest* cr, int tick, const TDuration& d);
Rest* setRest(int tick, int track, Fraction, bool useDots, Tuplet* tuplet, bool useFullMeasureRest = true);
ChordRest* addClone(ChordRest* cr, const Fraction& tick, const TDuration& d);
Rest* setRest(const Fraction& tick, int track, const Fraction&, bool useDots, Tuplet* tuplet, bool useFullMeasureRest = true);
void upDown(bool up, UpDownMode, bool updateSelection = true);
void upDownDelta(int pitchDelta, bool updateSelection);
ChordRest* searchNote(int tick, int track) const;
ChordRest* searchNote(const Fraction& tick, int track) const;
// undo/redo ops
void addArticulation(SymId);
@ -696,10 +696,10 @@ class Score : public QObject, public ScoreElement {
void localInsertChord(const Position&);
void globalInsertChord(const Position&);
void cloneVoice(int strack, int dtrack, Segment* sf, int lTick, bool link = true, bool spanner = true);
void cloneVoice(int strack, int dtrack, Segment* sf, const Fraction& lTick, bool link = true, bool spanner = true);
void repitchNote(const Position& pos, bool replace);
void regroupNotesAndRests(int startTick, int endTick, int track);
void regroupNotesAndRests(const Fraction& startTick, const Fraction& endTick, int track);
bool checkTimeDelete(Segment*, Segment*);
void timeDelete(Measure*, Segment*, const Fraction&);
@ -713,7 +713,7 @@ class Score : public QObject, public ScoreElement {
virtual inline void setUpdateAll();
virtual inline void setLayoutAll();
virtual inline void setLayout(int);
virtual inline void setLayout(const Fraction& f);
virtual inline CmdState& cmdState();
virtual inline void addLayoutFlags(LayoutFlags);
virtual inline void setInstrumentsChanged(bool);
@ -780,19 +780,19 @@ class Score : public QObject, public ScoreElement {
SelectionFilter& selectionFilter() { return _selectionFilter; }
void setSelection(const Selection& s);
int pos();
Measure* tick2measure(int tick) const;
Measure* tick2measureMM(int tick) const;
MeasureBase* tick2measureBase(int tick) const;
Segment* tick2segment(int tick, bool first, SegmentType st, bool useMMrest = false) const;
Segment* tick2segment(int tick) const;
Segment* tick2segment(int tick, bool first) const;
Segment* tick2segmentMM(int tick, bool first, SegmentType st) const;
Segment* tick2segmentMM(int tick) const;
Segment* tick2segmentMM(int tick, bool first) const;
Segment* tick2segmentEnd(int track, int tick) const;
Segment* tick2leftSegment(int tick) const;
Segment* tick2rightSegment(int tick) const;
Fraction pos();
Measure* tick2measure(const Fraction& tick) const;
Measure* tick2measureMM(const Fraction& tick) const;
MeasureBase* tick2measureBase(const Fraction& tick) const;
Segment* tick2segment(const Fraction& tick, bool first, SegmentType st, bool useMMrest = false) const;
Segment* tick2segment(const Fraction& tick) const;
Segment* tick2segment(const Fraction& tick, bool first) const;
Segment* tick2segmentMM(const Fraction& tick, bool first, SegmentType st) const;
Segment* tick2segmentMM(const Fraction& tick) const;
Segment* tick2segmentMM(const Fraction& tick, bool first) const;
Segment* tick2segmentEnd(int track, const Fraction& tick) const;
Segment* tick2leftSegment(const Fraction& tick) const;
Segment* tick2rightSegment(const Fraction& tick) const;
void fixTicks();
Element* nextElement();
Element* prevElement();
@ -822,7 +822,7 @@ class Score : public QObject, public ScoreElement {
void spell();
void spell(int startStaff, int endStaff, Segment* startSegment, Segment* endSegment);
void spell(Note*);
int nextSeg(int tick, int track);
Fraction nextSeg(const Fraction& tick, int track);
virtual MStyle& style() { return _style; }
virtual const MStyle& style() const { return _style; }
@ -848,22 +848,22 @@ class Score : public QObject, public ScoreElement {
bool genCourtesyClef() const { return styleB(Sid::genCourtesyClef); }
// These position are in ticks and not uticks
int playPos() const { return pos(POS::CURRENT); }
void setPlayPos(int tick) { setPos(POS::CURRENT, tick); }
int loopInTick() const { return pos(POS::LEFT); }
int loopOutTick() const { return pos(POS::RIGHT); }
void setLoopInTick(int tick) { setPos(POS::LEFT, tick); }
void setLoopOutTick(int tick) { setPos(POS::RIGHT, tick); }
Fraction playPos() const { return pos(POS::CURRENT); }
void setPlayPos(const Fraction& tick) { setPos(POS::CURRENT, tick); }
Fraction loopInTick() const { return pos(POS::LEFT); }
Fraction loopOutTick() const { return pos(POS::RIGHT); }
void setLoopInTick(const Fraction& tick) { setPos(POS::LEFT, tick); }
void setLoopOutTick(const Fraction& tick) { setPos(POS::RIGHT, tick); }
int pos(POS pos) const { return _pos[int(pos)]; }
void setPos(POS pos, int tick);
Fraction pos(POS pos) const { return _pos[int(pos)]; }
void setPos(POS pos, Fraction tick);
bool noteEntryMode() const { return inputState().noteEntryMode(); }
void setNoteEntryMode(bool val) { inputState().setNoteEntryMode(val); }
NoteEntryMethod noteEntryMethod() const { return inputState().noteEntryMethod(); }
void setNoteEntryMethod(NoteEntryMethod m) { inputState().setNoteEntryMethod(m); }
bool usingNoteEntryMethod(NoteEntryMethod m) { return inputState().usingNoteEntryMethod(m); }
int inputPos() const;
Fraction inputPos() const;
int inputTrack() const { return inputState().track(); }
const InputState& inputState() const { return _is; }
InputState& inputState() { return _is; }
@ -880,12 +880,12 @@ class Score : public QObject, public ScoreElement {
void renderMidi(EventMap* events);
void renderMidi(EventMap* events, bool metronome, bool expandRepeats);
BeatType tick2beatType(int tick);
BeatType tick2beatType(const Fraction& tick);
int mscVersion() const { return _mscVersion; }
void setMscVersion(int v) { _mscVersion = v; }
void addLyrics(int tick, int staffIdx, const QString&);
void addLyrics(const Fraction& tick, int staffIdx, const QString&);
void updateSwing();
void createPlayEvents();
@ -898,10 +898,10 @@ class Score : public QObject, public ScoreElement {
virtual inline TimeSigMap* sigmap() const;
void setTempo(Segment*, qreal);
void setTempo(int tick, qreal bps);
void removeTempo(int tick);
void setPause(int tick, qreal seconds);
qreal tempo(int tick) const;
void setTempo(const Fraction& tick, qreal bps);
void removeTempo(const Fraction& tick);
void setPause(const Fraction& tick, qreal seconds);
qreal tempo(const Fraction& tick) const;
bool defaultsRead() const { return _defaultsRead; }
void setDefaultsRead(bool b) { _defaultsRead = b; }
@ -922,7 +922,7 @@ class Score : public QObject, public ScoreElement {
void cmdDeleteTuplet(Tuplet*, bool replaceWithRest);
// void moveBracket(int staffIdx, int srcCol, int dstCol);
Measure* getCreateMeasure(int tick);
Measure* getCreateMeasure(const Fraction& tick);
void adjustBracketsDel(int sidx, int eidx);
void adjustBracketsIns(int sidx, int eidx);
@ -961,7 +961,7 @@ class Score : public QObject, public ScoreElement {
MeasureBase* measure(int idx) const;
Measure* crMeasure(int idx) const;
int endTick() const;
Fraction endTick() const;
Segment* firstSegment(SegmentType s) const;
Segment* firstSegmentMM(SegmentType s) const;
@ -992,7 +992,7 @@ class Score : public QObject, public ScoreElement {
void removeAudio();
void doLayout();
void doLayoutRange(int, int);
void doLayoutRange(const Fraction&, const Fraction&);
void layoutLinear(bool layoutAll, LayoutContext& lc);
void layoutSystemsUndoRedo();
@ -1078,22 +1078,21 @@ class Score : public QObject, public ScoreElement {
const std::multimap<int, Spanner*>& spanner() const { return _spanner.map(); }
SpannerMap& spannerMap() { return _spanner; }
bool isSpannerStartEnd(int tick, int track) const;
bool isSpannerStartEnd(const Fraction& tick, int track) const;
void removeSpanner(Spanner*);
void addSpanner(Spanner*);
void cmdAddSpanner(Spanner* spanner, const QPointF& pos);
void cmdAddSpanner(Spanner* spanner, int staffIdx, Segment* startSegment, Segment* endSegment);
void checkSpanner(int startTick, int lastTick);
void checkSpanner(const Fraction& startTick, const Fraction& lastTick);
const std::set<Spanner*> unmanagedSpanners() { return _unmanagedSpanner; }
void addUnmanagedSpanner(Spanner*);
void removeUnmanagedSpanner(Spanner*);
Hairpin* addHairpin(HairpinType, int tickStart, int tickEnd, int track);
Hairpin* addHairpin(HairpinType, const Fraction& tickStart, const Fraction& tickEnd, int track);
ChordRest* findCR(int tick, int track) const;
ChordRest* findCRinStaff(int tick, int staffIdx) const;
// void layoutSpanner(); // unused
void insertTime(int tickPos, int tickLen);
ChordRest* findCR(Fraction tick, int track) const;
ChordRest* findCRinStaff(const Fraction& tick, int staffIdx) const;
void insertTime(const Fraction& tickPos, const Fraction&tickLen);
ScoreFont* scoreFont() const { return _scoreFont; }
void setScoreFont(ScoreFont* f) { _scoreFont = f; }
@ -1102,7 +1101,7 @@ class Score : public QObject, public ScoreElement {
void setNoteHeadWidth( qreal n) { _noteHeadWidth = n; }
QList<int> uniqueStaves() const;
void transpositionChanged(Part*, Interval, int tickStart = 0, int tickEnd = -1);
void transpositionChanged(Part*, Interval, Fraction tickStart = { 0, 1 }, Fraction tickEnd = { -1, 1 } );
void moveUp(ChordRest*);
void moveDown(ChordRest*);
@ -1265,7 +1264,7 @@ class MasterScore : public Score {
virtual void setUpdateAll() override;
virtual void setLayoutAll() override;
virtual void setLayout(int t) override;
virtual void setLayout(const Fraction&) override;
virtual CmdState& cmdState() override { return _cmdState; }
virtual void addLayoutFlags(LayoutFlags val) override { _cmdState.layoutFlags |= val; }
@ -1365,7 +1364,7 @@ inline std::list<MidiInputEvent>* Score::activeMidiPitches() { return _master
inline void Score::setUpdateAll() { _masterScore->setUpdateAll(); }
inline void Score::setLayoutAll() { _masterScore->setLayoutAll(); }
inline void Score::setLayout(int tick) { _masterScore->setLayout(tick); }
inline void Score::setLayout(const Fraction& f) { _masterScore->setLayout(f); }
inline CmdState& Score::cmdState() { return _masterScore->cmdState(); }
inline void Score::addLayoutFlags(LayoutFlags f) { _masterScore->addLayoutFlags(f); }

View file

@ -1283,17 +1283,17 @@ Fraction BaseDiff::afrac(int score) const
{
Q_ASSERT(score == 0 || score == 1);
if (ctx[score] && ctx[score]->isElement())
return toElement(ctx[score])->afrac();
return toElement(ctx[score])->tick();
if (before[score] && before[score]->isElement()) {
const Element* bef = toElement(before[score]);
Fraction f = bef->afrac();
Fraction f = bef->tick();
if (bef->isDurationElement()) {
const DurationElement* de = toDurationElement(bef);
return f + de->actualFraction();
return f + de->actualTicks();
}
return f;
}
return 0;
return Fraction(0,1);
}
//---------------------------------------------------------
@ -1349,7 +1349,7 @@ Fraction ElementDiff::afrac(int score) const
Q_ASSERT(score == 0 || score == 1);
const ScoreElement* se = el[score];
if (se && se->isElement())
return toElement(se)->afrac();
return toElement(se)->tick();
return BaseDiff::afrac(score);
}

View file

@ -279,7 +279,7 @@ void Score::readStaff(XmlReader& e)
int staff = e.intAttribute("id", 1) - 1;
int measureIdx = 0;
e.setCurrentMeasureIndex(0);
e.initTick(0);
e.setTick(Fraction(0,1));
e.setTrack(staff * VOICES);
if (staff == 0) {
@ -296,7 +296,7 @@ void Score::readStaff(XmlReader& e)
//
Measure* m = e.lastMeasure(); // measure->prevMeasure();
Fraction f(m ? m->timesig() : Fraction(4,4));
measure->setLen(f);
measure->setTicks(f);
measure->setTimesig(f);
measure->read(e, staff);
@ -304,7 +304,7 @@ void Score::readStaff(XmlReader& e)
if (!measure->isMMRest()) {
measures()->add(measure);
e.setLastMeasure(measure);
e.initTick(measure->tick() + measure->ticks());
e.setTick(measure->tick() + measure->ticks());
}
else {
// this is a multi measure rest
@ -324,7 +324,7 @@ void Score::readStaff(XmlReader& e)
measures()->add(mb);
}
else if (tag == "tick")
e.initTick(fileDivision(e.readInt()));
e.setTick(Fraction::fromTicks(fileDivision(e.readInt())));
else
e.unknown();
}
@ -341,7 +341,7 @@ void Score::readStaff(XmlReader& e)
measure->setTick(e.tick());
measures()->add(measure);
}
e.initTick(measure->tick());
e.setTick(measure->tick());
e.setCurrentMeasureIndex(measureIdx++);
measure->read(e, staff);
measure->checkMeasure(staff);
@ -356,7 +356,7 @@ void Score::readStaff(XmlReader& e)
}
}
else if (tag == "tick")
e.initTick(fileDivision(e.readInt()));
e.setTick(Fraction::fromTicks(fileDivision(e.readInt())));
else
e.unknown();
}
@ -1082,7 +1082,7 @@ qDebug("createRevision");
// Returns true if <voice> tag was written.
//---------------------------------------------------------
static bool writeVoiceMove(XmlWriter& xml, Segment* seg, int startTick, int track, int* lastTrackWrittenPtr)
static bool writeVoiceMove(XmlWriter& xml, Segment* seg, const Fraction& startTick, int track, int* lastTrackWrittenPtr)
{
bool voiceTagWritten = false;
int& lastTrackWritten = *lastTrackWrittenPtr;
@ -1098,11 +1098,11 @@ static bool writeVoiceMove(XmlWriter& xml, Segment* seg, int startTick, int trac
voiceTagWritten = true;
}
if ((xml.afrac() != seg->afrac()) || (track != xml.curTrack())) {
if ((xml.curTick() != seg->tick()) || (track != xml.curTrack())) {
Location curr = Location::absolute();
Location dest = Location::absolute();
curr.setFrac(xml.afrac());
dest.setFrac(seg->afrac());
curr.setFrac(xml.curTick());
dest.setFrac(seg->tick());
curr.setTrack(xml.curTrack());
dest.setTrack(track);
@ -1125,9 +1125,10 @@ static bool writeVoiceMove(XmlWriter& xml, Segment* seg, int startTick, int trac
void Score::writeSegments(XmlWriter& xml, int strack, int etrack,
Segment* fs, Segment* ls, bool writeSystemElements, bool forceTimeSig)
{
const int startTick = xml.curTick();
const int endTick = ls ? ls->tick() : lastMeasure()->endTick();
const bool clip = xml.clipboardmode();
Fraction startTick = xml.curTick();
Fraction endTick = ls ? ls->tick() : lastMeasure()->endTick();
bool clip = xml.clipboardmode();
// in clipboard mode, ls might be in an mmrest
// since we are traversing regular measures,
// force them out of mmRest
@ -1154,7 +1155,7 @@ void Score::writeSegments(XmlWriter& xml, int strack, int etrack,
for (auto i = spanner().begin(); i != endIt; ++i) {
Spanner* s = i->second;
#else
auto sl = spannerMap().findOverlapping(fs->tick(), endTick);
auto sl = spannerMap().findOverlapping(fs->tick().ticks(), endTick.ticks());
for (auto i : sl) {
Spanner* s = i.value;
#endif
@ -1324,54 +1325,6 @@ void Score::writeSegments(XmlWriter& xml, int strack, int etrack,
Tuplet* Score::searchTuplet(XmlReader& /*e*/, int /*id*/)
{
#if 0 // TODOx
QDomElement e = de;
QDomDocument doc = e.ownerDocument();
QString tag;
for (e = doc.documentElement(); !e.isNull(); e = e.nextSiblingElement()) {
tag = e.tagName();
if (tag == "museScore")
break;
}
if (tag != "museScore") {
qDebug("Score::searchTuplet(): no museScore found");
return 0;
}
for (e = e.firstChildElement(); !e.isNull(); e = e.nextSiblingElement()) {
tag = e.tagName();
if (tag == "Score" || tag == "Part")
break;
}
if (tag != "Score" && tag != "Part") {
qDebug("Score::searchTuplet(): no Score/Part found");
return 0;
}
if (tag == "Score")
e = e.firstChildElement();
else
e = e.nextSiblingElement();
for (; !e.isNull(); e = e.nextSiblingElement()) {
if (e.tagName() == "Staff") {
for (QDomElement ee = e.firstChildElement(); !ee.isNull(); ee = ee.nextSiblingElement()) {
if (ee.tagName() == "Measure") {
for (QDomElement eee = ee.firstChildElement(); !eee.isNull(); eee = eee.nextSiblingElement()) {
if (eee.tagName() == "Tuplet") {
Tuplet* tuplet = new Tuplet(this);
QList<Spanner*> spannerList;
QList<Tuplet*> tuplets;
tuplet->read(eee);
if (tuplet->id() == id)
return tuplet;
delete tuplet;
}
}
}
}
}
}
#endif
return 0;
}

View file

@ -116,12 +116,14 @@ Segment::Segment(Measure* m)
init();
}
Segment::Segment(Measure* m, SegmentType st, int t)
Segment::Segment(Measure* m, SegmentType st, const Fraction& t)
: Element(m->score(), ElementFlag::EMPTY | ElementFlag::ENABLED | ElementFlag::NOT_SELECTABLE)
{
setParent(m);
// Q_ASSERT(t >= Fraction(0,1));
// Q_ASSERT(t <= m->ticks());
_segmentType = st;
setRtick(t);
_tick = t;
init();
}
@ -205,6 +207,15 @@ void Segment::init()
_next = 0;
}
//---------------------------------------------------------
// tick
//---------------------------------------------------------
Fraction Segment::tick() const
{
return _tick + measure()->tick();
}
//---------------------------------------------------------
// next1
/// return next \a Segment, dont stop searching at end
@ -445,9 +456,12 @@ void Segment::checkElement(Element* el, int track)
{
// generated elements can be overwritten
if (_elist[track] && !_elist[track]->generated()) {
qDebug("add(%s): there is already a %s at %s(%d) track %d. score %p %s",
el->name(), _elist[track]->name(),
qPrintable(score()->sigmap()->pos(tick())), tick(), track, score(), score()->isMaster() ? "Master" : "Part");
qDebug("add(%s): there is already a %s at track %d tick %d",
el->name(),
_elist[track]->name(),
track,
tick().ticks()
);
// abort();
}
}
@ -561,9 +575,9 @@ void Segment::add(Element* el)
}
// the tick position of a tuplet is the tick position of its
// first element:
ChordRest* cr = toChordRest(el);
if (cr->tuplet() && !cr->tuplet()->elements().empty() && cr->tuplet()->elements().front() == cr && cr->tuplet()->tick() < 0)
cr->tuplet()->setTick(cr->tick());
// ChordRest* cr = toChordRest(el);
// if (cr->tuplet() && !cr->tuplet()->elements().empty() && cr->tuplet()->elements().front() == cr && cr->tuplet()->tick() < 0)
// cr->tuplet()->setTick(cr->tick());
}
// fall through
@ -607,7 +621,7 @@ void Segment::remove(Element* el)
measure()->checkMultiVoices(staffIdx);
// spanners with this cr as start or end element will need relayout
SpannerMap& smap = score()->spannerMap();
auto spanners = smap.findOverlapping(tick(), tick());
auto spanners = smap.findOverlapping(tick().ticks(), tick().ticks());
for (auto interval : spanners) {
Spanner* s = interval.value;
Element* start = s->startElement();
@ -845,7 +859,7 @@ QVariant Segment::getProperty(Pid propertyId) const
{
switch (propertyId) {
case Pid::TICK:
return _tick.ticks();
return _tick;
case Pid::LEADING_SPACE:
return extraLeadingSpace();
default:
@ -875,7 +889,7 @@ bool Segment::setProperty(Pid propertyId, const QVariant& v)
{
switch (propertyId) {
case Pid::TICK:
setRtick(v.toInt());
setRtick(v.value<Fraction>());
break;
case Pid::LEADING_SPACE:
setExtraLeadingSpace(v.value<Spatium>());
@ -1069,24 +1083,18 @@ void Segment::scanElements(void* data, void (*func)(void*, Element*), bool all)
Element* Segment::firstElement(int staff)
{
if (segmentType() == SegmentType::ChordRest) {
for (int v = staff * VOICES; v/VOICES == staff; v++) {
Element* el = element(v);
if (!el) { //there is no chord or rest on this voice
continue;
}
if (el->isChord()) {
return toChord(el)->notes().back();
}
else {
return el;
}
}
if (isChordRestType()) {
int strack = staff * VOICES;
int etrack = strack + VOICES;
for (int v = strack; v < etrack; ++v) {
Element* el = element(v);
if (!el)
continue;
return el->isChord() ? toChord(el)->notes().back() : el;
}
}
else {
else
return getElement(staff);
}
return 0;
}
@ -1395,7 +1403,7 @@ Element* Segment::lastElementOfSegment(Segment* s, int activeStaff)
Spanner* Segment::firstSpanner(int activeStaff)
{
std::multimap<int, Spanner*> mmap = score()->spanner();
auto range = mmap.equal_range(tick());
auto range = mmap.equal_range(tick().ticks());
if (range.first != range.second){ // range not empty
for (auto i = range.first; i != range.second; ++i) {
Spanner* s = i->second;
@ -1416,7 +1424,7 @@ Spanner* Segment::firstSpanner(int activeStaff)
Spanner* Segment::lastSpanner(int activeStaff)
{
std::multimap<int, Spanner*> mmap = score()->spanner();
auto range = mmap.equal_range(tick());
auto range = mmap.equal_range(tick().ticks());
if (range.first != range.second){ // range not empty
for (auto i = --range.second; i != range.first; --i) {
Spanner* s = i->second;
@ -1795,7 +1803,7 @@ QString Segment::accessibleExtraInfo() const
QString startSpanners = "";
QString endSpanners = "";
auto spanners = score()->spannerMap().findOverlapping(this->tick(), this->tick());
auto spanners = score()->spannerMap().findOverlapping(tick().ticks(), tick().ticks());
for (auto interval : spanners) {
Spanner* s = interval.value;
if (!score()->selectionFilter().canSelect(s)) continue;
@ -2069,82 +2077,4 @@ qreal Segment::minHorizontalDistance(Segment* ns, bool systemHeaderGap) const
return w;
}
//---------------------------------------------------------
// setTick
// *** deprecated ***
//---------------------------------------------------------
void Segment::setTick(int t)
{
setRtick(t - measure()->tick());
}
//---------------------------------------------------------
// tick
// *** deprecated ***
//---------------------------------------------------------
int Segment::tick() const
{
return rtick() + measure()->tick();
}
//---------------------------------------------------------
// ticks
//---------------------------------------------------------
int Segment::ticks() const
{
return _ticks.ticks();
}
//---------------------------------------------------------
// setTicks
//---------------------------------------------------------
void Segment::setTicks(int val)
{
_ticks = Fraction::fromTicks(val);
}
//---------------------------------------------------------
// rtick
// tickposition relative to measure start
//---------------------------------------------------------
int Segment::rtick() const
{
return _tick.ticks();
}
//---------------------------------------------------------
// setRtick
//---------------------------------------------------------
void Segment::setRtick(int val)
{
_tick = Fraction::fromTicks(val);
}
//---------------------------------------------------------
// rfrac
// return relative position of segment in measure
//---------------------------------------------------------
Fraction Segment::rfrac() const
{
return _tick;
}
//---------------------------------------------------------
// afrac
// return absolute position of segment
// *** deprecated ***
//---------------------------------------------------------
Fraction Segment::afrac() const
{
return _tick + Fraction::fromTicks(measure()->tick());
}
} // namespace Ms

View file

@ -73,7 +73,7 @@ class Segment final : public Element {
public:
Segment(Measure* m = 0);
Segment(Measure*, SegmentType, int tick);
Segment(Measure*, SegmentType, const Fraction&);
Segment(const Segment&);
~Segment();
@ -154,14 +154,12 @@ class Segment final : public Element {
qreal stretch() const { return _stretch; }
void setStretch(qreal v) { _stretch = v; }
void setTick(int t);
virtual int tick() const override;
virtual int rtick() const override;
Fraction rfrac() const;
Fraction afrac() const;
void setRtick(int val);
int ticks() const;
void setTicks(int val);
virtual Fraction rtick() const override { return _tick; }
void setRtick(const Fraction& v) { Q_ASSERT(v >= Fraction(0,1)); _tick = v; }
virtual Fraction tick() const override;
Fraction ticks() const { return _ticks; }
void setTicks(const Fraction& v) { _ticks = v; }
bool splitsTuplet() const;
@ -192,7 +190,6 @@ class Segment final : public Element {
virtual QString accessibleExtraInfo() const override;
Element* firstInNextSegments(int activeStaff); //<
Element* lastInPrevSegments(int activeStaff); //<
Element* firstElement(int staff); //< These methods are used for navigation

View file

@ -75,17 +75,17 @@ Selection::Selection(Score* s)
// tickStart
//---------------------------------------------------------
int Selection::tickStart() const
Fraction Selection::tickStart() const
{
switch (_state) {
case SelState::RANGE:
return _startSegment->tick();
case SelState::LIST: {
ChordRest* cr = firstChordRest();
return (cr) ? cr->tick() : -1;
return (cr) ? cr->tick() : Fraction(-1,1);
}
default:
return -1;
return Fraction(-1,1);
}
}
@ -93,26 +93,25 @@ int Selection::tickStart() const
// tickEnd
//---------------------------------------------------------
int Selection::tickEnd() const
Fraction Selection::tickEnd() const
{
switch (_state) {
case SelState::RANGE: {
if (_endSegment) {
if (_endSegment)
return _endSegment->tick();
}
else { // endsegment == 0 if end of score
Measure* m = _score->lastMeasure();
return m->tick() + m->ticks();
return m->endTick();
}
break;
}
case SelState::LIST: {
ChordRest* cr = lastChordRest();
return (cr) ? cr->tick() : -1;
return (cr) ? cr->segment()->tick() : Fraction(-1,1);
break;
}
default:
return -1;
return Fraction(-1,1);
}
}
@ -456,7 +455,7 @@ void Selection::updateSelectedElements()
update();
return;
}
if (_state == SelState::RANGE && _plannedTick1 != -1 && _plannedTick2 != -1) {
if (_state == SelState::RANGE && _plannedTick1 != Fraction(-1,1) && _plannedTick2 != Fraction(-1,1)) {
const int staffStart = _staffStart;
const int staffEnd = _staffEnd;
deselectAll();
@ -473,8 +472,8 @@ void Selection::updateSelectedElements()
return;
}
setRange(s1, s2, staffStart, staffEnd);
_plannedTick1 = -1;
_plannedTick2 = -1;
_plannedTick1 = Fraction(-1,1);
_plannedTick2 = Fraction(-1,1);
}
for (Element* e : _el)
@ -531,8 +530,8 @@ void Selection::updateSelectedElements()
}
}
}
int stick = startSegment()->tick();
int etick = tickEnd();
Fraction stick = startSegment()->tick();
Fraction etick = tickEnd();
for (auto i = _score->spanner().begin(); i != _score->spanner().end(); ++i) {
Spanner* sp = (*i).second;
@ -542,9 +541,9 @@ void Selection::updateSelectedElements()
if (!canSelectVoice(sp->track()))
continue;
// ignore voltas
if (sp->type() == ElementType::VOLTA)
if (sp->isVolta())
continue;
if (sp->type() == ElementType::SLUR) {
if (sp->isSlur()) {
// ignore if start & end elements not calculated yet
if (!sp->startElement() || !sp->endElement())
continue;
@ -583,7 +582,7 @@ void Selection::setRange(Segment* startSegment, Segment* endSegment, int staffSt
// creating MM rests is pending).
//---------------------------------------------------------
void Selection::setRangeTicks(int tick1, int tick2, int staffStart, int staffEnd)
void Selection::setRangeTicks(const Fraction& tick1, const Fraction& tick2, int staffStart, int staffEnd)
{
Q_ASSERT(staffEnd > staffStart && staffStart >= 0 && staffEnd >= 0 && staffEnd <= _score->nstaves());
@ -710,7 +709,7 @@ bool hasElementInTrack(Segment* startSeg, Segment* endSeg, int track)
// firstElementInTrack
//---------------------------------------------------------
int firstElementInTrack(Segment* startSeg, Segment* endSeg, int track)
static Fraction firstElementInTrack(Segment* startSeg, Segment* endSeg, int track)
{
for (Segment* seg = startSeg; seg != endSeg; seg = seg->next1MM()) {
if (!seg->enabled())
@ -718,7 +717,7 @@ int firstElementInTrack(Segment* startSeg, Segment* endSeg, int track)
if (seg->element(track))
return seg->tick();
}
return -1;
return Fraction(-1,1);
}
//---------------------------------------------------------
@ -734,13 +733,13 @@ QByteArray Selection::staffMimeData() const
xml.setClipboardmode(true);
xml.setFilter(selectionFilter());
int ticks = tickEnd() - tickStart();
Fraction ticks = tickEnd() - tickStart();
int staves = staffEnd() - staffStart();
if (!MScore::testMode) {
xml.stag(QString("StaffList version=\"" MSC_VERSION "\" tick=\"%1\" len=\"%2\" staff=\"%3\" staves=\"%4\"").arg(tickStart()).arg(ticks).arg(staffStart()).arg(staves));
xml.stag(QString("StaffList version=\"" MSC_VERSION "\" tick=\"%1\" len=\"%2\" staff=\"%3\" staves=\"%4\"").arg(tickStart().ticks()).arg(ticks.ticks()).arg(staffStart()).arg(staves));
}
else {
xml.stag(QString("StaffList version=\"2.00\" tick=\"%1\" len=\"%2\" staff=\"%3\" staves=\"%4\"").arg(tickStart()).arg(ticks).arg(staffStart()).arg(staves));
xml.stag(QString("StaffList version=\"2.00\" tick=\"%1\" len=\"%2\" staff=\"%3\" staves=\"%4\"").arg(tickStart().ticks()).arg(ticks.ticks()).arg(staffStart()).arg(staves));
}
Segment* seg1 = _startSegment;
Segment* seg2 = _endSegment;
@ -762,8 +761,8 @@ QByteArray Selection::staffMimeData() const
for (int voice = 0; voice < VOICES; voice++) {
if (hasElementInTrack(seg1, seg2, startTrack + voice)
&& xml.canWriteVoice(voice)) {
int offset = firstElementInTrack(seg1, seg2, startTrack+voice) - tickStart();
xml.tag(QString("voice id=\"%1\"").arg(voice), offset);
Fraction offset = firstElementInTrack(seg1, seg2, startTrack+voice) - tickStart();
xml.tag(QString("voice id=\"%1\"").arg(voice), offset.ticks());
}
}
xml.etag(); // </voiceOffset>
@ -783,8 +782,7 @@ QByteArray Selection::staffMimeData() const
QByteArray Selection::symbolListMimeData() const
{
struct MAPDATA {
struct MapData {
Element* e;
Segment* s;
};
@ -797,11 +795,11 @@ QByteArray Selection::symbolListMimeData() const
int topTrack = 1000000;
int bottomTrack = 0;
Segment* firstSeg = nullptr;
int firstTick = 0x7FFFFFFF;
MAPDATA mapData;
Segment* seg = nullptr;
std::multimap<qint64, MAPDATA> map;
Segment* firstSeg = 0;
Fraction firstTick = Fraction(0x7FFFFFFF,1);
MapData mapData;
Segment* seg = 0;
std::multimap<qint64, MapData> map;
// scan selection element list, inserting relevant elements in a tick-sorted map
foreach (Element* e, _el) {
@ -937,7 +935,7 @@ Enabling copying of more element types requires enabling pasting in Score::paste
}
mapData.e = e;
mapData.s = seg;
map.insert(std::pair<qint64,MAPDATA>( ((qint64)track << 32) + seg->tick(), mapData));
map.insert(std::pair<qint64,MapData>( ((qint64)track << 32) + seg->tick().ticks(), mapData));
}
xml.stag(QString("SymbolList version=\"" MSC_VERSION "\" fromtrack=\"%1\" totrack=\"%2\"")
@ -953,7 +951,7 @@ Enabling copying of more element types requires enabling pasting in Score::paste
currTrack = track;
seg = firstSeg;
}
xml.tag("tickOffset", (int)(iter->first & 0xFFFFFFFF) - firstTick);
xml.tag("tickOffset", (int)(iter->first & 0xFFFFFFFF) - firstTick.ticks());
numSegs = 0;
// with figured bass, we need to look for the proper segment
// not only according to ChordRest elements, but also annotations
@ -1079,7 +1077,7 @@ static bool checkStart(Element* e)
// return true if element is part of a tuplet, but not the end
//---------------------------------------------------------
static bool checkEnd(Element* e, int endTick)
static bool checkEnd(Element* e, const Fraction& endTick)
{
if (e == 0 || !e->isChordRest())
return false;
@ -1119,7 +1117,7 @@ bool Selection::canCopy() const
if (_state != SelState::RANGE)
return true;
int endTick = _endSegment ? _endSegment->tick() : _score->lastSegment()->tick();
Fraction endTick = _endSegment ? _endSegment->tick() : _score->lastSegment()->tick();
for (int staffIdx = _staffStart; staffIdx != _staffEnd; ++staffIdx) {
@ -1259,7 +1257,7 @@ void Selection::extendRangeSelection(ChordRest* cr)
// extending by a chord rest.
//---------------------------------------------------------
void Selection::extendRangeSelection(Segment* seg, Segment* segAfter, int staffIdx, int tick, int etick)
void Selection::extendRangeSelection(Segment* seg, Segment* segAfter, int staffIdx, const Fraction& tick, const Fraction& etick)
{
bool activeIsFirst = false;
int activeStaff = _activeTrack / VOICES;

View file

@ -42,7 +42,7 @@ struct ElementPattern {
int voice;
const System* system;
bool subtypeValid;
int durationTicks;
Fraction durationTicks;
};
//---------------------------------------------------------
@ -74,6 +74,10 @@ enum class SelState : char {
// is selected
};
//---------------------------------------------------------
// SelectionFilterType
//---------------------------------------------------------
enum class SelectionFilterType {
NONE = 0,
FIRST_VOICE = 1 << 0,
@ -100,6 +104,11 @@ enum class SelectionFilterType {
ALL = -1
};
//---------------------------------------------------------
// SelectionFilter
//---------------------------------------------------------
class SelectionFilter {
Score* _score;
int _filtered;
@ -130,8 +139,8 @@ class Selection {
Segment* _startSegment;
Segment* _endSegment; // next segment after selection
int _plannedTick1 = -1; // Will be actually selected on updateSelectedElements() call.
int _plannedTick2 = -1; // Used by setRangeTicks() to restore proper selection after
Fraction _plannedTick1 { -1, 1 }; // Will be actually selected on updateSelectedElements() call.
Fraction _plannedTick2 { -1, 1 }; // Used by setRangeTicks() to restore proper selection after
// command end in case some changes are expected to segments'
// structure (e.g. MMRests reconstruction).
@ -185,14 +194,14 @@ class Selection {
void setStartSegment(Segment* s) { _startSegment = s; }
void setEndSegment(Segment* s) { _endSegment = s; }
void setRange(Segment* startSegment, Segment* endSegment, int staffStart, int staffEnd);
void setRangeTicks(int tick1, int tick2, int staffStart, int staffEnd);
void setRangeTicks(const Fraction& tick1, const Fraction& tick2, int staffStart, int staffEnd);
Segment* activeSegment() const { return _activeSegment; }
void setActiveSegment(Segment* s) { _activeSegment = s; }
ChordRest* activeCR() const;
bool isStartActive() const;
bool isEndActive() const;
int tickStart() const;
int tickEnd() const;
Fraction tickStart() const;
Fraction tickEnd() const;
int staffStart() const { return _staffStart; }
int staffEnd() const { return _staffEnd; }
int activeTrack() const { return _activeTrack; }
@ -203,7 +212,7 @@ class Selection {
void updateSelectedElements();
bool measureRange(Measure** m1, Measure** m2) const;
void extendRangeSelection(ChordRest* cr);
void extendRangeSelection(Segment* seg, Segment* segAfter, int staffIdx, int tick, int etick);
void extendRangeSelection(Segment* seg, Segment* segAfter, int staffIdx, const Fraction& tick, const Fraction& etick);
};

View file

@ -140,6 +140,7 @@ class TimeSigMap : public std::map<int, SigEvent > {
void dump() const;
const SigEvent& timesig(int tick) const;
const SigEvent& timesig(const Fraction& f) const { return timesig(f.ticks()); }
void tickValues(int t, int* bar, int* beat, int* tick) const;
int bar2tick(int bar, int beat) const;

View file

@ -163,7 +163,7 @@ bool SlurSegment::edit(EditData& ed)
void SlurSegment::changeAnchor(EditData& ed, Element* element)
{
if (ed.curGrip == Grip::START) {
int ticks = spanner()->endElement()->tick() - element->tick();
Fraction ticks = spanner()->endElement()->tick() - element->tick();
spanner()->undoChangeProperty(Pid::SPANNER_TICK, element->tick());
spanner()->undoChangeProperty(Pid::SPANNER_TICKS, ticks);
int diff = element->track() - spanner()->track();
@ -183,6 +183,7 @@ void SlurSegment::changeAnchor(EditData& ed, Element* element)
s->undoChangeProperty(Pid::SPANNER_TRACK2, s->track() + diff);
}
}
const size_t segments = spanner()->spannerSegments().size();
ups(ed.curGrip).off = QPointF();
spanner()->layout();
@ -215,7 +216,7 @@ void SlurSegment::computeBezier(QPointF p6o)
Measure* m1 = slur()->startCR()->segment()->measure();
Measure* m2 = slur()->endCR()->segment()->measure();
qDebug("zero slur at tick %d(%d) track %d in measure %d-%d tick %d ticks %d",
m1->tick(), tick(), track(), m1->no(), m2->no(), slur()->tick(), slur()->ticks());
m1->tick().ticks(), tick().ticks(), track(), m1->no(), m2->no(), slur()->tick().ticks(), slur()->ticks().ticks());
slur()->setBroken(true);
return;
}
@ -944,8 +945,8 @@ static bool isDirectionMixture(Chord* c1, Chord* c2)
SpannerSegment* Slur::layoutSystem(System* system)
{
int stick = system->firstMeasure()->tick();
int etick = system->lastMeasure()->endTick();
Fraction stick = system->firstMeasure()->tick();
Fraction etick = system->lastMeasure()->endTick();
SlurSegment* slurSegment = toSlurSegment(getNextLayoutSystemSegment(system, [this]() { return new SlurSegment(score()); }));
@ -959,7 +960,7 @@ SpannerSegment* Slur::layoutSystem(System* system)
setTrack2(track());
if (startCR() == 0 || startCR()->measure() == 0) {
qDebug("Slur::layout(): track %d-%d %p - %p tick %d-%d null start anchor",
track(), track2(), startCR(), endCR(), tick(), tick2());
track(), track2(), startCR(), endCR(), tick().ticks(), tick2().ticks());
return slurSegment;
}
if (endCR() == 0) { // sanity check
@ -1054,7 +1055,7 @@ void Slur::layout()
qreal _spatium = spatium();
if (score() == gscore || tick() == -1) {
if (score() == gscore || tick() == Fraction(-1,1)) {
//
// when used in a palette, slur has no parent and
// tick and tick2 has no meaning so no layout is
@ -1076,11 +1077,12 @@ void Slur::layout()
}
if (startCR() == 0 || startCR()->measure() == 0) {
qDebug("Slur::layout(): track %d-%d %p - %p tick %d-%d null start anchor",
track(), track2(), startCR(), endCR(), tick(), tick2());
qDebug("track %d-%d %p - %p tick %d-%d null start anchor",
track(), track2(), startCR(), endCR(), tick().ticks(), tick2().ticks());
return;
}
if (endCR() == 0) { // sanity check
qDebug("no end CR for %d", (tick()+ticks()).ticks());
setEndElement(startCR());
setTick2(tick());
}

View file

@ -25,7 +25,7 @@ namespace Ms {
class SlurSegment final : public SlurTieSegment {
protected:
virtual void changeAnchor(EditData&, Element*);
virtual void changeAnchor(EditData&, Element*) override;
public:
SlurSegment(Score* s) : SlurTieSegment(s) {}
@ -43,7 +43,7 @@ class SlurSegment final : public SlurTieSegment {
virtual bool edit(EditData&) override;
virtual void updateGrips(EditData&) const override;
Slur* slur() const { return (Slur*)spanner(); }
Slur* slur() const { return toSlur(spanner()); }
virtual void computeBezier(QPointF so = QPointF());
};

View file

@ -155,7 +155,7 @@ void SlurTieSegment::editDrag(EditData& ed)
Element* e = ed.view->elementNear(ed.pos);
if (e && e->isNote()) {
Note* note = toNote(e);
int tick = note->chord()->tick();
Fraction tick = note->chord()->tick();
if ((g == Grip::END && tick > slurTie()->tick()) || (g == Grip::START && tick < slurTie()->tick2())) {
if (km != (Qt::ShiftModifier | Qt::ControlModifier)) {
Chord* c = note->chord();

View file

@ -35,7 +35,7 @@ class SpannerWriter : public ConnectorInfoWriter {
public:
SpannerWriter(XmlWriter& xml, const Element* current, const Spanner* spanner, int track, Fraction frac, bool start);
static void fillSpannerPosition(Location& l, const MeasureBase* endpoint, int tick, bool clipboardmode);
static void fillSpannerPosition(Location& l, const MeasureBase* endpoint, const Fraction& tick, bool clipboardmode);
};
//---------------------------------------------------------
@ -366,20 +366,20 @@ void Spanner::removeUnmanaged()
// insertTimeUnmanaged
//---------------------------------------------------------
void Spanner::insertTimeUnmanaged(int fromTick, int len)
void Spanner::insertTimeUnmanaged(const Fraction& fromTick, const Fraction& len)
{
int newTick1 = tick();
int newTick2 = tick2();
Fraction newTick1 = tick();
Fraction newTick2 = tick2();
// check spanner start and end point
if (len > 0) { // adding time
if (len > Fraction(0,1)) { // adding time
if (tick() > fromTick) // start after insertion point: shift start to right
newTick1 += len;
if (tick2() > fromTick) // end after insertion point: shift end to right
newTick2 += len;
}
if (len < 0) { // removing time
int toTick = fromTick - len;
if (len < Fraction(0,1)) { // removing time
Fraction toTick = fromTick - len;
if (tick() > fromTick) { // start after beginning of removed time
if (tick() < toTick) { // start within removed time: bring start at removing point
if (parent()) {
@ -444,9 +444,9 @@ QVariant Spanner::getProperty(Pid propertyId) const
{
switch (propertyId) {
case Pid::SPANNER_TICK:
return tick();
return _tick;
case Pid::SPANNER_TICKS:
return ticks();
return _ticks;
case Pid::SPANNER_TRACK2:
return track2();
case Pid::ANCHOR:
@ -456,7 +456,7 @@ QVariant Spanner::getProperty(Pid propertyId) const
case Pid::LOCATION_VOICES:
return (track2() % VOICES) - (track() / VOICES);
case Pid::LOCATION_FRACTIONS:
return Fraction::fromTicks(_ticks);
return _ticks;
case Pid::LOCATION_MEASURES:
case Pid::LOCATION_GRACE:
case Pid::LOCATION_NOTE:
@ -475,14 +475,14 @@ bool Spanner::setProperty(Pid propertyId, const QVariant& v)
{
switch (propertyId) {
case Pid::SPANNER_TICK:
setTick(v.toInt());
setTick(v.value<Fraction>());
setStartElement(0); // invalidate
setEndElement(0); //
if (score() && score()->spannerMap().removeSpanner(this))
score()->addSpanner(this);
break;
case Pid::SPANNER_TICKS:
setTicks(v.toInt());
setTicks(v.value<Fraction>());
setEndElement(0); // invalidate
break;
case Pid::TRACK:
@ -561,25 +561,22 @@ void Spanner::computeEndElement()
case Anchor::SEGMENT: {
if (track2() == -1)
setTrack2(track());
if (ticks() == 0 && isTextLine() && parent()) // special case palette
if (ticks().isZero() && isTextLine() && parent()) // special case palette
setTicks(score()->lastSegment()->tick() - _tick);
// find last cr on this staff that ends before tick2
_endElement = score()->findCRinStaff(tick2(), track2() / VOICES);
if (!_endElement) {
qDebug("%s no end element for tick %d", name(), tick2());
qDebug("%s no end element for tick %d", name(), tick2().ticks());
return;
}
if (!endCR()->measure()->isMMRest()) {
ChordRest* cr = endCR();
int nticks = cr->tick() + cr->actualTicks() - _tick;
// allow fudge factor for tuplets
// TODO: replace with fraction-based calculation
int fudge = cr->tuplet() ? 5 : 0;
if (qAbs(_ticks - nticks) > fudge) {
qDebug("%s ticks changed, %d -> %d", name(), _ticks, nticks);
Fraction nticks = cr->tick() + cr->actualTicks() - _tick;
if ((_ticks - nticks).isNotZero()) {
qDebug("%s ticks changed, %d -> %d", name(), _ticks.ticks(), nticks.ticks());
setTicks(nticks);
if (type() == ElementType::OTTAVA)
if (isOttava())
staff()->updateOttava();
}
}
@ -587,9 +584,9 @@ void Spanner::computeEndElement()
break;
case Anchor::MEASURE:
_endElement = score()->tick2measure(tick2() - 1);
_endElement = score()->tick2measure(tick2() - Fraction(1, 1920));
if (!_endElement) {
qDebug("Spanner::computeEndElement(), measure not found for tick %d\n", tick2()-1);
qDebug("Spanner::computeEndElement(), measure not found for tick %d\n", tick2().ticks()-1);
_endElement = score()->lastMeasure();
}
break;
@ -738,7 +735,7 @@ ChordRest* Spanner::endCR()
{
Q_ASSERT(_anchor == Anchor::SEGMENT || _anchor == Anchor::CHORD);
if ((!_endElement || _endElement->score() != score())) {
Segment* s = score()->tick2segmentMM(tick2(), false, SegmentType::ChordRest);
Segment* s = score()->tick2segmentMM(tick2(), false, SegmentType::ChordRest);
_endElement = s ? toChordRest(s->element(track2())) : 0;
}
return toChordRest(_endElement);
@ -847,7 +844,7 @@ void Spanner::setEndElement(Element* e)
Spanner* Spanner::nextSpanner(Element* e, int activeStaff)
{
std::multimap<int, Spanner*> mmap = score()->spanner();
auto range = mmap.equal_range(tick());
auto range = mmap.equal_range(tick().ticks());
if (range.first != range.second) { // range not empty
for (auto i = range.first; i != range.second; ++i) {
if (i->second == e) {
@ -882,7 +879,7 @@ Spanner* Spanner::nextSpanner(Element* e, int activeStaff)
Spanner* Spanner::prevSpanner(Element* e, int activeStaff)
{
std::multimap<int, Spanner*> mmap = score()->spanner();
auto range = mmap.equal_range(tick());
auto range = mmap.equal_range(tick().ticks());
if (range.first != range.second) { // range not empty
for (auto i = range.first; i != range.second; ++i) {
if (i->second == e) {
@ -930,7 +927,7 @@ Element* Spanner::prevSegmentElement()
// setTick
//---------------------------------------------------------
void Spanner::setTick(int v)
void Spanner::setTick(const Fraction& v)
{
_tick = v;
if (score())
@ -941,43 +938,22 @@ void Spanner::setTick(int v)
// setTick2
//---------------------------------------------------------
void Spanner::setTick2(int v)
void Spanner::setTick2(const Fraction& f)
{
setTicks(v - _tick);
setTicks(f - _tick);
}
//---------------------------------------------------------
// setTicks
//---------------------------------------------------------
void Spanner::setTicks(int v)
void Spanner::setTicks(const Fraction& f)
{
_ticks = v;
_ticks = f;
if (score())
score()->spannerMap().setDirty();
}
//---------------------------------------------------------
// afrac
//---------------------------------------------------------
Fraction Spanner::afrac() const
{
return Fraction::fromTicks(_tick);
}
//---------------------------------------------------------
// rfrac
//---------------------------------------------------------
Fraction Spanner::rfrac() const
{
const Measure* m = toMeasure(findMeasure());
if (m)
return Fraction::fromTicks(_tick - m->tick());
return afrac();
}
//---------------------------------------------------------
// triggerLayout
//---------------------------------------------------------
@ -1146,6 +1122,23 @@ void Spanner::layoutSystemsDone()
segments = std::move(validSegments);
}
//--------------------------------------------------
// fraction
//---------------------------------------------------------
#if 0
static Fraction fraction(const XmlWriter& xml, const Element* current, const Fraction& t)
{
Fraction tick(t);
if (!xml.clipboardmode()) {
const Measure* m = toMeasure(current->findMeasure());
if (m)
tick -= m->tick();
}
return tick;
}
#endif
//--------------------------------------------------
// Spanner::writeSpannerStart
//---------------------------------------------------------
@ -1166,37 +1159,6 @@ void Spanner::writeSpannerEnd(XmlWriter& xml, const Element* current, int track,
w.write();
}
//--------------------------------------------------
// fraction
//---------------------------------------------------------
static Fraction fraction(const XmlWriter& xml, const Element* current, int tick) {
if (!xml.clipboardmode()) {
const Measure* m = toMeasure(current->findMeasure());
if (m)
tick -= m->tick();
}
return Fraction::fromTicks(tick);
}
//--------------------------------------------------
// Spanner::writeSpannerStart
//---------------------------------------------------------
void Spanner::writeSpannerStart(XmlWriter& xml, const Element* current, int track, int tick) const
{
writeSpannerStart(xml, current, track, fraction(xml, current, tick));
}
//--------------------------------------------------
// Spanner::writeSpannerEnd
//---------------------------------------------------------
void Spanner::writeSpannerEnd(XmlWriter& xml, const Element* current, int track, int tick) const
{
writeSpannerEnd(xml, current, track, fraction(xml, current, tick));
}
//--------------------------------------------------
// Spanner::readSpanner
//---------------------------------------------------------
@ -1221,21 +1183,21 @@ void Spanner::readSpanner(XmlReader& e, Score* current, int track)
// SpannerWriter::fillSpannerPosition
//---------------------------------------------------------
void SpannerWriter::fillSpannerPosition(Location& l, const MeasureBase* m, int tick, bool clipboardmode)
void SpannerWriter::fillSpannerPosition(Location& l, const MeasureBase* m, const Fraction& tick, bool clipboardmode)
{
if (clipboardmode) {
l.setMeasure(0);
l.setFrac(Fraction::fromTicks(tick));
l.setFrac(tick);
}
else {
if (!m) {
qWarning("fillSpannerPosition: couldn't find spanner's endpoint's measure");
l.setMeasure(0);
l.setFrac(Fraction::fromTicks(tick));
l.setFrac(tick);
return;
}
l.setMeasure(m->measureIndex());
l.setFrac(Fraction::fromTicks(tick - m->tick()));
l.setFrac(tick - m->tick());
}
}
@ -1258,12 +1220,14 @@ SpannerWriter::SpannerWriter(XmlWriter& xml, const Element* current, const Spann
// elements and will try to obtain this info from the spanner itself.
if (!start) {
_prevLoc.setTrack(sp->track());
fillSpannerPosition(_prevLoc, sp->score()->tick2measure(sp->tick()), sp->tick(), clipboardmode);
Measure* m = sp->score()->tick2measure(sp->tick());
fillSpannerPosition(_prevLoc, m, sp->tick(), clipboardmode);
}
else {
const int track2 = (sp->track2() != -1) ? sp->track2() : sp->track();
_nextLoc.setTrack(track2);
fillSpannerPosition(_nextLoc, sp->score()->tick2measure(sp->tick2()), sp->tick2(), clipboardmode);
Measure* m = sp->score()->tick2measure(sp->tick2());
fillSpannerPosition(_nextLoc, m, sp->tick2(), clipboardmode);
}
}
else {

View file

@ -141,8 +141,8 @@ class Spanner : public Element {
Element* _endElement { 0 };
Anchor _anchor { Anchor::SEGMENT };
int _tick { -1 };
int _ticks { 0 };
Fraction _tick { Fraction(-1, 1) };
Fraction _ticks { Fraction(0, 1) };
int _track2 { -1 };
bool _broken { false };
@ -170,27 +170,22 @@ class Spanner : public Element {
virtual ElementType type() const = 0;
virtual void setScore(Score* s) override;
void writeSpannerStart(XmlWriter& xml, const Element* current, int track, Fraction frac = -1) const;
void writeSpannerEnd(XmlWriter& xml, const Element* current, int track, Fraction frac = -1) const;
void writeSpannerStart(XmlWriter& xml, const Element* current, int track, int tick) const;
void writeSpannerEnd(XmlWriter& xml, const Element* current, int track, int tick) const;
void writeSpannerStart(XmlWriter& xml, const Element* current, int track, Fraction frac = { -1, 1 }) const;
void writeSpannerEnd(XmlWriter& xml, const Element* current, int track, Fraction frac = { -1, 1 }) const;
static void readSpanner(XmlReader& e, Element* current, int track);
static void readSpanner(XmlReader& e, Score* current, int track);
virtual int tick() const override { return _tick; }
int tick2() const { return _tick + _ticks; }
int ticks() const { return _ticks; }
virtual Fraction tick() const override { return _tick; }
Fraction tick2() const { return _tick + _ticks; }
Fraction ticks() const { return _ticks; }
void setTick(int v);
void setTick2(int v);
void setTicks(int v);
void setTick(const Fraction&);
void setTick2(const Fraction&);
void setTicks(const Fraction&);
int track2() const { return _track2; }
void setTrack2(int v) { _track2 = v; }
Fraction rfrac() const override;
Fraction afrac() const override;
bool broken() const { return _broken; }
void setBroken(bool v) { _broken = v; }
@ -217,7 +212,7 @@ class Spanner : public Element {
virtual void scanElements(void* data, void (*func)(void*, Element*), bool all=true) override;
bool removeSpannerBack();
virtual void removeUnmanaged();
virtual void insertTimeUnmanaged(int tick, int len);
virtual void insertTimeUnmanaged(const Fraction& tick, const Fraction& len);
QVariant getProperty(Pid propertyId) const;
bool setProperty(Pid propertyId, const QVariant& v);

View file

@ -34,7 +34,7 @@ void SpannerMap::update() const
{
std::vector< ::Interval<Spanner*> > intervals;
for (auto i : *this)
intervals.push_back(Interval<Spanner*>(i.second->tick(), i.second->tick2(), i.second));
intervals.push_back(Interval<Spanner*>(i.second->tick().ticks(), i.second->tick2().ticks(), i.second));
tree = IntervalTree<Spanner*>(intervals);
dirty = false;
}
@ -81,7 +81,7 @@ void SpannerMap::addSpanner(Spanner* s)
}
#endif
#endif
insert(std::pair<int,Spanner*>(s->tick(), s));
insert(std::pair<int,Spanner*>(s->tick().ticks(), s));
dirty = true;
}

View file

@ -39,7 +39,7 @@ void Score::cmdSplitMeasure(ChordRest* cr)
void Score::splitMeasure(Segment* segment)
{
if (segment->rtick() == 0) {
if (segment->rtick().isZero()) {
MScore::setError(CANNOT_SPLIT_MEASURE_FIRST_BEAT);
return;
}
@ -52,10 +52,10 @@ void Score::splitMeasure(Segment* segment)
ScoreRange range;
range.read(measure->first(), measure->last());
int stick = measure->tick();
int etick = measure->endTick();
Fraction stick = measure->tick();
Fraction etick = measure->endTick();
std::list<std::tuple<Spanner*, int, int>> sl;
std::list<std::tuple<Spanner*, Fraction, Fraction>> sl;
for (auto i : spanner()) {
Spanner* s = i.second;
Element* start = s->startElement();
@ -80,21 +80,21 @@ void Score::splitMeasure(Segment* segment)
insertMeasure(ElementType::MEASURE, m2, true);
Measure* m1 = toMeasure(m2->prev());
int tick = segment->tick();
Fraction tick = segment->tick();
m1->setTick(measure->tick());
m2->setTick(tick);
int ticks1 = segment->tick() - measure->tick();
int ticks2 = measure->ticks() - ticks1;
Fraction ticks1 = segment->tick() - measure->tick();
Fraction ticks2 = measure->ticks() - ticks1;
m1->setTimesig(measure->timesig());
m2->setTimesig(measure->timesig());
m1->adjustToLen(Fraction::fromTicks(ticks1), false);
m2->adjustToLen(Fraction::fromTicks(ticks2), false);
m1->adjustToLen(ticks1.reduced(), false);
m2->adjustToLen(ticks2.reduced(), false);
range.write(this, m1->tick());
for (auto i : sl) {
Spanner* s = std::get<0>(i);
int t = std::get<1>(i);
int ticks = std::get<2>(i);
Spanner* s = std::get<0>(i);
Fraction t = std::get<1>(i);
Fraction ticks = std::get<2>(i);
if (s->tick() != t)
s->undoChangeProperty(Pid::SPANNER_TICK, t);
if (s->ticks() != ticks)

View file

@ -278,28 +278,13 @@ QString Staff::partName() const
return _part->partName();
}
//---------------------------------------------------------
// ~Staff
//---------------------------------------------------------
Staff::~Staff()
{
#if 0
if (_linkedStaves) {
_linkedStaves->remove(this);
if (_linkedStaves->empty())
delete _linkedStaves;
}
#endif
}
//---------------------------------------------------------
// Staff::clefType
//---------------------------------------------------------
ClefTypeList Staff::clefType(int tick) const
ClefTypeList Staff::clefType(const Fraction& tick) const
{
ClefTypeList ct = clefs.clef(tick);
ClefTypeList ct = clefs.clef(tick.ticks());
if (ct._concertClef == ClefType::INVALID) {
switch (staffType(tick)->group()) {
case StaffGroup::TAB:
@ -323,7 +308,7 @@ ClefTypeList Staff::clefType(int tick) const
// Staff::clef
//---------------------------------------------------------
ClefType Staff::clef(int tick) const
ClefType Staff::clef(const Fraction& tick) const
{
ClefTypeList c = clefType(tick);
return score()->styleB(Sid::concertPitch) ? c._concertClef : c._transposingClef;
@ -336,10 +321,10 @@ ClefType Staff::clef(int tick) const
// return last tick of score if not found
//---------------------------------------------------------
int Staff::nextClefTick(int tick) const
Fraction Staff::nextClefTick(const Fraction& tick) const
{
int t = clefs.nextClefTick(tick);
return t != -1 ? t : score()->endTick();
Fraction t = Fraction::fromTicks(clefs.nextClefTick(tick.ticks()));
return t != Fraction(-1,1) ? t : score()->endTick();
}
@ -387,10 +372,9 @@ void Staff::dumpTimeSigs(const char* title) const
void Staff::setClef(Clef* clef)
{
// qDebug("Staff::setClef generated %d", clef->generated());
if (clef->generated())
return;
int tick = clef->segment()->tick();
Fraction tick = clef->segment()->tick();
for (Segment* s = clef->segment()->next1(); s && s->tick() == tick; s = s->next1()) {
if ((s->segmentType() == SegmentType::Clef || s->segmentType() == SegmentType::HeaderClef)
&& s->element(clef->track())
@ -399,7 +383,7 @@ void Staff::setClef(Clef* clef)
return;
}
}
clefs.setClef(clef->segment()->tick(), clef->clefTypeList());
clefs.setClef(clef->segment()->tick().ticks(), clef->clefTypeList());
DUMP_CLEFS("setClef");
}
@ -407,12 +391,11 @@ void Staff::setClef(Clef* clef)
// removeClef
//---------------------------------------------------------
void Staff::removeClef(Clef* clef)
void Staff::removeClef(const Clef* clef)
{
// qDebug("Staff::removeClef generated %d", clef->generated());
if (clef->generated())
return;
int tick = clef->segment()->tick();
Fraction tick = clef->segment()->tick();
for (Segment* s = clef->segment()->next1(); s && s->tick() == tick; s = s->next1()) {
if ((s->segmentType() == SegmentType::Clef || s->segmentType() == SegmentType::HeaderClef)
&& s->element(clef->track())
@ -421,13 +404,13 @@ void Staff::removeClef(Clef* clef)
return;
}
}
clefs.erase(clef->segment()->tick());
clefs.erase(clef->segment()->tick().ticks());
for (Segment* s = clef->segment()->prev1(); s && s->tick() == tick; s = s->prev1()) {
if ((s->segmentType() == SegmentType::Clef || s->segmentType() == SegmentType::HeaderClef)
&& s->element(clef->track())
&& !s->element(clef->track())->generated()) {
// a previous clef at the same tick position gets valid
clefs.setClef(tick, toClef(s->element(clef->track()))->clefTypeList());
clefs.setClef(tick.ticks(), toClef(s->element(clef->track()))->clefTypeList());
break;
}
}
@ -438,7 +421,7 @@ void Staff::removeClef(Clef* clef)
// timeStretch
//---------------------------------------------------------
Fraction Staff::timeStretch(int tick) const
Fraction Staff::timeStretch(const Fraction& tick) const
{
TimeSig* timesig = timeSig(tick);
return timesig ? timesig->stretch() : Fraction(1,1);
@ -449,14 +432,14 @@ Fraction Staff::timeStretch(int tick) const
// lookup time signature before or at tick
//---------------------------------------------------------
TimeSig* Staff::timeSig(int tick) const
TimeSig* Staff::timeSig(const Fraction& tick) const
{
auto i = timesigs.upper_bound(tick);
auto i = timesigs.upper_bound(tick.ticks());
if (i != timesigs.begin())
--i;
if (i == timesigs.end())
return 0;
else if (tick < i->first)
else if (tick < Fraction::fromTicks(i->first))
return 0;
return i->second;
}
@ -466,9 +449,9 @@ TimeSig* Staff::timeSig(int tick) const
// lookup time signature at tick or after
//---------------------------------------------------------
TimeSig* Staff::nextTimeSig(int tick) const
TimeSig* Staff::nextTimeSig(const Fraction& tick) const
{
auto i = timesigs.lower_bound(tick);
auto i = timesigs.lower_bound(tick.ticks());
return (i == timesigs.end()) ? 0 : i->second;
}
@ -476,7 +459,7 @@ TimeSig* Staff::nextTimeSig(int tick) const
// group
//---------------------------------------------------------
const Groups& Staff::group(int tick) const
const Groups& Staff::group(const Fraction& tick) const
{
TimeSig* ts = timeSig(tick);
if (ts) {
@ -495,7 +478,7 @@ const Groups& Staff::group(int tick) const
void Staff::addTimeSig(TimeSig* timesig)
{
if (timesig->segment()->segmentType() == SegmentType::TimeSig)
timesigs[timesig->segment()->tick()] = timesig;
timesigs[timesig->segment()->tick().ticks()] = timesig;
// dumpTimeSigs("after addTimeSig");
}
@ -506,7 +489,7 @@ void Staff::addTimeSig(TimeSig* timesig)
void Staff::removeTimeSig(TimeSig* timesig)
{
if (timesig->segment()->segmentType() == SegmentType::TimeSig)
timesigs.erase(timesig->segment()->tick());
timesigs.erase(timesig->segment()->tick().ticks());
// dumpTimeSigs("after removeTimeSig");
}
@ -525,38 +508,36 @@ void Staff::clearTimeSig()
// locates the key sig currently in effect at tick
//---------------------------------------------------------
KeySigEvent Staff::keySigEvent(int tick) const
KeySigEvent Staff::keySigEvent(const Fraction& tick) const
{
return _keys.key(tick);
return _keys.key(tick.ticks());
}
//---------------------------------------------------------
// setKey
//---------------------------------------------------------
void Staff::setKey(int tick, KeySigEvent k)
void Staff::setKey(const Fraction& tick, KeySigEvent k)
{
_keys.setKey(tick, k);
// dumpKeys("setKey");
_keys.setKey(tick.ticks(), k);
}
//---------------------------------------------------------
// removeKey
//---------------------------------------------------------
void Staff::removeKey(int tick)
void Staff::removeKey(const Fraction& tick)
{
_keys.erase(tick);
// dumpKeys("removeKey");
_keys.erase(tick.ticks());
}
//---------------------------------------------------------
// prevkey
//---------------------------------------------------------
KeySigEvent Staff::prevKey(int tick) const
KeySigEvent Staff::prevKey(const Fraction& tick) const
{
return _keys.prevKey(tick);
return _keys.prevKey(tick.ticks());
}
//---------------------------------------------------------
@ -566,10 +547,10 @@ KeySigEvent Staff::prevKey(int tick) const
// return 0, if no such a key sig
//---------------------------------------------------------
int Staff::nextKeyTick(int tick) const
Fraction Staff::nextKeyTick(const Fraction& tick) const
{
int t = _keys.nextKeyTick(tick);
return t != -1 ? t : score()->endTick();
Fraction t = Fraction::fromTicks(_keys.nextKeyTick(tick.ticks()));
return t != Fraction(-1,1) ? t : score()->endTick();
}
//---------------------------------------------------------
@ -580,9 +561,9 @@ int Staff::nextKeyTick(int tick) const
// return 0, if no such a key sig
//---------------------------------------------------------
int Staff::currentKeyTick(int tick) const
Fraction Staff::currentKeyTick(const Fraction& tick) const
{
return _keys.currentKeyTick(tick);
return Fraction::fromTicks(_keys.currentKeyTick(tick.ticks()));
}
//---------------------------------------------------------
@ -611,7 +592,7 @@ void Staff::write(XmlWriter& xml) const
xml.tag("transposeChromatic", v.chromatic);
}
staffType(0)->write(xml);
staffType(Fraction(0,1))->write(xml);
ClefTypeList ct = _defaultClefType;
if (ct._concertClef == ct._transposingClef) {
if (ct._concertClef != ClefType::G)
@ -675,7 +656,7 @@ bool Staff::readProperties(XmlReader& e)
if (tag == "StaffType") {
StaffType st;
st.read(e);
setStaffType(0, st);
setStaffType(Fraction(0,1), st);
}
else if (tag == "defaultClef") { // sets both default transposing and concert clef
QString val(e.readElementText());
@ -691,7 +672,7 @@ bool Staff::readProperties(XmlReader& e)
setDefaultClefType(ClefTypeList(defaultClefType()._concertClef, Clef::clefType(val)));
}
else if (tag == "small") // obsolete
setSmall(0, e.readInt());
setSmall(Fraction(0,1), e.readInt());
else if (tag == "invisible")
setInvisible(e.readInt());
else if (tag == "hideWhenEmpty")
@ -767,7 +748,7 @@ bool Staff::readProperties(XmlReader& e)
qreal Staff::height() const
{
int tick = 0; // TODO
Fraction tick = Fraction(0,1); // TODO
// return (lines(tick) == 1 ? 2 : lines(tick)-1) * spatium(tick) * staffType(tick)->lineDistance().val();
return (lines(tick)-1) * spatium(tick) * staffType(tick)->lineDistance().val();
}
@ -776,7 +757,7 @@ qreal Staff::height() const
// spatium
//---------------------------------------------------------
qreal Staff::spatium(int tick) const
qreal Staff::spatium(const Fraction& tick) const
{
return score()->spatium() * mag(tick);
}
@ -785,7 +766,7 @@ qreal Staff::spatium(int tick) const
// mag
//---------------------------------------------------------
qreal Staff::mag(int tick) const
qreal Staff::mag(const Fraction& tick) const
{
return (small(tick) ? score()->styleD(Sid::smallStaffMag) : 1.0) * userMag(tick);
}
@ -794,7 +775,7 @@ qreal Staff::mag(int tick) const
// userMag
//---------------------------------------------------------
qreal Staff::userMag(int tick) const
qreal Staff::userMag(const Fraction& tick) const
{
return staffType(tick)->userMag();
}
@ -803,7 +784,7 @@ qreal Staff::userMag(int tick) const
// setUserMag
//---------------------------------------------------------
void Staff::setUserMag(int tick, qreal m)
void Staff::setUserMag(const Fraction& tick, qreal m)
{
staffType(tick)->setUserMag(m);
}
@ -812,7 +793,7 @@ void Staff::setUserMag(int tick, qreal m)
// small
//---------------------------------------------------------
bool Staff::small(int tick) const
bool Staff::small(const Fraction& tick) const
{
return staffType(tick)->small();
}
@ -821,7 +802,7 @@ bool Staff::small(int tick) const
// setSmall
//---------------------------------------------------------
void Staff::setSmall(int tick, bool val)
void Staff::setSmall(const Fraction& tick, bool val)
{
staffType(tick)->setSmall(val);
}
@ -830,7 +811,7 @@ void Staff::setSmall(int tick, bool val)
// swing
//---------------------------------------------------------
SwingParameters Staff::swing(int tick) const
SwingParameters Staff::swing(const Fraction& tick) const
{
SwingParameters sp;
int swingUnit = 0;
@ -847,7 +828,7 @@ SwingParameters Staff::swing(int tick) const
sp.swingUnit = swingUnit;
if (_swingList.empty())
return sp;
QMap<int, SwingParameters>::const_iterator i = _swingList.upperBound(tick);
QMap<int, SwingParameters>::const_iterator i = _swingList.upperBound(tick.ticks());
if (i == _swingList.begin())
return sp;
--i;
@ -858,11 +839,11 @@ SwingParameters Staff::swing(int tick) const
// capo
//---------------------------------------------------------
int Staff::capo(int tick) const
int Staff::capo(const Fraction& tick) const
{
if (_capoList.empty())
return 0;
QMap<int, int>::const_iterator i = _capoList.upperBound(tick);
QMap<int, int>::const_iterator i = _capoList.upperBound(tick.ticks());
if (i == _capoList.begin())
return 0;
--i;
@ -873,11 +854,11 @@ int Staff::capo(int tick) const
// channel
//---------------------------------------------------------
int Staff::channel(int tick, int voice) const
int Staff::channel(const Fraction& tick, int voice) const
{
if (_channelList[voice].empty())
return 0;
QMap<int, int>::const_iterator i = _channelList[voice].upperBound(tick);
QMap<int, int>::const_iterator i = _channelList[voice].upperBound(tick.ticks());
if (i == _channelList[voice].begin())
return 0;
--i;
@ -889,7 +870,7 @@ int Staff::channel(int tick, int voice) const
// returns logical line number of middle staff line
//---------------------------------------------------------
int Staff::middleLine(int tick) const
int Staff::middleLine(const Fraction& tick) const
{
return lines(tick) - 1;
}
@ -899,7 +880,7 @@ int Staff::middleLine(int tick) const
// returns logical line number of bottom staff line
//---------------------------------------------------------
int Staff::bottomLine(int tick) const
int Staff::bottomLine(const Fraction& tick) const
{
return (lines(tick) - 1) * 2;
}
@ -908,7 +889,7 @@ int Staff::bottomLine(int tick) const
// slashStyle
//---------------------------------------------------------
bool Staff::slashStyle(int tick) const
bool Staff::slashStyle(const Fraction& tick) const
{
return staffType(tick)->slashStyle();
}
@ -917,7 +898,7 @@ bool Staff::slashStyle(int tick) const
// setSlashStyle
//---------------------------------------------------------
void Staff::setSlashStyle(int tick, bool val)
void Staff::setSlashStyle(const Fraction& tick, bool val)
{
staffType(tick)->setSlashStyle(val);
}
@ -940,7 +921,7 @@ bool Staff::primaryStaff() const
Staff* staff = toStaff(e);
if (staff->score() == score()) {
s.append(staff);
if (!staff->isTabStaff(0))
if (!staff->isTabStaff(Fraction(0,1)))
ss.append(staff);
}
}
@ -954,17 +935,17 @@ bool Staff::primaryStaff() const
// staffType
//---------------------------------------------------------
const StaffType* Staff::staffType(int tick) const
const StaffType* Staff::staffType(const Fraction& tick) const
{
return &_staffTypeList.staffType(tick);
}
const StaffType* Staff::constStaffType(int tick) const
const StaffType* Staff::constStaffType(const Fraction& tick) const
{
return &_staffTypeList.staffType(tick);
}
StaffType* Staff::staffType(int tick)
StaffType* Staff::staffType(const Fraction& tick)
{
return &_staffTypeList.staffType(tick);
}
@ -975,13 +956,13 @@ StaffType* Staff::staffType(int tick)
// position tick. Update layout range.
//---------------------------------------------------------
void Staff::staffTypeListChanged(int tick)
void Staff::staffTypeListChanged(const Fraction& tick)
{
score()->setLayout(tick);
auto i = _staffTypeList.find(tick);
auto i = _staffTypeList.find(tick.ticks());
++i;
if (i != _staffTypeList.end())
score()->setLayout(i->first);
score()->setLayout(Fraction::fromTicks(i->first));
else
score()->setLayout(score()->lastMeasure()->endTick());
}
@ -990,16 +971,8 @@ void Staff::staffTypeListChanged(int tick)
// setStaffType
//---------------------------------------------------------
StaffType* Staff::setStaffType(int tick, const StaffType& nst)
StaffType* Staff::setStaffType(const Fraction& tick, const StaffType& nst)
{
#if 0
#ifndef NDEBUG
auto i = _staffTypeList.find(tick);
if (i != _staffTypeList.end()) {
qDebug("there is already a type at %d", tick);
}
#endif
#endif
return _staffTypeList.setStaffType(tick, nst);
}
@ -1014,12 +987,12 @@ void Staff::init(const InstrumentTemplate* t, const StaffType* staffType, int ci
if (!pst)
pst = StaffType::getDefaultPreset(t->staffGroup);
setStaffType(0, *pst);
setStaffType(Fraction(0,1), *pst);
if (cidx >= MAX_STAVES) {
setSmall(0, false);
setSmall(Fraction(0,1), false);
}
else {
setSmall(0, t->smallStaff[cidx]);
setSmall(Fraction(0,1), t->smallStaff[cidx]);
setBracketType(0, t->bracket[cidx]);
setBracketSpan(0, t->bracketSpan[cidx]);
setBarLineSpan(t->barlineSpan[cidx]);
@ -1064,7 +1037,7 @@ void Staff::initFromStaffType(const StaffType* staffType)
staffType = StaffType::getDefaultPreset(StaffGroup::STANDARD);
// use selected staff type
setStaffType(0, *staffType);
setStaffType(Fraction(0,1), *staffType);
}
//---------------------------------------------------------
@ -1091,17 +1064,17 @@ bool Staff::show() const
bool Staff::genKeySig()
{
if (constStaffType(0)->group() == StaffGroup::TAB)
if (constStaffType(Fraction(0,1))->group() == StaffGroup::TAB)
return false;
else
return constStaffType(0)->genKeysig();
return constStaffType(Fraction(0,1))->genKeysig();
}
//---------------------------------------------------------
// showLedgerLines
//---------------------------------------------------------
bool Staff::showLedgerLines(int tick) const
bool Staff::showLedgerLines(const Fraction& tick) const
{
return staffType(tick)->showLedgerLines();
}
@ -1118,8 +1091,8 @@ void Staff::updateOttava()
const Spanner* s = i.second;
if (s->type() == ElementType::OTTAVA && s->staffIdx() == staffIdx) {
const Ottava* o = static_cast<const Ottava*>(s);
_pitchOffsets.setPitchOffset(o->tick(), o->pitchShift());
_pitchOffsets.setPitchOffset(o->tick2(), 0);
_pitchOffsets.setPitchOffset(o->tick().ticks(), o->pitchShift());
_pitchOffsets.setPitchOffset(o->tick2().ticks(), 0);
}
}
}
@ -1137,25 +1110,25 @@ void Staff::undoSetColor(const QColor& /*val*/)
// insertTime
//---------------------------------------------------------
void Staff::insertTime(int tick, int len)
void Staff::insertTime(const Fraction& tick, const Fraction& len)
{
if (len == 0)
if (len.isZero())
return;
// move all keys and clefs >= tick
if (len < 0) {
if (len < Fraction(0,1)) {
// remove entries between tickpos >= tick and tickpos < (tick+len)
_keys.erase(_keys.lower_bound(tick), _keys.lower_bound(tick-len));
clefs.erase(clefs.lower_bound(tick), clefs.lower_bound(tick-len));
_keys.erase(_keys.lower_bound(tick.ticks()), _keys.lower_bound((tick - len).ticks()));
clefs.erase(clefs.lower_bound(tick.ticks()), clefs.lower_bound((tick - len).ticks()));
}
KeyList kl2;
for (auto i = _keys.lower_bound(tick); i != _keys.end();) {
for (auto i = _keys.lower_bound(tick.ticks()); i != _keys.end();) {
KeySigEvent kse = i->second;
int t = i->first;
Fraction t = Fraction::fromTicks(i->first);
_keys.erase(i++);
kl2[t + len] = kse;
kl2[(t + len).ticks()] = kse;
}
_keys.insert(kl2.begin(), kl2.end());
@ -1173,15 +1146,15 @@ void Staff::insertTime(int tick, int len)
}
ClefList cl2;
for (auto i = clefs.lower_bound(tick); i != clefs.end();) {
for (auto i = clefs.lower_bound(tick.ticks()); i != clefs.end();) {
ClefTypeList ctl = i->second;
int t = i->first;
Fraction t = Fraction::fromTicks(i->first);
if (clef && tick == t) {
++i;
continue;
}
clefs.erase(i++);
cl2.setClef(t + len, ctl);
cl2.setClef((t + len).ticks(), ctl);
}
clefs.insert(cl2.begin(), cl2.end());
@ -1239,9 +1212,9 @@ QVariant Staff::getProperty(Pid id) const
{
switch (id) {
case Pid::SMALL:
return small(0);
return small(Fraction(0,1));
case Pid::MAG:
return userMag(0);
return userMag(Fraction(0,1));
case Pid::COLOR:
return color();
case Pid::PLAYBACK_VOICE1:
@ -1276,12 +1249,12 @@ bool Staff::setProperty(Pid id, const QVariant& v)
{
switch (id) {
case Pid::SMALL:
setSmall(0, v.toBool());
setSmall(Fraction(0,1), v.toBool());
break;
case Pid::MAG: {
qreal _spatium = spatium(0);
setUserMag(0, v.toReal());
score()->spatiumChanged(_spatium, spatium(0));
qreal _spatium = spatium(Fraction(0,1));
setUserMag(Fraction(0,1), v.toReal());
score()->spatiumChanged(_spatium, spatium(Fraction(0,1)));
}
break;
case Pid::COLOR:
@ -1380,7 +1353,7 @@ void Staff::scaleChanged(double oldVal, double newVal)
// isPitchedStaff
//---------------------------------------------------------
bool Staff::isPitchedStaff(int tick) const
bool Staff::isPitchedStaff(const Fraction& tick) const
{
return staffType(tick)->group() == StaffGroup::STANDARD;
}
@ -1389,7 +1362,7 @@ bool Staff::isPitchedStaff(int tick) const
// isTabStaff
//---------------------------------------------------------
bool Staff::isTabStaff(int tick) const
bool Staff::isTabStaff(const Fraction& tick) const
{
return staffType(tick)->group() == StaffGroup::TAB;
}
@ -1398,7 +1371,7 @@ bool Staff::isTabStaff(int tick) const
// isDrumStaff
//---------------------------------------------------------
bool Staff::isDrumStaff(int tick) const
bool Staff::isDrumStaff(const Fraction& tick) const
{
return staffType(tick)->group() == StaffGroup::PERCUSSION;
}
@ -1407,7 +1380,7 @@ bool Staff::isDrumStaff(int tick) const
// lines
//---------------------------------------------------------
int Staff::lines(int tick) const
int Staff::lines(const Fraction& tick) const
{
return staffType(tick)->lines();
}
@ -1416,7 +1389,7 @@ int Staff::lines(int tick) const
// setLines
//---------------------------------------------------------
void Staff::setLines(int tick, int val)
void Staff::setLines(const Fraction& tick, int val)
{
staffType(tick)->setLines(val);
}
@ -1426,7 +1399,7 @@ void Staff::setLines(int tick, int val)
// distance between staff lines
//---------------------------------------------------------
qreal Staff::lineDistance(int tick) const
qreal Staff::lineDistance(const Fraction& tick) const
{
return staffType(tick)->lineDistance().val();
}

View file

@ -102,7 +102,6 @@ class Staff final : public ScoreElement {
public:
Staff(Score* score = 0);
~Staff();
void init(const InstrumentTemplate*, const StaffType *staffType, int);
void initFromStaffType(const StaffType* staffType);
void init(const Staff*);
@ -132,36 +131,36 @@ class Staff final : public ScoreElement {
int bracketLevels() const;
ClefList& clefList() { return clefs; }
ClefTypeList clefType(int tick) const;
ClefTypeList clefType(const Fraction&) const;
ClefTypeList defaultClefType() const { return _defaultClefType; }
void setDefaultClefType(const ClefTypeList& l) { _defaultClefType = l; }
ClefType clef(int tick) const;
int nextClefTick(int tick) const;
ClefType clef(const Fraction&) const;
Fraction nextClefTick(const Fraction&) const;
void setClef(Clef*);
void removeClef(Clef*);
void removeClef(const Clef*);
void addTimeSig(TimeSig*);
void removeTimeSig(TimeSig*);
void clearTimeSig();
Fraction timeStretch(int tick) const;
TimeSig* timeSig(int tick) const;
TimeSig* nextTimeSig(int tick) const;
bool isLocalTimeSignature(int tick) { return timeStretch(tick) != Fraction(1, 1); }
Fraction timeStretch(const Fraction&) const;
TimeSig* timeSig(const Fraction&) const;
TimeSig* nextTimeSig(const Fraction&) const;
bool isLocalTimeSignature(const Fraction& tick) { return timeStretch(tick) != Fraction(1, 1); }
const Groups& group(int tick) const;
const Groups& group(const Fraction&) const;
KeyList* keyList() { return &_keys; }
Key key(int tick) const { return keySigEvent(tick).key(); }
KeySigEvent keySigEvent(int tick) const;
int nextKeyTick(int tick) const;
int currentKeyTick(int tick) const;
KeySigEvent prevKey(int tick) const;
void setKey(int tick, KeySigEvent);
void removeKey(int tick);
KeyList* keyList() { return &_keys; }
Key key(const Fraction& tick) const { return keySigEvent(tick).key(); }
KeySigEvent keySigEvent(const Fraction&) const;
Fraction nextKeyTick(const Fraction&) const;
Fraction currentKeyTick(const Fraction&) const;
KeySigEvent prevKey(const Fraction&) const;
void setKey(const Fraction&, KeySigEvent);
void removeKey(const Fraction&);
bool show() const;
bool slashStyle(int tick) const;
bool slashStyle(const Fraction&) const;
bool invisible() const { return _invisible; }
void setInvisible(bool val) { _invisible = val; }
bool cutaway() const { return _cutaway; }
@ -182,57 +181,52 @@ class Staff final : public ScoreElement {
void setBarLineTo(int val) { _barLineTo = val; }
qreal height() const;
int channel(int tick, int voice) const;
int channel(const Fraction&, int voice) const;
void clearChannelList(int voice) { _channelList[voice].clear(); }
void insertIntoChannelList(int voice, int tick, int channelId) { _channelList[voice].insert(tick, channelId); }
void insertIntoChannelList(int voice, const Fraction& tick, int channelId) { _channelList[voice].insert(tick.ticks(), channelId); }
SwingParameters swing(int tick) const;
SwingParameters swing(const Fraction&) const;
void clearSwingList() { _swingList.clear(); }
void insertIntoSwingList(int tick, SwingParameters sp) { _swingList.insert(tick, sp); }
void insertIntoSwingList(const Fraction& tick, SwingParameters sp) { _swingList.insert(tick.ticks(), sp); }
int capo(int tick) const;
int capo(const Fraction&) const;
void clearCapoList() { _capoList.clear(); }
void insertIntoCapoList(int tick, int fretId) { _capoList.insert(tick, fretId); }
void insertIntoCapoList(const Fraction& tick, int fretId) { _capoList.insert(tick.ticks(), fretId); }
//==== staff type
const StaffType* staffType(int tick) const;
const StaffType* constStaffType(int tick) const;
StaffType* staffType(int tick);
StaffType* setStaffType(int tick, const StaffType&);
void staffTypeListChanged(int tick);
//==== staff type helper function
const StaffType* staffType(const Fraction&) const;
const StaffType* constStaffType(const Fraction&) const;
StaffType* staffType(const Fraction&);
StaffType* setStaffType(const Fraction&, const StaffType&);
void staffTypeListChanged(const Fraction&);
bool isPitchedStaff(int tick) const;
bool isTabStaff(int tick) const;
bool isDrumStaff(int tick) const;
bool isPitchedStaff(const Fraction&) const;
bool isTabStaff(const Fraction&) const;
bool isDrumStaff(const Fraction&) const;
int lines(int tick) const;
void setLines(int tick, int lines);
qreal lineDistance(int tick) const;
int lines(const Fraction&) const;
void setLines(const Fraction&, int lines);
qreal lineDistance(const Fraction&) const;
void setSlashStyle(int tick, bool val);
int middleLine(int tick) const;
int bottomLine(int tick) const;
void setSlashStyle(const Fraction&, bool val);
int middleLine(const Fraction&) const;
int bottomLine(const Fraction&) const;
qreal userMag(int tick) const;
void setUserMag(int tick, qreal m);
qreal mag(int tick) const;
bool small(int tick) const;
void setSmall(int tick, bool val);
qreal spatium(int tick) const;
qreal userMag(const Fraction&) const;
void setUserMag(const Fraction&, qreal m);
qreal mag(const Fraction&) const;
bool small(const Fraction&) const;
void setSmall(const Fraction&, bool val);
qreal spatium(const Fraction&) const;
//===========
VeloList& velocities() { return _velocities; }
PitchList& pitchOffsets() { return _pitchOffsets; }
int pitchOffset(int tick) { return _pitchOffsets.pitchOffset(tick); }
int pitchOffset(const Fraction& tick) { return _pitchOffsets.pitchOffset(tick.ticks()); }
void updateOttava();
// LinkedStaves* linkedStaves() const { return _linkedStaves; }
// void setLinkedStaves(LinkedStaves* l) { _linkedStaves = l; }
QList<Staff*> staffList() const;
// void linkTo(Staff* staff);
// bool isLinked(Staff* staff);
// void unlink(Staff* staff);
bool primaryStaff() const;
qreal userDist() const { return _userDist; }
@ -240,12 +234,12 @@ class Staff final : public ScoreElement {
void spatiumChanged(qreal /*oldValue*/, qreal /*newValue*/);
bool genKeySig();
bool showLedgerLines(int tick) const;
bool showLedgerLines(const Fraction&) const;
QColor color() const { return _color; }
void setColor(const QColor& val) { _color = val; }
void undoSetColor(const QColor& val);
void insertTime(int tick, int len);
void insertTime(const Fraction&, const Fraction& len);
virtual QVariant getProperty(Pid) const override;
virtual bool setProperty(Pid, const QVariant&) override;

View file

@ -20,12 +20,12 @@ namespace Ms {
// staffType
//---------------------------------------------------------
const StaffType& StaffTypeList::staffType(int tick) const
const StaffType& StaffTypeList::staffType(const Fraction& tick) const
{
static const StaffType st;
if (empty())
return st;
auto i = upper_bound(tick);
auto i = upper_bound(tick.ticks());
if (i == begin())
return st;
return (--i)->second;
@ -35,17 +35,11 @@ const StaffType& StaffTypeList::staffType(int tick) const
// staffType
//---------------------------------------------------------
StaffType& StaffTypeList::staffType(int tick)
StaffType& StaffTypeList::staffType(const Fraction& tick)
{
// static StaffType st;
// if (empty())
// return st;
Q_ASSERT(!empty());
auto i = upper_bound(tick);
auto i = upper_bound(tick.ticks());
Q_ASSERT(i != begin());
// if (i == begin())
// return st;
return (--i)->second;
}
@ -53,13 +47,13 @@ StaffType& StaffTypeList::staffType(int tick)
// setStaffType
//---------------------------------------------------------
StaffType* StaffTypeList::setStaffType(int tick, const StaffType& st)
StaffType* StaffTypeList::setStaffType(const Fraction& tick, const StaffType& st)
{
Q_ASSERT(tick >= 0);
auto i = find(tick);
Q_ASSERT(tick >= Fraction(0,1));
auto i = find(tick.ticks());
StaffType* nst;
if (i == end()) {
auto k = insert(std::pair<int, StaffType>(tick, st));
auto k = insert(std::pair<int, StaffType>(tick.ticks(), st));
nst = &(k.first->second);
}
else {

View file

@ -29,9 +29,9 @@ class StaffTypeList : public std::map<int, StaffType> {
public:
StaffTypeList() {}
StaffType& staffType(int tick);
const StaffType& staffType(int tick) const;
StaffType* setStaffType(int tick, const StaffType&);
StaffType& staffType(const Fraction&);
const StaffType& staffType(const Fraction&) const;
StaffType* setStaffType(const Fraction&, const StaffType&);
void read(XmlReader&, Score*);
};

View file

@ -88,8 +88,8 @@ void Stem::layout()
const Staff* stf = staff();
if (chord()) {
setMag(chord()->mag());
int tick = chord()->tick();
const StaffType* st = stf ? stf->staffType(tick) : nullptr;
Fraction tick = chord()->tick();
const StaffType* st = stf ? stf->staffType(tick) : 0;
if (st && st->isTabStaff() ) { // TAB staves
if (st->stemThrough()) {
// if stems through staves, gets Y pos. of stem-side note relative to chord other side

Some files were not shown because too many files have changed in this diff Show more