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