1 //=============================================================================
2 //  MuseScore
3 //  Music Composition & Notation
4 //
5 //  Copyright (C) 2002-2011 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 "part.h"
14 #include "staff.h"
15 #include "xml.h"
16 #include "score.h"
17 #include "style.h"
18 #include "note.h"
19 #include "drumset.h"
20 #include "instrtemplate.h"
21 #include "text.h"
22 #include "measure.h"
23 #include "stringdata.h"
24 #include "stafftype.h"
25 #include "sym.h"
26 #include "chordrest.h"
27 #include "fret.h"
28 
29 namespace Ms {
30 
31 //---------------------------------------------------------
32 //   Part
33 //---------------------------------------------------------
34 
Part(Score * s)35 Part::Part(Score* s)
36    : ScoreElement(s)
37       {
38       _color   = DEFAULT_COLOR;
39       _show    = true;
40       _soloist = false;
41       _instruments.setInstrument(new Instrument, -1);   // default instrument
42       _preferSharpFlat = PreferSharpFlat::DEFAULT;
43       }
44 
45 //---------------------------------------------------------
46 //   initFromInstrTemplate
47 //---------------------------------------------------------
48 
initFromInstrTemplate(const InstrumentTemplate * t)49 void Part::initFromInstrTemplate(const InstrumentTemplate* t)
50       {
51       _partName = t->trackName;
52       setInstrument(Instrument::fromTemplate(t));
53       }
54 
55 //---------------------------------------------------------
56 //   staff
57 //---------------------------------------------------------
58 
staff(int idx) const59 Staff* Part::staff(int idx) const
60       {
61       return _staves[idx];
62       }
63 
64 //---------------------------------------------------------
65 //   Part::masterPart
66 //---------------------------------------------------------
67 
masterPart() const68 const Part* Part::masterPart() const
69       {
70       if (score()->isMaster())
71             return this;
72       if (_staves.empty())
73             return this;
74 
75       Staff* st = _staves[0];
76       LinkedElements* links = st->links();
77       if (!links)
78             return this;
79 
80       for (ScoreElement* le : *links) {
81             if (le->isStaff() && toStaff(le)->score()->isMaster()) {
82                   if (Part* p = toStaff(le)->part())
83                         return p;
84                   }
85             }
86       return this;
87       }
88 
89 //---------------------------------------------------------
90 //   Part::masterPart
91 //---------------------------------------------------------
92 
masterPart()93 Part* Part::masterPart()
94       {
95       return const_cast<Part*>(const_cast<const Part*>(this)->masterPart());
96       }
97 
98 //---------------------------------------------------------
99 //   readProperties
100 //---------------------------------------------------------
101 
readProperties(XmlReader & e)102 bool Part::readProperties(XmlReader& e)
103       {
104       const QStringRef& tag(e.name());
105       if (tag == "Staff") {
106             Staff* staff = new Staff(score());
107             staff->setPart(this);
108             score()->staves().push_back(staff);
109             _staves.push_back(staff);
110             staff->read(e);
111             }
112       else if (tag == "Instrument") {
113             Instrument* instr = new Instrument;
114             instr->read(e, this);
115             setInstrument(instr, Fraction(-1, 1));
116             }
117       else if (tag == "name")
118             instrument()->setLongName(e.readElementText());
119       else if (tag == "color")
120             _color = e.readInt();
121       else if (tag == "shortName")
122             instrument()->setShortName(e.readElementText());
123       else if (tag == "trackName")
124             _partName = e.readElementText();
125       else if (tag == "show")
126             _show = e.readInt();
127       else if (tag == "soloist")
128             _soloist = e.readInt();
129       else if (tag == "preferSharpFlat")
130             _preferSharpFlat =
131                e.readElementText() == "sharps" ? PreferSharpFlat::SHARPS : PreferSharpFlat::FLATS;
132       else
133             return false;
134       return true;
135       }
136 
137 //---------------------------------------------------------
138 //   read
139 //---------------------------------------------------------
140 
read(XmlReader & e)141 void Part::read(XmlReader& e)
142       {
143       while (e.readNextStartElement()) {
144             if (!readProperties(e))
145                   e.unknown();
146             }
147       if (_partName.isEmpty())
148             _partName = instrument()->trackName();
149       }
150 
151 //---------------------------------------------------------
152 //   write
153 //---------------------------------------------------------
154 
write(XmlWriter & xml) const155 void Part::write(XmlWriter& xml) const
156       {
157       xml.stag(this);
158       for (const Staff* staff : _staves)
159             staff->write(xml);
160       if (!_show)
161             xml.tag("show", _show);
162       if (_soloist)
163             xml.tag("soloist", _soloist);
164       xml.tag("trackName", _partName);
165       if (_color != DEFAULT_COLOR)
166             xml.tag("color", _color);
167       if (_preferSharpFlat != PreferSharpFlat::DEFAULT)
168             xml.tag("preferSharpFlat",
169                _preferSharpFlat == PreferSharpFlat::SHARPS ? "sharps" : "flats");
170       instrument()->write(xml, this);
171       xml.etag();
172       }
173 
174 //---------------------------------------------------------
175 //   setLongNames
176 //---------------------------------------------------------
177 
setLongNames(QList<StaffName> & name,const Fraction & tick)178 void Part::setLongNames(QList<StaffName>& name, const Fraction& tick)
179       {
180       instrument(tick)->longNames() = name;
181       }
182 
setShortNames(QList<StaffName> & name,const Fraction & tick)183 void Part::setShortNames(QList<StaffName>& name, const Fraction& tick)
184       {
185       instrument(tick)->shortNames() = name;
186       }
187 
188 //---------------------------------------------------------
189 //   setStaves
190 //---------------------------------------------------------
191 
setStaves(int n)192 void Part::setStaves(int n)
193       {
194       int ns = _staves.size();
195       if (n < ns) {
196             qDebug("Part::setStaves(): remove staves not implemented!");
197             return;
198             }
199       int staffIdx = score()->staffIdx(this) + ns;
200       for (int i = ns; i < n; ++i) {
201             Staff* staff = new Staff(score());
202             staff->setPart(this);
203             _staves.push_back(staff);
204             score()->staves().insert(staffIdx, staff);
205             for (Measure* m = score()->firstMeasure(); m; m = m->nextMeasure()) {
206                   m->insertStaff(staff, staffIdx);
207                   if (m->hasMMRest())
208                         m->mmRest()->insertStaff(staff, staffIdx);
209                   }
210             ++staffIdx;
211             }
212       }
213 
214 //---------------------------------------------------------
215 //   insertStaff
216 //---------------------------------------------------------
217 
insertStaff(Staff * staff,int idx)218 void Part::insertStaff(Staff* staff, int idx)
219       {
220       if (idx < 0 || idx > _staves.size())
221             idx = _staves.size();
222       _staves.insert(idx, staff);
223       staff->setPart(this);
224       }
225 
226 //---------------------------------------------------------
227 //   removeStaff
228 //---------------------------------------------------------
229 
removeStaff(Staff * staff)230 void Part::removeStaff(Staff* staff)
231       {
232       if (!_staves.removeOne(staff)) {
233             qDebug("Part::removeStaff: not found %p", staff);
234             return;
235             }
236       }
237 
238 //---------------------------------------------------------
239 //   setMidiProgram
240 //    TODO
241 //---------------------------------------------------------
242 
setMidiProgram(int program,int bank)243 void Part::setMidiProgram(int program, int bank)
244       {
245       Channel* c = instrument()->channel(0);
246       c->setProgram(program);
247       c->setBank(bank);
248 //      instrument()->setChannel(0, c);
249       }
250 
251 //---------------------------------------------------------
252 //   midiProgram
253 //---------------------------------------------------------
254 
midiProgram() const255 int Part::midiProgram() const
256       {
257       return instrument()->playbackChannel(0, masterScore())->program();
258       }
259 
260 //---------------------------------------------------------
261 //   midiChannel
262 //---------------------------------------------------------
263 
midiChannel() const264 int Part::midiChannel() const
265       {
266       return masterScore()->midiChannel(instrument()->channel(0)->channel());
267       }
268 
269 //---------------------------------------------------------
270 //   midiPort
271 //---------------------------------------------------------
272 
midiPort() const273 int Part::midiPort() const
274       {
275       return masterScore()->midiPort(instrument()->channel(0)->channel());
276       }
277 
278 //---------------------------------------------------------
279 //   setMidiChannel
280 //   Called from importmusicxml, importMidi and importGtp*.
281 //   Specify tick to set MIDI channel to an InstrumentChange element.
282 //   Usage:
283 //   setMidiChannel(channel)       to set channel
284 //   setMidiChannel(-1, port)      to set port
285 //   setMidiChannel(channel, port) to set both
286 //---------------------------------------------------------
287 
setMidiChannel(int ch,int port,const Fraction & tick)288 void Part::setMidiChannel(int ch, int port, const Fraction& tick)
289       {
290       Channel* channel = instrument(tick)->channel(0);
291       if (channel->channel() == -1)
292             masterScore()->addMidiMapping(channel, this, port, ch);
293       else
294             masterScore()->updateMidiMapping(channel, this, port, ch);
295       }
296 
297 //---------------------------------------------------------
298 //   setInstrument
299 //---------------------------------------------------------
300 
setInstrument(Instrument * i,Fraction tick)301 void Part::setInstrument(Instrument* i, Fraction tick)
302       {
303       _instruments.setInstrument(i, tick.ticks());
304       }
305 
setInstrument(const Instrument && i,Fraction tick)306 void Part::setInstrument(const Instrument&& i, Fraction tick)
307       {
308       _instruments.setInstrument(new Instrument(i), tick.ticks());
309       }
310 
setInstrument(const Instrument & i,Fraction tick)311 void Part::setInstrument(const Instrument& i, Fraction tick)
312       {
313       _instruments.setInstrument(new Instrument(i), tick.ticks());
314       }
315 
316 //---------------------------------------------------------
317 //   removeInstrument
318 //---------------------------------------------------------
319 
removeInstrument(const Fraction & tick)320 void Part::removeInstrument(const Fraction& tick)
321       {
322       auto i = _instruments.find(tick.ticks());
323       if (i == _instruments.end()) {
324             qDebug("Part::removeInstrument: not found at tick %d", tick.ticks());
325             return;
326             }
327       _instruments.erase(i);
328       }
329 
330 //---------------------------------------------------------
331 //   instrument
332 //---------------------------------------------------------
333 
instrument(Fraction tick)334 Instrument* Part::instrument(Fraction tick)
335       {
336       return _instruments.instrument(tick.ticks());
337       }
338 
339 //---------------------------------------------------------
340 //   instrument
341 //---------------------------------------------------------
342 
instrument(Fraction tick) const343 const Instrument* Part::instrument(Fraction tick) const
344       {
345       return _instruments.instrument(tick.ticks());
346       }
347 
348 //---------------------------------------------------------
349 //   instruments
350 //---------------------------------------------------------
351 
instruments() const352 const InstrumentList* Part::instruments() const
353       {
354       return &_instruments;
355       }
356 
357 //---------------------------------------------------------
358 //   instrumentId
359 //---------------------------------------------------------
360 
instrumentId(const Fraction & tick) const361 QString Part::instrumentId(const Fraction& tick) const
362       {
363       return instrument(tick)->instrumentId();
364       }
365 
366 //---------------------------------------------------------
367 //   longName
368 //---------------------------------------------------------
369 
longName(const Fraction & tick) const370 QString Part::longName(const Fraction& tick) const
371       {
372       const QList<StaffName>& nl = longNames(tick);
373       return nl.empty() ? "" : nl[0].name();
374       }
375 
376 //---------------------------------------------------------
377 //   instrumentName
378 //---------------------------------------------------------
379 
instrumentName(const Fraction & tick) const380 QString Part::instrumentName(const Fraction& tick) const
381       {
382       return instrument(tick)->trackName();
383       }
384 
385 //---------------------------------------------------------
386 //   shortName
387 //---------------------------------------------------------
388 
shortName(const Fraction & tick) const389 QString Part::shortName(const Fraction& tick) const
390       {
391       const QList<StaffName>& nl = shortNames(tick);
392       return nl.empty() ? "" : nl[0].name();
393       }
394 
395 //---------------------------------------------------------
396 //   setLongName
397 //---------------------------------------------------------
398 
setLongName(const QString & s)399 void Part::setLongName(const QString& s)
400       {
401       instrument()->setLongName(s);
402       }
403 
404 //---------------------------------------------------------
405 //   setShortName
406 //---------------------------------------------------------
407 
setShortName(const QString & s)408 void Part::setShortName(const QString& s)
409       {
410       instrument()->setShortName(s);
411       }
412 
413 //---------------------------------------------------------
414 //   setPlainLongName
415 //---------------------------------------------------------
416 
setPlainLongName(const QString & s)417 void Part::setPlainLongName(const QString& s)
418       {
419       setLongName(XmlWriter::xmlString(s));
420       }
421 
422 //---------------------------------------------------------
423 //   setPlainShortName
424 //---------------------------------------------------------
425 
setPlainShortName(const QString & s)426 void Part::setPlainShortName(const QString& s)
427       {
428       setShortName(XmlWriter::xmlString(s));
429       }
430 
431 //---------------------------------------------------------
432 //   getProperty
433 //---------------------------------------------------------
434 
getProperty(Pid id) const435 QVariant Part::getProperty(Pid id) const
436       {
437       switch (id) {
438             case Pid::VISIBLE:
439                   return QVariant(_show);
440             case Pid::USE_DRUMSET:
441                   return instrument()->useDrumset();
442             case Pid::PREFER_SHARP_FLAT:
443                   return int(preferSharpFlat());
444             default:
445                   return QVariant();
446             }
447       }
448 
449 //---------------------------------------------------------
450 //   setProperty
451 //---------------------------------------------------------
452 
setProperty(Pid id,const QVariant & property)453 bool Part::setProperty(Pid id, const QVariant& property)
454       {
455       switch (id) {
456             case Pid::VISIBLE:
457                   setShow(property.toBool());
458                   break;
459             case Pid::USE_DRUMSET:
460                   instrument()->setUseDrumset(property.toBool());
461                   break;
462             case Pid::PREFER_SHARP_FLAT:
463                   setPreferSharpFlat(PreferSharpFlat(property.toInt()));
464                   break;
465             default:
466                   qDebug("Part::setProperty: unknown id %d", int(id));
467                   break;
468             }
469       score()->setLayoutAll();
470       return true;
471       }
472 
473 //---------------------------------------------------------
474 //   startTrack
475 //---------------------------------------------------------
476 
startTrack() const477 int Part::startTrack() const
478       {
479       return _staves.front()->idx() * VOICES;
480       }
481 
482 //---------------------------------------------------------
483 //   endTrack
484 //---------------------------------------------------------
485 
endTrack() const486 int Part::endTrack() const
487       {
488       return _staves.back()->idx() * VOICES + VOICES;
489       }
490 
491 //---------------------------------------------------------
492 //   insertTime
493 //---------------------------------------------------------
494 
insertTime(const Fraction & tick,const Fraction & len)495 void Part::insertTime(const Fraction& tick, const Fraction& len)
496       {
497       if (len.isZero())
498             return;
499 
500       // move all instruments
501 
502       if (len < Fraction(0,1)) {
503             // remove instruments between tickpos >= tick and tickpos < (tick+len)
504             // ownership goes back to class InstrumentChange()
505 
506             auto si = _instruments.lower_bound(tick.ticks());
507             auto ei = _instruments.lower_bound((tick-len).ticks());
508             _instruments.erase(si, ei);
509             }
510 
511       InstrumentList il;
512       for (auto i = _instruments.lower_bound(tick.ticks()); i != _instruments.end();) {
513             Instrument* instrument = i->second;
514             int t = i->first;
515             _instruments.erase(i++);
516             _instruments[t + len.ticks()] = instrument;
517             }
518       _instruments.insert(il.begin(), il.end());
519       }
520 
521 //---------------------------------------------------------
522 //   lyricCount
523 //---------------------------------------------------------
524 
lyricCount() const525 int Part::lyricCount() const
526       {
527       if (!score())
528             return 0;
529 
530       if (!score()->firstMeasure())
531             return 0;
532 
533       size_t count = 0;
534       SegmentType st = SegmentType::ChordRest;
535       for (Segment* seg = score()->firstMeasure()->first(st); seg; seg = seg->next1(st)) {
536             for (int i = startTrack(); i < endTrack() ; ++i) {
537                   ChordRest* cr = toChordRest(seg->element(i));
538                   if (cr)
539                         count += cr->lyrics().size();
540                   }
541             }
542       return int(count);
543       }
544 
545 //---------------------------------------------------------
546 //   harmonyCount
547 //---------------------------------------------------------
548 
harmonyCount() const549 int Part::harmonyCount() const
550       {
551       if (!score())
552             return 0;
553 
554       Measure* firstM = score()->firstMeasure();
555       if (!firstM)
556             return 0;
557 
558       SegmentType st = SegmentType::ChordRest;
559       int count = 0;
560       for (const Segment* seg = firstM->first(st); seg; seg = seg->next1(st)) {
561             for (const Element* e : seg->annotations()) {
562                   if ((e->isHarmony() || (e->isFretDiagram() && toFretDiagram(e)->harmony())) && e->track() >= startTrack() && e->track() < endTrack())
563                         count++;
564                   }
565             }
566       return count;
567       }
568 
569 //---------------------------------------------------------
570 //   updateHarmonyChannels
571 ///   update the harmony channel by creating a new channel
572 ///   when appropriate or using the existing one
573 ///
574 ///   checkRemoval can be set to true to check to see if we
575 ///   can remove the harmony channel
576 //---------------------------------------------------------
updateHarmonyChannels(bool isDoOnInstrumentChanged,bool checkRemoval)577 void Part::updateHarmonyChannels(bool isDoOnInstrumentChanged, bool checkRemoval)
578       {
579 
580       auto onInstrumentChanged = [this]() {
581             masterScore()->rebuildMidiMapping();
582             masterScore()->updateChannel();
583             score()->setInstrumentsChanged(true);
584             score()->setLayoutAll(); //do we need this?
585             };
586 
587 
588       // usage of harmony count is okay even if expensive since checking harmony channel will shortcircuit if existent
589       // harmonyCount will only be called on loading of a score (where it will need to be scanned for harmony anyway)
590       // or when the first harmony of a score is just added
591       if (checkRemoval) {
592             //may be a bit expensive since it gets called after every single delete or undo, but it should be okay for now
593             //~OPTIM~
594             if (harmonyCount() == 0) {
595                   Instrument* instr = instrument();
596                   int hChIdx = instr->channelIdx(Channel::HARMONY_NAME);
597                   if (hChIdx != -1) {
598                         Channel* hChan = instr->channel(hChIdx);
599                         instr->removeChannel(hChan);
600                         delete hChan;
601                         if (isDoOnInstrumentChanged)
602                               onInstrumentChanged();
603                         return;
604                         }
605                   }
606             }
607 
608       if (!harmonyChannel() && harmonyCount() > 0) {
609             Instrument* instr = instrument();
610             Channel* c = new Channel(*instr->channel(0));
611             // default to program 0, which is piano in General MIDI
612             c->setProgram(0);
613             if (c->bank() == 128) // drumset?
614                   c->setBank(0);
615             c->setName(Channel::HARMONY_NAME);
616             instr->appendChannel(c);
617             onInstrumentChanged();
618             }
619       }
620 
621 //---------------------------------------------------------
622 //   harmonyChannel
623 //---------------------------------------------------------
624 
harmonyChannel() const625 const Channel* Part::harmonyChannel() const
626       {
627             const Instrument* instr = instrument();
628             if (!instr)
629                   return nullptr;
630 
631             int chanIdx = instr->channelIdx(Channel::HARMONY_NAME);
632             if (chanIdx == -1)
633                   return nullptr;
634 
635             const Channel* chan = instr->channel(chanIdx);
636             Q_ASSERT(chan);
637             return chan;
638       }
639 
640 //---------------------------------------------------------
641 //   hasPitchedStaff
642 //---------------------------------------------------------
643 
hasPitchedStaff() const644 bool Part::hasPitchedStaff() const
645       {
646       if (!staves())
647             return false;
648       for (Staff* s : *staves()) {
649             if (s && s->isPitchedStaff(Fraction(0,1)))
650                   return true;
651             }
652       return false;
653       }
654 
655 //---------------------------------------------------------
656 //   hasTabStaff
657 //---------------------------------------------------------
658 
hasTabStaff() const659 bool Part::hasTabStaff() const
660       {
661       if (!staves())
662             return false;
663       for (Staff* s : *staves()) {
664             if (s && s->isTabStaff(Fraction(0,1)))
665                   return true;
666             }
667       return false;
668       }
669 
670 //---------------------------------------------------------
671 //   hasDrumStaff
672 //---------------------------------------------------------
673 
hasDrumStaff() const674 bool Part::hasDrumStaff() const
675       {
676       if (!staves())
677             return false;
678       for (Staff* s : *staves()) {
679             if (s && s->isDrumStaff(Fraction(0,1)))
680                   return true;
681             }
682       return false;
683       }
684 }
685 
686