Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-Studio-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2021 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : */
22 : #include "masterscore.h"
23 :
24 : #include "io/buffer.h"
25 :
26 : #include "compat/writescorehook.h"
27 : #include "editing/editautomationpoints.h"
28 : #include "editing/editkeysig.h"
29 : #include "editing/editmeasures.h"
30 : #include "editing/transaction/transaction.h"
31 : #include "editing/transaction/undostack.h"
32 : #include "rw/mscloader.h"
33 : #include "rw/xmlreader.h"
34 : #include "rw/rwregister.h"
35 :
36 : #include "style/defaultstyle.h"
37 :
38 : #include "engravingproject.h"
39 :
40 : #include "automation/internal/scoreautomationcontroller.h"
41 :
42 : #include "barline.h"
43 : #include "excerpt.h"
44 : #include "factory.h"
45 : #include "clef.h"
46 : #include "key.h"
47 : #include "keysig.h"
48 : #include "part.h"
49 : #include "repeatlist.h"
50 : #include "rest.h"
51 : #include "sig.h"
52 : #include "staff.h"
53 : #include "timesig.h"
54 : #include "linkedobjects.h"
55 :
56 : #include "log.h"
57 :
58 : using namespace mu;
59 : using namespace muse::io;
60 : using namespace mu::engraving;
61 :
62 : //---------------------------------------------------------
63 : // MasterScore
64 : //---------------------------------------------------------
65 :
66 2169 : MasterScore::MasterScore(const muse::modularity::ContextPtr& iocCtx, std::weak_ptr<engraving::EngravingProject> project)
67 4338 : : Score(iocCtx)
68 : {
69 2169 : m_project = project;
70 2169 : m_transactionManager = std::make_unique<TransactionManager>(this);
71 2169 : m_undoStack = new UndoStack();
72 2169 : m_sigmap = new TimeSigMap();
73 2169 : m_automationController = new ScoreAutomationController();
74 2169 : m_expandedRepeatList = new RepeatList(this);
75 2169 : m_nonExpandedRepeatList = new RepeatList(this);
76 2169 : setMasterScore(this);
77 :
78 : #if defined(Q_OS_WIN)
79 : metaTags().insert({ u"platform", u"Microsoft Windows" });
80 : #elif defined(Q_OS_MAC)
81 : metaTags().insert({ u"platform", u"Apple Macintosh" });
82 : #elif defined(Q_OS_LINUX)
83 2169 : metaTags().insert({ u"platform", u"Linux" });
84 : #else
85 : metaTags().insert({ u"platform", u"Unknown" });
86 : #endif
87 2169 : metaTags().insert({ u"movementNumber", u"" });
88 2169 : metaTags().insert({ u"movementTitle", u"" });
89 2169 : metaTags().insert({ u"workNumber", u"" });
90 2169 : metaTags().insert({ u"workTitle", u"" });
91 2169 : metaTags().insert({ u"arranger", u"" });
92 2169 : metaTags().insert({ u"composer", u"" });
93 2169 : metaTags().insert({ u"lyricist", u"" });
94 2169 : metaTags().insert({ u"translator", u"" });
95 2169 : metaTags().insert({ u"source", u"" });
96 2169 : metaTags().insert({ u"copyright", u"" });
97 2169 : metaTags().insert({ u"creationDate", muse::Date::currentDate().toString(muse::DateFormat::ISODate) });
98 4338 : }
99 :
100 2061 : MasterScore::MasterScore(const muse::modularity::ContextPtr& iocCtx, const MStyle& s, std::weak_ptr<engraving::EngravingProject> project)
101 2061 : : MasterScore{iocCtx, project}
102 : {
103 2061 : setStyle(s);
104 2061 : }
105 :
106 3888 : MasterScore::~MasterScore()
107 : {
108 1944 : if (m_project.lock()) {
109 0 : m_project.lock()->m_masterScore = nullptr;
110 : }
111 :
112 1944 : delete m_expandedRepeatList;
113 1944 : delete m_nonExpandedRepeatList;
114 1944 : delete m_sigmap;
115 1944 : delete m_undoStack;
116 1944 : delete m_automationController;
117 1944 : muse::DeleteAll(m_excerpts);
118 3888 : }
119 :
120 : //---------------------------------------------------------
121 : // fileInfo
122 : //---------------------------------------------------------
123 :
124 1095 : IFileInfoProviderPtr MasterScore::fileInfo() const
125 : {
126 1095 : return m_fileInfoProvider;
127 : }
128 :
129 3039 : void MasterScore::setFileInfoProvider(IFileInfoProviderPtr fileInfoProvider)
130 : {
131 3039 : m_fileInfoProvider = fileInfoProvider;
132 3039 : }
133 :
134 1 : String MasterScore::name() const
135 : {
136 1 : return fileInfo()->displayName();
137 : }
138 :
139 505 : AutomationDataConstPtr MasterScore::automationData() const
140 : {
141 505 : return m_automationController->automationData();
142 : }
143 :
144 1008 : void MasterScore::setAutomationData(AutomationDataPtr data)
145 : {
146 1008 : m_automationController->setAutomationData(std::move(data));
147 1008 : }
148 :
149 1 : void MasterScore::editAutomationPoints(const AutomationCurveKey& key, AutomationPointEdits& edits, bool undoable)
150 : {
151 1 : IF_ASSERT_FAILED(key.isValid() && !edits.empty()) {
152 0 : return;
153 : }
154 :
155 1 : if (undoable) {
156 1 : undo(new EditAutomationPoints(this, m_automationController, key, edits));
157 : } else {
158 0 : m_automationController->editPoints(key, edits);
159 : }
160 : }
161 :
162 451 : void MasterScore::onTimeInserted(const Fraction& tick, const Fraction& len, const std::vector<RepeatSegmentInfo>& oldSegments)
163 : {
164 451 : m_automationController->insertTime(tick, len, oldSegments);
165 451 : }
166 :
167 : //---------------------------------------------------------
168 : // invalidateRepeatLists
169 : //---------------------------------------------------------
170 :
171 8592 : void MasterScore::invalidateRepeatList()
172 : {
173 8592 : m_expandedRepeatList->setScoreChanged();
174 8592 : m_nonExpandedRepeatList->setScoreChanged();
175 8592 : }
176 :
177 : //---------------------------------------------------------
178 : // setExpandRepeats
179 : //---------------------------------------------------------
180 :
181 216 : void MasterScore::setExpandRepeats(bool expand)
182 : {
183 216 : if (m_expandRepeats == expand) {
184 216 : return;
185 : }
186 0 : m_expandRepeats = expand;
187 0 : invalidateRepeatList();
188 : }
189 :
190 : //---------------------------------------------------------
191 : // updateRepeatListTempo
192 : /// needed for usage in Seq::processMessages
193 : //---------------------------------------------------------
194 :
195 0 : void MasterScore::updateRepeatListTempo()
196 : {
197 0 : m_expandedRepeatList->updateUticks();
198 0 : m_nonExpandedRepeatList->updateUticks();
199 0 : }
200 :
201 0 : void MasterScore::updateRepeatList()
202 : {
203 0 : m_expandedRepeatList->update(true);
204 0 : m_nonExpandedRepeatList->update(false);
205 0 : }
206 :
207 : //---------------------------------------------------------
208 : // repeatList
209 : //---------------------------------------------------------
210 :
211 1316 : const RepeatList& MasterScore::repeatList() const
212 : {
213 1316 : if (m_expandRepeats) {
214 1316 : m_expandedRepeatList->update(true);
215 1316 : return *m_expandedRepeatList;
216 : }
217 :
218 0 : m_nonExpandedRepeatList->update(false);
219 0 : return *m_nonExpandedRepeatList;
220 : }
221 :
222 36570 : const RepeatList& MasterScore::repeatList(bool expandRepeats, bool updateTies) const
223 : {
224 36570 : if (expandRepeats) {
225 36570 : m_expandedRepeatList->update(true, updateTies);
226 36570 : return *m_expandedRepeatList;
227 : }
228 :
229 0 : m_nonExpandedRepeatList->update(false, updateTies);
230 0 : return *m_nonExpandedRepeatList;
231 : }
232 :
233 8644 : const TempoTimeline& MasterScore::tempoTimeline() const
234 : {
235 8644 : return tempoTimeline(masterScore()->expandRepeats());
236 : }
237 :
238 9531 : const TempoTimeline& MasterScore::tempoTimeline(bool expandRepeats) const
239 : {
240 9531 : m_automationController->ensureInitialized(const_cast<MasterScore*>(this));
241 9531 : return m_automationController->tempoTimeline(expandRepeats);
242 : }
243 :
244 26 : bool MasterScore::setTempoMultiplier(BeatsPerSecond val)
245 : {
246 26 : IF_ASSERT_FAILED(val > BeatsPerSecond(0.0)) {
247 0 : return false;
248 : }
249 :
250 26 : if (m_automationController->tempoTimeline().tempoMultiplier() == val) {
251 0 : return false;
252 : }
253 :
254 26 : m_automationController->setTempoMultiplier(val);
255 26 : return true;
256 : }
257 :
258 0 : void MasterScore::setTempoTimelineOverride(std::optional<TempoTimeline> timeline)
259 : {
260 0 : m_automationController->setTempoTimelineOverride(std::move(timeline));
261 0 : }
262 :
263 : //---------------------------------------------------------
264 : // addExcerpt
265 : //---------------------------------------------------------
266 :
267 110 : void MasterScore::addExcerpt(Excerpt* ex, size_t index)
268 : {
269 110 : if (!ex->inited()) {
270 110 : initParts(ex);
271 : }
272 :
273 110 : excerpts().insert(excerpts().begin() + (index == muse::nidx ? excerpts().size() : index), ex);
274 110 : setExcerptsChanged(true);
275 110 : }
276 :
277 : //---------------------------------------------------------
278 : // removeExcerpt
279 : //---------------------------------------------------------
280 :
281 2 : void MasterScore::removeExcerpt(Excerpt* ex)
282 : {
283 2 : if (muse::remove(excerpts(), ex)) {
284 1 : setExcerptsChanged(true);
285 : // delete ex;
286 : } else {
287 1 : LOGD("removeExcerpt:: ex not found");
288 : }
289 2 : }
290 :
291 : //---------------------------------------------------------
292 : // clone
293 : //---------------------------------------------------------
294 :
295 0 : MasterScore* MasterScore::clone()
296 : {
297 0 : auto buffer = Buffer::opened(IODevice::WriteOnly);
298 :
299 0 : rw::RWRegister::writer()->writeScore(this, &buffer);
300 :
301 0 : buffer.close();
302 :
303 0 : muse::ByteArray scoreData = buffer.data();
304 0 : MasterScore* score = new MasterScore(iocContext(), style(), m_project);
305 :
306 0 : XmlReader r(scoreData);
307 0 : MscLoader().readMasterScore(score, r, true);
308 :
309 0 : score->doLayout();
310 0 : return score;
311 0 : }
312 :
313 165 : Score* MasterScore::createScore()
314 : {
315 165 : return new Score(this, DefaultStyle::baseStyle());
316 : }
317 :
318 0 : Score* MasterScore::createScore(const MStyle& s)
319 : {
320 0 : return new Score(this, s);
321 : }
322 :
323 : //---------------------------------------------------------
324 : // setPos
325 : //---------------------------------------------------------
326 :
327 0 : Fraction MasterScore::loopBoundaryTick(LoopBoundaryType type) const
328 : {
329 0 : IF_ASSERT_FAILED(type != LoopBoundaryType::Unknown) {
330 0 : return Fraction();
331 : }
332 0 : return m_loopBoundaries[size_t(type)];
333 : }
334 :
335 0 : void MasterScore::setLoopBoundaryTick(LoopBoundaryType type, Fraction tick)
336 : {
337 0 : IF_ASSERT_FAILED(type != LoopBoundaryType::Unknown) {
338 0 : return;
339 : }
340 0 : if (tick < Fraction(0, 1)) {
341 0 : tick = Fraction(0, 1);
342 : }
343 0 : if (tick > lastMeasure()->endTick()) {
344 : // End Reverb may last longer than written notation, but cursor position should not
345 0 : tick = lastMeasure()->endTick();
346 : }
347 :
348 0 : m_loopBoundaries[size_t(type)] = tick;
349 : // even though tick position might not have changed, layout might have
350 : // so we should update cursor here
351 : // however, we must be careful not to call setLoopBoundaryTick() again while handling posChanged, or recursion results
352 0 : for (Score* s : scoreList()) {
353 0 : s->notifyLoopBoundaryTickChanged(type, unsigned(tick.ticks()));
354 0 : }
355 : }
356 :
357 : //---------------------------------------------------------
358 : // setUpdateAll
359 : //---------------------------------------------------------
360 :
361 404 : void MasterScore::setUpdateAll()
362 : {
363 404 : m_cmdState.setUpdateMode(UpdateMode::UpdateAll);
364 404 : }
365 :
366 : //---------------------------------------------------------
367 : // setLayoutAll
368 : //---------------------------------------------------------
369 :
370 9097 : void MasterScore::setLayoutAll(staff_idx_t staff, const EngravingItem* e)
371 : {
372 9097 : m_cmdState.setTick(Fraction(0, 1));
373 9097 : m_cmdState.setTick(Fraction::max());
374 :
375 9097 : if (e && e->score() == this) {
376 : // TODO: map staff number properly
377 2352 : const staff_idx_t startStaff = staff == muse::nidx ? 0 : staff;
378 2352 : const staff_idx_t endStaff = staff == muse::nidx ? (nstaves() - 1) : staff;
379 2352 : m_cmdState.setStaff(startStaff);
380 2352 : m_cmdState.setStaff(endStaff);
381 :
382 2352 : m_cmdState.setElement(e);
383 : }
384 9097 : }
385 :
386 : //---------------------------------------------------------
387 : // setLayout
388 : //---------------------------------------------------------
389 :
390 919228 : void MasterScore::setLayout(const Fraction& t, staff_idx_t staff, const EngravingItem* e)
391 : {
392 919228 : if (t >= Fraction(0, 1)) {
393 919228 : m_cmdState.setTick(t);
394 : }
395 :
396 919228 : if (e && e->score() == this) {
397 : // TODO: map staff number properly
398 868675 : m_cmdState.setStaff(staff);
399 868675 : m_cmdState.setElement(e);
400 : }
401 919228 : }
402 :
403 15454 : void MasterScore::setLayout(const Fraction& tick1, const Fraction& tick2, staff_idx_t staff1, staff_idx_t staff2, const EngravingItem* e)
404 : {
405 15454 : if (tick1 >= Fraction(0, 1)) {
406 15454 : m_cmdState.setTick(tick1);
407 : }
408 15454 : if (tick2 >= Fraction(0, 1)) {
409 15454 : m_cmdState.setTick(tick2);
410 : }
411 :
412 15454 : if (e && e->score() == this) {
413 : // TODO: map staff number properly
414 14082 : m_cmdState.setStaff(staff1);
415 14082 : m_cmdState.setStaff(staff2);
416 :
417 14082 : m_cmdState.setElement(e);
418 : }
419 15454 : }
420 :
421 9 : void MasterScore::initAutomation()
422 : {
423 9 : IF_ASSERT_FAILED(m_automationController) {
424 0 : return;
425 : }
426 9 : m_automationController->init(this);
427 : }
428 :
429 967 : void MasterScore::updateAutomation(const ScoreChanges& changes)
430 : {
431 967 : m_automationController->update(changes);
432 967 : }
433 :
434 : //---------------------------------------------------------
435 : // setPlaybackScore
436 : //---------------------------------------------------------
437 :
438 6044 : void MasterScore::setPlaybackScore(Score* score)
439 : {
440 6044 : if (m_playbackScore == score) {
441 2035 : return;
442 : }
443 :
444 4009 : m_playbackScore = score;
445 4009 : m_playbackSettingsLinks.clear();
446 :
447 4009 : if (!m_playbackScore) {
448 987 : return;
449 : }
450 :
451 7432 : for (Part* part : score->parts()) {
452 8911 : for (const auto& pair : part->instruments()) {
453 4501 : Instrument* instr = pair.second;
454 9843 : for (InstrChannel* ch : instr->channel()) {
455 5342 : InstrChannel* pChannel = playbackChannel(ch);
456 5342 : IF_ASSERT_FAILED(pChannel) {
457 0 : continue;
458 : }
459 5342 : m_playbackSettingsLinks.emplace_back(pChannel, ch, /* excerpt */ true);
460 : }
461 : }
462 : }
463 : }
464 :
465 : //---------------------------------------------------------
466 : // updateExpressive
467 : // change patches to their expressive equivalent or vica versa, if possible
468 : // This works only with MuseScore general soundfont
469 : //
470 : // The first version of the function decides whether to make patches expressive
471 : // or not, based on the synth settings. The second will switch patches based on
472 : // the value of the expressive parameter.
473 : //---------------------------------------------------------
474 :
475 0 : void MasterScore::updateExpressive(Synthesizer* synth)
476 : {
477 0 : SynthesizerState s = synthesizerState();
478 0 : SynthesizerGroup g = s.group(u"master");
479 :
480 0 : int method = 1;
481 0 : for (const IdValue& idVal : g) {
482 0 : if (idVal.id == 4) {
483 0 : method = idVal.data.toInt();
484 0 : break;
485 : }
486 : }
487 :
488 0 : updateExpressive(synth, (method != 0));
489 0 : }
490 :
491 0 : void MasterScore::updateExpressive(Synthesizer* synth, bool expressive, bool force /* = false */)
492 : {
493 0 : if (!synth) {
494 0 : return;
495 : }
496 :
497 0 : if (!force) {
498 0 : SynthesizerState s = synthesizerState();
499 0 : SynthesizerGroup g = s.group(u"master");
500 :
501 0 : for (const IdValue& idVal : g) {
502 0 : if (idVal.id == 4) {
503 0 : int method = idVal.data.toInt();
504 0 : if (expressive == (method == 0)) {
505 0 : return; // method and expression change don't match, so don't switch
506 : }
507 : }
508 : }
509 0 : }
510 :
511 0 : for (Part* p : parts()) {
512 0 : for (const auto& pair : p->instruments()) {
513 0 : pair.second->switchExpressive(this, synth, expressive, force);
514 : }
515 : }
516 : }
517 :
518 : //---------------------------------------------------------
519 : // rebuildAndUpdateExpressive
520 : // implicitly rebuild midi mappings as well. Should be preferred over
521 : // just updateExpressive, in most cases.
522 : //---------------------------------------------------------
523 :
524 0 : void MasterScore::rebuildAndUpdateExpressive(Synthesizer* synth)
525 : {
526 : // Rebuild midi mappings to make sure we have playback channels
527 0 : rebuildMidiMapping();
528 :
529 0 : updateExpressive(synth);
530 :
531 : // Rebuild midi mappings again to be safe
532 0 : rebuildMidiMapping();
533 0 : }
534 :
535 : //---------------------------------------------------------
536 : // insertMeasure
537 : // Create a new MeasureBase of Measure type and insert
538 : // before measure.
539 : // If measure is zero, append new MeasureBase.
540 : //---------------------------------------------------------
541 :
542 274 : MeasureBase* MasterScore::insertMeasure(MeasureBase* beforeMeasure, const InsertMeasureOptions& options)
543 : {
544 274 : Fraction tick;
545 274 : if (beforeMeasure) {
546 51 : if (beforeMeasure->isMeasure()) {
547 51 : if (toMeasure(beforeMeasure)->isMMRest()) {
548 0 : beforeMeasure = toMeasure(beforeMeasure)->prev();
549 0 : beforeMeasure = beforeMeasure ? beforeMeasure->next() : firstMeasure();
550 0 : deselectAll();
551 : }
552 111 : for (size_t staffIdx = 0; staffIdx < nstaves(); ++staffIdx) {
553 60 : if (toMeasure(beforeMeasure)->isMeasureRepeatGroupWithPrevM(staffIdx)) {
554 0 : MScore::setError(MsError::CANNOT_SPLIT_MEASURE_REPEAT);
555 0 : return nullptr;
556 : }
557 : }
558 : }
559 51 : tick = beforeMeasure->tick();
560 : } else {
561 223 : tick = last() ? last()->endTick() : Fraction(0, 1);
562 : }
563 :
564 274 : const bool isBeginning = tick.isZero();
565 :
566 : // Use nominal time signature of current or previous measure, depending on whether
567 : // the time sig from `beforeMeasure` will be moved to the newly created measure
568 : const Fraction currentTimeSig
569 603 : = sigmap()->timesig(!options.moveSignaturesClef && !isBeginning && beforeMeasure && beforeMeasure->prevMeasure()
570 329 : ? beforeMeasure->prevMeasure()->tick()
571 : : tick)
572 274 : .nominal();
573 :
574 274 : Measure* masterMeasure = nullptr;
575 274 : Fraction ticks = { 0, 1 };
576 :
577 562 : for (Score* score : scoreList()) {
578 288 : MeasureBase* actualBeforeMeasure = nullptr;
579 :
580 288 : if (beforeMeasure) {
581 61 : if (beforeMeasure->score() == score) {
582 51 : actualBeforeMeasure = beforeMeasure;
583 10 : } else if (!beforeMeasure->isMeasure() && beforeMeasure->links()) {
584 0 : for (EngravingObject* m : *beforeMeasure->links()) {
585 0 : if (m && m->isMeasureBase() && m->score() == score) {
586 0 : actualBeforeMeasure = toMeasureBase(m);
587 0 : break;
588 : }
589 : }
590 : }
591 : // if beforeMeasure is measure; or if din't find linked frame, use measure
592 61 : if (!actualBeforeMeasure) {
593 10 : actualBeforeMeasure = score->tick2measure(tick);
594 : }
595 :
596 61 : if (!actualBeforeMeasure) {
597 0 : LOGD("measure not found");
598 : }
599 : }
600 :
601 288 : Measure* newMeasure = Factory::createMeasure(score);
602 288 : newMeasure->setTick(tick);
603 :
604 288 : if (actualBeforeMeasure) {
605 61 : actualBeforeMeasure = actualBeforeMeasure->top(); // don't try to insert in front of nested frame
606 : }
607 288 : newMeasure->setNext(actualBeforeMeasure);
608 288 : newMeasure->setPrev(actualBeforeMeasure ? actualBeforeMeasure->prev() : score->last());
609 :
610 288 : newMeasure->setTimesig(currentTimeSig);
611 288 : newMeasure->setTicks(currentTimeSig);
612 :
613 288 : undo(new InsertMeasures(newMeasure, newMeasure, options.moveStaffTypeChanges));
614 :
615 288 : ticks = newMeasure->ticks();
616 288 : Measure* measureInsert = nullptr; // insert before
617 288 : if (actualBeforeMeasure) {
618 61 : if (actualBeforeMeasure->isMeasure()) {
619 61 : measureInsert = toMeasure(actualBeforeMeasure);
620 : } else {
621 0 : measureInsert = score->tick2measure(actualBeforeMeasure->tick());
622 : }
623 : }
624 :
625 288 : if (score->isMaster()) {
626 274 : masterMeasure = newMeasure;
627 : }
628 :
629 288 : std::vector<TimeSig*> timeSigList;
630 288 : std::vector<KeySig*> keySigList;
631 288 : std::vector<Clef*> initClefList;
632 288 : std::vector<Clef*> previousClefList;
633 288 : std::vector<Clef*> specialCaseClefs;
634 288 : std::vector<Clef*> afterBarlineClefs;
635 288 : std::vector<BarLine*> previousBarLinesList;
636 :
637 288 : Measure* pm = newMeasure->prevMeasure();
638 :
639 : //
640 : // remove clefs, barlines, time and key signatures
641 : //
642 288 : bool headerKeySig = false;
643 288 : if (measureInsert) {
644 : // if inserting before first measure, always preserve clefs and signatures
645 : // at the begining of the score (move them back)
646 :
647 61 : if (measureInsert->hasMMRest() && score->style().value(Sid::createMultiMeasureRests).toBool()) {
648 1 : measureInsert = measureInsert->mmRest();
649 : }
650 :
651 61 : if (pm && !options.moveSignaturesClef && !isBeginning) {
652 40 : Segment* ps = pm->findSegment(SegmentType::Clef, tick);
653 40 : if (ps && ps->enabled()) {
654 0 : for (size_t staffIdx = 0; staffIdx < score->nstaves(); ++staffIdx) {
655 0 : EngravingItem* pc = ps->element(staffIdx * VOICES);
656 0 : if (pc) {
657 0 : previousClefList.push_back(toClef(pc));
658 0 : doUndoRemoveElement(pc);
659 0 : pc->undoUnlink();
660 0 : if (ps->empty()) {
661 0 : undoRemoveElement(ps);
662 : }
663 : }
664 : }
665 : }
666 : }
667 :
668 61 : if (options.moveSignaturesClef || isBeginning) {
669 49 : for (size_t staffIdx = 0; staffIdx < score->nstaves(); ++staffIdx) {
670 112 : for (Segment* s = measureInsert->first(); s && s->rtick().isZero(); s = s->next()) {
671 84 : if (!s->enabled()) {
672 0 : continue;
673 : }
674 84 : EngravingItem* e = s->element(staffIdx * VOICES);
675 84 : bool specialCase = false;
676 84 : bool initClef = false;
677 84 : bool moveClef = false;
678 84 : bool moveOther = false;
679 84 : if (e && e->isClef()) {
680 14 : if (s->isHeaderClefType()) {
681 : // if it's a header clef, we only add if it's an init clef
682 : // (other header clefs are handled by undo(new InsertMeasures())
683 13 : initClef = isBeginning && !toClef(e)->forInstrumentChange();
684 13 : moveClef = initClef;
685 : } else {
686 1 : ClefToBarlinePosition clefPos = toClef(e)->clefToBarlinePosition();
687 1 : if (isBeginning) {
688 : // special case:
689 : // there is a non-header clef at global tick 0, and we are inserting at the beginning of the score.
690 : // this clef will be moved with the measure it accompanies, but it will be moved before the barline.
691 1 : specialCase = true;
692 1 : moveClef = true;
693 0 : } else if (clefPos == ClefToBarlinePosition::AFTER) {
694 : // non header clef at the begining of the measure
695 0 : moveClef = true;
696 : }
697 : }
698 : } else {
699 : // otherwise, we only add if e is not generated
700 70 : moveOther = e && (!e->generated() || tick.isZero());
701 : }
702 84 : if (!moveClef && !moveOther) {
703 0 : continue; // this item will remain with the old measure
704 : }
705 : // otherwise, this item is moved back to the new measure
706 84 : EngravingItem* ee = 0;
707 84 : if (e->isKeySig()) {
708 18 : KeySig* ks = toKeySig(e);
709 18 : if (ks->forInstrumentChange()) {
710 0 : continue;
711 : }
712 18 : keySigList.push_back(ks);
713 : // if instrument change on that place, set correct key signature for instrument change
714 18 : const TrackRange trackRange = e->part()->trackRange();
715 18 : bool ic = s->next(SegmentType::ChordRest)->findAnnotation(ElementType::INSTRUMENT_CHANGE,
716 18 : trackRange.startTrack,
717 18 : trackRange.endTrack - 1);
718 18 : if (ic) {
719 0 : KeySigEvent ke = ks->keySigEvent();
720 0 : ke.setForInstrumentChange(true);
721 0 : EditKeySig::undoChangeKeySig(transactionManager()->currentOrDummyTransaction(), this, ks->staff(),
722 0 : e->tick(), ke);
723 0 : } else {
724 18 : ee = e;
725 : }
726 18 : if (s->header()) {
727 13 : headerKeySig = true;
728 : }
729 66 : } else if (e->isTimeSig()) {
730 17 : TimeSig* ts = toTimeSig(e);
731 17 : timeSigList.push_back(ts);
732 17 : ee = e;
733 49 : } else if (e->isClef()) {
734 14 : Clef* clef = toClef(e);
735 14 : if (specialCase) {
736 1 : specialCaseClefs.push_back(clef);
737 13 : } else if (initClef) {
738 13 : initClefList.push_back(clef);
739 : } else {
740 0 : afterBarlineClefs.push_back(toClef(e));
741 : }
742 14 : ee = e;
743 : }
744 84 : if (ee) {
745 49 : doUndoRemoveElement(ee);
746 49 : ee->undoUnlink();
747 49 : if (s->empty() && s->isTimeSigType()) {
748 13 : undoRemoveElement(s);
749 : }
750 : }
751 : }
752 : }
753 :
754 21 : if (masterMeasure && measureInsert->repeatStart()) {
755 0 : masterMeasure->undoChangeProperty(Pid::REPEAT_START, true);
756 0 : measureInsert->undoChangeProperty(Pid::REPEAT_START, false);
757 : }
758 : }
759 227 : } else if (!measureInsert && tick == Fraction(0, 1)) {
760 : // If inserting measure into an empty score, restore default C key signature
761 : // and 4/4 time signature
762 38 : score->restoreInitialKeySigAndTimeSig();
763 : }
764 :
765 288 : if (pm && !options.moveSignaturesClef && !options.ignoreBarLines) {
766 0 : Segment* pbs = pm->findSegment(SegmentType::EndBarLine, tick);
767 0 : if (pbs && pbs->enabled()) {
768 0 : for (size_t staffIdx = 0; staffIdx < score->nstaves(); ++staffIdx) {
769 0 : EngravingItem* pb = pbs->element(staffIdx * VOICES);
770 0 : if (pb && !pb->generated()) {
771 0 : previousBarLinesList.push_back(toBarLine(pb));
772 0 : doUndoRemoveElement(pb);
773 0 : if (pbs->empty()) {
774 0 : pbs->setEnabled(false);
775 : }
776 : }
777 : }
778 : }
779 0 : if (masterMeasure && pm->repeatEnd()) {
780 0 : masterMeasure->undoChangeProperty(Pid::REPEAT_END, true);
781 0 : pm->undoChangeProperty(Pid::REPEAT_END, false);
782 : }
783 : }
784 :
785 : //
786 : // move clef, barline, time, key signatures
787 : //
788 305 : for (TimeSig* ts : timeSigList) {
789 17 : TimeSig* nts = Factory::copyTimeSig(*ts);
790 17 : Segment* s = newMeasure->undoGetSegmentR(SegmentType::TimeSig, Fraction(0, 1));
791 17 : nts->setOwnershipParent(s);
792 17 : doUndoAddElement(nts);
793 : }
794 306 : for (KeySig* ks : keySigList) {
795 18 : KeySig* nks = Factory::copyKeySig(*ks);
796 18 : Segment* s = newMeasure->undoGetSegmentR(SegmentType::KeySig, Fraction(0, 1));
797 18 : if (headerKeySig || newMeasure->tick().isZero()) {
798 17 : s->setHeader(true);
799 : }
800 18 : nks->setOwnershipParent(s);
801 18 : if (!nks->isAtonal()) {
802 18 : nks->setKey(nks->concertKey()); // to set correct (transposing) key
803 : }
804 18 : doUndoAddElement(nks);
805 : }
806 301 : for (Clef* clef : initClefList) {
807 13 : Clef* nClef = Factory::copyClef(*clef);
808 13 : Segment* s = newMeasure->undoGetSegmentR(SegmentType::HeaderClef, Fraction(0, 1));
809 13 : s->setHeader(true);
810 13 : nClef->setOwnershipParent(s);
811 13 : doUndoAddElement(nClef);
812 : }
813 288 : for (Clef* clef : afterBarlineClefs) {
814 0 : Clef* nClef = Factory::copyClef(*clef);
815 0 : Segment* s = newMeasure->undoGetSegmentR(SegmentType::Clef, Fraction(0, 1));
816 0 : s->setHeader(true);
817 0 : nClef->setOwnershipParent(s);
818 0 : doUndoAddElement(nClef);
819 : }
820 288 : for (Clef* clef : previousClefList) {
821 0 : Clef* nClef = Factory::copyClef(*clef);
822 0 : Segment* s = newMeasure->undoGetSegmentR(SegmentType::Clef, newMeasure->ticks());
823 0 : nClef->setOwnershipParent(s);
824 0 : doUndoAddElement(nClef);
825 : }
826 289 : for (Clef* clef : specialCaseClefs) {
827 1 : Clef* nClef = Factory::copyClef(*clef);
828 1 : Segment* s = newMeasure->undoGetSegmentR(SegmentType::Clef, newMeasure->ticks());
829 1 : nClef->setOwnershipParent(s);
830 1 : doUndoAddElement(nClef);
831 : }
832 288 : for (BarLine* barLine : previousBarLinesList) {
833 0 : BarLine* nBarLine = Factory::copyBarLine(*barLine);
834 0 : Segment* s = newMeasure->undoGetSegmentR(SegmentType::EndBarLine, newMeasure->ticks());
835 0 : nBarLine->setOwnershipParent(s);
836 0 : doUndoAddElement(nBarLine);
837 : }
838 562 : }
839 :
840 274 : undoInsertTime(tick, ticks);
841 :
842 274 : if (masterMeasure && !options.createMeasureRests) {
843 : //
844 : // fill measure with rest
845 : // undoAddCR adds rest to linked staves as well
846 490 : for (size_t staffIdx = 0; staffIdx < nstaves(); ++staffIdx) {
847 271 : size_t track = staffIdx * VOICES;
848 271 : Rest* rest = Factory::createRest(dummy(), TDuration(DurationType::V_MEASURE));
849 271 : Fraction timeStretch(staff(staffIdx)->timeStretch(masterMeasure->tick()));
850 271 : rest->setTicks(masterMeasure->ticks() * timeStretch);
851 271 : rest->setTrack(track);
852 271 : undoAddCR(rest, masterMeasure, tick);
853 : }
854 : }
855 :
856 274 : if (options.needDeselectAll) {
857 274 : deselectAll();
858 : }
859 :
860 274 : return masterMeasure;
861 : }
|