bool winEvent( MSG *msg, long *result )
    {
        if (msg->message != WM_COPYDATA)
            return false;
        
        Q_ASSERT(msg->hwnd == winId());
        COPYDATASTRUCT *data = (COPYDATASTRUCT*)msg->lParam;
        QString message = QString::fromLatin1( (char*)data->lpData, data->cbData / 2 );

        emit app->arguments( message.split( QChar('\0') ) );
        
        if (result)
            *result = 0;

        return true;
    }
Example #2
0
int main(int argc, char *argv[])
{
  try
  {
    for (int n = 1; n < argc; n++) {
      if (strcmp(argv[n], "--licenses") == 0) {
        QFile licenses(":/misc/licenses.txt");
        licenses.open(QIODevice::ReadOnly | QIODevice::Text);
        QByteArray contents = licenses.readAll();
        printf("%.*s\n", (int)contents.size(), contents.data());
        return 0;
      }
    }

    int newArgc = argc;
    char **newArgv = appendCommandLineArguments(&newArgc, argv);

    // Supress SSL related warnings on OSX
    // See https://bugreports.qt.io/browse/QTBUG-43173 for more info
    //
#ifdef Q_OS_MAC
    qputenv("QT_LOGGING_RULES", "qt.network.ssl.warning=false");

    // Request OpenGL 4.1 if possible on OSX, otherwise it defaults to 2.0
    // This needs to be done before we create the QGuiApplication
    //
    QSurfaceFormat format = QSurfaceFormat::defaultFormat();
    format.setMajorVersion(3);
    format.setMinorVersion(2);
    format.setProfile(QSurfaceFormat::CoreProfile);
    QSurfaceFormat::setDefaultFormat(format);
#endif

    QGuiApplication app(newArgc, newArgv);
    initQt(&app);

    // init breakpad.
    setupCrashDumper();

    UniqueApplication* uniqueApp = new UniqueApplication();
    if (!uniqueApp->ensureUnique())
      return EXIT_SUCCESS;

#ifdef Q_OS_UNIX
    // install signals handlers for proper app closing.
    SignalManager signalManager(&app);
    Q_UNUSED(signalManager);
#endif

    initLogger();
    QLOG_INFO() << "Starting Plex Media Player version:" << qPrintable(Version::GetVersionString()) << "build date:" << qPrintable(Version::GetBuildDate());
    QLOG_INFO() << qPrintable(QString("  Running on: %1 [%2] arch %3").arg(QSysInfo::prettyProductName()).arg(QSysInfo::kernelVersion()).arg(QSysInfo::currentCpuArchitecture()));
    QLOG_INFO() << "  Qt Version:" << QT_VERSION_STR << qPrintable(QString("[%1]").arg(QSysInfo::buildAbi()));

    // Quit app and apply update if we find one.
    if (UpdateManager::CheckForUpdates())
    {
      app.quit();
      return 0;
    }

#ifdef Q_OS_WIN32
    initD3DDevice();
#endif

#ifdef Q_OS_UNIX
    setlocale(LC_NUMERIC, "C");
#endif

    // Initialize all the components. This needs to be done
    // early since most everything else relies on it
    //
    ComponentManager::Get().initialize();

    // enable remote inspection if we have the correct setting for it.
    if (SettingsComponent::Get().value(SETTINGS_SECTION_MAIN, "remoteInspector").toBool())
      qputenv("QTWEBENGINE_REMOTE_DEBUGGING", "0.0.0.0:9992");

    QtWebEngine::initialize();

    // Qt and QWebEngineProfile set the locale, which breaks parsing and
    // formatting float numbers in a few countries.
#ifdef Q_OS_UNIX
    setlocale(LC_NUMERIC, "C");
#endif

    // start our helper
    HelperLauncher::Get().connectToHelper();

    // load QtWebChannel so that we can register our components with it.
    QQmlApplicationEngine *engine = KonvergoEngine::Get();
    KonvergoWindow::RegisterClass();
    engine->rootContext()->setContextProperty("components", &ComponentManager::Get().getQmlPropertyMap());

    // This controls how big the web view will zoom using semantic zoom
    // over a specific number of pixels and we run out of space for on screen
    // tiles in chromium. This only happens on OSX since on other platforms
    // we can use the GPU to transfer tiles directly but we set the limit on all platforms
    // to keep it consistent.
    //
    // See more discussion in: https://github.com/plexinc/plex-media-player/issues/10
    // The number of pixels here are REAL pixels, the code in webview.qml will compensate
    // for a higher DevicePixelRatio
    //
    engine->rootContext()->setContextProperty("webMaxHeight", 1440);

    // the only way to detect if QML parsing fails is to hook to this signal and then see
    // if we get a valid object passed to it. Any error messages will be reported on stderr
    // but since no normal user should ever see this it should be fine
    //
    QObject::connect(engine, &QQmlApplicationEngine::objectCreated, [=](QObject* object, const QUrl& url)
    {
      Q_UNUSED(url);

      if (object == 0)
        throw FatalException(QObject::tr("Failed to parse application engine script."));

      QObject* rootObject = engine->rootObjects().first();

      QObject* webChannel = qvariant_cast<QObject*>(rootObject->property("webChannel"));
      Q_ASSERT(webChannel);
      ComponentManager::Get().setWebChannel(qobject_cast<QWebChannel*>(webChannel));

      KonvergoWindow* window = qobject_cast<KonvergoWindow*>(rootObject);
      Q_ASSERT(window);
      QObject::connect(uniqueApp, &UniqueApplication::otherApplicationStarted, window, &KonvergoWindow::otherAppFocus);

    });
    engine->load(QUrl(QStringLiteral("qrc:/ui/webview.qml")));

    updateLogLevel();

    // run our application
    int ret = app.exec();

    delete KonvergoEngine::Get();
    delete uniqueApp;

    return ret;
  }
  catch (FatalException& e)
  {

    QLOG_FATAL() << "Unhandled FatalException:" << qPrintable(e.message());

    QGuiApplication app(argc, argv);
    QString text = e.message() + "<br>" + QObject::tr("Please visit Plex support forums for support.");

    QQmlApplicationEngine* engine = new QQmlApplicationEngine(NULL);
    engine->rootContext()->setContextProperty("errorTitle", QObject::tr("A critical error occurred."));
    engine->rootContext()->setContextProperty("errorText", text);
    engine->load(QUrl(QStringLiteral("qrc:/ui/errormessage.qml")));

    app.exec();
    return 1;

  }
}
int main(int argc, char *argv[])
{
  try
  {
    QCommandLineParser parser;
    parser.setApplicationDescription("Plex Media Player");
    parser.addHelpOption();
    parser.addVersionOption();
    parser.addOptions({{{"l", "licenses"}, "Show license information"}});
    parser.addOptions({{{"a", "from-auto-update"}, "When invoked from auto-update"}});

    char **newArgv = appendCommandLineArguments(argc, argv, g_qtFlags);
    argc += g_qtFlags.size();

    // Suppress SSL related warnings on OSX
    // See https://bugreports.qt.io/browse/QTBUG-43173 for more info
    //
#ifdef Q_OS_MAC
    qputenv("QT_LOGGING_RULES", "qt.network.ssl.warning=false");
#endif

    // Qt calls setlocale(LC_ALL, "") in a bunch of places, which breaks
    // float/string processing in mpv and ffmpeg.
#ifdef Q_OS_UNIX
    qputenv("LC_ALL", "C");
    qputenv("LC_NUMERIC", "C");
#endif

    detectOpenGLEarly();

    preinitQt();

    QGuiApplication app(argc, newArgv);
    app.setWindowIcon(QIcon(":/images/icon.png"));

    // Get the arguments from the app, this is the parsed version of newArgc and newArgv
    QStringList args = app.arguments();

    // Remove the qt flags above so that our command line parser doesn't get cranky.
    for (auto flag : g_qtFlags)
      args.removeAll(flag);

    // Now parse the command line.
    parser.process(args);

    if (parser.isSet("licenses"))
    {
      ShowLicenseInfo();
      return EXIT_SUCCESS;
    }

    // init breakpad.
    setupCrashDumper();

    UniqueApplication* uniqueApp = new UniqueApplication();
    if (!uniqueApp->ensureUnique())
      return EXIT_SUCCESS;

#ifdef Q_OS_UNIX
    // install signals handlers for proper app closing.
    SignalManager signalManager(&app);
    Q_UNUSED(signalManager);
#endif

    Log::Init();

    // Quit app and apply update if we find one.
    if (UpdateManager::CheckForUpdates())
    {
      app.quit();
      return 0;
    }

    detectOpenGLLate();

#ifdef Q_OS_WIN32
    initD3DDevice();
#endif

    Codecs::preinitCodecs();

    // Initialize all the components. This needs to be done
    // early since most everything else relies on it
    //
    ComponentManager::Get().initialize();

    // enable remote inspection if we have the correct setting for it.
    if (SettingsComponent::Get().value(SETTINGS_SECTION_MAIN, "remoteInspector").toBool())
      qputenv("QTWEBENGINE_REMOTE_DEBUGGING", "0.0.0.0:9992");

    QtWebEngine::initialize();

    // start our helper
    HelperLauncher::Get().connectToHelper();

    // load QtWebChannel so that we can register our components with it.
    QQmlApplicationEngine *engine = Globals::Engine();

    KonvergoWindow::RegisterClass();
    Globals::SetContextProperty("components", &ComponentManager::Get().getQmlPropertyMap());

    // the only way to detect if QML parsing fails is to hook to this signal and then see
    // if we get a valid object passed to it. Any error messages will be reported on stderr
    // but since no normal user should ever see this it should be fine
    //
    QObject::connect(engine, &QQmlApplicationEngine::objectCreated, [=](QObject* object, const QUrl& url)
    {
      Q_UNUSED(url);

      if (object == nullptr)
        throw FatalException(QObject::tr("Failed to parse application engine script."));

      KonvergoWindow* window = Globals::MainWindow();

      QObject* webChannel = qvariant_cast<QObject*>(window->property("webChannel"));
      Q_ASSERT(webChannel);
      ComponentManager::Get().setWebChannel(qobject_cast<QWebChannel*>(webChannel));

      QObject::connect(uniqueApp, &UniqueApplication::otherApplicationStarted, window, &KonvergoWindow::otherAppFocus);
    });
    engine->load(QUrl(QStringLiteral("qrc:/ui/webview.qml")));

    Log::UpdateLogLevel();

    // run our application
    int ret = app.exec();

    delete uniqueApp;
    Globals::EngineDestroy();

    Log::Uninit();
    return ret;
  }
  catch (FatalException& e)
  {
    QLOG_FATAL() << "Unhandled FatalException:" << qPrintable(e.message());
    QApplication errApp(argc, argv);

    auto  msg = new ErrorMessage(e.message(), true);
    msg->show();

    errApp.exec();

    Log::Uninit();
    return 1;
  }
}
Example #4
0
void
AutomaticIPod::PlayCountsDatabase::bootstrap()
{
    qDebug() << "Starting bootstrapping...";
    
    gMoose.forward( "container://Notification/Twiddly/Bootstrap/Started" );
    
    beginTransaction();    
    
    QSqlQuery query( m_db );
    // this will fail if the metadata table doesn't exist, which is fine
    query.exec( "DELETE FROM metadata WHERE key='bootstrap_complete'" );
    query.exec( "DELETE FROM metadata WHERE key='plugin_ctime'" );
    query.exec( "DELETE FROM itunes_db" );

#ifdef Q_OS_MAC
    ITunesLibrary lib;
    
    // for wizard progress screen
    std::cout << lib.trackCount() << std::endl;
    
    int i = 0;
    while (lib.hasTracks())
    {
        ITunesLibrary::Track const t = lib.nextTrack();
        QString const plays = QString::number( t.playCount() );
        
        query.exec( "INSERT OR IGNORE INTO itunes_db ( persistent_id, play_count ) "
                    "VALUES ( '" + t.uniqueId() + "', '" + plays + "' )" );

        std::cout << ++i << std::endl;
    }

#else

    ITunesLibrary lib;
    int i = 0;
    
    // These cout statements are for the progress indicator in the client,
    // do not remove!
    std::cout << lib.trackCount() << std::endl;
    
    while ( lib.hasTracks() )
    {
        try
        {
            ITunesLibrary::Track t = lib.nextTrack();

            if ( !t.isNull() )
            {
                QString sql = "INSERT OR IGNORE INTO itunes_db ( persistent_id, path, play_count ) "
                              "VALUES ( :pid, :path, :plays )";
                exec( sql, t );
            }
        }
        catch ( ITunesException& )
        {
            // Move on...
        }

        std::cout << ++i << std::endl;
    }

#endif

    // if either INSERTS fail we'll rebootstrap next time
    query.exec( "CREATE TABLE metadata (key VARCHAR( 32 ), value VARCHAR( 32 ))" );
    query.exec( "INSERT INTO metadata (key, value) VALUES ('bootstrap_complete', 'true')" );
    
    QString const t = QString::number( common::fileCreationTime( pluginPath() ) );
    query.exec( "INSERT INTO metadata (key, value) VALUES ('plugin_ctime', '"+t+"')" );

    endTransaction();

    gMoose.forward( "container://Notification/Twiddly/Bootstrap/Finished" );
}