Example #1
0
int main(int argc, const char* argv[]) {
    disableQtBearerPoll(); // Fixes wifi ping spikes
    
    QString applicationName = "High Fidelity Interface - " + qgetenv("USERNAME");

    bool instanceMightBeRunning = true;

#ifdef Q_OS_WIN
    // Try to create a shared memory block - if it can't be created, there is an instance of
    // interface already running. We only do this on Windows for now because of the potential
    // for crashed instances to leave behind shared memory instances on unix.
    QSharedMemory sharedMemory { applicationName };
    instanceMightBeRunning = !sharedMemory.create(1, QSharedMemory::ReadOnly);
#endif

    if (instanceMightBeRunning) {
        // Try to connect and send message to existing interface instance
        QLocalSocket socket;

        socket.connectToServer(applicationName);

        static const int LOCAL_SERVER_TIMEOUT_MS = 500;

        // Try to connect - if we can't connect, interface has probably just gone down
        if (socket.waitForConnected(LOCAL_SERVER_TIMEOUT_MS)) {

            QStringList arguments;
            for (int i = 0; i < argc; ++i) {
                arguments << argv[i];
            }

            QCommandLineParser parser;
            QCommandLineOption urlOption("url", "", "value");
            parser.addOption(urlOption);
            parser.process(arguments);

            if (parser.isSet(urlOption)) {
                QUrl url = QUrl(parser.value(urlOption));
                if (url.isValid() && url.scheme() == HIFI_URL_SCHEME) {
                    qDebug() << "Writing URL to local socket";
                    socket.write(url.toString().toUtf8());
                    if (!socket.waitForBytesWritten(5000)) {
                        qDebug() << "Error writing URL to local socket";
                    }
                }
            }

            socket.close();

            qDebug() << "Interface instance appears to be running, exiting";

            return EXIT_SUCCESS;
        }

#ifdef Q_OS_WIN
        return EXIT_SUCCESS;
#endif
    }

    // Check OpenGL version.
    // This is done separately from the main Application so that start-up and shut-down logic within the main Application is
    // not made more complicated than it already is.
    {
        OpenGLVersionChecker openGLVersionChecker(argc, const_cast<char**>(argv));
        if (!openGLVersionChecker.isValidVersion()) {
            qCDebug(interfaceapp, "Early exit due to OpenGL version.");
            return 0;
        }
    }

    QElapsedTimer startupTime;
    startupTime.start();

    // Debug option to demonstrate that the client's local time does not
    // need to be in sync with any other network node. This forces clock
    // skew for the individual client
    const char* CLOCK_SKEW = "--clockSkew";
    const char* clockSkewOption = getCmdOption(argc, argv, CLOCK_SKEW);
    if (clockSkewOption) {
        int clockSkew = atoi(clockSkewOption);
        usecTimestampNowForceClockSkew(clockSkew);
        qCDebug(interfaceapp, "clockSkewOption=%s clockSkew=%d", clockSkewOption, clockSkew);
    }

    // Oculus initialization MUST PRECEDE OpenGL context creation.
    // The nature of the Application constructor means this has to be either here,
    // or in the main window ctor, before GL startup.
    Application::initPlugins();

    int exitCode;
    {
        QSettings::setDefaultFormat(QSettings::IniFormat);
        Application app(argc, const_cast<char**>(argv), startupTime);

        // Setup local server
        QLocalServer server { &app };

        // We failed to connect to a local server, so we remove any existing servers.
        server.removeServer(applicationName);
        server.listen(applicationName);

        QObject::connect(&server, &QLocalServer::newConnection, &app, &Application::handleLocalServerConnection);

        QTranslator translator;
        translator.load("i18n/interface_en");
        app.installTranslator(&translator);

        qCDebug(interfaceapp, "Created QT Application.");
        exitCode = app.exec();
        server.close();
    }

    Application::shutdownPlugins();

    qCDebug(interfaceapp, "Normal exit.");
    return exitCode;
}
Example #2
0
int main(int argc, const char* argv[]) {
#ifdef Q_OS_WIN
    // Run only one instance of Interface at a time.
    HANDLE mutex = CreateMutex(NULL, FALSE, "High Fidelity Interface - " + qgetenv("USERNAME"));
    DWORD result = GetLastError();
    if (result == ERROR_ALREADY_EXISTS || result == ERROR_ACCESS_DENIED) {
        // Interface is already running.
        HWND otherInstance = NULL;
        EnumWindows(enumWindowsCallback, (LPARAM)&otherInstance);
        if (otherInstance) {
            // Show other instance.
            SendMessage(otherInstance, UWM_SHOW_APPLICATION, 0, 0);

            // Send command line --url value to other instance.
            if (argc >= 3) {
                QStringList arguments;
                for (int i = 0; i < argc; i += 1) {
                    arguments << argv[i];
                }

                QCommandLineParser parser;
                QCommandLineOption urlOption("url", "", "value");
                parser.addOption(urlOption);
                parser.process(arguments);

                if (parser.isSet(urlOption)) {
                    QUrl url = QUrl(parser.value(urlOption));
                    if (url.isValid() && url.scheme() == HIFI_URL_SCHEME) {
                        QByteArray urlBytes = url.toString().toLatin1();
                        const char* urlChars = urlBytes.data();
                        COPYDATASTRUCT cds;
                        cds.cbData = urlBytes.length() + 1;
                        cds.lpData = (PVOID)urlChars;
                        SendMessage(otherInstance, WM_COPYDATA, 0, (LPARAM)&cds);
                    }
                }
            }
        }
        return 0;
    }
#endif

    QElapsedTimer startupTime;
    startupTime.start();
    
    // Debug option to demonstrate that the client's local time does not 
    // need to be in sync with any other network node. This forces clock 
    // skew for the individual client
    const char* CLOCK_SKEW = "--clockSkew";
    const char* clockSkewOption = getCmdOption(argc, argv, CLOCK_SKEW);
    if (clockSkewOption) {
        int clockSkew = atoi(clockSkewOption);
        usecTimestampNowForceClockSkew(clockSkew);
        qCDebug(interfaceapp, "clockSkewOption=%s clockSkew=%d", clockSkewOption, clockSkew);
    }
    // Oculus initialization MUST PRECEDE OpenGL context creation.
    // The nature of the Application constructor means this has to be either here,
    // or in the main window ctor, before GL startup.
    Application::initPlugins();

    int exitCode;
    {
        QSettings::setDefaultFormat(QSettings::IniFormat);
        Application app(argc, const_cast<char**>(argv), startupTime);

        QTranslator translator;
        translator.load("interface_en");
        app.installTranslator(&translator);
    
        qCDebug(interfaceapp, "Created QT Application.");
        exitCode = app.exec();
    }

    Application::shutdownPlugins();
#ifdef Q_OS_WIN
    ReleaseMutex(mutex);
#endif

    qCDebug(interfaceapp, "Normal exit.");
    return exitCode;
}