/*
* SPDX-License-Identifier: GPL-3.0-only
* MuseScore-Studio-CLA-applies
*
* MuseScore Studio
* Music Composition & Notation
*
* Copyright (C) 2021 MuseScore Limited and others
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include
#include
#include
#include
#include
#include "appfactory.h"
#include "internal/commandlineparser.h"
#include "global/iapplication.h"
#include "muse_framework_config.h"
#include "app_config.h"
#include "log.h"
#ifndef MUSE_MODULE_DIAGNOSTICS_CRASHPAD_CLIENT
static void crashCallback(int signum)
{
const char* signame = "UNKNOWN SIGNAME";
const char* sigdescript = "";
switch (signum) {
case SIGILL:
signame = "SIGILL";
sigdescript = "Illegal Instruction";
break;
case SIGSEGV:
signame = "SIGSEGV";
sigdescript = "Invalid memory reference";
break;
}
LOGE() << "Oops! Application crashed with signal: [" << signum << "] " << signame << "-" << sigdescript;
exit(EXIT_FAILURE);
}
#endif
static void app_init_qrc()
{
Q_INIT_RESOURCE(app);
#ifdef Q_OS_WIN
Q_INIT_RESOURCE(app_win);
#endif
}
int main(int argc, char** argv)
{
#ifndef MUSE_MODULE_DIAGNOSTICS_CRASHPAD_CLIENT
signal(SIGSEGV, crashCallback);
signal(SIGILL, crashCallback);
signal(SIGFPE, crashCallback);
#endif
// ====================================================
// Setup global Qt application variables
// ====================================================
app_init_qrc();
qputenv("QT_STYLE_OVERRIDE", "Fusion");
qputenv("QML_DISABLE_DISK_CACHE", "true");
// HACK: Workaround for crash #28840. This disables the incremental GC
if (!qEnvironmentVariableIsSet("MU_QV4_GC_TIMELIMIT")) {
qputenv("QV4_GC_TIMELIMIT", "0");
}
if (!qEnvironmentVariableIsSet("QT_QUICK_FLICKABLE_WHEEL_DECELERATION")) {
qputenv("QT_QUICK_FLICKABLE_WHEEL_DECELERATION", "5000");
}
#ifdef Q_OS_LINUX
if (qEnvironmentVariable("MU_QT_QPA_PLATFORM") != "offscreen") {
qputenv("QT_QPA_PLATFORMTHEME", "gtk3");
}
//! NOTE Forced X11, with Wayland there are a number of problems now
if (qEnvironmentVariable("MU_QT_QPA_PLATFORM") == "") {
qputenv("QT_QPA_PLATFORM", "xcb");
}
#endif
#ifdef Q_OS_WIN
// NOTE: There are some problems with rendering the application window on some integrated graphics processors
// see https://github.com/musescore/MuseScore/issues/8270
if (!qEnvironmentVariableIsSet("QT_OPENGL_BUGLIST")) {
qputenv("QT_OPENGL_BUGLIST", ":/resources/win_opengl_buglist.json");
}
#endif
QGuiApplication::styleHints()->setMousePressAndHoldInterval(250);
// Can't use MUSE_APP_TITLE until next major release, because this "application name" is used to determine
// where user settings are stored. Changing it would result in all user settings being lost.
#ifdef MUSE_APP_UNSTABLE
QCoreApplication::setApplicationName("MuseScore4Development");
#else
QCoreApplication::setApplicationName("MuseScore4");
#endif
QCoreApplication::setOrganizationName("MuseScore");
QCoreApplication::setOrganizationDomain("musescore.org");
QCoreApplication::setApplicationVersion(MUSE_APP_VERSION);
#if !defined(Q_OS_WIN) && !defined(Q_OS_DARWIN) && !defined(Q_OS_WASM)
// Any OS that uses Freedesktop.org Desktop Entry Specification (e.g. Linux, BSD)
#ifndef MUSE_APP_INSTALL_SUFFIX
#define MUSE_APP_INSTALL_SUFFIX ""
#endif
QGuiApplication::setDesktopFileName("org.musescore.MuseScore" MUSE_APP_INSTALL_SUFFIX);
#endif
using namespace muse;
using namespace mu::app;
auto fixSslBackend = []() {
#ifdef Q_OS_WIN
// NOTE: Force schannel backend. Qt prefers OpenSSL when qopensslbackend.dll
// is present, which can crash on ABI mismatch with bundled OpenSSL.
// see https://github.com/musescore/MuseScore/issues/33401
QSslSocket::setActiveBackend("schannel");
#endif
};
// ====================================================
// Parse command line options
// ====================================================
#ifdef MUE_ENABLE_CONSOLEAPP
CommandLineParser commandLineParser;
commandLineParser.init();
commandLineParser.parse(argc, argv);
IApplication::RunMode runMode = commandLineParser.runMode();
QCoreApplication* qapp = nullptr;
if (runMode == IApplication::RunMode::AudioPluginRegistration) {
qapp = new QCoreApplication(argc, argv);
} else {
qapp = new QApplication(argc, argv);
}
fixSslBackend();
commandLineParser.processBuiltinArgs(*qapp);
CmdOptions opt = commandLineParser.options();
#else
QCoreApplication* qapp = new QApplication(argc, argv);
fixSslBackend();
CmdOptions opt;
opt.runMode = IApplication::RunMode::GuiApp;
#endif
AppFactory f;
std::shared_ptr app = f.newApp(opt);
app->setup();
app->setupNewContext();
LOGI() << QString("SSL Info: supported: %1, build: %2, runtime: %3, active backend: %4, available backends: %5")
.arg(QSslSocket::supportsSsl())
.arg(QSslSocket::sslLibraryBuildVersionString())
.arg(QSslSocket::sslLibraryVersionString())
.arg(QSslSocket::activeBackend())
.arg(QSslSocket::availableBackends().join(", "));
// ====================================================
// Run main loop
// ====================================================
int code = qapp->exec();
// ====================================================
// Quit
// ====================================================
app->finish();
delete qapp;
LOGI() << "Goodbye!! code: " << code;
return code;
}