Skip to content

Commit

Permalink
fix #46401: breath segments placed too early
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcSabatella committed Feb 7, 2015
1 parent b9e10df commit d79bd3a
Show file tree
Hide file tree
Showing 26 changed files with 895 additions and 69 deletions.
13 changes: 11 additions & 2 deletions libmscore/chordrest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -773,11 +773,20 @@ Element* ChordRest::drop(const DropData& data)
case Element::Type::BREATH:
{
Breath* b = static_cast<Breath*>(e);
b->setTrack(staffIdx() * VOICES);
int track = staffIdx() * VOICES;
b->setTrack(track);

// find start tick of next note in staff
#if 0
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();
#endif

// TODO: insert automatically in all staves?

Segment* seg = m->undoGetSegment(Segment::Type::Breath, tick());
Segment* seg = m->undoGetSegment(Segment::Type::Breath, bt);
b->setParent(seg);
score()->undoAddElement(b);
}
Expand Down
35 changes: 23 additions & 12 deletions libmscore/measure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -817,28 +817,24 @@ void Measure::add(Element* el)
;
if (s) {
if (st == Segment::Type::ChordRest) {
// add ChordRest segment after all other segments with same tick
// except EndBarLine
while (s && s->segmentType() != st && s->tick() == t) {
if (s->segmentType() == Segment::Type::EndBarLine
|| s->segmentType() == Segment::Type::Breath // place chord _before_ breath
) {
if (s->segmentType() == Segment::Type::EndBarLine) {
break;
}
s = s->next();
}
}
else {
// use order of segments in segment.h
if (s && s->tick() == t) {
while (s && s->segmentType() <= st) {
if (s->next() && s->next()->tick() != t)
break;
s = s->next();
}
}
//
// place breath _after_ chord
//
if (s && st == Segment::Type::Breath)
s = s->next();
}
}
seg->setParent(this);
Expand Down Expand Up @@ -1941,10 +1937,25 @@ void Measure::read(XmlReader& e, int staffIdx)
breath->setTrack(e.track());
int tick = e.tick();
breath->read(e);
if (e.tick() < tick)
tick = e.tick(); // use our own tick if we explicitly reset to earlier position
else
tick = lastTick; // otherwise use last tick (of previous tick, chord, or rest tag)
if (score()->mscVersion() < 205) {
// 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;
if (e.tick() < tick)
prevTick = e.tick(); // use our own tick if we explicitly reset to earlier position
else
prevTick = lastTick; // otherwise use tick of previous tick/chord/rest tag
// find segment
Segment* prev = findSegment(Segment::Type::ChordRest, prevTick);
if (prev) {
// find chordrest
ChordRest* lastCR = static_cast<ChordRest*>(prev->element(e.track()));
if (lastCR)
tick = prevTick + lastCR->actualTicks();
}
}
segment = getSegment(Segment::Type::Breath, tick);
segment->add(breath);
}
Expand Down
5 changes: 3 additions & 2 deletions libmscore/mscore.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@

namespace Ms {

#define MSC_VERSION "2.04"
static const int MSCVERSION = 204;
#define MSC_VERSION "2.05"
static const int MSCVERSION = 205;

// History:
// 1.3 added staff->_barLineSpan
Expand Down Expand Up @@ -50,6 +50,7 @@ static const int MSCVERSION = 204;
// 2.02 save instrumentId, note slashes
// 2.03 save Box topGap, bottomGap in spatium units
// 2.04 added hideSystemBarLine flag to Staff
// 2.05 breath segment changed to use tick of following chord rather than preceding chord



Expand Down
9 changes: 1 addition & 8 deletions libmscore/score.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -511,19 +511,12 @@ void Score::fixTicks()
if (s->segmentType() == Segment::Type::Breath) {
qreal length = 0.0;
int tick = s->tick();
// find breath elements
// find longest pause
for (int i = 0, n = ntracks(); i < n; ++i) {
Element* e = s->element(i);
if (e && e->type() == Element::Type::BREATH) {
Breath* b = static_cast<Breath*>(e);
length = qMax(length, b->pause());
// find start tick of next note
// currently, breaths are always added in voice 0
Segment* next = s->nextCR(i);
if (next)
tick = qMax(tick, next->tick());
else
tick = lastSegment()->tick();
}
}
if (length != 0.0)
Expand Down
4 changes: 2 additions & 2 deletions libmscore/segment.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ class Segment : public Element {
TimeSig = 0x8,
StartRepeatBarLine = 0x10,
BarLine = 0x20,
ChordRest = 0x40,
Breath = 0x80,
Breath = 0x40,
ChordRest = 0x80,
EndBarLine = 0x100,
TimeSigAnnounce = 0x200,
KeySigAnnounce = 0x400,
Expand Down
3 changes: 3 additions & 0 deletions libmscore/undo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1267,6 +1267,9 @@ void Score::undoAddElement(Element* element)
Breath* breath = static_cast<Breath*>(element);
int tick = breath->segment()->tick();
Measure* m = score->tick2measure(tick);
// breath appears before barline
if (m->tick() == tick)
m = m->prevMeasure();
Segment* seg = m->undoGetSegment(Segment::Type::Breath, tick);
Breath* nbreath = static_cast<Breath*>(ne);
int ntrack = staffIdx * VOICES + nbreath->voice();
Expand Down
2 changes: 1 addition & 1 deletion mscore/capella.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ static void processBasicDrawObj(QList<BasicDrawObj*> objects, Segment* s, int tr
Breath* b = new Breath(score);
b->setTrack(track);
b->setBreathType(3);
Segment* seg = s->measure()->getSegment(Segment::Type::Breath, s->tick());
Segment* seg = s->measure()->getSegment(Segment::Type::Breath, s->tick() + cr ? cr->actualTicks() : 0);
seg->add(b);
}
break;
Expand Down
14 changes: 4 additions & 10 deletions mscore/exportxml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1685,12 +1685,9 @@ void ExportMusicXml::wavyLineStartStop(Chord* chord, Notations& notations, Ornam

static Breath* hasBreathMark(Chord* ch)
{
Segment* s = ch->segment();
s = s->next1();
Breath* b = 0;
if (s && s->segmentType() == Segment::Type::Breath)
b = static_cast<Breath*>(s->element(ch->track()));
return b;
int tick = ch->tick() + ch->actualTicks();
Segment* s = ch->measure()->findSegment(Segment::Type::Breath, tick);
return s ? static_cast<Breath*>(s->element(ch->track())) : 0;
}

//---------------------------------------------------------
Expand Down Expand Up @@ -4698,12 +4695,9 @@ void ExportMusicXml::write(QIODevice* dev)
continue;

// generate backup or forward to the start time of the element
// but not for breath, which has the same start time as the
// previous note, while tick is already at the end of that note
if (tick != seg->tick()) {
attr.doAttr(xml, false);
if (el->type() != Element::Type::BREATH)
moveToTick(seg->tick());
moveToTick(seg->tick());
}

// handle annotations and spanners (directions attached to this note or rest)
Expand Down
3 changes: 2 additions & 1 deletion mscore/importove.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1750,11 +1750,12 @@ void OveToMScore::convertArticulation(
case OVE::ArticulationType::Pause :{
Breath* b = new Breath(score_);
b->setTrack(track);
Segment* seg = measure->getSegment(Segment::Type::Breath, absTick);
Segment* seg = measure->getSegment(Segment::Type::Breath, absTick + cr ? cr->actualTicks() : 0);
seg->add(b);
break;
}
case OVE::ArticulationType::Grand_Pause :{
// TODO?
break;
}
case OVE::ArticulationType::Up_Bow :{
Expand Down
2 changes: 1 addition & 1 deletion mscore/importxml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5085,7 +5085,7 @@ void MusicXml::xmlNotations(Note* note, ChordRest* cr, int trk, int tick, int ti
// b->setTrack(trk + voice); TODO check next line
b->setTrack(track);
b->setBreathType(breath);
Segment* seg = measure->getSegment(Segment::Type::Breath, tick);
Segment* seg = measure->getSegment(Segment::Type::Breath, tick + ticks);
seg->add(b);
}

Expand Down
2 changes: 1 addition & 1 deletion mtest/libmscore/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#=============================================================================

subdirs(
album barline beam chordsymbol clef clef_courtesy compat concertpitch copypaste
album barline beam breath chordsymbol clef clef_courtesy compat concertpitch copypaste
copypastesymbollist dynamic element hairpin instrumentchange join keysig layout parts measure midi
note plugins repeat selectionfilter selectionrangedelete split splitstaff timesig tools transpose tuplet text
)
Expand Down
17 changes: 17 additions & 0 deletions mtest/libmscore/breath/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#=============================================================================
# MuseScore
# Music Composition & Notation
# $Id:$
#
# Copyright (C) 2011 Werner Schweer
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2
# as published by the Free Software Foundation and appearing in
# the file LICENSE.GPL
#=============================================================================

set(TARGET tst_breath)

include(${PROJECT_SOURCE_DIR}/mtest/cmake.inc)

Loading

0 comments on commit d79bd3a

Please sign in to comment.