1 //=============================================================================
2 //  MuseScore
3 //  Music Composition & Notation
4 //
5 //  Copyright (C) 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 "config.h"
14 #include "musescoreCore.h"
15 #include "style.h"
16 #include "mscore.h"
17 #include "sequencer.h"
18 #include "element.h"
19 #include "dynamic.h"
20 #include "accidental.h"
21 #include "figuredbass.h"
22 #include "stafftype.h"
23 #include "note.h"
24 #include "spanner.h"
25 #include "volta.h"
26 #include "ottava.h"
27 #include "trill.h"
28 #include "repeat.h"
29 #include "jump.h"
30 #include "marker.h"
31 #include "layoutbreak.h"
32 #include "hairpin.h"
33 #include "glissando.h"
34 #include "page.h"
35 #include "slur.h"
36 #include "lyrics.h"
37 #include "accidental.h"
38 #include "notedot.h"
39 #include "tie.h"
40 #include "staff.h"
41 #include "beam.h"
42 #include "timesig.h"
43 #include "part.h"
44 #include "measure.h"
45 #include "score.h"
46 #include "keysig.h"
47 #include "harmony.h"
48 #include "stafftext.h"
49 #include "mscoreview.h"
50 #include "chord.h"
51 #include "hook.h"
52 #include "stem.h"
53 #include "stemslash.h"
54 #include "fraction.h"
55 #include "excerpt.h"
56 #include "spatium.h"
57 #include "barline.h"
58 #include "skyline.h"
59 
60 namespace Ms {
61 
62 bool MScore::debugMode = false;
63 bool MScore::testMode = false;
64 
65 // #ifndef NDEBUG
66 bool MScore::showSegmentShapes   = false;
67 bool MScore::showSkylines        = false;
68 bool MScore::showMeasureShapes   = false;
69 bool MScore::noHorizontalStretch = false;
70 bool MScore::noVerticalStretch   = false;
71 bool MScore::showBoundingRect    = false;
72 bool MScore::showSystemBoundingRect    = false;
73 bool MScore::showCorruptedMeasures = true;
74 bool MScore::useFallbackFont       = true;
75 // #endif
76 
77 bool  MScore::saveTemplateMode = false;
78 bool  MScore::noGui = false;
79 
80 MStyle* MScore::_defaultStyleForParts;
81 
82 QString MScore::_globalShare;
83 int     MScore::_vRaster;
84 int     MScore::_hRaster;
85 bool    MScore::_verticalOrientation = false;
86 qreal   MScore::verticalPageGap = 5.0;
87 qreal   MScore::horizontalPageGapEven = 1.0;
88 qreal   MScore::horizontalPageGapOdd = 50.0;
89 
90 QColor  MScore::selectColor[VOICES];
91 QColor  MScore::defaultColor;
92 QColor  MScore::layoutBreakColor;
93 QColor  MScore::frameMarginColor;
94 QColor  MScore::bgColor;
95 QColor  MScore::dropColor;
96 bool    MScore::warnPitchRange;
97 int     MScore::pedalEventsMinTicks;
98 
99 bool    MScore::harmonyPlayDisableCompatibility;
100 bool    MScore::harmonyPlayDisableNew;
101 bool    MScore::playRepeats;
102 bool    MScore::panPlayback;
103 int     MScore::playbackSpeedIncrement;
104 qreal   MScore::nudgeStep;
105 qreal   MScore::nudgeStep10;
106 qreal   MScore::nudgeStep50;
107 int     MScore::defaultPlayDuration;
108 
109 QString MScore::lastError;
110 int     MScore::division    = 480; // 3840;   // pulses per quarter note (PPQ) // ticks per beat
111 int     MScore::sampleRate  = 44100;
112 int     MScore::mtcType;
113 
114 bool    MScore::noExcerpts = false;
115 bool    MScore::noImages = false;
116 bool    MScore::pdfPrinting = false;
117 bool    MScore::svgPrinting = false;
118 
119 double  MScore::pixelRatio  = 0.8;        // DPI / logicalDPI
120 
121 MPaintDevice* MScore::_paintDevice;
122 
123 Sequencer* MScore::seq = 0;
124 MuseScoreCore* MuseScoreCore::mscoreCore;
125 
126 extern void initDrumset();
127 extern void initScoreFonts();
128 extern QString mscoreGlobalShare;
129 
130 std::vector<MScoreError> MScore::errorList {
131       { MS_NO_ERROR,                     0,    0                                                                           },
132 
133       { NO_NOTE_SELECTED,                "s1", QT_TRANSLATE_NOOP("error", "No note selected:\nPlease select a note and retry")                     },
134       { NO_CHORD_REST_SELECTED,          "s2", QT_TRANSLATE_NOOP("error", "No chord/rest selected:\nPlease select a chord or rest and retry")      },
135       { NO_LYRICS_SELECTED,              "s3", QT_TRANSLATE_NOOP("error", "No note or lyrics selected:\nPlease select a note or lyrics and retry") },
136       { NO_NOTE_REST_SELECTED,           "s4", QT_TRANSLATE_NOOP("error", "No note or rest selected:\nPlease select a note or rest and retry")     },
137       { NO_FLIPPABLE_SELECTED,           "s5", QT_TRANSLATE_NOOP("error", "No flippable element selected:\nPlease select an element that can be flipped and retry") },
138       { NO_STAFF_SELECTED,               "s6", QT_TRANSLATE_NOOP("error", "No staff selected:\nPlease select one or more staves and retry")        },
139       { NO_NOTE_FIGUREDBASS_SELECTED,    "s7", QT_TRANSLATE_NOOP("error", "No note or figured bass selected:\nPlease select a note or figured bass and retry") },
140 
141       { CANNOT_INSERT_TUPLET,            "t1", QT_TRANSLATE_NOOP("error", "Cannot insert chord/rest in tuplet")                                    },
142       { CANNOT_SPLIT_TUPLET,             "t2", QT_TRANSLATE_NOOP("error", "Cannot split tuplet")                                                   },
143       { CANNOT_SPLIT_MEASURE_FIRST_BEAT, "m1", QT_TRANSLATE_NOOP("error", "Cannot split measure here:\n" "First beat of measure")                  },
144       { CANNOT_SPLIT_MEASURE_TUPLET,     "m2", QT_TRANSLATE_NOOP("error", "Cannot split measure here:\n" "Cannot split tuplet")                    },
145 
146       { NO_DEST,                         "p1", QT_TRANSLATE_NOOP("error", "No destination to paste")                                               },
147       { DEST_TUPLET,                     "p2", QT_TRANSLATE_NOOP("error", "Cannot paste into tuplet")                                              },
148       { TUPLET_CROSSES_BAR,              "p3", QT_TRANSLATE_NOOP("error", "Tuplet cannot cross barlines")                                          },
149       { DEST_LOCAL_TIME_SIGNATURE,       "p4", QT_TRANSLATE_NOOP("error", "Cannot paste in local time signature")                                  },
150       { DEST_TREMOLO,                    "p5", QT_TRANSLATE_NOOP("error", "Cannot paste in tremolo")                                               },
151       { NO_MIME,                         "p6", QT_TRANSLATE_NOOP("error", "Nothing to paste")                                                      },
152       { DEST_NO_CR,                      "p7", QT_TRANSLATE_NOOP("error", "Destination is not a chord or rest")                                    },
153       { CANNOT_CHANGE_LOCAL_TIMESIG,     "l1", QT_TRANSLATE_NOOP("error", "Cannot change local time signature:\nMeasure is not empty")             },
154       };
155 
156 MsError MScore::_error { MS_NO_ERROR };
157 
158 //---------------------------------------------------------
159 //   Direction
160 //---------------------------------------------------------
161 
toDirection(const QString & s)162 Direction toDirection(const QString& s)
163       {
164       Direction val;
165       if (s == "up")
166             val = Direction::UP;
167       else if (s == "down")
168             val = Direction::DOWN;
169       else if (s == "auto")
170             val = Direction::AUTO;
171       else
172             val = Direction(s.toInt());
173       return val;
174       }
175 
176 //---------------------------------------------------------
177 //   Direction::toString
178 //---------------------------------------------------------
179 
toString(Direction val)180 const char* toString(Direction val)
181       {
182       switch (val) {
183             case Direction::AUTO: return "auto";
184             case Direction::UP:   return "up";
185             case Direction::DOWN: return "down";
186             }
187 #if (!defined (_MSCVER) && !defined (_MSC_VER))
188       __builtin_unreachable();
189 #else
190       // The MSVC __assume() optimizer hint is similar, though not identical, to __builtin_unreachable()
191       __assume(0);
192 #endif
193       }
194 
195 //---------------------------------------------------------
196 //   Direction::toUserString
197 //---------------------------------------------------------
198 
toUserString(Direction val)199 QString toUserString(Direction val)
200       {
201       switch (val) {
202             case Direction::AUTO: return qApp->translate("Direction", "Auto");
203             case Direction::UP:   return qApp->translate("Direction", "Up");
204             case Direction::DOWN: return qApp->translate("Direction", "Down");
205             }
206 #if (!defined (_MSCVER) && !defined (_MSC_VER))
207       __builtin_unreachable();
208 #else
209       // The MSVC __assume() optimizer hint is similar, though not identical, to __builtin_unreachable()
210       __assume(0);
211 #endif
212       }
213 
214 //---------------------------------------------------------
215 //   fillComboBox
216 //---------------------------------------------------------
217 
fillComboBoxDirection(QComboBox * cb)218 void fillComboBoxDirection(QComboBox* cb)
219       {
220       cb->clear();
221       cb->addItem(toUserString(Direction::AUTO), QVariant::fromValue<Direction>(Direction::AUTO));
222       cb->addItem(toUserString(Direction::UP),   QVariant::fromValue<Direction>(Direction::UP));
223       cb->addItem(toUserString(Direction::DOWN), QVariant::fromValue<Direction>(Direction::DOWN));
224       }
225 
226 //---------------------------------------------------------
227 //   doubleToSpatium
228 //---------------------------------------------------------
229 
doubleToSpatium(double d)230 static Spatium doubleToSpatium(double d)
231       {
232       return Spatium(d);
233       }
234 
235 //---------------------------------------------------------
236 //   init
237 //---------------------------------------------------------
238 
init()239 void MScore::init()
240       {
241       static bool initDone = false;
242       if (initDone)
243             return;
244 
245       if (!QMetaType::registerConverter<Spatium, double>(&Spatium::toDouble))
246             qFatal("registerConverter Spatium::toDouble failed");
247       if (!QMetaType::registerConverter<double, Spatium>(&doubleToSpatium))
248             qFatal("registerConverter doubleToSpatium failed");
249 //      if (!QMetaType::registerComparators<Spatium>())
250 //            qFatal("registerComparators for Spatium failed");
251 
252 #ifdef SCRIPT_INTERFACE
253       qRegisterMetaType<Note::ValueType>   ("ValueType");
254 
255       qRegisterMetaType<MScore::DirectionH>("DirectionH");
256       qRegisterMetaType<Spanner::Anchor>   ("Anchor");
257       qRegisterMetaType<NoteHead::Group>   ("NoteHeadGroup");
258       qRegisterMetaType<NoteHead::Type>("NoteHeadType");
259       qRegisterMetaType<SegmentType>("SegmentType");
260       qRegisterMetaType<FiguredBassItem::Modifier>("Modifier");
261       qRegisterMetaType<FiguredBassItem::Parenthesis>("Parenthesis");
262       qRegisterMetaType<FiguredBassItem::ContLine>("ContLine");
263       qRegisterMetaType<Volta::Type>("VoltaType");
264       qRegisterMetaType<OttavaType>("OttavaType");
265       qRegisterMetaType<Trill::Type>("TrillType");
266       qRegisterMetaType<Dynamic::Range>("DynamicRange");
267       qRegisterMetaType<Jump::Type>("JumpType");
268       qRegisterMetaType<Marker::Type>("MarkerType");
269       qRegisterMetaType<Beam::Mode>("BeamMode");
270       qRegisterMetaType<HairpinType>("HairpinType");
271       qRegisterMetaType<Lyrics::Syllabic>("Syllabic");
272       qRegisterMetaType<LayoutBreak::Type>("LayoutBreakType");
273 
274       //classed enumerations
275 //      qRegisterMetaType<MSQE_StyledPropertyListIdx::E>("StyledPropertyListIdx");
276 //      qRegisterMetaType<MSQE_BarLineType::E>("BarLineType");
277 #endif
278       qRegisterMetaType<Fraction>("Fraction");
279 
280       if (!QMetaType::registerConverter<Fraction, QString>(&Fraction::toString))
281           qFatal("registerConverter Fraction::toString failed");
282 
283 #ifdef Q_OS_WIN
284       QDir dir(QCoreApplication::applicationDirPath() + QString("/../" INSTALL_NAME));
285       _globalShare = dir.absolutePath() + "/";
286 #elif defined(Q_OS_IOS)
287       {
288       extern QString resourcePath();
289       _globalShare = resourcePath();
290       }
291 
292 #elif defined(Q_OS_MAC)
293       QDir dir(QCoreApplication::applicationDirPath() + QString("/../Resources"));
294       _globalShare = dir.absolutePath() + "/";
295 #else
296       // Try relative path (needed for portable AppImage and non-standard installations)
297       QDir dir(QCoreApplication::applicationDirPath() + QString("/../share/" INSTALL_NAME));
298       if (dir.exists())
299             _globalShare = dir.absolutePath() + "/";
300       else // Fall back to default location (e.g. if binary has moved relative to share)
301             _globalShare = QString( INSTPREFIX "/share/" INSTALL_NAME);
302 #endif
303 
304       selectColor[0].setNamedColor("#0065BF");   //blue
305       selectColor[1].setNamedColor("#007F00");   //green
306       selectColor[2].setNamedColor("#C53F00");   //orange
307       selectColor[3].setNamedColor("#C31989");   //purple
308 
309       defaultColor           = Qt::black;
310       dropColor              = QColor("#1778db");
311       defaultPlayDuration    = 300;      // ms
312       warnPitchRange         = true;
313       pedalEventsMinTicks    = 1;
314       playRepeats            = true;
315       panPlayback            = true;
316       playbackSpeedIncrement = 5;
317 
318       lastError           = "";
319 
320       layoutBreakColor    = QColor("#A0A0A4");
321       frameMarginColor    = QColor("#A0A0A4");
322       bgColor.setNamedColor("#dddddd");
323 
324       //
325       //  initialize styles
326       //
327       _baseStyle.precomputeValues();
328       QSettings s;
329       QString defStyle = s.value("score/style/defaultStyleFile").toString();
330       if (!(MScore::testMode || defStyle.isEmpty())) {
331             QFile f(defStyle);
332             if (f.open(QIODevice::ReadOnly)) {
333                   qDebug("load default style <%s>", qPrintable(defStyle));
334                   _defaultStyle.load(&f);
335                   f.close();
336                   }
337             }
338       _defaultStyle.precomputeValues();
339       QString partStyle = s.value("score/style/partStyleFile").toString();
340       if (!(MScore::testMode || partStyle.isEmpty())) {
341             QFile f(partStyle);
342             if (f.open(QIODevice::ReadOnly)) {
343                   qDebug("load default style for parts <%s>", qPrintable(partStyle));
344                   _defaultStyleForParts = new MStyle(_defaultStyle);
345                   _defaultStyleForParts->load(&f);
346                   _defaultStyleForParts->precomputeValues();
347                   }
348             }
349 
350       //
351       //  load internal fonts
352       //
353       //
354       // do not load application specific fonts
355       // for MAC, they are in Resources/fonts
356       //
357 #if !defined(Q_OS_MAC) && !defined(Q_OS_IOS)
358       static const char* fonts[] = {
359             ":/fonts/musejazz/MuseJazzText.otf",
360             ":/fonts/campania/Campania.otf",
361             ":/fonts/edwin/Edwin-Roman.otf",
362             ":/fonts/edwin/Edwin-Bold.otf",
363             ":/fonts/edwin/Edwin-Italic.otf",
364             ":/fonts/edwin/Edwin-BdIta.otf",
365             ":/fonts/FreeSans.ttf",
366             ":/fonts/FreeSerif.ttf",
367             ":/fonts/FreeSerifBold.ttf",
368             ":/fonts/FreeSerifItalic.ttf",
369             ":/fonts/FreeSerifBoldItalic.ttf",
370             ":/fonts/mscoreTab.ttf",
371             ":/fonts/mscore-BC.ttf",
372             ":/fonts/leland/LelandText.otf",
373             ":/fonts/bravura/BravuraText.otf",
374             ":/fonts/gootville/GootvilleText.otf",
375             ":/fonts/mscore/MScoreText.ttf",
376             ":/fonts/petaluma/PetalumaText.otf",
377             ":/fonts/petaluma/PetalumaScript.otf",
378             };
379 
380       for (unsigned i = 0; i < sizeof(fonts)/sizeof(*fonts); ++i) {
381             QString str(fonts[i]);
382             if (-1 == QFontDatabase::addApplicationFont(str)) {
383                   if (!MScore::testMode)
384                         qDebug("Mscore: fatal error: cannot load internal font <%s>", qPrintable(str));
385                   if (!MScore::debugMode && !MScore::testMode)
386                         exit(-1);
387                   }
388             }
389 #endif
390 // Workaround for QTBUG-73241 (solved in Qt 5.12.2) in Windows 10, see https://musescore.org/en/node/280244
391 #if defined(Q_OS_WIN) && (QT_VERSION < QT_VERSION_CHECK(5, 12, 2))
392 if (QOperatingSystemVersion::current().majorVersion() >= 10) {
393       const QDir additionalFontsDir(QString("%1/Microsoft/Windows/Fonts").arg(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)));
394       if (additionalFontsDir.exists()) {
395             QFileInfoList fileList = additionalFontsDir.entryInfoList();
396             for (int i = 0; i < fileList.size(); ++i) {
397                   QFileInfo fileInfo = fileList.at(i);
398                   QFontDatabase::addApplicationFont(fileInfo.filePath());
399                   }
400             }
401       }
402 #endif
403       initScoreFonts();
404       StaffType::initStaffTypes();
405       initDrumset();
406       FiguredBass::readConfigFile(0);
407 
408 #ifdef DEBUG_SHAPES
409       testShapes();
410 #endif
411 
412       initDone = true;
413       }
414 
415 //---------------------------------------------------------
416 //   readDefaultStyle
417 //---------------------------------------------------------
418 
readDefaultStyle(QString file)419 bool MScore::readDefaultStyle(QString file)
420       {
421       if (file.isEmpty())
422             return false;
423       MStyle style = defaultStyle();
424       QFile f(file);
425       if (!f.open(QIODevice::ReadOnly))
426             return false;
427       bool rv = style.load(&f, true);
428       if (rv)
429             setDefaultStyle(style);
430       f.close();
431       return rv;
432       }
433 
434 //---------------------------------------------------------
435 //   defaultStyleForPartsHasChanged
436 //---------------------------------------------------------
437 
defaultStyleForPartsHasChanged()438 void MScore::defaultStyleForPartsHasChanged()
439       {
440 // TODO what is needed here?
441 //      delete _defaultStyleForParts;
442 //      _defaultStyleForParts = 0;
443       }
444 
445 //---------------------------------------------------------
446 //   errorMessage
447 //---------------------------------------------------------
448 
errorMessage()449 const char* MScore::errorMessage()
450       {
451       for (MScoreError& e : errorList) {
452             if (e.no == _error)
453                   return e.txt;
454             }
455       return QT_TRANSLATE_NOOP("error", "Unknown error");
456       }
457 
458 //---------------------------------------------------------
459 //   errorGroup
460 //---------------------------------------------------------
461 
errorGroup()462 const char* MScore::errorGroup()
463       {
464       for (MScoreError& e : errorList) {
465             if (e.no == _error)
466                   return e.group;
467             }
468       return "";
469       }
470 
471 //---------------------------------------------------------
472 //   paintDevice
473 //---------------------------------------------------------
474 
paintDevice()475 MPaintDevice* MScore::paintDevice()
476       {
477       if (!_paintDevice)
478             _paintDevice = new MPaintDevice();
479       return _paintDevice;
480       }
481 
482 //---------------------------------------------------------
483 //   metric
484 //---------------------------------------------------------
485 
metric(PaintDeviceMetric m) const486 int MPaintDevice::metric(PaintDeviceMetric m) const
487       {
488       switch (m) {
489             case QPaintDevice::PdmDpiY:
490                   return int(DPI);
491             default:
492 //printf("debug: metric %d\n", int(m));
493                   return 1;
494             }
495       }
496 
497 //---------------------------------------------------------
498 //   paintEngine
499 //---------------------------------------------------------
500 
paintEngine() const501 QPaintEngine* MPaintDevice::paintEngine() const
502       {
503 //printf("paint engine\n");
504       return 0;
505       }
506 
507 }
508 
509