1 //=============================================================================
2 // MuseScore
3 // Music Composition & Notation
4 //
5 // Copyright (C) 2013 Werner Schweer
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License version 2
9 // as published by the Free Software Foundation and appearing in
10 // the file LICENCE.GPL
11 //=============================================================================
12
13 #include "importmidi_tie.h"
14 #include "libmscore/element.h"
15 #include "libmscore/segment.h"
16 #include "libmscore/chordrest.h"
17 #include "libmscore/chord.h"
18 #include "libmscore/note.h"
19
20 #ifdef QT_DEBUG
21 #include "libmscore/staff.h"
22 #include "libmscore/score.h"
23 #include "libmscore/measure.h"
24 #endif
25
26
27 namespace Ms {
28 namespace MidiTie {
29
30
isTied(const Segment * seg,int strack,int voice,Ms::Tie * (Note::* tieFunc)()const)31 bool isTied(const Segment *seg, int strack, int voice,
32 Ms::Tie*(Note::*tieFunc)() const)
33 {
34 ChordRest *cr = static_cast<ChordRest *>(seg->element(strack + voice));
35 if (cr && cr->isChord()) {
36 Chord *chord = toChord(cr);
37 const auto ¬es = chord->notes();
38 for (const Note *note: notes) {
39 if ((note->*tieFunc)())
40 return true;
41 }
42 }
43 return false;
44 }
45
isTiedFor(const Segment * seg,int strack,int voice)46 bool isTiedFor(const Segment *seg, int strack, int voice)
47 {
48 return isTied(seg, strack, voice, &Note::tieFor);
49 }
50
isTiedBack(const Segment * seg,int strack,int voice)51 bool isTiedBack(const Segment *seg, int strack, int voice)
52 {
53 return isTied(seg, strack, voice, &Note::tieBack);
54 }
55
56
addSeg(const Segment * seg,int strack)57 void TieStateMachine::addSeg(const Segment *seg, int strack)
58 {
59 bool isChord = false;
60 for (int voice = 0; voice < VOICES; ++voice) {
61 ChordRest *cr = static_cast<ChordRest *>(seg->element(strack + voice));
62 if (!cr || !cr->isChord())
63 continue;
64 if (!isChord)
65 isChord = true;
66
67 bool tiedFor = isTiedFor(seg, strack, voice);
68 bool tiedBack = isTiedBack(seg, strack, voice);
69
70 if (tiedFor && !tiedBack)
71 tiedVoices.insert(voice);
72 else if (!tiedFor && tiedBack)
73 tiedVoices.erase(voice);
74 }
75 if (!isChord)
76 return;
77
78 if (tiedVoices.empty() && (state_ == State::TIED_FOR
79 || state_ == State::TIED_BOTH)) {
80 state_ = State::TIED_BACK;
81 }
82 else if (tiedVoices.empty() && state_ == State::TIED_BACK) {
83 state_ = State::UNTIED;
84 }
85 else if (!tiedVoices.empty() && (state_ == State::TIED_BACK
86 || state_ == State::UNTIED)) {
87 state_ = State::TIED_FOR;
88 }
89 else if (!tiedVoices.empty() && state_ == State::TIED_FOR) {
90 state_ = State::TIED_BOTH;
91 }
92 }
93
94
95 #ifdef QT_DEBUG
96
printInconsistentTieLocation(int measureIndex,int staffIndex)97 void printInconsistentTieLocation(int measureIndex, int staffIndex)
98 {
99 qDebug() << "Ties are inconsistent; measure number (from 1):"
100 << measureIndex + 1
101 << ", staff index (from 0):" << staffIndex;
102 }
103
areTiesConsistent(const Staff * staff)104 bool areTiesConsistent(const Staff *staff)
105 {
106 const int strack = staff->idx() * VOICES;
107
108 for (int voice = 0; voice < VOICES; ++voice) {
109 bool isTie = false;
110 for (Segment *seg = staff->score()->firstSegment(SegmentType::All); seg; seg = seg->next1()) {
111 if (seg->segmentType() == SegmentType::ChordRest) {
112 ChordRest *cr = static_cast<ChordRest *>(seg->element(strack + voice));
113
114 if (cr && cr->isRest() && isTie) {
115 printInconsistentTieLocation(seg->measure()->no(), staff->idx());
116 return false;
117 }
118 if (isTiedBack(seg, strack, voice)) {
119 if (!isTie) {
120 printInconsistentTieLocation(seg->measure()->no(), staff->idx());
121 return false;
122 }
123 isTie = false;
124 }
125 if (isTiedFor(seg, strack, voice)) {
126 if (isTie) {
127 printInconsistentTieLocation(seg->measure()->no(), staff->idx());
128 return false;
129 }
130 isTie = true;
131 }
132 }
133 }
134 if (isTie)
135 return false;
136 }
137 return true;
138 }
139
140 #endif
141
142
143 } // namespace MidiTie
144 } // namespace Ms
145
146