pull *all* patches from the experimental branch
authormirabilos <tg@debian.org>
Fri, 14 Dec 2018 03:20:57 +0000 (04:20 +0100)
committermirabilos <mirabilos@evolvis.org>
Fri, 14 Dec 2018 03:20:57 +0000 (04:20 +0100)
debian/patches/experiments/lyrics-hyphen-max-8sp.diff [new file with mode: 0644]
debian/patches/experiments/revert-restriking-patch.diff [new file with mode: 0644]
debian/patches/series
debian/patches/upstream/lyrics-hyphen-syllable-closer.diff [new file with mode: 0644]

diff --git a/debian/patches/experiments/lyrics-hyphen-max-8sp.diff b/debian/patches/experiments/lyrics-hyphen-max-8sp.diff
new file mode 100644 (file)
index 0000000..c685e7e
--- /dev/null
@@ -0,0 +1,16 @@
+Description: Halve default lyrics hyphenation step
+Author: mirabilos <m@mirbsd.org>
+Forwarded: not-needed
+Justification: made configurable in 3.x
+
+--- a/libmscore/lyrics.h
++++ b/libmscore/lyrics.h
+@@ -60,7 +60,7 @@ class Lyrics : public Text {
+       // metrics for dashes and melisma; all in sp. units:
+       static constexpr qreal  MELISMA_DEFAULT_LINE_THICKNESS      = 0.10;     // for melisma line only;
+       static constexpr qreal  MELISMA_DEFAULT_PAD                 = 0.10;     // the empty space before a melisma line
+-      static constexpr qreal  LYRICS_DASH_DEFAULT_STEP            = 16.0;     // the max. distance between dashes
++      static constexpr qreal  LYRICS_DASH_DEFAULT_STEP            = 8.00;     // the max. distance between dashes
+       static constexpr qreal  LYRICS_DASH_DEFAULT_PAD             = 0.05;     // the min. empty space before and after a dash
+       static constexpr qreal  LYRICS_DASH_MIN_LENGTH              = 0.25;     // below this length, the dash is skipped
+       static constexpr qreal  LYRICS_WORD_MIN_DISTANCE            = 0.33;     // min. distance between lyrics from different words
diff --git a/debian/patches/experiments/revert-restriking-patch.diff b/debian/patches/experiments/revert-restriking-patch.diff
new file mode 100644 (file)
index 0000000..4334673
--- /dev/null
@@ -0,0 +1,288 @@
+Description: Revert the unison restriking patch
+ The restriking patch went into 2.2 (and thus 2.2.1, 2.3, 2.3.1)
+ while it is not unquestioned. It was never meant to last; MIDI
+ channel assignment to individual voices must be made user-friendly,
+ but then, a reversal was intended by upstream. This diff implements
+ said reversal, in preparation of those other (UI, mostly) changes.
+Author: mirabilos <m@mirbsd.org>
+Bug: https://musescore.org/en/node/12971
+Forwarded: https://github.com/musescore/MuseScore/pull/3797
+ except reversal of commit d5a81add16497f9b4b7fac5717ea005c31dcc1cf
+
+--- a/libmscore/rendermidi.cpp
++++ b/libmscore/rendermidi.cpp
+@@ -166,7 +166,7 @@ static void playNote(EventMap* events, c
+       NPlayEvent ev(ME_NOTEON, channel, pitch, velo);
+       ev.setOriginatingStaff(staffIdx);
+       ev.setTuning(note->tuning());
+-      ev.setNote(note);
++      ev.notes.push_back(note);
+       if (offTime < onTime)
+             offTime = onTime;
+       events->insert(std::pair<int, NPlayEvent>(onTime, ev));
+--- a/mscore/exportaudio.cpp
++++ b/mscore/exportaudio.cpp
+@@ -23,8 +23,6 @@
+ #include "libmscore/score.h"
+ #include "libmscore/note.h"
+ #include "libmscore/part.h"
+-#include "libmscore/staff.h"
+-#include "libmscore/chord.h"
+ #include "libmscore/mscore.h"
+ #include "synthesizer/msynthesizer.h"
+ #include "musescore.h"
+@@ -133,35 +131,13 @@ bool MuseScore::saveAudio(Score* score,
+                       playTime  += n;
+                       frames    -= n;
+-                      const NPlayEvent& event = playPos->second;
+-                      if (event.isChannelEvent()) {
+-                              int channelIdx = event.channel();
+-                              Channel* c = score->midiMapping(channelIdx)->articulation;
+-                              int type = event.type();
+-                              int syntiIndex = synti->index(c->synti);
+-                              if (type == ME_NOTEON) {
+-                                    bool mute;
+-                                    const Note* note = event.note();
+-                                    if (note) {
+-                                          Instrument* instr = note->staff()->part()->instrument(note->chord()->tick());
+-                                          const Channel* a = instr->channel(note->subchannel());
+-                                          mute = a->mute || a->soloMute;
+-                                          }
+-                                    else
+-                                          mute = false;
+-
+-                                    if (!mute) {
+-                                          if (event.discard()) { // ignore noteoff but restrike noteon
+-                                                if (event.velo() > 0)
+-                                                      synti->play(NPlayEvent(ME_NOTEON, event.channel(), event.pitch(), 0), syntiIndex);
+-                                                else
+-                                                      continue;
+-                                                }
+-                                          synti->play(event, syntiIndex);
+-                                          }
+-                                    }
+-                              else if (type == ME_CONTROLLER || type == ME_PITCHBEND)
+-                                    synti->play(event, syntiIndex);
++                      const NPlayEvent& e = playPos->second;
++                      if (e.isChannelEvent()) {
++                            int channelIdx = e.channel();
++                            Channel* c = score->midiMapping(channelIdx)->articulation;
++                            if (!c->mute) {
++                                  synti->play(e, synti->index(c->synti));
++                                  }
+                             }
+                       }
+                 if (frames) {
+--- a/mscore/exportmidi.cpp
++++ b/mscore/exportmidi.cpp
+@@ -289,18 +289,9 @@ bool ExportMidi::write(const QString& na
+                         for (auto i = events.begin(); i != events.end(); ++i) {
+                               const NPlayEvent& event = i->second;
+-                              if (event.discard() == staffIdx + 1 && event.velo() > 0)
+-                                    // turn note off so we can restrike it in another track
+-                                    track.insert(pauseMap.addPauseTicks(i->first), MidiEvent(ME_NOTEON, channel,
+-                                                                     event.pitch(), 0));
+-
+                               if (event.getOriginatingStaff() != staffIdx)
+                                     continue;
+-                              if (event.discard() && event.velo() == 0)
+-                                    // ignore noteoff but restrike noteon
+-                                    continue;
+-
+                               char eventPort    = cs->midiPort(event.channel());
+                               char eventChannel = cs->midiChannel(event.channel());
+                               if (port != eventPort || channel != eventChannel)
+--- a/mscore/musescore.cpp
++++ b/mscore/musescore.cpp
+@@ -5657,36 +5657,14 @@ bool MuseScore::saveMp3(Score* score, co
+                               playTime  += n;
+                               frames    -= n;
+                               }
+-                        const NPlayEvent& event = playPos->second;
+-                        if (event.isChannelEvent()) {
+-                              int channelIdx = event.channel();
++                        const NPlayEvent& e = playPos->second;
++                        if (e.isChannelEvent()) {
++                              int channelIdx = e.channel();
+                               Channel* c = score->midiMapping(channelIdx)->articulation;
+-                              int type = event.type();
+-                              int syntiIndex = synti->index(c->synti);
+-                              if (type == ME_NOTEON) {
+-                                    bool mute;
+-                                    const Note* note = event.note();
+-                                    if (note) {
+-                                          Instrument* instr = note->staff()->part()->instrument(note->chord()->tick());
+-                                          const Channel* a = instr->channel(note->subchannel());
+-                                          mute = a->mute || a->soloMute;
+-                                          }
+-                                    else
+-                                          mute = false;
+-
+-                                    if (!mute) {
+-                                          if (event.discard()) { // ignore noteoff but restrike noteon
+-                                                if (event.velo() > 0)
+-                                                      synti->play(NPlayEvent(ME_NOTEON, event.channel(), event.pitch(), 0), syntiIndex);
+-                                                else
+-                                                      continue;
+-                                                }
+-                                          synti->play(event, syntiIndex);
+-                                          }
++                              if (!c->mute) {
++                                    synti->play(e, synti->index(c->synti));
+                                     }
+-                              else if (type == ME_CONTROLLER || type == ME_PITCHBEND)
+-                                    synti->play(event, syntiIndex);
+-                            }
++                              }
+                         }
+                   if (frames) {
+                         float bu[frames * 2];
+--- a/mscore/seq.cpp
++++ b/mscore/seq.cpp
+@@ -512,8 +512,9 @@ void Seq::playEvent(const NPlayEvent& ev
+       int type = event.type();
+       if (type == ME_NOTEON) {
+             bool mute;
+-            const Note* note = event.note();
+-            if (note) {
++
++            if (!event.notes.empty()) {
++                  const Note* note = event.notes[0];
+                   Instrument* instr = note->staff()->part()->instrument(note->chord()->tick());
+                   const Channel* a = instr->channel(note->subchannel());
+                   mute = a->mute || a->soloMute;
+@@ -521,15 +522,8 @@ void Seq::playEvent(const NPlayEvent& ev
+             else
+                   mute = false;
+-            if (!mute) {
+-                  if (event.discard()) { // ignore noteoff but restrike noteon
+-                        if (event.velo() > 0)
+-                              putEvent(NPlayEvent(ME_NOTEON, event.channel(), event.pitch(), 0) ,framePos);
+-                        else
+-                              return;
+-                        }
++            if (!mute)
+                   putEvent(event, framePos);
+-                  }
+             }
+       else if (type == ME_CONTROLLER || type == ME_PITCHBEND)
+             putEvent(event, framePos);
+@@ -1494,20 +1488,18 @@ void Seq::heartBeatTimeout()
+                         break;
+             const NPlayEvent& n = guiPos->second;
+             if (n.type() == ME_NOTEON) {
+-                  const Note* note1 = n.note();
+-                  if (n.velo()) {
++                  for (auto it = n.notes.cbegin(); it != n.notes.cend(); ++it) {
++                        const Note* note1 = *it;
+                         while (note1) {
+-                              note1->setMark(true);
+-                              markedNotes.append(note1);
+-                              r |= note1->canvasBoundingRect();
+-                              note1 = note1->tieFor() ? note1->tieFor()->endNote() : 0;
+-                              }
+-                        }
+-                  else {
+-                        while (note1) {
+-                              note1->setMark(false);
++                              if (n.velo()) {
++                                    note1->setMark(true);
++                                    markedNotes.append(note1);
++                                    }
++                              else {
++                                    note1->setMark(false);
++                                    markedNotes.removeOne(note1);
++                                    }
+                               r |= note1->canvasBoundingRect();
+-                              markedNotes.removeOne(note1);
+                               note1 = note1->tieFor() ? note1->tieFor()->endNote() : 0;
+                               }
+                         }
+--- a/mtest/libmscore/midi/tst_midi.cpp
++++ b/mtest/libmscore/midi/tst_midi.cpp
+@@ -378,7 +378,6 @@ void TestMidi::events()
+       QTextStream out(&filehandler);
+       multimap<int, NPlayEvent> ::iterator iter;
+       for (auto iter = events.begin(); iter!= events.end(); ++iter){
+-            if (iter->second.discard()) continue;
+             out << qSetFieldWidth(5) << "Tick  =  ";
+             out << qSetFieldWidth(5) << iter->first;
+             out << qSetFieldWidth(5) << "   Type  = ";
+--- a/synthesizer/event.cpp
++++ b/synthesizer/event.cpp
+@@ -390,28 +390,37 @@ void EventMap::fixupMIDI()
+       auto it = begin();
+       while (it != end()) {
++            bool discard = false;
++
+             /* ME_NOTEOFF is never emitted, no need to check for it */
+             if (it->second.type() == ME_NOTEON) {
+                   unsigned short np = info[it->second.channel()].nowPlaying[it->second.pitch()];
+                   if (it->second.velo() == 0) {
+                         /* already off (should not happen) or still playing? */
+                         if (np == 0 || --np > 0)
+-                              it->second.setDiscard(1);
++                              discard = true;
+                         else {
+                               /* hoist NOTEOFF to same track as NOTEON */
+                               it->second.setOriginatingStaff(info[it->second.channel()].event[it->second.pitch()]->getOriginatingStaff());
++                              /* copy linked Notes */
++                              it->second.notes = info[it->second.channel()].event[it->second.pitch()]->notes;
+                               }
+                         }
+-                  else {
+-                        if (++np > 1)
+-                              /* restrike, possibly on different track */
+-                              it->second.setDiscard(info[it->second.channel()].event[it->second.pitch()]->getOriginatingStaff() + 1);
+-                        info[it->second.channel()].event[it->second.pitch()] = &(it->second);
++                  else if (++np > 1) {
++                        /* already playing */
++                        discard = true;
++                        /* carry over the corresponding score notes */
++                        info[it->second.channel()].event[it->second.pitch()]->notes.insert(info[it->second.channel()].event[it->second.pitch()]->notes.end(), it->second.notes.begin(), it->second.notes.end());
+                         }
++                  else
++                        info[it->second.channel()].event[it->second.pitch()] = &(it->second);
+                   info[it->second.channel()].nowPlaying[it->second.pitch()] = np;
+                   }
+-            ++it;
++            if (discard)
++                  it = erase(it);
++            else
++                  ++it;
+             }
+             free((void *)info);
+--- a/synthesizer/event.h
++++ b/synthesizer/event.h
+@@ -234,9 +234,7 @@ class PlayEvent : public MidiCoreEvent {
+ //---------------------------------------------------------
+ class NPlayEvent : public PlayEvent {
+-      const Note* _note = 0;
+       int _origin = -1;
+-      int _discard = 0;
+    public:
+       NPlayEvent() : PlayEvent() {}
+@@ -245,13 +243,10 @@ class NPlayEvent : public PlayEvent {
+       NPlayEvent(const MidiCoreEvent& e) : PlayEvent(e) {}
+       NPlayEvent(BeatType beatType);
+-      const Note* note() const       { return _note; }
+-      void setNote(const Note* v)    { _note = v; }
++      std::vector<const Note*> notes;
+       int getOriginatingStaff() const { return _origin; }
+       void setOriginatingStaff(int i) { _origin = i; }
+-      void setDiscard(int d) { _discard = d; }
+-      int discard() const { return _discard; }
+       };
+ //---------------------------------------------------------
index 825eb57..41ca264 100644 (file)
@@ -5,6 +5,9 @@ debian-specific/debundle-openssl.diff
 debian-specific/testsuite.diff
 upstream/save-locale-dependent-preferences.diff
 upstream/mscx-reproducible-save-chordlist.diff
+upstream/lyrics-hyphen-syllable-closer.diff
 upstream/mtest-fix-freetype-includes.diff
 experiments/better-batch-convert.diff
 upstream/new-manpage.diff
+experiments/lyrics-hyphen-max-8sp.diff
+experiments/revert-restriking-patch.diff
diff --git a/debian/patches/upstream/lyrics-hyphen-syllable-closer.diff b/debian/patches/upstream/lyrics-hyphen-syllable-closer.diff
new file mode 100644 (file)
index 0000000..533f98d
--- /dev/null
@@ -0,0 +1,42 @@
+Description: Draw the first and last hyphen closer to the syllable
+Author: mirabilos <m@mirbsd.org>
+Applied-Upstream: master, commit:2c78cd4
+
+--- a/libmscore/lyrics.cpp
++++ b/libmscore/lyrics.cpp
+@@ -22,7 +22,7 @@ namespace Ms {
+ // some useful values:
+ static const qreal      HALF                                = 0.5;
+-static const qreal      TWICE                               = 2.0;
++static const qreal      MINTWODASHES                        = 1.5;
+ //---------------------------------------------------------
+ //   searchNextLyrics
+@@ -881,13 +881,13 @@ void LyricsLineSegment::layout()
+                   else                                                        //   if within system
+                         _numOfDashes = 0;                                     //     draw no dash
+                   }
+-            else if (len < (Lyrics::LYRICS_DASH_DEFAULT_STEP * TWICE * sp)) { // if no room for two dashes
++            else if (len < (Lyrics::LYRICS_DASH_DEFAULT_STEP * MINTWODASHES * sp)) { // if no room for two dashes
+                   _numOfDashes = 1;                                           //    draw one dash
+                   if (_dashLength > len)                                      // if no room for a full dash
+                         _dashLength = len;                                    //    shorten it
+                   }
+             else
+-                  _numOfDashes = len / (Lyrics::LYRICS_DASH_DEFAULT_STEP * sp);// draw several dashes
++                  _numOfDashes = len / (Lyrics::LYRICS_DASH_DEFAULT_STEP * sp) + 1;// draw several dashes
+             }
+       // set bounding box
+@@ -914,8 +914,8 @@ void LyricsLineSegment::draw(QPainter* p
+       if (lyricsLine()->lyrics()->ticks() > 0)           // melisma
+             painter->drawLine(QPointF(), pos2());
+       else {                                          // dash(es)
+-            qreal step  = pos2().x() / (_numOfDashes+1);
+-            qreal x     = step - _dashLength * HALF;
++            qreal step  = pos2().x() / _numOfDashes;
++            qreal x     = step * HALF - _dashLength * HALF;
+             for (int i = 0; i < _numOfDashes; i++, x += step)
+                   painter->drawLine(QPointF(x, 0.0), QPointF(x + _dashLength, 0.0));
+             }