main.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. #include <locale.h>
  2. #include <QGuiApplication>
  3. #include <QApplication>
  4. #include <QFileInfo>
  5. #include <QIcon>
  6. #include <QtQml>
  7. #include <QtWebEngine/qtwebengineglobal.h>
  8. #include <QErrorMessage>
  9. #include "shared/Names.h"
  10. #include "system/SystemComponent.h"
  11. #include "system/UpdateManager.h"
  12. #include "QsLog.h"
  13. #include "Paths.h"
  14. #include "player/PlayerComponent.h"
  15. #include "breakpad/CrashDumps.h"
  16. #include "Version.h"
  17. #include "settings/SettingsComponent.h"
  18. #include "settings/SettingsSection.h"
  19. #include "ui/KonvergoWindow.h"
  20. #include "ui/KonvergoEngine.h"
  21. #include "ui/ErrorMessage.h"
  22. #include "UniqueApplication.h"
  23. #include "utils/HelperLauncher.h"
  24. #include "utils/Log.h"
  25. #if defined(Q_OS_MAC) || defined(Q_OS_LINUX)
  26. #include "SignalManager.h"
  27. #endif
  28. /////////////////////////////////////////////////////////////////////////////////////////
  29. static void preinitQt()
  30. {
  31. QCoreApplication::setApplicationName(Names::MainName());
  32. QCoreApplication::setApplicationVersion(Version::GetVersionString());
  33. QCoreApplication::setOrganizationDomain("plex.tv");
  34. #ifdef Q_OS_WIN32
  35. QVariant useOpengl = SettingsComponent::readPreinitValue(SETTINGS_SECTION_MAIN, "useOpenGL");
  36. // Warning: this must be the same as the default value as declared in
  37. // the settings_description.json file, or confusion will result.
  38. if (useOpengl.type() != QMetaType::Bool)
  39. useOpengl = false;
  40. if (useOpengl.toBool())
  41. QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL);
  42. else
  43. QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
  44. #endif
  45. }
  46. /////////////////////////////////////////////////////////////////////////////////////////
  47. char** appendCommandLineArguments(int argc, char **argv, const QStringList& args)
  48. {
  49. size_t newSize = (argc + args.length() + 1) * sizeof(char*);
  50. char** newArgv = (char**)calloc(1, newSize);
  51. memcpy(newArgv, argv, (size_t)(argc * sizeof(char*)));
  52. int pos = argc;
  53. foreach(const QString& str, args)
  54. newArgv[pos++] = qstrdup(str.toUtf8().data());
  55. return newArgv;
  56. }
  57. /////////////////////////////////////////////////////////////////////////////////////////
  58. void ShowLicenseInfo()
  59. {
  60. QFile licenses(":/misc/licenses.txt");
  61. licenses.open(QIODevice::ReadOnly | QIODevice::Text);
  62. QByteArray contents = licenses.readAll();
  63. printf("%.*s\n", contents.size(), contents.data());
  64. }
  65. /////////////////////////////////////////////////////////////////////////////////////////
  66. int main(int argc, char *argv[])
  67. {
  68. try
  69. {
  70. QCommandLineParser parser;
  71. parser.setApplicationDescription("Plex Media Player");
  72. parser.addHelpOption();
  73. parser.addVersionOption();
  74. parser.addOptions({{{"l", "licenses"}, "Show license information"}});
  75. char **newArgv = appendCommandLineArguments(argc, argv, {"--enable-viewport", "--enable-viewport-meta"});
  76. argc += 2;
  77. #ifdef KONVERGO_OPENELEC
  78. newArgv = appendCommandLineArguments(argc, newArgv, {"--disable-gpu"});
  79. argc ++;
  80. #endif
  81. // Suppress SSL related warnings on OSX
  82. // See https://bugreports.qt.io/browse/QTBUG-43173 for more info
  83. //
  84. #ifdef Q_OS_MAC
  85. qputenv("QT_LOGGING_RULES", "qt.network.ssl.warning=false");
  86. // Request OpenGL 4.1 if possible on OSX, otherwise it defaults to 2.0
  87. // This needs to be done before we create the QGuiApplication
  88. //
  89. QSurfaceFormat format = QSurfaceFormat::defaultFormat();
  90. format.setMajorVersion(3);
  91. format.setMinorVersion(2);
  92. format.setProfile(QSurfaceFormat::CoreProfile);
  93. QSurfaceFormat::setDefaultFormat(format);
  94. #endif
  95. preinitQt();
  96. QGuiApplication app(argc, newArgv);
  97. app.setWindowIcon(QIcon(":/images/icon.png"));
  98. // Get the arguments from the app, this is the parsed version of newArgc and newArgv
  99. QStringList args = app.arguments();
  100. // Remove the viewport arguments so that the parser doesn't barf
  101. args.removeAll("--enable-viewport");
  102. args.removeAll("--enable-viewport-meta");
  103. args.removeAll("--disable-gpu");
  104. // Now parse the command line.
  105. parser.process(args);
  106. if (parser.isSet("licenses"))
  107. {
  108. ShowLicenseInfo();
  109. return EXIT_SUCCESS;
  110. }
  111. // init breakpad.
  112. setupCrashDumper();
  113. UniqueApplication* uniqueApp = new UniqueApplication();
  114. if (!uniqueApp->ensureUnique())
  115. return EXIT_SUCCESS;
  116. #ifdef Q_OS_UNIX
  117. // install signals handlers for proper app closing.
  118. SignalManager signalManager(&app);
  119. Q_UNUSED(signalManager);
  120. #endif
  121. Log::Init();
  122. // Quit app and apply update if we find one.
  123. if (UpdateManager::CheckForUpdates())
  124. {
  125. app.quit();
  126. return 0;
  127. }
  128. #ifdef Q_OS_WIN32
  129. initD3DDevice();
  130. #endif
  131. #ifdef Q_OS_UNIX
  132. setlocale(LC_NUMERIC, "C");
  133. #endif
  134. // Initialize all the components. This needs to be done
  135. // early since most everything else relies on it
  136. //
  137. ComponentManager::Get().initialize();
  138. // enable remote inspection if we have the correct setting for it.
  139. if (SettingsComponent::Get().value(SETTINGS_SECTION_MAIN, "remoteInspector").toBool())
  140. qputenv("QTWEBENGINE_REMOTE_DEBUGGING", "0.0.0.0:9992");
  141. QtWebEngine::initialize();
  142. // Qt and QWebEngineProfile set the locale, which breaks parsing and
  143. // formatting float numbers in a few countries.
  144. #ifdef Q_OS_UNIX
  145. setlocale(LC_NUMERIC, "C");
  146. #endif
  147. // start our helper
  148. HelperLauncher::Get().connectToHelper();
  149. // load QtWebChannel so that we can register our components with it.
  150. QQmlApplicationEngine *engine = KonvergoEngine::Get();
  151. KonvergoWindow::RegisterClass();
  152. engine->rootContext()->setContextProperty("components", &ComponentManager::Get().getQmlPropertyMap());
  153. // the only way to detect if QML parsing fails is to hook to this signal and then see
  154. // if we get a valid object passed to it. Any error messages will be reported on stderr
  155. // but since no normal user should ever see this it should be fine
  156. //
  157. QObject::connect(engine, &QQmlApplicationEngine::objectCreated, [=](QObject* object, const QUrl& url)
  158. {
  159. Q_UNUSED(url);
  160. if (object == nullptr)
  161. throw FatalException(QObject::tr("Failed to parse application engine script."));
  162. QObject* rootObject = engine->rootObjects().first();
  163. QObject* webChannel = qvariant_cast<QObject*>(rootObject->property("webChannel"));
  164. Q_ASSERT(webChannel);
  165. ComponentManager::Get().setWebChannel(qobject_cast<QWebChannel*>(webChannel));
  166. KonvergoWindow* window = qobject_cast<KonvergoWindow*>(rootObject);
  167. Q_ASSERT(window);
  168. QObject::connect(uniqueApp, &UniqueApplication::otherApplicationStarted, window, &KonvergoWindow::otherAppFocus);
  169. });
  170. engine->load(QUrl(QStringLiteral("qrc:/ui/webview.qml")));
  171. Log::UpdateLogLevel();
  172. // run our application
  173. int ret = app.exec();
  174. delete KonvergoEngine::Get();
  175. delete uniqueApp;
  176. return ret;
  177. }
  178. catch (FatalException& e)
  179. {
  180. QLOG_FATAL() << "Unhandled FatalException:" << qPrintable(e.message());
  181. QApplication errApp(argc, argv);
  182. auto msg = new ErrorMessage(e.message(), true);
  183. msg->show();
  184. errApp.exec();
  185. return 1;
  186. }
  187. }