1 //=========================================================
2 //  MusE
3 //  Linux Music Editor
4 //  $Id: app.cpp,v 1.113.2.68 2009/12/21 14:51:51 spamatica Exp $
5 //
6 //  (C) Copyright 1999-2011 Werner Schweer (ws@seh.de)
7 //
8 //  This program is free software; you can redistribute it and/or
9 //  modify it under the terms of the GNU General Public License
10 //  as published by the Free Software Foundation; version 2 of
11 //  the License, or (at your option) any later version.
12 //
13 //  This program is distributed in the hope that it will be useful,
14 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 //  GNU General Public License for more details.
17 //
18 //  You should have received a copy of the GNU General Public License
19 //  along with this program; if not, write to the Free Software
20 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 //
22 //=========================================================
23 
24 #include <QApplication>
25 #include <QCommandLineParser>
26 #include <QCommandLineOption>
27 #include <QDir>
28 #include <QFile>
29 //#include <QFileInfo>
30 #include <QFileInfoList>
31 #include <QDirIterator>
32 #include <QKeyEvent>
33 #include <QMessageBox>
34 #include <QLocale>
35 #include <QSplashScreen>
36 #include <QTimer>
37 #include <QTranslator>
38 #include <QIcon>
39 #include <QString>
40 #include <QStringList>
41 //#include <QStyle>
42 #include <QStyleFactory>
43 #include <QStyleHints>
44 #include <QStandardPaths>
45 #include <QTime>
46 #include <QDebug>
47 #include <QElapsedTimer>
48 
49 //#include <iostream>
50 
51 #include <time.h>
52 #ifndef _WIN32
53 #include <sys/mman.h>
54 #endif
55 
56 #include "config.h"
57 
58 #ifdef ALSA_SUPPORT
59 #include <alsa/asoundlib.h>
60 #endif
61 
62 #include "al/al.h"
63 #include "al/dsp.h"
64 #include "app.h"
65 #include "audio.h"
66 #include "audiodev.h"
67 #include "gconfig.h"
68 #include "globals.h"
69 #include "helper.h"
70 #include "sync.h"
71 #include "functions.h"
72 #include "appearance.h"
73 #include "midiseq.h"
74 #include "minstrument.h"
75 #include "midiport.h"
76 #include "mididev.h"
77 #include "plugin.h"
78 #include "wavepreview.h"
79 #include "plugin_cache_writer.h"
80 #include "pluglist.h"
81 #include "metronome_class.h"
82 #include "audio_convert/audio_converter_plugin.h"
83 #include "audio_convert/audio_converter_settings_group.h"
84 #include "wave.h"
85 #include "conf.h"
86 
87 #ifdef HAVE_LASH
88 #include <lash/lash.h>
89 #endif
90 
91 namespace MusECore {
92 extern bool initDummyAudio();
93 #ifdef HAVE_RTAUDIO
94 extern bool initRtAudio(bool forceDefault = false);
95 #endif
96 extern bool initJackAudio();
97 extern void initMidiController();
98 extern void initMetronome();
99 //extern void initOSC();
100 extern void initVST();
101 extern void initVST_Native();
102 //extern void initPlugins();
103 extern void initDSSI();
104 #ifdef LV2_SUPPORT
105 extern void initLV2();
106 extern void deinitLV2();
107 #endif
108 //extern bool readConfiguration();
109 
110 //extern void initMidiSequencer();
111 //extern void exitMidiSequencer();
112 extern void initAudio();
113 extern void initAudioPrefetch();
114 extern void initMidiSynth();
115 
116 #ifdef ALSA_SUPPORT
117 extern snd_seq_t * alsaSeq;
118 #endif
119 
120 extern void setAlsaClientName(const char*);
121 }
122 
123 namespace MusEGui {
124 void initIcons(int cursorSize, const QString& gpath, const QString& upath);
125 void initShortCuts();
126 #ifdef HAVE_LASH
127 extern lash_client_t * lash_client;
128 #endif
129 extern QStringList projectRecentList;
130 }
131 
132 enum AudioDriverSelect {
133   DriverConfigSetting,
134   DummyAudioOverride,
135   JackAudioOverride,
136   RtAudioOverride,
137 
138 };
139 
140 static QString locale_override;
141 
142 //---------------------------------------------------------
143 //   MuseApplication
144 //---------------------------------------------------------
145 
146 class MuseApplication : public QApplication {
147       MusEGui::MusE* muse;
148 
149    public:
MuseApplication(int & argc,char ** argv)150       MuseApplication(int& argc, char** argv)
151          : QApplication(argc, argv)
152             {
153             muse = nullptr;
154             }
155 
156 
setMuse(MusEGui::MusE * m)157       void setMuse(MusEGui::MusE* m) {
158             muse = m;
159 
160             connect(this,SIGNAL(focusChanged(QWidget*,QWidget*)),muse,SLOT(focusChanged(QWidget*,QWidget*)));
161 #ifdef HAVE_LASH
162             if(MusEGlobal::useLASH)
163               startTimer (300);
164 #endif
165             }
166 
notify(QObject * receiver,QEvent * event)167       bool notify(QObject* receiver, QEvent* event) override {
168          const bool flag = QApplication::notify(receiver, event);
169          const QEvent::Type type = event->type();
170          if (type == QEvent::KeyPress) {
171             const QMetaObject * mo = receiver->metaObject();
172             if (mo){
173                if (strcmp(mo->className(), "QWidgetWindow") == 0)
174                  return false;
175             }
176             QKeyEvent* ke = (QKeyEvent*)event;
177             MusEGlobal::globalKeyState = ke->modifiers();
178 
179             bool accepted = ke->isAccepted();
180               if (!accepted) {
181                int key = ke->key();
182                if (((QInputEvent*)ke)->modifiers() & Qt::ShiftModifier)
183                   key += Qt::SHIFT;
184                if (((QInputEvent*)ke)->modifiers() & Qt::AltModifier)
185                   key += Qt::ALT;
186                if (((QInputEvent*)ke)->modifiers() & Qt::ControlModifier)
187                   key+= Qt::CTRL;
188                if(muse)
189                  muse->kbAccel(key);
190                return true;
191             }
192          }
193          else if (type == QEvent::KeyRelease) {
194             QKeyEvent* ke = (QKeyEvent*)event;
195             ///MusEGlobal::globalKeyState = ke->stateAfter();
196             MusEGlobal::globalKeyState = ke->modifiers();
197          }
198 
199          return flag;
200       }
201 
202 #ifdef HAVE_LASH
timerEvent(QTimerEvent *)203      virtual void timerEvent (QTimerEvent*) {
204             if(muse && MusEGlobal::useLASH)
205               muse->lash_idle_cb ();
206             }
207 #endif /* HAVE_LASH */
208 
209       };
210 
211 //---------------------------------------------------------
212 //   localeList
213 //---------------------------------------------------------
214 
localeList()215 static QString localeList()
216       {
217       // Find out what translations are available:
218       QStringList deliveredLocaleListFiltered;
219       QString distLocale = MusEGlobal::museGlobalShare + "/locale";
220       QFileInfo distLocaleFi(distLocale);
221       if (distLocaleFi.isDir()) {
222             QDir dir = QDir(distLocale);
223             QStringList deliveredLocaleList = dir.entryList();
224             for(QStringList::iterator it = deliveredLocaleList.begin(); it != deliveredLocaleList.end(); ++it) {
225                   QString item = *it;
226                   if (item.endsWith(".qm")) {
227                         int inipos = item.indexOf("muse_") + 5;
228                         int finpos = item.lastIndexOf(".qm");
229                         deliveredLocaleListFiltered << item.mid(inipos, finpos - inipos);
230                         }
231                   }
232             return deliveredLocaleListFiltered.join(",");
233             }
234       return QString("No translations found!");
235       }
236 
fallbackDummy()237 void fallbackDummy() {
238 
239   fprintf(stderr, "Falling back to dummy audio driver\n");
240   QMessageBox::critical(nullptr, "MusE fatal error", "MusE <b>failed</b> to find selected <b>audio server</b>.<br><br>"
241                                                   "<i>MusE will continue <b>without audio support</b> (-a switch)!</i>");
242   MusEGlobal::realTimeScheduling = true;
243   MusECore::initDummyAudio();
244 }
245 
246 //---------------------------------------------------------
247 //   printExtraHelpText
248 //---------------------------------------------------------
249 
printExtraHelpText()250 static void printExtraHelpText()
251       {
252       printf("\n");
253 #ifdef HAVE_LASH
254       printf("LASH and ");
255 #endif
256       printf("Qt options are also accepted. Some common Qt options:\n");
257       printf("   -style [=] style           Set application GUI style (Fusion, Windows etc.)\n"
258                       "   -stylesheet [=] stylesheet Set application styleSheet\n"
259                       "   -session [=] session       Restore application from an earlier session\n"
260                       "   -widgetcount               Print debug message at end, about undestroyed/maximum widgets\n"
261                       "   -reverse                   Set application's layout direction to Qt::RightToLeft\n"
262                       "   -graphicssystem            Set backend used for on-screen widgets/QPixmaps: raster or opengl\n"
263                       "   -qmljsdebugger = port      Activate QML/JS debugger with port, formatted port:1234[,block]\n"
264       );
265 
266       printf("\n");
267 
268       printf("Some useful environment variables:\n\n");
269       printf("   LANG: Help browser language suffix (en etc.)\n\n");
270       printf("These variables are read ONCE upon first-time run, to fill the Plugin Paths\n"
271                       " in Global Settings. Afterwards the paths can be altered in Global Settings:\n\n");
272       printf("   LADSPA_PATH: Override where to look for ladspa plugins, or else\n"
273                       "     ~/ladspa:~/.ladspa:/usr/local/lib64/ladspa:/usr/lib64/ladspa:/usr/local/lib/ladspa:/usr/lib/ladspa\n\n");
274 #ifdef DSSI_SUPPORT
275       printf("   DSSI_PATH: Override where to look for dssi plugins, or else\n"
276                       "     ~/dssi:~/.dssi:/usr/local/lib64/dssi:/usr/lib64/dssi:/usr/local/lib/dssi:/usr/lib/dssi\n\n" );
277       printf("   VST_PATH: Override where dssi-vst (if installed) looks for Wine vst plugins, or else\n"
278                       "     ~/vst win 32bit:~/.vst win 32bit or ~/vst:~/.vst on windows\n\n");
279 #endif
280 #ifdef VST_NATIVE_SUPPORT
281       printf("   LXVST_PATH: Override where to look for Linux vst plugins, or else VST_PATH, or else\n"
282                       "     ~/lxvst:~/.lxvst:/usr/local/lib64/lxvst:/usr/local/lib/lxvst:/usr/lib64/lxvst:/usr/lib/lxvst\n"
283                       "     also on Linux ~/vst:~/.vst:/usr/local/lib64/vst:/usr/local/lib/vst:/usr/lib64/vst:/usr/lib/vst\n\n");
284 #endif
285 #ifdef LV2_SUPPORT
286       printf("   LV2_PATH: Override where to look for LV2 plugins or else\n"
287                       "     ~/.lv2:/usr/local/lib/lv2:/usr/lib/lv2\n\n");
288 #endif
289       }
290 
291 enum CommandLineParseResult
292 {
293     CommandLineOk,
294     CommandLineError,
295     CommandLineVersionRequested,
296     CommandLineHelpRequested
297 };
298 
parseCommandLine(QCommandLineParser & parser,QString * errorMessage,QString & open_filename,AudioDriverSelect & audioType,bool & force_plugin_rescan,bool & dont_plugin_rescan)299 CommandLineParseResult parseCommandLine(
300   QCommandLineParser &parser, QString *errorMessage,
301   QString& open_filename, AudioDriverSelect& audioType, bool& force_plugin_rescan, bool& dont_plugin_rescan)
302 {
303   parser.setApplicationDescription(APP_DESCRIPTION);
304   const QString version_string(VERSION);
305   const QString git_string(GITSTRING);
306   if(git_string.isEmpty())
307     QCoreApplication::setApplicationVersion(version_string);
308   else
309     QCoreApplication::setApplicationVersion(version_string + ", (" + git_string + ")");
310   const QCommandLineOption helpOption = parser.addHelpOption();
311   const QCommandLineOption versionOption = parser.addVersionOption();
312 
313   parser.addPositionalArgument("filename", QCoreApplication::translate("main", "File to open"));
314 
315   QCommandLineOption option_a("a", QCoreApplication::translate("main", "Alsa midi only (using dummy audio driver)"));
316   parser.addOption(option_a);
317 
318 #ifdef HAVE_RTAUDIO
319   QCommandLineOption option_t("t", QCoreApplication::translate("main", "Use RtAudio driver"));
320   parser.addOption(option_t);
321 #endif
322   QCommandLineOption option_j("j", QCoreApplication::translate("main", "Use JAckAudio driver to connect to Jack audio server"));
323   parser.addOption(option_j);
324   QCommandLineOption option_J("J", QCoreApplication::translate("main", "Do not try to auto-start the Jack audio server"));
325   parser.addOption(option_J);
326   QCommandLineOption option_F("F", QCoreApplication::translate("main",
327     "Do not auto-populate midi ports with midi devices found, at startup"));
328   parser.addOption(option_F);
329   QCommandLineOption option_A("A", QCoreApplication::translate("main", "Force inclusion of ALSA midi even if using Jack"));
330   parser.addOption(option_A);
331   QCommandLineOption option_P("P", QCoreApplication::translate("main",
332     "Set audio driver real time priority to n (Dummy only, default 40. Else fixed by Jack.)"), "n");
333   parser.addOption(option_P);
334   QCommandLineOption option_Y("Y", QCoreApplication::translate("main",
335     "Force midi real time priority to n (default: audio driver prio -1)\n"), "n");
336   parser.addOption(option_Y);
337 
338   QCommandLineOption option_R("R", QCoreApplication::translate("main",
339     "Force plugin cache re-creation. (Automatic if any plugin path directories changed.)"));
340   parser.addOption(option_R);
341   QCommandLineOption option_C("C", QCoreApplication::translate("main",
342     "Do not re-create plugin cache. Avoids repeated re-creations in some circumstances. Use with care."));
343   parser.addOption(option_C);
344   QCommandLineOption option_p("p", QCoreApplication::translate("main", "Don't load LADSPA plugins"));
345   parser.addOption(option_p);
346   QCommandLineOption option_S("S", QCoreApplication::translate("main", "Don't load MESS plugins"));
347   parser.addOption(option_S);
348 #ifdef VST_SUPPORT
349   QCommandLineOption option_V("V", QCoreApplication::translate("main", "Don't load VST plugins"));
350   parser.addOption(option_V);
351 #endif
352 #ifdef VST_NATIVE_SUPPORT
353   QCommandLineOption option_N("N", QCoreApplication::translate("main", "Don't load LinuxVST plugins"));
354   parser.addOption(option_N);
355 #endif
356 #ifdef DSSI_SUPPORT
357   QCommandLineOption option_I("I", QCoreApplication::translate("main", "Don't load DSSI plugins"));
358   parser.addOption(option_I);
359 #endif
360 #ifdef LV2_SUPPORT
361   QCommandLineOption option_2("2", QCoreApplication::translate("main", "Don't load LV2 plugins"));
362   parser.addOption(option_2);
363 #endif
364 #ifdef HAVE_LASH
365   QCommandLineOption option_L("L", QCoreApplication::translate("main", "Don't use LASH"));
366   parser.addOption(option_L);
367 #endif
368 
369   QCommandLineOption option_l(QCommandLineOption("l", QCoreApplication::translate("main",
370     "Force locale to the given language/country code (xx = ") + localeList() + ")",  "xx"));
371   parser.addOption(option_l);
372   QCommandLineOption option_u("u", QCoreApplication::translate("main",
373     "Ubuntu/unity workaround: don't allow sharing menus and mdi-subwins."));
374   parser.addOption(option_u);
375   QCommandLineOption option_d("d", QCoreApplication::translate("main", "Debug mode: no threads, no RT"));
376   parser.addOption(option_d);
377   QCommandLineOption option_D("D", QCoreApplication::translate("main",
378     "Debug mode: enable some debug messages specify twice for lots of debug messages this may slow down MusE massively!"));
379   parser.addOption(option_D);
380   QCommandLineOption option_m("m", QCoreApplication::translate("main", "Debug mode: trace midi Input"));
381   parser.addOption(option_m);
382   QCommandLineOption option_M("M", QCoreApplication::translate("main", "Debug mode: trace midi Output"));
383   parser.addOption(option_M);
384   QCommandLineOption option_s("s", QCoreApplication::translate("main", "Debug mode: trace sync\n"));
385   parser.addOption(option_s);
386 
387 #ifdef PYTHON_SUPPORT
388   QCommandLineOption option_y("y", QCoreApplication::translate("main", "Enable Python control support"));
389   parser.addOption(option_y);
390   QCommandLineOption option_pyro_ns_host("pyro-ns-host",
391     QCoreApplication::translate("main", "Pyro nameserver host name"), "hostname");
392   parser.addOption(option_pyro_ns_host);
393   QCommandLineOption option_pyro_ns_port("pyro-ns-port",
394     QCoreApplication::translate("main", "Pyro nameserver host port"), "port");
395   parser.addOption(option_pyro_ns_port);
396   QCommandLineOption option_pyro_daemon_host("pyro-daemon-host",
397     QCoreApplication::translate("main", "Pyro daemon host name"), "hostname");
398   parser.addOption(option_pyro_daemon_host);
399   QCommandLineOption option_pyro_daemon_port("pyro-daemon-port",
400     QCoreApplication::translate("main", "Pyro daemon host port"), "port");
401   parser.addOption(option_pyro_daemon_port);
402   QCommandLineOption option_pyro_comm_timeout("pyro-comm-timeout",
403     QCoreApplication::translate("main", "Pyro communication timeout in seconds"), "timeout");
404   parser.addOption(option_pyro_comm_timeout);
405 #endif
406 
407   if(!parser.parse(QCoreApplication::arguments()))
408   {
409     *errorMessage = parser.errorText();
410     return CommandLineError;
411   }
412 
413   if(parser.isSet(versionOption))
414     return CommandLineVersionRequested;
415 
416   if(parser.isSet(helpOption))
417     return CommandLineHelpRequested;
418 
419   const QStringList used_positional_args = parser.positionalArguments();
420   const int used_positional_args_sz = used_positional_args.size();
421   if(used_positional_args_sz > 1)
422   {
423     *errorMessage = "Error: Expected only one positional argument";
424     return CommandLineError;
425   }
426   else if(used_positional_args_sz == 1)
427   {
428     open_filename = used_positional_args.first();
429   }
430 
431   if(parser.isSet(option_a))
432     audioType = DummyAudioOverride;
433 
434   if(parser.isSet(option_l))
435     locale_override = parser.value(option_l);
436 
437 #ifdef HAVE_RTAUDIO
438   if(parser.isSet(option_t))
439     audioType = RtAudioOverride;
440 #endif
441 
442   if(parser.isSet(option_J))
443     MusEGlobal::noAutoStartJack = true;
444 
445   if(parser.isSet(option_j))
446     audioType = JackAudioOverride;
447 
448   if(parser.isSet(option_F))
449     MusEGlobal::populateMidiPortsOnStart = false;
450 
451   if(parser.isSet(option_A))
452     MusEGlobal::useAlsaWithJack = true;
453 
454   if(parser.isSet(option_d))
455   {
456     MusEGlobal::debugMode = true;
457     MusEGlobal::realTimeScheduling = false;
458   }
459 
460   if(parser.isSet(option_D))
461   {
462     if(!MusEGlobal::debugMsg)
463       MusEGlobal::debugMsg=true;
464     else
465       MusEGlobal::heavyDebugMsg=true;
466   }
467 
468   if(parser.isSet(option_m))
469     MusEGlobal::midiInputTrace = true;
470 
471   if(parser.isSet(option_M))
472     MusEGlobal::midiOutputTrace = true;
473 
474   if(parser.isSet(option_s))
475     MusEGlobal::debugSync = true;
476 
477   if(parser.isSet(option_u))
478     MusEGlobal::unityWorkaround = true;
479 
480   if(parser.isSet(option_P))
481     MusEGlobal::realTimePriority = parser.value(option_P).toInt();
482 
483   if(parser.isSet(option_Y))
484     MusEGlobal::midiRTPrioOverride = parser.value(option_Y).toInt();
485 
486   if(parser.isSet(option_p))
487     MusEGlobal::loadPlugins = false;
488 
489   if(parser.isSet(option_R))
490     force_plugin_rescan = true;
491 
492   if(parser.isSet(option_C))
493     dont_plugin_rescan = true;
494 
495   if(parser.isSet(option_S))
496     MusEGlobal::loadMESS = false;
497 
498 #ifdef VST_SUPPORT
499   if(parser.isSet(option_V))
500     MusEGlobal::loadVST = false;
501 #endif
502 
503 #ifdef VST_NATIVE_SUPPORT
504   if(parser.isSet(option_N))
505     MusEGlobal::loadNativeVST = false;
506 #endif
507 
508 #ifdef DSSI_SUPPORT
509   if(parser.isSet(option_I))
510     MusEGlobal::loadDSSI = false;
511 #endif
512 
513 #ifdef HAVE_LASH
514   if(parser.isSet(option_L))
515     MusEGlobal::useLASH = false;
516 #endif
517 
518 #ifdef LV2_SUPPORT
519   if(parser.isSet(option_2))
520     MusEGlobal::loadLV2 = false;
521 #endif
522 
523 #ifdef PYTHON_SUPPORT
524   if(parser.isSet(option_y))
525   {
526     MusEGlobal::usePythonBridge = true;
527 
528     if(parser.isSet(option_pyro_ns_host))
529       MusEGlobal::pythonBridgePyroNSHostname = parser.value(option_pyro_ns_host);
530 
531     if(parser.isSet(option_pyro_ns_port))
532       MusEGlobal::pythonBridgePyroNSPort = parser.value(option_pyro_ns_port);
533 
534     if(parser.isSet(option_pyro_daemon_host))
535       MusEGlobal::pythonBridgePyroDaemonHostname = parser.value(option_pyro_daemon_host);
536 
537     if(parser.isSet(option_pyro_daemon_port))
538       MusEGlobal::pythonBridgePyroDaemonPort = parser.value(option_pyro_daemon_port);
539 
540     if(parser.isSet(option_pyro_comm_timeout))
541       MusEGlobal::pythonBridgePyroCommTimeout = parser.value(option_pyro_comm_timeout).toFloat();
542   }
543 #endif
544 
545   return CommandLineOk;
546 }
547 
548 
549 //---------------------------------------------------------
550 //   main
551 //---------------------------------------------------------
552 
main(int argc,char * argv[])553 int main(int argc, char* argv[])
554 {
555       // Get the separator used for file paths.
556       const QChar list_separator = QDir::listSeparator();
557 
558       // Get environment variables for various paths.
559       // "The Qt environment manipulation functions are thread-safe, but this requires that
560       //   the C library equivalent functions like getenv and putenv are not directly called."
561       // "Note: on desktop Windows, qgetenv() may produce data loss if the original string
562       //   contains Unicode characters not representable in the ANSI encoding.
563       //  Use qEnvironmentVariable() instead. On Unix systems, this function is lossless."
564       #if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
565         const QString ladspa_path = qEnvironmentVariable("LADSPA_PATH");
566         const QString dssi_path = qEnvironmentVariable("DSSI_PATH");
567         const QString vst_path = qEnvironmentVariable("VST_PATH");
568         // This Linux VST path is known to be used by Ardour.
569         const QString lxvst_path = qEnvironmentVariable("LXVST_PATH");
570         const QString lv2_path = qEnvironmentVariable("LV2_PATH");
571       #else
572         // "To convert the data to a QString use QString::fromLocal8Bit()."
573         const QString ladspa_path = QString::fromLocal8Bit(qgetenv("LADSPA_PATH"));
574         const QString dssi_path = QString::fromLocal8Bit(qgetenv("DSSI_PATH"));
575         const QString vst_path = QString::fromLocal8Bit(qgetenv("VST_PATH"));
576         const QString lxvst_path = QString::fromLocal8Bit(qgetenv("LXVST_PATH"));
577         const QString lv2_path = QString::fromLocal8Bit(qgetenv("LV2_PATH"));
578       #endif
579 
580 
581       QString last_project_filename;
582       bool last_project_was_template = false;
583       bool last_project_loaded_config = false;
584       bool plugin_rescan_already_done = false;
585       int rv = 0;
586 
587       //==============================================
588       // BEGIN Restart loop. For (re)starting the app.
589       //==============================================
590 
591       bool is_restarting = true; // First-time init true.
592       while(is_restarting)
593       {
594         is_restarting = false;
595 
596         //QTime timer; // Deprecated
597         QElapsedTimer timer;
598         timer.start();
599 
600         // Make working copies of the arguments.
601         const int argument_count = argc;
602         int argc_copy = argc;
603         char** argv_copy = nullptr;
604         if(argument_count > 0)
605         {
606           argv_copy = (char**)malloc(argument_count * sizeof(char*));
607           int len = 0;
608           for(int i = 0; i < argument_count; ++i)
609           {
610             argv_copy[i] = nullptr;
611             if(argv[i])
612             {
613               len = strlen(argv[i]);
614               argv_copy[i] = (char*)malloc(len + 2);
615               strcpy(argv_copy[i], argv[i]);
616             }
617           }
618         }
619 
620         // Let LASH remove its recognized arguments first (generally longer than Qt's).
621         // Tip: LADISH's LASH emulation (current 1.0) does not take any arguments.
622   #ifdef HAVE_LASH
623         lash_args_t * lash_args = 0;
624         lash_args = lash_extract_args (&argc_copy, &argv_copy);
625   #endif
626 
627         // Now create the application, and let Qt remove recognized arguments.
628         QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
629         QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
630 
631         // Qt style must be set before app object is created (->Qt docu)
632         // Should the standard Qt style (Fusion) get removed in future,
633         //   we're OK to just keep the current system style here (kybos)
634         if (QStyleFactory::keys().contains(MusEGlobal::defaultStyle, Qt::CaseInsensitive))
635             QApplication::setStyle(MusEGlobal::defaultStyle);
636 
637         //========================
638         //  Application instance:
639         //========================
640 
641         MuseApplication app(argc_copy, argv_copy);
642 //        if (QStyle* def_style = app.style())
643 //        {
644 //          const QString appStyleObjName = def_style->objectName();
645 //          MusEGui::Appearance::getSetDefaultStyle(&appStyleObjName);
646 //        }
647 
648         qDebug() << "->" << qPrintable(QTime::currentTime().toString("hh:mm:ss.zzz"))
649                  << "Read configuration...";
650 
651         app.setOrganizationName(ORGANIZATION_NAME);
652         app.setOrganizationDomain(ORGANIZATION_DOMAIN);
653         app.setApplicationName(PACKAGE_NAME);
654         app.setApplicationDisplayName(APP_DISPLAY_NAME);
655 
656         // NOTE: 'GenericConfigLocation' returned config dir (ie. ~./config).
657         //       'ConfigLocation' also returned config dir (ie. ~./config).
658         //       'AppConfigLocation' (Qt 5.5) returned config + organization name + application name dirs
659         //        (ie. ~./config/MusE/MusE-qt).
660         //       Beware, setting application name and organization name influence these locations.
661 
662           // "Returns a directory location where user-specific configuration files should be written.
663           //  This is an application-specific directory, and the returned path is never empty.
664           //  This enum value was added in Qt 5.5."
665         MusEGlobal::configPath = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
666 
667         // "Returns a directory location where user-specific non-essential (cached) data should be written.
668         //  This is an application-specific directory. The returned path is never empty."
669         // NOTE: This returned cache + organization name + application name dirs (ie. ~./cache/MusE/MusE-qt).
670         MusEGlobal::cachePath       = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
671 
672         MusEGlobal::museUser        = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
673         MusEGlobal::museGlobalLib   = QString(LIBDIR);
674         MusEGlobal::museGlobalShare = QString(SHAREDIR);
675 
676         const QByteArray appDir = qgetenv("APPDIR"); // running in AppImage
677         if (!appDir.isEmpty()) {
678             MusEGlobal::museGlobalLib   = appDir + MusEGlobal::museGlobalLib;
679             MusEGlobal::museGlobalShare = appDir + MusEGlobal::museGlobalShare;
680         }
681 
682         MusEGlobal::museProject     = MusEGlobal::museProjectInitPath; //getcwd(0, 0);
683         MusEGlobal::museInstruments = MusEGlobal::museGlobalShare + "/instruments";
684 
685         MusEGlobal::configName      = MusEGlobal::configPath + "/MusE-seq.cfg";
686 
687         const QString oldConfigPath(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation)
688           + "/" + PACKAGE_NAME);
689 
690         const QString old_qtconfig_name(oldConfigPath + "/MusE-qt.conf");
691         const QString new_qtconfig_name(oldConfigPath + "/MusE.conf");
692 
693         const QString new_plugin_cache_path(MusEGlobal::cachePath + "/scanner");
694 
695         // If the new-style plugin cache directory location doesn't exist yet, and an
696         //  old-style plugin cache directory exists, rename the old one to the new one.
697         if(!MusEGlobal::cachePath.isEmpty())
698         {
699           QDir new_plugin_cache_dir(new_plugin_cache_path);
700           if(!new_plugin_cache_dir.exists())
701           {
702             const QString old_plugin_cache_path(oldConfigPath + "/scanner");
703             QDir old_plugin_cache_dir(old_plugin_cache_path);
704             if(old_plugin_cache_dir.exists())
705             {
706               QDir(MusEGlobal::cachePath).mkpath(".");
707               if(!QDir().rename(old_plugin_cache_path, new_plugin_cache_path))
708                 fprintf(stderr, "Error renaming plugin cache dir:<%s> to:<%s>\n",
709                   old_plugin_cache_path.toLocal8Bit().constData(),
710                   new_plugin_cache_path.toLocal8Bit().constData());
711             }
712           }
713         }
714 
715         // If the new-style config directory location doesn't exist yet, and an
716         //  old-style config directory exists, rename the old one to the new one.
717         if(!MusEGlobal::configPath.isEmpty())
718         {
719           QDir new_config_dir(MusEGlobal::configPath);
720           if(!new_config_dir.exists())
721           {
722             QFileInfoList fil;
723             QDir old_config_dir(oldConfigPath);
724             if(old_config_dir.exists())
725               fil = old_config_dir.entryInfoList(QDir::AllEntries| QDir::NoDotAndDotDot);
726 
727             // Create the new directory AFTER grabbing the existing list so that
728             //  if the new directory is a subdirectory of the existing one,
729             //  it will not show up in the list.
730             new_config_dir.mkpath(".");
731 
732             if(!fil.isEmpty())
733             {
734               QFileInfo fi;
735               foreach(fi, fil)
736               {
737                 const QString afp(fi.absoluteFilePath());
738                 // DO NOT move the old MusE-qt config file.
739                 // Given an organization name and application name, that is where
740                 //  QSettings are stored it (ie. ~/.config/MusE not ~/.config/MusE/MusE).
741                 if(afp == old_qtconfig_name)
742                   continue;
743                 const QString fn = fi.fileName();
744                 const QString new_fn(MusEGlobal::configPath + "/" + fn);
745                 if(fi.isDir())
746                 {
747                   if(!QDir().rename(afp, new_fn))
748                     fprintf(stderr, "Error renaming config dir:<%s> to:<%s>\n",
749                       afp.toLocal8Bit().constData(), new_fn.toLocal8Bit().constData());
750                 }
751                 else
752                 {
753                   QFile f(afp);
754                   if(!f.rename(new_fn))
755                     fprintf(stderr, "Error renaming config file:<%s> to:<%s>\n",
756                       afp.toLocal8Bit().constData(), new_fn.toLocal8Bit().constData());
757                 }
758               }
759             }
760           }
761         }
762 
763         {
764           const QString old_config_name(MusEGlobal::configPath + "/MusE.cfg");
765           // Rename existing config file to new name.
766           QFile oldConfigFile(old_config_name);
767           if(oldConfigFile.exists())
768             oldConfigFile.rename(MusEGlobal::configName);
769         }
770 
771         bool cConfExists = false;
772         {
773           QFile cConf (MusEGlobal::configName);
774           cConfExists = cConf.exists();
775         }
776 
777         {
778           QFile oldQtConfigFile(old_qtconfig_name);
779           if(oldQtConfigFile.exists())
780             oldQtConfigFile.rename(new_qtconfig_name);
781         }
782 
783         // User instruments dir:
784         MusEGlobal::museUserInstruments = MusEGlobal::configPath + "/instruments";
785         // Create user instruments dir if it doesn't exist
786         {
787           QDir uinstrDir = QDir(MusEGlobal::museUserInstruments);
788           if(!uinstrDir.exists())
789           {
790             fprintf(stderr, "User instrument directory does not exist. Creating it.\n");
791             uinstrDir.mkpath(".");
792           }
793         }
794 
795         MusEGui::initShortCuts();
796 
797         // Discover available MusE audio converters, before reading configuration
798         MusEGlobal::audioConverterPluginList.discover(MusEGlobal::museGlobalLib, MusEGlobal::debugMsg);
799         // Default, non-local settings.
800         MusEGlobal::defaultAudioConverterSettings = new MusECore::AudioConverterSettingsGroup(false);
801         MusEGlobal::defaultAudioConverterSettings->populate(&MusEGlobal::audioConverterPluginList, false);
802 
803         MusECore::readConfiguration();
804 
805         // Need to put a sane defaults here because we can't use '~' in the file name strings.
806         if(!cConfExists)
807         {
808           MusEGlobal::config.projectBaseFolder = MusEGlobal::museUser + QString("/MusE");
809           MusEGlobal::config.startSong = "";
810         }
811 
812         app.instance()->setAttribute(Qt::AA_DontShowIconsInMenus, !MusEGlobal::config.showIconsInMenus);
813         app.instance()->setAttribute(Qt::AA_DontUseNativeDialogs, !MusEGlobal::config.useNativeStandardDialogs);
814 
815 #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
816         app.styleHints()->setShowShortcutsInContextMenus(true);
817 #endif
818 
819         //=================
820         //  LADSPA paths:
821         //=================
822         bool found = false;
823         if(MusEGlobal::config.pluginLadspaPathList.isEmpty())
824         {
825           if(ladspa_path.isEmpty())
826           {
827             MusEGlobal::config.pluginLadspaPathList <<
828               (MusEGlobal::museUser + QString("/ladspa")) <<
829               (MusEGlobal::museUser + QString("/.ladspa")) <<
830               QString("/usr/local/lib64/ladspa") <<
831               QString("/usr/local/lib/ladspa") <<
832               QString("/usr/lib64/ladspa") <<
833               QString("/usr/lib/ladspa");
834           }
835           else
836           {
837 // QString::*EmptyParts is deprecated, use Qt::*EmptyParts, new as of 5.14.
838 #if QT_VERSION >= 0x050e00
839             MusEGlobal::config.pluginLadspaPathList = ladspa_path.split(list_separator, Qt::SkipEmptyParts);
840 #else
841             MusEGlobal::config.pluginLadspaPathList = ladspa_path.split(list_separator, QString::SkipEmptyParts);
842 #endif
843             found = true;
844           }
845         }
846         if(!found && qputenv("LADSPA_PATH", MusEGlobal::config.pluginLadspaPathList.join(list_separator).toLocal8Bit()) == 0)
847           fprintf(stderr, "Error setting LADSPA_PATH\n");
848 
849         //===============
850         //  DSSI paths:
851         //===============
852         found = false;
853         if(MusEGlobal::config.pluginDssiPathList.isEmpty())
854         {
855           if(dssi_path.isEmpty())
856           {
857             MusEGlobal::config.pluginDssiPathList <<
858               (MusEGlobal::museUser + QString("/dssi")) <<
859               (MusEGlobal::museUser + QString("/.dssi")) <<
860               QString("/usr/local/lib64/dssi") <<
861               QString("/usr/local/lib/dssi") <<
862               QString("/usr/lib64/dssi") <<
863               QString("/usr/lib/dssi");
864           }
865           else
866           {
867 // QString::*EmptyParts is deprecated, use Qt::*EmptyParts, new as of 5.14.
868 #if QT_VERSION >= 0x050e00
869             MusEGlobal::config.pluginDssiPathList = dssi_path.split(list_separator, Qt::SkipEmptyParts);
870 #else
871             MusEGlobal::config.pluginDssiPathList = dssi_path.split(list_separator, QString::SkipEmptyParts);
872 #endif
873             found = true;
874           }
875         }
876         if(!found && qputenv("DSSI_PATH", MusEGlobal::config.pluginDssiPathList.join(list_separator).toLocal8Bit()) == 0)
877           fprintf(stderr, "Error setting DSSI_PATH\n");
878 
879         //=======================
880         //  Win VST (*.dll) paths:
881         //=======================
882         found = false;
883         if(MusEGlobal::config.pluginVstPathList.isEmpty())
884         {
885           if(vst_path.isEmpty())
886           {
887             MusEGlobal::config.pluginVstPathList <<
888 // On win, vst is usually where *.dll files are found. We don't want that with Linux *.so vst files.
889 // Otherwise on Linux for example, vst is where Linux vst *.so files are found.
890 #ifdef Q_OS_WIN
891               // TODO: Refine this for Q_OS_WIN. Where exactly do we look though?
892               (MusEGlobal::museUser + QString("/vst")) <<
893               (MusEGlobal::museUser + QString("/.vst"));
894 #else
895               (MusEGlobal::museUser + QString("/vst win 32bit")) <<
896               (MusEGlobal::museUser + QString("/.vst win 32bit"));
897 #endif
898           }
899           else
900           {
901 // QString::*EmptyParts is deprecated, use Qt::*EmptyParts, new as of 5.14.
902 #if QT_VERSION >= 0x050e00
903             MusEGlobal::config.pluginVstPathList = vst_path.split(list_separator, Qt::SkipEmptyParts);
904 #else
905             MusEGlobal::config.pluginVstPathList = vst_path.split(list_separator, QString::SkipEmptyParts);
906 #endif
907             found = true;
908           }
909         }
910         if(!found && qputenv("VST_PATH", MusEGlobal::config.pluginVstPathList.join(list_separator).toLocal8Bit()) == 0)
911           fprintf(stderr, "Error setting VST_PATH\n");
912 
913         //=======================
914         //  LinuxVST (*.so) paths:
915         //=======================
916         found = false;
917         if(MusEGlobal::config.pluginLinuxVstPathList.isEmpty())
918         {
919           if(lxvst_path.isEmpty())
920           {
921             if(vst_path.isEmpty())
922             {
923               MusEGlobal::config.pluginLinuxVstPathList <<
924 
925 // On win, vst is usually where *.dll files are found. We don't want that with Linux *.so vst files.
926 // Otherwise on Linux for example, vst is where Linux vst *.so files are found.
927 // On win, lxvst should be safe, likely where Linux vst *.so files might be found (if that's even a thing!).
928 #ifndef Q_OS_WIN
929                 (MusEGlobal::museUser + QString("/vst")) <<
930 #endif
931                 (MusEGlobal::museUser + QString("/lxvst")) <<
932 
933 #ifndef Q_OS_WIN
934                 (MusEGlobal::museUser + QString("/.vst")) <<
935 #endif
936                 (MusEGlobal::museUser + QString("/.lxvst")) <<
937 
938 #ifndef Q_OS_WIN
939                 QString("/usr/local/lib64/vst") <<
940 #endif
941                 QString("/usr/local/lib64/lxvst") <<
942 
943 #ifndef Q_OS_WIN
944                 QString("/usr/local/lib/vst") <<
945 #endif
946                 QString("/usr/local/lib/lxvst") <<
947 
948 #ifndef Q_OS_WIN
949                 QString("/usr/lib64/vst") <<
950 #endif
951                 QString("/usr/lib64/lxvst") <<
952 
953 #ifndef Q_OS_WIN
954                 QString("/usr/lib/vst")  <<
955 #endif
956                 QString("/usr/lib/lxvst");
957 
958             }
959             else
960             {
961 // QString::*EmptyParts is deprecated, use Qt::*EmptyParts, new as of 5.14.
962 #if QT_VERSION >= 0x050e00
963               MusEGlobal::config.pluginLinuxVstPathList = vst_path.split(list_separator, Qt::SkipEmptyParts);
964 #else
965               MusEGlobal::config.pluginLinuxVstPathList = vst_path.split(list_separator, QString::SkipEmptyParts);
966 #endif
967               found = true;
968             }
969           }
970           else
971           {
972 // QString::*EmptyParts is deprecated, use Qt::*EmptyParts, new as of 5.14.
973 #if QT_VERSION >= 0x050e00
974             MusEGlobal::config.pluginLinuxVstPathList = lxvst_path.split(list_separator, Qt::SkipEmptyParts);
975 #else
976             MusEGlobal::config.pluginLinuxVstPathList = lxvst_path.split(list_separator, QString::SkipEmptyParts);
977 #endif
978             found = true;
979           }
980         }
981         if(!found && qputenv("LXVST_PATH", MusEGlobal::config.pluginLinuxVstPathList.join(list_separator).toLocal8Bit()) == 0)
982           fprintf(stderr, "Error setting LXVST_PATH\n");
983 
984         //==============
985         //  LV2 paths:
986         //==============
987         // Special for LV2: Since we use the recommended lilv_world_load_all()
988         //  not lilv_world_load_bundle(), LV2_PATH seems to be the only way to set paths.
989         found = false;
990         if(MusEGlobal::config.pluginLv2PathList.isEmpty())
991         {
992           if(lv2_path.isEmpty())
993           {
994             MusEGlobal::config.pluginLv2PathList <<
995               (MusEGlobal::museUser + QString("/lv2")) <<
996               (MusEGlobal::museUser + QString("/.lv2")) <<
997               QString("/usr/local/lib64/lv2") <<
998               QString("/usr/local/lib/lv2") <<
999               QString("/usr/lib64/lv2") <<
1000               QString("/usr/lib/lv2");
1001           }
1002           else
1003           {
1004 // QString::*EmptyParts is deprecated, use Qt::*EmptyParts, new as of 5.14.
1005 #if QT_VERSION >= 0x050e00
1006             MusEGlobal::config.pluginLv2PathList = lv2_path.split(list_separator, Qt::SkipEmptyParts);
1007 #else
1008             MusEGlobal::config.pluginLv2PathList = lv2_path.split(list_separator, QString::SkipEmptyParts);
1009 #endif
1010             found = true;
1011           }
1012         }
1013         if(!found && qputenv("LV2_PATH", MusEGlobal::config.pluginLv2PathList.join(list_separator).toLocal8Bit()) == 0)
1014           fprintf(stderr, "Error setting LV2_PATH\n");
1015 
1016 
1017         // BEGIN  Parse command line options
1018         //----------------------------------
1019         QString open_filename;
1020         AudioDriverSelect audioType = DriverConfigSetting;
1021         bool force_plugin_rescan = false;
1022         bool dont_plugin_rescan = false;
1023         // A block because we don't want ths hanging around. Use it then lose it.
1024         {
1025           QCommandLineParser parser;
1026           QString errorMessage;
1027           switch (parseCommandLine(parser, &errorMessage, open_filename,
1028                                    audioType, force_plugin_rescan, dont_plugin_rescan))
1029           {
1030             case CommandLineOk:
1031                 break;
1032             case CommandLineError:
1033                 fputs(qPrintable(errorMessage), stderr);
1034                 fputs("\n\n", stderr);
1035                 fputs(qPrintable(parser.helpText()), stderr);
1036                 printExtraHelpText();
1037 #ifdef HAVE_LASH
1038                 if(lash_args) lash_args_destroy(lash_args);
1039 #endif
1040                 return 1;
1041             case CommandLineVersionRequested:
1042                 printf("%s %s\n", qPrintable(QCoreApplication::applicationName()),
1043                       qPrintable(QCoreApplication::applicationVersion()));
1044 #ifdef HAVE_LASH
1045                 if(lash_args) lash_args_destroy(lash_args);
1046 #endif
1047                 return 0;
1048             case CommandLineHelpRequested:
1049                 // Works OK, but we want extra help text. Also the lash args destroy thingy...
1050                 //parser.showHelp();
1051                 //Q_UNREACHABLE();
1052                 fputs(qPrintable(parser.helpText()), stdout);
1053                 printExtraHelpText();
1054 #ifdef HAVE_LASH
1055                 if(lash_args) lash_args_destroy(lash_args);
1056 #endif
1057                 return 0;
1058           }
1059         }
1060         // END Parse command line options
1061         //----------------------------------
1062 
1063         // Set some AL library namespace debug flags as well.
1064         // Make sure the AL namespace variables mirror our variables.
1065         AL::debugMsg = MusEGlobal::debugMsg;
1066         AL::denormalBias = MusEGlobal::denormalBias;
1067         AL::division = MusEGlobal::config.division;
1068         AL::sampleRate = MusEGlobal::sampleRate;
1069         AL::mtcType = MusEGlobal::mtcType;
1070 
1071 // REMOVE Tim. py. Removed. TEST Keep this? Think not. It was for getting the last option (the filename)
1072 //                                when we were using getopt() but now we use QCommandLineParser. Un-needed ?
1073 //         argc_copy -= optind;
1074 //         ++argc_copy;
1075 
1076         srand(time(nullptr));   // initialize random number generator
1077         //signal(SIGCHLD, catchSignal);  // interferes with initVST(). see also app.cpp, function catchSignal()
1078 
1079         static QTranslator translator(nullptr);
1080         {
1081           QString locale(QLocale::system().name());
1082           if (locale_override.length() >0 )
1083               locale = locale_override;
1084           if (locale != "C") {
1085               QString loc("muse_");
1086               loc += locale;
1087               if (!translator.load(loc, QString("."))) {
1088                     QString lp(MusEGlobal::museGlobalShare);
1089                     lp += QString("/locale");
1090                     if (!translator.load(loc, lp)) {
1091                           fprintf(stderr, "no locale <%s>/<%s>\n", loc.toLatin1().constData(), lp.toLatin1().constData());
1092                     }
1093               }
1094               app.installTranslator(&translator);
1095           }
1096 
1097           QLocale def_loc(locale);
1098           QLocale::setDefault(def_loc);
1099         }
1100 
1101         fprintf(stderr, "LOCALE %s\n",QLocale().name().toLatin1().data());
1102 
1103         if (QLocale().name() == "de" || locale_override == "de") {
1104           fprintf(stderr, "locale de - setting 'note h is B' override parameter.\n");
1105           MusEGlobal::hIsB = false;
1106         }
1107 
1108         QApplication::addLibraryPath(MusEGlobal::museGlobalLib + "/qtplugins");
1109         if (MusEGlobal::debugMsg) {
1110               QStringList list = app.libraryPaths();
1111               QStringList::Iterator it = list.begin();
1112               fprintf(stderr, "QtLibraryPath:\n");
1113               while(it != list.end()) {
1114                     fprintf(stderr, "  <%s>\n", (*it).toLatin1().constData());
1115                     ++it;
1116                     }
1117               }
1118 
1119         // NOTE: Set the stylesheet and style as early as possible!
1120         // Any later invites trouble - typically the colours may be off,
1121         //  but currently with Breeze or Oxygen, MDI sub windows  may be frozen!
1122         // Working with Breeze maintainer to fix problem... 2017/06/06 Tim.
1123 //        MusEGui::updateThemeAndStyle();
1124 
1125 
1126         qDebug() << "->" << qPrintable(QTime::currentTime().toString("hh:mm:ss.zzz"))
1127                  << "Load theme...";
1128 
1129         MusEGui::loadTheme(MusEGlobal::config.theme);
1130 //        MusEGui::loadThemeColors(MusEGlobal::config.theme);
1131 
1132         //-------------------------------------------------------
1133         //    BEGIN SHOW MUSE SPLASH SCREEN
1134         //-------------------------------------------------------
1135 
1136         QString splash_prefix;
1137         QSplashScreen* muse_splash = nullptr;
1138         if (MusEGlobal::config.showSplashScreen) {
1139             QPixmap splsh(MusEGlobal::museGlobalShare + "/splash.jpg");
1140 
1141             if (!splsh.isNull()) {
1142                 muse_splash = new QSplashScreen(splsh, Qt::WindowStaysOnTopHint);
1143                 muse_splash->setAttribute(Qt::WA_DeleteOnClose);  // Possibly also Qt::X11BypassWindowManagerHint
1144                 splash_prefix = QString("MusE ") + QString(VERSION) + ":";
1145                 muse_splash->show();
1146             }
1147         }
1148 
1149         //-------------------------------------------------------
1150         //    END SHOW MUSE SPLASH SCREEN
1151         //-------------------------------------------------------
1152 
1153         //-------------------------------------------------------
1154         //    BEGIN Plugin scanning
1155         //-------------------------------------------------------
1156 
1157         if(muse_splash)
1158         {
1159             muse_splash->showMessage(splash_prefix + QString(" Creating plugin cache files..."),
1160                                      Qt::AlignLeft|Qt::AlignBottom, Qt::yellow);
1161           qApp->processEvents();
1162         }
1163 
1164         qDebug() << "->" << qPrintable(QTime::currentTime().toString("hh:mm:ss.zzz"))
1165                  << "Scan plugins...";
1166 
1167         bool do_rescan = false;
1168         if(force_plugin_rescan)
1169         {
1170           force_plugin_rescan = false;
1171           if(!plugin_rescan_already_done)
1172           {
1173             do_rescan = true;
1174             plugin_rescan_already_done = true;
1175           }
1176         }
1177 
1178         if(MusEGlobal::config.pluginCacheTriggerRescan)
1179         {
1180           do_rescan = true;
1181           // Done with rescan trigger. Reset it now.
1182           MusEGlobal::config.pluginCacheTriggerRescan = false;
1183         }
1184 
1185         if (MusEGlobal::debugMsg)
1186             qDebug() << "Cache path for plugin scan:" << new_plugin_cache_path;
1187 
1188         // Scan all known plugins from the cache file, or if it does not exist
1189         //  create the cache file by reading plugins in a safe 'sandbox'.
1190         MusEPlugin::PluginScanInfoStruct::PluginType_t types = MusEPlugin::PluginScanInfoStruct::PluginTypeNone;
1191         if(MusEGlobal::loadPlugins)
1192           types |= MusEPlugin::PluginScanInfoStruct::PluginTypeLADSPA;
1193         if(MusEGlobal::loadMESS)
1194           types |= MusEPlugin::PluginScanInfoStruct::PluginTypeMESS;
1195         if(MusEGlobal::loadVST)
1196           types |= MusEPlugin::PluginScanInfoStruct::PluginTypeVST;
1197         if(MusEGlobal::loadNativeVST)
1198           types |= MusEPlugin::PluginScanInfoStruct::PluginTypeLinuxVST;
1199         if(MusEGlobal::loadDSSI)
1200           types |= (MusEPlugin::PluginScanInfoStruct::PluginTypeDSSI |
1201                     MusEPlugin::PluginScanInfoStruct::PluginTypeDSSIVST);
1202         if(MusEGlobal::loadLV2)
1203           types |= MusEPlugin::PluginScanInfoStruct::PluginTypeLV2;
1204 
1205         types |= MusEPlugin::PluginScanInfoStruct::PluginTypeUnknown;
1206 
1207         MusEPlugin::checkPluginCacheFiles(new_plugin_cache_path,
1208                                         // List of plugins to scan into and write to cache files from.
1209                                         &MusEPlugin::pluginList,
1210                                         // Don't bother reading any port information that might exist in the cache.
1211                                         false,
1212                                         // Whether to force recreation.
1213                                         do_rescan,
1214                                         // Whether to NOT recreate.
1215                                         dont_plugin_rescan,
1216                                         // When creating, where to find the application's own plugins.
1217                                         MusEGlobal::museGlobalLib,
1218                                         // Plugin types to check.
1219                                         types,
1220                                         // Debug messages.
1221                                         MusEGlobal::debugMsg);
1222 
1223         // Done with rescan trigger. Reset it now.
1224         if(do_rescan)
1225           MusEGlobal::config.pluginCacheTriggerRescan = false;
1226 
1227         //-------------------------------------------------------
1228         //   END Plugin scanning
1229         //-------------------------------------------------------
1230 
1231         qDebug() << "->" << qPrintable(QTime::currentTime().toString("hh:mm:ss.zzz"))
1232                  << "Init audio...";
1233 
1234         AL::initDsp();
1235 
1236         if(muse_splash)
1237         {
1238           muse_splash->showMessage(splash_prefix + QString(" Initializing audio system..."),
1239                                    Qt::AlignLeft|Qt::AlignBottom, Qt::yellow);
1240           qApp->processEvents();
1241         }
1242 
1243         MusECore::initAudio();
1244 
1245         MusEGui::initIcons(MusEGlobal::config.cursorSize,
1246                            MusEGlobal::museGlobalShare + "/themes/" + MusEGlobal::config.theme,
1247                            MusEGlobal::configPath + "/themes/" + MusEGlobal::config.theme);
1248 
1249         if (MusEGlobal::loadMESS)
1250           MusECore::initMidiSynth(); // Need to do this now so that Add Track -> Synth menu is populated when MusE is created.
1251 
1252         MusEGlobal::muse = new MusEGui::MusE();
1253         app.setMuse(MusEGlobal::muse);
1254 
1255         MusEGui::init_function_dialogs();
1256         MusEGui::retranslate_function_dialogs();
1257 
1258         if(muse_splash)
1259         {
1260           muse_splash->showMessage(splash_prefix + QString(" Initializing audio driver..."),
1261                                    Qt::AlignLeft|Qt::AlignBottom, Qt::yellow);
1262           qApp->processEvents();
1263         }
1264 
1265         if (MusEGlobal::config.useDenormalBias) {
1266             fprintf(stderr, "Denormal protection enabled.\n");
1267         }
1268         if (MusEGlobal::debugMsg) {
1269             fprintf(stderr, "global lib:       <%s>\n", MusEGlobal::museGlobalLib.toLatin1().constData());
1270             fprintf(stderr, "global share:     <%s>\n", MusEGlobal::museGlobalShare.toLatin1().constData());
1271             fprintf(stderr, "muse home:        <%s>\n", MusEGlobal::museUser.toLatin1().constData());
1272             fprintf(stderr, "project dir:      <%s>\n", MusEGlobal::museProject.toLatin1().constData());
1273             fprintf(stderr, "user instruments: <%s>\n", MusEGlobal::museUserInstruments.toLatin1().constData());
1274         }
1275 
1276         //rlimit lim; getrlimit(RLIMIT_RTPRIO, &lim);
1277         //fprintf(stderr, "RLIMIT_RTPRIO soft:%d hard:%d\n", lim.rlim_cur, lim.rlim_max);    // Reported 80, 80 even with non-RT kernel.
1278         if (MusEGlobal::realTimePriority < sched_get_priority_min(SCHED_FIFO))
1279               MusEGlobal::realTimePriority = sched_get_priority_min(SCHED_FIFO);
1280         else if (MusEGlobal::realTimePriority > sched_get_priority_max(SCHED_FIFO))
1281               MusEGlobal::realTimePriority = sched_get_priority_max(SCHED_FIFO);
1282         // If we requested to force the midi thread priority...
1283         if(MusEGlobal::midiRTPrioOverride > 0)
1284         {
1285           if (MusEGlobal::midiRTPrioOverride < sched_get_priority_min(SCHED_FIFO))
1286               MusEGlobal::midiRTPrioOverride = sched_get_priority_min(SCHED_FIFO);
1287           else if (MusEGlobal::midiRTPrioOverride > sched_get_priority_max(SCHED_FIFO))
1288               MusEGlobal::midiRTPrioOverride = sched_get_priority_max(SCHED_FIFO);
1289         }
1290 
1291 #ifdef HAVE_LASH
1292         bool using_jack = false;
1293 #endif
1294         if (MusEGlobal::debugMode) {
1295             MusEGlobal::realTimeScheduling = false;
1296             MusECore::initDummyAudio();
1297         }
1298         else if (audioType == DummyAudioOverride) {
1299             fprintf(stderr, "Force Dummy Audio driver\n");
1300             MusEGlobal::realTimeScheduling = true;
1301             MusECore::initDummyAudio();
1302         }
1303 #ifdef HAVE_RTAUDIO
1304         else if (audioType == RtAudioOverride) {
1305             fprintf(stderr, "Force RtAudio with Pulse Backend\n");
1306             MusEGlobal::realTimeScheduling = true;
1307             if(MusECore::initRtAudio(true))
1308               fallbackDummy();
1309             else
1310               fprintf(stderr, "Using rtAudio\n");
1311         }
1312 #endif
1313         else if (audioType == JackAudioOverride) {
1314           if(MusECore::initJackAudio())
1315             fallbackDummy();
1316           else
1317           {
1318 #ifdef HAVE_LASH
1319             using_jack = true;
1320 #endif
1321             fprintf(stderr, "...Using Jack\n");
1322           }
1323         }
1324         else if (audioType == DriverConfigSetting) {
1325           fprintf(stderr, "Select audio device from configuration : %d\n", MusEGlobal::config.deviceAudioBackend);
1326           switch (MusEGlobal::config.deviceAudioBackend) {
1327             case MusEGlobal::DummyAudio:
1328               {
1329                 fprintf(stderr, "User DummyAudio backend - selected through configuration\n");
1330                 MusEGlobal::realTimeScheduling = true;
1331                 MusECore::initDummyAudio();
1332                 break;
1333               }
1334             case MusEGlobal::RtAudioAlsa:
1335             case MusEGlobal::RtAudioOss:
1336 //            case MusEGlobal::RtAudioJack:
1337             case MusEGlobal::RtAudioChoice:
1338             case MusEGlobal::RtAudioPulse:
1339               {
1340                 fprintf(stderr, "User RtAudio backend - backend selected through configuration: ");
1341                 if(MusEGlobal::config.deviceAudioBackend >= MusEGlobal::numRtAudioDevices)
1342                   fprintf(stderr, "Unknown");
1343                 else
1344                   fprintf(stderr, "%s",
1345                     MusEGlobal::selectableAudioBackendDevices[MusEGlobal::config.deviceAudioBackend].
1346                       toLatin1().constData());
1347                 fprintf(stderr, "\n");
1348 
1349                 MusEGlobal::realTimeScheduling = true;
1350 #ifdef HAVE_RTAUDIO
1351                 if(MusECore::initRtAudio())
1352                   fallbackDummy();
1353                 else
1354                   fprintf(stderr, "Using rtAudio\n");
1355 #else
1356                 fallbackDummy();
1357 #endif
1358                 break;
1359               }
1360             case MusEGlobal::JackAudio:
1361               {
1362                 fprintf(stderr, "User JackAudio backend - backend selected through configuration\n");
1363                 if (MusECore::initJackAudio())
1364                 {
1365                   MusEGlobal::realTimeScheduling = true;
1366                   // Force default Pulse.
1367 #ifdef HAVE_RTAUDIO
1368                   if(MusECore::initRtAudio(true))
1369                     fallbackDummy();
1370                   else
1371                     fprintf(stderr, "Using rtAudio Pulse\n");
1372 #else
1373                   fallbackDummy();
1374 #endif
1375                 }
1376                 else
1377                 {
1378 #ifdef HAVE_LASH
1379                   using_jack = true;
1380 #endif
1381                   fprintf(stderr, "Using Jack\n");
1382                 }
1383 
1384                 break;
1385               }
1386           }
1387         }
1388 
1389         MusEGlobal::realTimeScheduling = MusEGlobal::audioDevice->isRealtime();
1390 
1391         // ??? With Jack2 this reports true even if it is not running realtime.
1392         // Jack says: "Cannot use real-time scheduling (RR/10)(1: Operation not permitted)". The kernel is non-RT.
1393         // I cannot seem to find a reliable answer to the question, even with dummy audio and system calls.
1394 
1395         // setup the prefetch fifo length now that the segmentSize is known
1396         MusEGlobal::fifoLength = 131072 / MusEGlobal::segmentSize;
1397         MusECore::initAudioPrefetch();
1398 
1399         // Set up the wave module now that sampleRate and segmentSize are known.
1400         MusECore::SndFile::initWaveModule(
1401           &MusEGlobal::sndFiles,
1402           &MusEGlobal::audioConverterPluginList,
1403           &MusEGlobal::defaultAudioConverterSettings,
1404           MusEGlobal::sampleRate,
1405           MusEGlobal::segmentSize);
1406 
1407         if(muse_splash)
1408         {
1409           muse_splash->showMessage(splash_prefix + QString(" Initializing midi devices..."),
1410                                    Qt::AlignLeft|Qt::AlignBottom, Qt::yellow);
1411           qApp->processEvents();
1412         }
1413 
1414         qDebug() << "->" << qPrintable(QTime::currentTime().toString("hh:mm:ss.zzz"))
1415                  << "Init MIDI...";
1416 
1417 // REMOVE Tim. startup. Removed 2019/02/21. It's been six years since 1.9.9.5 release.
1418 //        Remove this waiting part at some point if we're all good...
1419 //
1420 //         // WARNING Must do it this way. Call registerClient long AFTER Jack client
1421 //         //  is created and MusE ALSA client is created (in initMidiDevices),
1422 //         //  otherwise random crashes can occur within Jack <= 1.9.8.
1423 //         // Fixed in Jack 1.9.9.  Tim.
1424         // This initMidiDevices will automatically initialize the midiSeq sequencer thread,
1425         //  but not start it - that's a bit later on.
1426         MusECore::initMidiDevices();
1427 //         // Wait until things have settled. One second seems OK so far.
1428 //         for(int t = 0; t < 100; ++t)
1429 //           usleep(10000);
1430         // Now it is safe to call registerClient.
1431         MusEGlobal::audioDevice->registerClient();
1432 
1433         MusECore::initMidiController();
1434         MusECore::initMidiInstruments();
1435         MusECore::initMidiPorts();
1436 
1437         if(muse_splash)
1438         {
1439           muse_splash->showMessage(splash_prefix + QString(" Initializing plugins..."),
1440                                    Qt::AlignLeft|Qt::AlignBottom, Qt::yellow);
1441           qApp->processEvents();
1442         }
1443 
1444         qDebug() << "->" << qPrintable(QTime::currentTime().toString("hh:mm:ss.zzz"))
1445                  << "Init plugins...";
1446 
1447         if (MusEGlobal::loadPlugins)
1448               MusECore::initPlugins();
1449 
1450         qDebug() << "->" << qPrintable(QTime::currentTime().toString("hh:mm:ss.zzz"))
1451                  << "Init VST plugins...";
1452 
1453         if (MusEGlobal::loadVST)
1454               MusECore::initVST();
1455 
1456         qDebug() << "->" << qPrintable(QTime::currentTime().toString("hh:mm:ss.zzz"))
1457                  << "Init native VST plugins...";
1458 
1459         if (MusEGlobal::loadNativeVST)
1460               MusECore::initVST_Native();
1461 
1462         qDebug() << "->" << qPrintable(QTime::currentTime().toString("hh:mm:ss.zzz"))
1463                  << "Init DSSI plugins...";
1464 
1465         if(MusEGlobal::loadDSSI)
1466               MusECore::initDSSI();
1467 
1468   #ifdef LV2_SUPPORT
1469         qDebug() << "->" << qPrintable(QTime::currentTime().toString("hh:mm:ss.zzz"))
1470                  << "Init LV2 plugins...";
1471 
1472         if(MusEGlobal::loadLV2)
1473               MusECore::initLV2();
1474   #endif
1475 
1476         // Now that all the plugins are done loading from the global plugin cache list,
1477         //  we are done with it. Clear it to free up memory.
1478         // TODO Future: Will need to keep it around if we ever switch to using the list all the time
1479         //       instead of separate global plugin and synth lists.
1480         MusEPlugin::pluginList.clear();
1481 
1482         qDebug() << "->" << qPrintable(QTime::currentTime().toString("hh:mm:ss.zzz"))
1483                  << "Init OSC / metronome...";
1484 
1485         MusECore::initOSC();
1486 
1487         MusECore::initMetronome();
1488 
1489         const QString metro_presets = MusEGlobal::museGlobalShare + QString("/metronome");
1490         MusECore::initMetronomePresets(metro_presets, &MusEGlobal::metroAccentPresets, MusEGlobal::debugMsg);
1491         // If the global metronome accent settings are empty, it is unlikely the user did that, or wants that.
1492         // More likely it indicates this is a first-time init of the global settings.
1493         // In any case, if empty fill the global metronome accent settings with factory presets.
1494         if(MusEGlobal::metroGlobalSettings.metroAccentsMap &&
1495            MusEGlobal::metroGlobalSettings.metroAccentsMap->empty())
1496         {
1497           // Fill with defaults.
1498           MusEGlobal::metroAccentPresets.defaultAccents(
1499             MusEGlobal::metroGlobalSettings.metroAccentsMap,
1500             MusECore::MetroAccentsStruct::FactoryPreset);
1501         }
1502 
1503         MusECore::initWavePreview(MusEGlobal::segmentSize);
1504 
1505         MusECore::enumerateJackMidiDevices();
1506 
1507   #ifdef HAVE_LASH
1508         qDebug() << "->" << qPrintable(QTime::currentTime().toString("hh:mm:ss.zzz"))
1509                  << "Init LASH...";
1510 
1511         {
1512           MusEGui::lash_client = 0;
1513           if(MusEGlobal::useLASH)
1514           {
1515             if(muse_splash)
1516             {
1517               muse_splash->showMessage(splash_prefix + QString(" Initializing LASH support..."),
1518                                        Qt::AlignLeft|Qt::AlignBottom, Qt::yellow);
1519               qApp->processEvents();
1520             }
1521 
1522             int lash_flags = LASH_Config_File;
1523             const char *muse_name = PACKAGE_NAME;
1524             MusEGui::lash_client = lash_init (lash_args, muse_name, lash_flags, LASH_PROTOCOL(2,0));
1525   #ifdef ALSA_SUPPORT
1526             if(MusECore::alsaSeq)
1527               lash_alsa_client_id (MusEGui::lash_client, snd_seq_client_id (MusECore::alsaSeq));
1528   #endif
1529             //if (audioType != DummyAudio) {
1530             if (using_jack) {
1531                   const char *jack_name = MusEGlobal::audioDevice->clientName();
1532                   lash_jack_client_name (MusEGui::lash_client, jack_name);
1533             }
1534           }
1535           if(lash_args)
1536             lash_args_destroy(lash_args);
1537         }
1538   #endif /* HAVE_LASH */
1539 
1540 #ifndef _WIN32
1541         if (!MusEGlobal::debugMode) {
1542               if (mlockall(MCL_CURRENT | MCL_FUTURE))
1543                     perror("WARNING: Cannot lock memory:");
1544               }
1545 #endif
1546 
1547         qDebug() << "->" << qPrintable(QTime::currentTime().toString("hh:mm:ss.zzz"))
1548                  << "Populating Track context menu...";
1549 
1550         if(muse_splash)
1551         {
1552           muse_splash->showMessage(splash_prefix + QString(" Populating Track context menu..."),
1553                                    Qt::AlignLeft|Qt::AlignBottom, Qt::yellow);
1554           qApp->processEvents();
1555         }
1556 
1557         MusEGlobal::muse->populateAddTrack(); // could possibly be done in a thread.
1558 
1559         qDebug() << "->" << qPrintable(QTime::currentTime().toString("hh:mm:ss.zzz"))
1560                  << "Show GUI...";
1561 
1562         MusEGlobal::muse->show();
1563 
1564         // Let the configuration settings take effect. Do not save.
1565         MusEGlobal::muse->changeConfig(false);
1566         // Set style and stylesheet, and do not force the style
1567         //MusEGui::updateThemeAndStyle(); // Works better if called just after app created, above.
1568 
1569         MusEGlobal::muse->seqStart();
1570         MusEGlobal::muse->initStatusBar();
1571 
1572         // If the sequencer object was created, report timing.
1573         if(MusEGlobal::midiSeq)
1574           MusEGlobal::midiSeq->checkAndReportTimingResolution();
1575 
1576         //--------------------------------------------------
1577         // Set the audio device sync timeout value.
1578         //--------------------------------------------------
1579         // Enforce a 30 second timeout.
1580         // TODO: Split this up and have user adjustable normal (2 or 10 second default) value,
1581         //        plus a contribution from the total required precount time.
1582         //       Too bad we likely can't set it dynamically in the audio sync callback.
1583         // NOTE: This is also enforced casually in Song:seqSignal after a stop, start, or seek.
1584         MusEGlobal::audioDevice->setSyncTimeout(30000000);
1585 
1586         //--------------------------------------------------
1587         // Auto-fill the midi ports, if appropriate.
1588         // Only if NOT actually opening an existing file.
1589         // FIXME: Maybe check if it's a .med file (song may populate)
1590         //         or .mid file (always populate) or .wav file etc.
1591         //--------------------------------------------------
1592         if(MusEGlobal::populateMidiPortsOnStart &&
1593            ((!open_filename.isEmpty() && !QFile(open_filename).exists()) ||
1594            (open_filename.isEmpty() &&
1595            (MusEGlobal::config.startMode == 1 || MusEGlobal::config.startMode == 2) &&
1596            !MusEGlobal::config.startSongLoadConfig)))
1597           MusECore::populateMidiPorts();
1598 
1599         if(muse_splash)
1600         {
1601             muse_splash->showMessage(splash_prefix + QString(" Click to close splash screen..."),
1602                                      Qt::AlignLeft|Qt::AlignBottom, Qt::yellow);
1603 
1604           // From this point on, slap a timer on it so that it stays up for few seconds,
1605           //  since closing it now might be too short display time.
1606             QTimer::singleShot(3000, muse_splash, SLOT(close()));
1607         }
1608 
1609         qDebug() << "->" << qPrintable(QTime::currentTime().toString("hh:mm:ss.zzz"))
1610                  << "Load default project";
1611 
1612         //--------------------------------------------------
1613         // Load the default song.
1614         //--------------------------------------------------
1615         // When restarting, override with the last project file name used.
1616         if(last_project_filename.isEmpty())
1617         {
1618           MusEGlobal::muse->loadDefaultSong(open_filename, false, false);
1619         }
1620         else
1621         {
1622           MusEGlobal::muse->loadDefaultSong(
1623             last_project_filename, last_project_was_template, last_project_loaded_config);
1624         }
1625 
1626         QTimer::singleShot(100, MusEGlobal::muse, SLOT(showDidYouKnowDialogIfEnabled()));
1627 
1628         //--------------------------------------------------
1629         // Start the application...
1630         //--------------------------------------------------
1631 
1632         qDebug() << "->" << qPrintable(QTime::currentTime().toString("hh:mm:ss.zzz"))
1633                  << "Start application loop...";
1634 
1635         qDebug() << "Total start-up time:" << timer.elapsed() << "ms";
1636 
1637         rv = app.exec();
1638 
1639         //--------------------------------------------------
1640         // ... Application finished.
1641         //--------------------------------------------------
1642 
1643         if(MusEGlobal::debugMsg)
1644           fprintf(stderr, "app.exec() returned:%d\nDeleting main MusE object\n", rv);
1645 
1646         if (MusEGlobal::loadPlugins)
1647         {
1648           for (MusECore::iPlugin i = MusEGlobal::plugins.begin(); i != MusEGlobal::plugins.end(); ++i)
1649               delete (*i);
1650           MusEGlobal::plugins.clear();
1651         }
1652 
1653         MusECore::exitWavePreview();
1654 
1655   #ifdef LV2_SUPPORT
1656         if(MusEGlobal::loadLV2)
1657               MusECore::deinitLV2();
1658   #endif
1659 
1660         // In case the sequencer object is still alive, make sure to destroy it now.
1661         MusECore::exitMidiSequencer();
1662 
1663         // Grab the restart flag before deleting muse.
1664         is_restarting = MusEGlobal::muse->restartingApp();
1665 
1666         if (is_restarting)
1667             qDebug() << "\n->" << qPrintable(QTime::currentTime().toString("hh:mm:ss.zzz"))
1668                      << "Restarting application...";
1669 
1670         {
1671           // If the current project file name exists, set the last_project_filename
1672           //  variable so that if restarting, it starts with that file.
1673           // This should be OK since fresh untitled unsaved songs will not have a
1674           //  file yet, they will have a unique file name that does not exist until
1675           //  saved, so it will either use the existing open_filename, or default
1676           //  to normal operation (template, last song, or blank).
1677           const QString s = MusEGlobal::muse->lastProjectFilePath();
1678           const QFileInfo fi(s);
1679           if(fi.exists())
1680           {
1681             last_project_filename = s;
1682             last_project_was_template = MusEGlobal::muse->lastProjectWasTemplate();
1683             last_project_loaded_config = MusEGlobal::muse->lastProjectLoadedConfig();
1684           }
1685           else
1686           {
1687             last_project_filename.clear();
1688             last_project_was_template = false;
1689             last_project_loaded_config = false;
1690           }
1691         }
1692 
1693         // Now delete the application.
1694         delete MusEGlobal::muse;
1695         MusEGlobal::muse = nullptr;
1696 
1697         // These are owned by muse and deleted above. Reset to zero now.
1698         MusEGlobal::undoRedo = nullptr;
1699         MusEGlobal::undoAction = nullptr;
1700         MusEGlobal::redoAction = nullptr;
1701 
1702         // Reset the option index.
1703         // NOTE: See optind manual for special resetting values.
1704         //       Traditionally 1 is set, but here we may need GNU specific 0.
1705         //optind = 0;
1706 
1707         // Free the working copies of the arguments.
1708         if(argv_copy)
1709         {
1710           for(int i = 0; i < argument_count; ++i)
1711           {
1712             if(argv_copy[i])
1713               free(argv_copy[i]);
1714           }
1715           free(argv_copy);
1716         }
1717 
1718         // Reset these before restarting, seems to work better,
1719         //  makes a difference with the MDI freezing problem, above.
1720         app.setStyleSheet("");
1721 //        app.setStyle(MusEGlobal::config.style);
1722 
1723         // Reset the recently opened list.
1724         MusEGui::projectRecentList.clear();
1725 
1726         // Clear and delete these.
1727         if(MusEGlobal::defaultAudioConverterSettings)
1728           delete MusEGlobal::defaultAudioConverterSettings;
1729         MusEGlobal::defaultAudioConverterSettings = nullptr;
1730         MusEGlobal::audioConverterPluginList.clearDelete();
1731 
1732         // Clear the mixer configurations.
1733         MusEGlobal::config.mixer1.stripOrder.clear();
1734         MusEGlobal::config.mixer1.stripVisibility.clear();
1735         MusEGlobal::config.mixer1.stripConfigList.clear();
1736         MusEGlobal::config.mixer2.stripOrder.clear();
1737         MusEGlobal::config.mixer2.stripVisibility.clear();
1738         MusEGlobal::config.mixer2.stripConfigList.clear();
1739       }
1740 
1741       //============================================
1742       // END Restart loop. For (re)starting the app.
1743       //============================================
1744 
1745       if(MusEGlobal::debugMsg)
1746         fprintf(stderr, "Finished! Exiting main, return value:%d\n", rv);
1747       return rv;
1748 
1749       }
1750