mirror of
https://github.com/lubosz/overte.git
synced 2025-04-29 19:03:10 +02:00
Don't wait on the sandbox
This commit is contained in:
parent
b36fb81524
commit
201f81f20a
7 changed files with 204 additions and 244 deletions
|
@ -563,11 +563,8 @@ const bool DEFAULT_DESKTOP_TABLET_BECOMES_TOOLBAR = true;
|
||||||
const bool DEFAULT_HMD_TABLET_BECOMES_TOOLBAR = false;
|
const bool DEFAULT_HMD_TABLET_BECOMES_TOOLBAR = false;
|
||||||
const bool DEFAULT_PREFER_AVATAR_FINGER_OVER_STYLUS = false;
|
const bool DEFAULT_PREFER_AVATAR_FINGER_OVER_STYLUS = false;
|
||||||
|
|
||||||
Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bool runServer, QString runServerPathOption) :
|
Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
||||||
QApplication(argc, argv),
|
QApplication(argc, argv),
|
||||||
_shouldRunServer(runServer),
|
|
||||||
_runServerPath(runServerPathOption),
|
|
||||||
_runningMarker(this, RUNNING_MARKER_FILENAME),
|
|
||||||
_window(new MainWindow(desktop())),
|
_window(new MainWindow(desktop())),
|
||||||
_sessionRunTimer(startupTimer),
|
_sessionRunTimer(startupTimer),
|
||||||
_previousSessionCrashed(setupEssentials(argc, argv)),
|
_previousSessionCrashed(setupEssentials(argc, argv)),
|
||||||
|
@ -622,8 +619,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
// make sure the debug draw singleton is initialized on the main thread.
|
// make sure the debug draw singleton is initialized on the main thread.
|
||||||
DebugDraw::getInstance().removeMarker("");
|
DebugDraw::getInstance().removeMarker("");
|
||||||
|
|
||||||
_runningMarker.startRunningMarker();
|
|
||||||
|
|
||||||
PluginContainer* pluginContainer = dynamic_cast<PluginContainer*>(this); // set the container for any plugins that care
|
PluginContainer* pluginContainer = dynamic_cast<PluginContainer*>(this); // set the container for any plugins that care
|
||||||
PluginManager::getInstance()->setContainer(pluginContainer);
|
PluginManager::getInstance()->setContainer(pluginContainer);
|
||||||
|
|
||||||
|
@ -675,38 +670,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
static const QString OCULUS_STORE_ARG = "--oculus-store";
|
static const QString OCULUS_STORE_ARG = "--oculus-store";
|
||||||
setProperty(hifi::properties::OCULUS_STORE, arguments().indexOf(OCULUS_STORE_ARG) != -1);
|
setProperty(hifi::properties::OCULUS_STORE, arguments().indexOf(OCULUS_STORE_ARG) != -1);
|
||||||
|
|
||||||
static const QString NO_UPDATER_ARG = "--no-updater";
|
|
||||||
static const bool noUpdater = arguments().indexOf(NO_UPDATER_ARG) != -1;
|
|
||||||
static const bool wantsSandboxRunning = shouldRunServer();
|
|
||||||
static bool determinedSandboxState = false;
|
|
||||||
static bool sandboxIsRunning = false;
|
|
||||||
SandboxUtils sandboxUtils;
|
|
||||||
// updateHeartbeat() because we are going to poll shortly...
|
|
||||||
updateHeartbeat();
|
updateHeartbeat();
|
||||||
sandboxUtils.ifLocalSandboxRunningElse([&]() {
|
|
||||||
qCDebug(interfaceapp) << "Home sandbox appears to be running.....";
|
|
||||||
determinedSandboxState = true;
|
|
||||||
sandboxIsRunning = true;
|
|
||||||
}, [&]() {
|
|
||||||
qCDebug(interfaceapp) << "Home sandbox does not appear to be running....";
|
|
||||||
if (wantsSandboxRunning) {
|
|
||||||
QString contentPath = getRunServerPath();
|
|
||||||
SandboxUtils::runLocalSandbox(contentPath, true, RUNNING_MARKER_FILENAME, noUpdater);
|
|
||||||
sandboxIsRunning = true;
|
|
||||||
}
|
|
||||||
determinedSandboxState = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
// SandboxUtils::runLocalSandbox currently has 2 sec delay after spawning sandbox, so 4
|
|
||||||
// sec here is ok I guess. TODO: ping sandbox so we know it is up, perhaps?
|
|
||||||
quint64 MAX_WAIT_TIME = USECS_PER_SECOND * 4;
|
|
||||||
auto startWaiting = usecTimestampNow();
|
|
||||||
while (!determinedSandboxState && (usecTimestampNow() - startWaiting <= MAX_WAIT_TIME)) {
|
|
||||||
QCoreApplication::processEvents();
|
|
||||||
// updateHeartbeat() while polling so we don't scare the deadlock watchdog
|
|
||||||
updateHeartbeat();
|
|
||||||
usleep(USECS_PER_MSEC * 50); // 20hz
|
|
||||||
}
|
|
||||||
|
|
||||||
// start the nodeThread so its event loop is running
|
// start the nodeThread so its event loop is running
|
||||||
QThread* nodeThread = new QThread(this);
|
QThread* nodeThread = new QThread(this);
|
||||||
|
@ -1223,6 +1187,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// If launched from Steam, let it handle updates
|
// If launched from Steam, let it handle updates
|
||||||
|
const QString HIFI_NO_UPDATER_COMMAND_LINE_KEY = "--no-updater";
|
||||||
|
bool noUpdater = arguments().indexOf(HIFI_NO_UPDATER_COMMAND_LINE_KEY) != -1;
|
||||||
if (!noUpdater) {
|
if (!noUpdater) {
|
||||||
auto applicationUpdater = DependencyManager::get<AutoUpdater>();
|
auto applicationUpdater = DependencyManager::get<AutoUpdater>();
|
||||||
connect(applicationUpdater.data(), &AutoUpdater::newVersionIsAvailable, dialogsManager.data(), &DialogsManager::showUpdateDialog);
|
connect(applicationUpdater.data(), &AutoUpdater::newVersionIsAvailable, dialogsManager.data(), &DialogsManager::showUpdateDialog);
|
||||||
|
@ -1465,110 +1431,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
const auto testScript = property(hifi::properties::TEST).toUrl();
|
const auto testScript = property(hifi::properties::TEST).toUrl();
|
||||||
scriptEngines->loadScript(testScript, false);
|
scriptEngines->loadScript(testScript, false);
|
||||||
} else {
|
} else {
|
||||||
enum HandControllerType {
|
PROFILE_RANGE(render, "GetSandboxStatus");
|
||||||
Vive,
|
auto reply = SandboxUtils::getStatus();
|
||||||
Oculus
|
connect(reply, &QNetworkReply::finished, this, [=] {
|
||||||
};
|
handleSandboxStatus(reply);
|
||||||
static const std::map<HandControllerType, int> MIN_CONTENT_VERSION = {
|
});
|
||||||
{ Vive, 1 },
|
|
||||||
{ Oculus, 27 }
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get sandbox content set version
|
|
||||||
auto acDirPath = PathUtils::getAppDataPath() + "../../" + BuildInfo::MODIFIED_ORGANIZATION + "/assignment-client/";
|
|
||||||
auto contentVersionPath = acDirPath + "content-version.txt";
|
|
||||||
qCDebug(interfaceapp) << "Checking " << contentVersionPath << " for content version";
|
|
||||||
int contentVersion = 0;
|
|
||||||
QFile contentVersionFile(contentVersionPath);
|
|
||||||
if (contentVersionFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
||||||
QString line = contentVersionFile.readAll();
|
|
||||||
contentVersion = line.toInt(); // returns 0 if conversion fails
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get controller availability
|
|
||||||
bool hasHandControllers = false;
|
|
||||||
HandControllerType handControllerType = Vive;
|
|
||||||
if (PluginUtils::isViveControllerAvailable()) {
|
|
||||||
hasHandControllers = true;
|
|
||||||
handControllerType = Vive;
|
|
||||||
} else if (PluginUtils::isOculusTouchControllerAvailable()) {
|
|
||||||
hasHandControllers = true;
|
|
||||||
handControllerType = Oculus;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check tutorial content versioning
|
|
||||||
bool hasTutorialContent = contentVersion >= MIN_CONTENT_VERSION.at(handControllerType);
|
|
||||||
|
|
||||||
// Check HMD use (may be technically available without being in use)
|
|
||||||
bool hasHMD = PluginUtils::isHMDAvailable();
|
|
||||||
bool isUsingHMD = hasHMD && hasHandControllers && _displayPlugin->isHmd();
|
|
||||||
|
|
||||||
Setting::Handle<bool> tutorialComplete { "tutorialComplete", false };
|
|
||||||
Setting::Handle<bool> firstRun { Settings::firstRun, true };
|
|
||||||
|
|
||||||
bool isTutorialComplete = tutorialComplete.get();
|
|
||||||
bool shouldGoToTutorial = isUsingHMD && hasTutorialContent && !isTutorialComplete;
|
|
||||||
|
|
||||||
qCDebug(interfaceapp) << "HMD:" << hasHMD << ", Hand Controllers: " << hasHandControllers << ", Using HMD: " << isUsingHMD;
|
|
||||||
qCDebug(interfaceapp) << "Tutorial version:" << contentVersion << ", sufficient:" << hasTutorialContent <<
|
|
||||||
", complete:" << isTutorialComplete << ", should go:" << shouldGoToTutorial;
|
|
||||||
|
|
||||||
// when --url in command line, teleport to location
|
|
||||||
const QString HIFI_URL_COMMAND_LINE_KEY = "--url";
|
|
||||||
int urlIndex = arguments().indexOf(HIFI_URL_COMMAND_LINE_KEY);
|
|
||||||
QString addressLookupString;
|
|
||||||
if (urlIndex != -1) {
|
|
||||||
addressLookupString = arguments().value(urlIndex + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString TUTORIAL_PATH = "/tutorial_begin";
|
|
||||||
|
|
||||||
if (shouldGoToTutorial) {
|
|
||||||
if (sandboxIsRunning) {
|
|
||||||
qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";
|
|
||||||
DependencyManager::get<AddressManager>()->goToLocalSandbox(TUTORIAL_PATH);
|
|
||||||
} else {
|
|
||||||
qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";
|
|
||||||
if (firstRun.get()) {
|
|
||||||
showHelp();
|
|
||||||
}
|
|
||||||
if (addressLookupString.isEmpty()) {
|
|
||||||
DependencyManager::get<AddressManager>()->goToEntry();
|
|
||||||
} else {
|
|
||||||
DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
bool isFirstRun = firstRun.get();
|
|
||||||
|
|
||||||
if (isFirstRun) {
|
|
||||||
showHelp();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this is a first run we short-circuit the address passed in
|
|
||||||
if (isFirstRun) {
|
|
||||||
if (isUsingHMD) {
|
|
||||||
if (sandboxIsRunning) {
|
|
||||||
qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";
|
|
||||||
DependencyManager::get<AddressManager>()->goToLocalSandbox();
|
|
||||||
} else {
|
|
||||||
qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";
|
|
||||||
DependencyManager::get<AddressManager>()->goToEntry();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
DependencyManager::get<AddressManager>()->goToEntry();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
qCDebug(interfaceapp) << "Not first run... going to" << qPrintable(addressLookupString.isEmpty() ? QString("previous location") : addressLookupString);
|
|
||||||
DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_connectionMonitor.init();
|
|
||||||
|
|
||||||
// After all of the constructor is completed, then set firstRun to false.
|
|
||||||
firstRun.set(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Monitor model assets (e.g., from Clara.io) added to the world that may need resizing.
|
// Monitor model assets (e.g., from Clara.io) added to the world that may need resizing.
|
||||||
|
@ -2474,6 +2341,118 @@ void Application::resizeGL() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::handleSandboxStatus(QNetworkReply* reply) {
|
||||||
|
PROFILE_RANGE(render, "HandleSandboxStatus");
|
||||||
|
|
||||||
|
bool sandboxIsRunning = SandboxUtils::readStatus(reply->readAll());
|
||||||
|
qDebug() << "HandleSandboxStatus" << sandboxIsRunning;
|
||||||
|
|
||||||
|
enum HandControllerType {
|
||||||
|
Vive,
|
||||||
|
Oculus
|
||||||
|
};
|
||||||
|
static const std::map<HandControllerType, int> MIN_CONTENT_VERSION = {
|
||||||
|
{ Vive, 1 },
|
||||||
|
{ Oculus, 27 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get sandbox content set version
|
||||||
|
auto acDirPath = PathUtils::getAppDataPath() + "../../" + BuildInfo::MODIFIED_ORGANIZATION + "/assignment-client/";
|
||||||
|
auto contentVersionPath = acDirPath + "content-version.txt";
|
||||||
|
qCDebug(interfaceapp) << "Checking " << contentVersionPath << " for content version";
|
||||||
|
int contentVersion = 0;
|
||||||
|
QFile contentVersionFile(contentVersionPath);
|
||||||
|
if (contentVersionFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
|
QString line = contentVersionFile.readAll();
|
||||||
|
contentVersion = line.toInt(); // returns 0 if conversion fails
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get controller availability
|
||||||
|
bool hasHandControllers = false;
|
||||||
|
HandControllerType handControllerType = Vive;
|
||||||
|
if (PluginUtils::isViveControllerAvailable()) {
|
||||||
|
hasHandControllers = true;
|
||||||
|
handControllerType = Vive;
|
||||||
|
} else if (PluginUtils::isOculusTouchControllerAvailable()) {
|
||||||
|
hasHandControllers = true;
|
||||||
|
handControllerType = Oculus;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check tutorial content versioning
|
||||||
|
bool hasTutorialContent = contentVersion >= MIN_CONTENT_VERSION.at(handControllerType);
|
||||||
|
|
||||||
|
// Check HMD use (may be technically available without being in use)
|
||||||
|
bool hasHMD = PluginUtils::isHMDAvailable();
|
||||||
|
bool isUsingHMD = hasHMD && hasHandControllers && _displayPlugin->isHmd();
|
||||||
|
|
||||||
|
Setting::Handle<bool> tutorialComplete{ "tutorialComplete", false };
|
||||||
|
Setting::Handle<bool> firstRun{ Settings::firstRun, true };
|
||||||
|
|
||||||
|
bool isTutorialComplete = tutorialComplete.get();
|
||||||
|
bool shouldGoToTutorial = isUsingHMD && hasTutorialContent && !isTutorialComplete;
|
||||||
|
|
||||||
|
qCDebug(interfaceapp) << "HMD:" << hasHMD << ", Hand Controllers: " << hasHandControllers << ", Using HMD: " << isUsingHMD;
|
||||||
|
qCDebug(interfaceapp) << "Tutorial version:" << contentVersion << ", sufficient:" << hasTutorialContent <<
|
||||||
|
", complete:" << isTutorialComplete << ", should go:" << shouldGoToTutorial;
|
||||||
|
|
||||||
|
// when --url in command line, teleport to location
|
||||||
|
const QString HIFI_URL_COMMAND_LINE_KEY = "--url";
|
||||||
|
int urlIndex = arguments().indexOf(HIFI_URL_COMMAND_LINE_KEY);
|
||||||
|
QString addressLookupString;
|
||||||
|
if (urlIndex != -1) {
|
||||||
|
addressLookupString = arguments().value(urlIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString TUTORIAL_PATH = "/tutorial_begin";
|
||||||
|
|
||||||
|
if (shouldGoToTutorial) {
|
||||||
|
if (sandboxIsRunning) {
|
||||||
|
qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";
|
||||||
|
DependencyManager::get<AddressManager>()->goToLocalSandbox(TUTORIAL_PATH);
|
||||||
|
} else {
|
||||||
|
qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";
|
||||||
|
if (firstRun.get()) {
|
||||||
|
showHelp();
|
||||||
|
}
|
||||||
|
if (addressLookupString.isEmpty()) {
|
||||||
|
DependencyManager::get<AddressManager>()->goToEntry();
|
||||||
|
} else {
|
||||||
|
DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
bool isFirstRun = firstRun.get();
|
||||||
|
|
||||||
|
if (isFirstRun) {
|
||||||
|
showHelp();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is a first run we short-circuit the address passed in
|
||||||
|
if (isFirstRun) {
|
||||||
|
if (isUsingHMD) {
|
||||||
|
if (sandboxIsRunning) {
|
||||||
|
qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";
|
||||||
|
DependencyManager::get<AddressManager>()->goToLocalSandbox();
|
||||||
|
} else {
|
||||||
|
qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";
|
||||||
|
DependencyManager::get<AddressManager>()->goToEntry();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DependencyManager::get<AddressManager>()->goToEntry();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qCDebug(interfaceapp) << "Not first run... going to" << qPrintable(addressLookupString.isEmpty() ? QString("previous location") : addressLookupString);
|
||||||
|
DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_connectionMonitor.init();
|
||||||
|
|
||||||
|
// After all of the constructor is completed, then set firstRun to false.
|
||||||
|
firstRun.set(false);
|
||||||
|
}
|
||||||
|
|
||||||
bool Application::importJSONFromURL(const QString& urlString) {
|
bool Application::importJSONFromURL(const QString& urlString) {
|
||||||
// we only load files that terminate in just .json (not .svo.json and not .ava.json)
|
// we only load files that terminate in just .json (not .svo.json and not .ava.json)
|
||||||
// if they come from the High Fidelity Marketplace Assets CDN
|
// if they come from the High Fidelity Marketplace Assets CDN
|
||||||
|
|
|
@ -112,17 +112,7 @@ class Application : public QApplication,
|
||||||
// TODO? Get rid of those
|
// TODO? Get rid of those
|
||||||
friend class OctreePacketProcessor;
|
friend class OctreePacketProcessor;
|
||||||
|
|
||||||
private:
|
|
||||||
bool _shouldRunServer { false };
|
|
||||||
QString _runServerPath;
|
|
||||||
RunningMarker _runningMarker;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// startup related getter/setters
|
|
||||||
bool shouldRunServer() const { return _shouldRunServer; }
|
|
||||||
bool hasRunServerPath() const { return !_runServerPath.isEmpty(); }
|
|
||||||
QString getRunServerPath() const { return _runServerPath; }
|
|
||||||
|
|
||||||
// virtual functions required for PluginContainer
|
// virtual functions required for PluginContainer
|
||||||
virtual ui::Menu* getPrimaryMenu() override;
|
virtual ui::Menu* getPrimaryMenu() override;
|
||||||
virtual void requestReset() override { resetSensors(true); }
|
virtual void requestReset() override { resetSensors(true); }
|
||||||
|
@ -146,7 +136,7 @@ public:
|
||||||
static void initPlugins(const QStringList& arguments);
|
static void initPlugins(const QStringList& arguments);
|
||||||
static void shutdownPlugins();
|
static void shutdownPlugins();
|
||||||
|
|
||||||
Application(int& argc, char** argv, QElapsedTimer& startup_time, bool runServer, QString runServerPathOption);
|
Application(int& argc, char** argv, QElapsedTimer& startup_time);
|
||||||
~Application();
|
~Application();
|
||||||
|
|
||||||
void postLambdaEvent(std::function<void()> f) override;
|
void postLambdaEvent(std::function<void()> f) override;
|
||||||
|
@ -452,6 +442,8 @@ private slots:
|
||||||
void addAssetToWorldInfoTimeout();
|
void addAssetToWorldInfoTimeout();
|
||||||
void addAssetToWorldErrorTimeout();
|
void addAssetToWorldErrorTimeout();
|
||||||
|
|
||||||
|
void handleSandboxStatus(QNetworkReply* reply);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void initDisplay();
|
static void initDisplay();
|
||||||
void init();
|
void init();
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include <QCommandLineParser>
|
#include <QCommandLineParser>
|
||||||
|
#include <QtCore/QProcess>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QLocalSocket>
|
#include <QLocalSocket>
|
||||||
|
@ -20,6 +21,7 @@
|
||||||
|
|
||||||
#include <BuildInfo.h>
|
#include <BuildInfo.h>
|
||||||
#include <gl/OpenGLVersionChecker.h>
|
#include <gl/OpenGLVersionChecker.h>
|
||||||
|
#include <SandboxUtils.h>
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,7 +30,6 @@
|
||||||
#include "InterfaceLogging.h"
|
#include "InterfaceLogging.h"
|
||||||
#include "UserActivityLogger.h"
|
#include "UserActivityLogger.h"
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
#include <QtCore/QProcess>
|
|
||||||
|
|
||||||
#ifdef HAS_BUGSPLAT
|
#ifdef HAS_BUGSPLAT
|
||||||
#include <BugSplat.h>
|
#include <BugSplat.h>
|
||||||
|
@ -50,50 +51,49 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
disableQtBearerPoll(); // Fixes wifi ping spikes
|
disableQtBearerPoll(); // Fixes wifi ping spikes
|
||||||
|
|
||||||
|
QElapsedTimer startupTime;
|
||||||
|
startupTime.start();
|
||||||
|
|
||||||
// Set application infos
|
// Set application infos
|
||||||
QCoreApplication::setApplicationName(BuildInfo::INTERFACE_NAME);
|
QCoreApplication::setApplicationName(BuildInfo::INTERFACE_NAME);
|
||||||
QCoreApplication::setOrganizationName(BuildInfo::MODIFIED_ORGANIZATION);
|
QCoreApplication::setOrganizationName(BuildInfo::MODIFIED_ORGANIZATION);
|
||||||
QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN);
|
QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN);
|
||||||
QCoreApplication::setApplicationVersion(BuildInfo::VERSION);
|
QCoreApplication::setApplicationVersion(BuildInfo::VERSION);
|
||||||
|
|
||||||
const QString& applicationName = getInterfaceSharedMemoryName();
|
|
||||||
|
|
||||||
bool instanceMightBeRunning = true;
|
|
||||||
|
|
||||||
QStringList arguments;
|
QStringList arguments;
|
||||||
for (int i = 0; i < argc; ++i) {
|
for (int i = 0; i < argc; ++i) {
|
||||||
arguments << argv[i];
|
arguments << argv[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
||||||
// allow multiple interfaces to run if this environment variable is set.
|
|
||||||
if (QProcessEnvironment::systemEnvironment().contains("HIFI_ALLOW_MULTIPLE_INSTANCES")) {
|
|
||||||
instanceMightBeRunning = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
|
QCommandLineOption urlOption("url", "", "value");
|
||||||
|
QCommandLineOption noUpdaterOption("no-updater", "Do not show auto-updater");
|
||||||
QCommandLineOption checkMinSpecOption("checkMinSpec", "Check if machine meets minimum specifications");
|
QCommandLineOption checkMinSpecOption("checkMinSpec", "Check if machine meets minimum specifications");
|
||||||
QCommandLineOption runServerOption("runServer", "Whether to run the server");
|
QCommandLineOption runServerOption("runServer", "Whether to run the server");
|
||||||
QCommandLineOption serverContentPathOption("serverContentPath", "Where to find server content", "serverContentPath");
|
QCommandLineOption serverContentPathOption("serverContentPath", "Where to find server content", "serverContentPath");
|
||||||
QCommandLineOption allowMultipleInstancesOption("allowMultipleInstances", "Allow multiple instances to run");
|
QCommandLineOption allowMultipleInstancesOption("allowMultipleInstances", "Allow multiple instances to run");
|
||||||
|
parser.addOption(urlOption);
|
||||||
|
parser.addOption(noUpdaterOption);
|
||||||
parser.addOption(checkMinSpecOption);
|
parser.addOption(checkMinSpecOption);
|
||||||
parser.addOption(runServerOption);
|
parser.addOption(runServerOption);
|
||||||
parser.addOption(serverContentPathOption);
|
parser.addOption(serverContentPathOption);
|
||||||
parser.addOption(allowMultipleInstancesOption);
|
parser.addOption(allowMultipleInstancesOption);
|
||||||
parser.parse(arguments);
|
parser.parse(arguments);
|
||||||
bool runServer = parser.isSet(runServerOption);
|
|
||||||
bool serverContentPathOptionIsSet = parser.isSet(serverContentPathOption);
|
|
||||||
QString serverContentPathOptionValue = serverContentPathOptionIsSet ? parser.value(serverContentPathOption) : QString();
|
|
||||||
bool allowMultipleInstances = parser.isSet(allowMultipleInstancesOption);
|
|
||||||
|
|
||||||
|
|
||||||
|
const QString& applicationName = getInterfaceSharedMemoryName();
|
||||||
|
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
|
||||||
|
|
||||||
|
// allow multiple interfaces to run if this environment variable is set.
|
||||||
|
bool allowMultipleInstances = parser.isSet(allowMultipleInstancesOption) ||
|
||||||
|
QProcessEnvironment::systemEnvironment().contains("HIFI_ALLOW_MULTIPLE_INSTANCES");
|
||||||
if (allowMultipleInstances) {
|
if (allowMultipleInstances) {
|
||||||
instanceMightBeRunning = false;
|
instanceMightBeRunning = false;
|
||||||
}
|
}
|
||||||
|
@ -108,11 +108,6 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
// Try to connect - if we can't connect, interface has probably just gone down
|
// Try to connect - if we can't connect, interface has probably just gone down
|
||||||
if (socket.waitForConnected(LOCAL_SERVER_TIMEOUT_MS)) {
|
if (socket.waitForConnected(LOCAL_SERVER_TIMEOUT_MS)) {
|
||||||
QCommandLineParser parser;
|
|
||||||
QCommandLineOption urlOption("url", "", "value");
|
|
||||||
parser.addOption(urlOption);
|
|
||||||
parser.process(arguments);
|
|
||||||
|
|
||||||
if (parser.isSet(urlOption)) {
|
if (parser.isSet(urlOption)) {
|
||||||
QUrl url = QUrl(parser.value(urlOption));
|
QUrl url = QUrl(parser.value(urlOption));
|
||||||
if (url.isValid() && url.scheme() == HIFI_URL_SCHEME) {
|
if (url.isValid() && url.scheme() == HIFI_URL_SCHEME) {
|
||||||
|
@ -156,9 +151,6 @@ int main(int argc, const char* argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QElapsedTimer startupTime;
|
|
||||||
startupTime.start();
|
|
||||||
|
|
||||||
// Debug option to demonstrate that the client's local time does not
|
// 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
|
// need to be in sync with any other network node. This forces clock
|
||||||
// skew for the individual client
|
// skew for the individual client
|
||||||
|
@ -199,7 +191,21 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
int exitCode;
|
int exitCode;
|
||||||
{
|
{
|
||||||
Application app(argc, const_cast<char**>(argv), startupTime, runServer, serverContentPathOptionValue);
|
RunningMarker runningMarker(nullptr, RUNNING_MARKER_FILENAME);
|
||||||
|
runningMarker.writeRunningMarkerFile();
|
||||||
|
|
||||||
|
bool noUpdater = parser.isSet(noUpdaterOption);
|
||||||
|
bool runServer = parser.isSet(runServerOption);
|
||||||
|
bool serverContentPathOptionIsSet = parser.isSet(serverContentPathOption);
|
||||||
|
QString serverContentPath = serverContentPathOptionIsSet ? parser.value(serverContentPathOption) : QString();
|
||||||
|
if (runServer) {
|
||||||
|
SandboxUtils::runLocalSandbox(serverContentPath, true, RUNNING_MARKER_FILENAME, noUpdater);
|
||||||
|
}
|
||||||
|
|
||||||
|
Application app(argc, const_cast<char**>(argv), startupTime);
|
||||||
|
|
||||||
|
// Now that the main event loop is setup, launch running marker thread
|
||||||
|
runningMarker.startRunningMarker();
|
||||||
|
|
||||||
// If we failed the OpenGLVersion check, log it.
|
// If we failed the OpenGLVersion check, log it.
|
||||||
if (override) {
|
if (override) {
|
||||||
|
|
|
@ -9,63 +9,52 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <QDataStream>
|
#include "SandboxUtils.h"
|
||||||
#include <QDebug>
|
|
||||||
#include <QFile>
|
|
||||||
#include <QFileInfo>
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QStandardPaths>
|
|
||||||
#include <QThread>
|
|
||||||
#include <QTimer>
|
|
||||||
|
|
||||||
#include <NumericalConstants.h>
|
#include <NumericalConstants.h>
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
#include <RunningMarker.h>
|
#include <RunningMarker.h>
|
||||||
|
|
||||||
#include "SandboxUtils.h"
|
|
||||||
#include "NetworkAccessManager.h"
|
#include "NetworkAccessManager.h"
|
||||||
#include "NetworkLogging.h"
|
#include "NetworkLogging.h"
|
||||||
|
|
||||||
|
namespace SandboxUtils {
|
||||||
|
|
||||||
void SandboxUtils::ifLocalSandboxRunningElse(std::function<void()> localSandboxRunningDoThis,
|
QNetworkReply* getStatus() {
|
||||||
std::function<void()> localSandboxNotRunningDoThat) {
|
auto& networkAccessManager = NetworkAccessManager::getInstance();
|
||||||
|
|
||||||
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
|
||||||
QNetworkRequest sandboxStatus(SANDBOX_STATUS_URL);
|
QNetworkRequest sandboxStatus(SANDBOX_STATUS_URL);
|
||||||
sandboxStatus.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
sandboxStatus.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||||
sandboxStatus.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
|
sandboxStatus.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
|
||||||
QNetworkReply* reply = networkAccessManager.get(sandboxStatus);
|
return networkAccessManager.get(sandboxStatus);
|
||||||
|
|
||||||
connect(reply, &QNetworkReply::finished, this, [reply, localSandboxRunningDoThis, localSandboxNotRunningDoThat]() {
|
|
||||||
if (reply->error() == QNetworkReply::NoError) {
|
|
||||||
auto statusData = reply->readAll();
|
|
||||||
auto statusJson = QJsonDocument::fromJson(statusData);
|
|
||||||
if (!statusJson.isEmpty()) {
|
|
||||||
auto statusObject = statusJson.object();
|
|
||||||
auto serversValue = statusObject.value("servers");
|
|
||||||
if (!serversValue.isUndefined() && serversValue.isObject()) {
|
|
||||||
auto serversObject = serversValue.toObject();
|
|
||||||
auto serversCount = serversObject.size();
|
|
||||||
const int MINIMUM_EXPECTED_SERVER_COUNT = 5;
|
|
||||||
if (serversCount >= MINIMUM_EXPECTED_SERVER_COUNT) {
|
|
||||||
localSandboxRunningDoThis();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
localSandboxNotRunningDoThat();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool readStatus(QByteArray statusData) {
|
||||||
|
auto statusJson = QJsonDocument::fromJson(statusData);
|
||||||
|
|
||||||
void SandboxUtils::runLocalSandbox(QString contentPath, bool autoShutdown, QString runningMarkerName, bool noUpdater) {
|
if (!statusJson.isEmpty()) {
|
||||||
QString applicationDirPath = QFileInfo(QCoreApplication::applicationFilePath()).path();
|
auto statusObject = statusJson.object();
|
||||||
QString serverPath = applicationDirPath + "/server-console/server-console.exe";
|
auto serversValue = statusObject.value("servers");
|
||||||
qCDebug(networking) << "Application dir path is: " << applicationDirPath;
|
if (!serversValue.isUndefined() && serversValue.isObject()) {
|
||||||
|
auto serversObject = serversValue.toObject();
|
||||||
|
auto serversCount = serversObject.size();
|
||||||
|
const int MINIMUM_EXPECTED_SERVER_COUNT = 5;
|
||||||
|
if (serversCount >= MINIMUM_EXPECTED_SERVER_COUNT) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void runLocalSandbox(QString contentPath, bool autoShutdown, QString runningMarkerName, bool noUpdater) {
|
||||||
|
QString serverPath = "./server-console/server-console.exe";
|
||||||
|
qCDebug(networking) << "Running marker path is: " << runningMarkerName;
|
||||||
qCDebug(networking) << "Server path is: " << serverPath;
|
qCDebug(networking) << "Server path is: " << serverPath;
|
||||||
qCDebug(networking) << "autoShutdown: " << autoShutdown;
|
qCDebug(networking) << "autoShutdown: " << autoShutdown;
|
||||||
qCDebug(networking) << "noUpdater: " << noUpdater;
|
qCDebug(networking) << "noUpdater: " << noUpdater;
|
||||||
|
@ -80,7 +69,7 @@ void SandboxUtils::runLocalSandbox(QString contentPath, bool autoShutdown, QStri
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasContentPath) {
|
if (hasContentPath) {
|
||||||
QString serverContentPath = applicationDirPath + "/" + contentPath;
|
QString serverContentPath = "./" + contentPath;
|
||||||
args << "--contentPath" << serverContentPath;
|
args << "--contentPath" << serverContentPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,10 +82,8 @@ void SandboxUtils::runLocalSandbox(QString contentPath, bool autoShutdown, QStri
|
||||||
args << "--noUpdater";
|
args << "--noUpdater";
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(networking) << applicationDirPath;
|
|
||||||
qCDebug(networking) << "Launching sandbox with:" << args;
|
qCDebug(networking) << "Launching sandbox with:" << args;
|
||||||
qCDebug(networking) << QProcess::startDetached(serverPath, args);
|
qCDebug(networking) << QProcess::startDetached(serverPath, args);
|
||||||
|
}
|
||||||
// Sleep a short amount of time to give the server a chance to start
|
|
||||||
usleep(2000000); /// do we really need this??
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,21 +12,16 @@
|
||||||
#ifndef hifi_SandboxUtils_h
|
#ifndef hifi_SandboxUtils_h
|
||||||
#define hifi_SandboxUtils_h
|
#define hifi_SandboxUtils_h
|
||||||
|
|
||||||
#include <functional>
|
#include <QtCore/QString>
|
||||||
#include <QtCore/QObject>
|
|
||||||
|
|
||||||
|
class QNetworkReply;
|
||||||
|
|
||||||
const QString SANDBOX_STATUS_URL = "http://localhost:60332/status";
|
namespace SandboxUtils {
|
||||||
|
const QString SANDBOX_STATUS_URL = "http://localhost:60332/status";
|
||||||
|
|
||||||
class SandboxUtils : public QObject {
|
QNetworkReply* getStatus();
|
||||||
Q_OBJECT
|
bool readStatus(QByteArray statusData);
|
||||||
public:
|
void runLocalSandbox(QString contentPath, bool autoShutdown, QString runningMarkerName, bool noUpdater);
|
||||||
/// determines if the local sandbox is likely running. It does not account for custom setups, and is only
|
|
||||||
/// intended to detect the standard local sandbox install.
|
|
||||||
void ifLocalSandboxRunningElse(std::function<void()> localSandboxRunningDoThis,
|
|
||||||
std::function<void()> localSandboxNotRunningDoThat);
|
|
||||||
|
|
||||||
static void runLocalSandbox(QString contentPath, bool autoShutdown, QString runningMarkerName, bool noUpdater);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_SandboxUtils_h
|
#endif // hifi_SandboxUtils_h
|
||||||
|
|
|
@ -33,11 +33,11 @@ void RunningMarker::startRunningMarker() {
|
||||||
_runningMarkerThread->setObjectName("Running Marker Thread");
|
_runningMarkerThread->setObjectName("Running Marker Thread");
|
||||||
_runningMarkerThread->start();
|
_runningMarkerThread->start();
|
||||||
|
|
||||||
writeRunningMarkerFiler(); // write the first file, even before timer
|
writeRunningMarkerFile(); // write the first file, even before timer
|
||||||
|
|
||||||
_runningMarkerTimer = new QTimer();
|
_runningMarkerTimer = new QTimer();
|
||||||
QObject::connect(_runningMarkerTimer, &QTimer::timeout, [=](){
|
QObject::connect(_runningMarkerTimer, &QTimer::timeout, [=](){
|
||||||
writeRunningMarkerFiler();
|
writeRunningMarkerFile();
|
||||||
});
|
});
|
||||||
_runningMarkerTimer->start(RUNNING_STATE_CHECK_IN_MSECS);
|
_runningMarkerTimer->start(RUNNING_STATE_CHECK_IN_MSECS);
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ RunningMarker::~RunningMarker() {
|
||||||
_runningMarkerThread->deleteLater();
|
_runningMarkerThread->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunningMarker::writeRunningMarkerFiler() {
|
void RunningMarker::writeRunningMarkerFile() {
|
||||||
QFile runningMarkerFile(getFilePath());
|
QFile runningMarkerFile(getFilePath());
|
||||||
|
|
||||||
// always write, even it it exists, so that it touches the files
|
// always write, even it it exists, so that it touches the files
|
||||||
|
|
|
@ -27,10 +27,11 @@ public:
|
||||||
|
|
||||||
QString getFilePath();
|
QString getFilePath();
|
||||||
static QString getMarkerFilePath(QString name);
|
static QString getMarkerFilePath(QString name);
|
||||||
protected:
|
|
||||||
void writeRunningMarkerFiler();
|
void writeRunningMarkerFile();
|
||||||
void deleteRunningMarkerFile();
|
void deleteRunningMarkerFile();
|
||||||
|
|
||||||
|
private:
|
||||||
QObject* _parent { nullptr };
|
QObject* _parent { nullptr };
|
||||||
QString _name;
|
QString _name;
|
||||||
QThread* _runningMarkerThread { nullptr };
|
QThread* _runningMarkerThread { nullptr };
|
||||||
|
|
Loading…
Reference in a new issue