From ed88232fb06bc8096d20637dc6abdcd8b52ed31d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 16 Jun 2016 09:19:42 -0700 Subject: [PATCH 01/34] Move session id storage to AccountManager --- interface/src/DiscoverabilityManager.cpp | 14 ++++++-------- interface/src/DiscoverabilityManager.h | 1 - libraries/networking/src/AccountManager.cpp | 7 +++++-- libraries/networking/src/AccountManager.h | 3 ++- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/interface/src/DiscoverabilityManager.cpp b/interface/src/DiscoverabilityManager.cpp index 24256fdf39..c4d985419e 100644 --- a/interface/src/DiscoverabilityManager.cpp +++ b/interface/src/DiscoverabilityManager.cpp @@ -80,7 +80,8 @@ void DiscoverabilityManager::updateLocation() { locationObject.insert(FRIENDS_ONLY_KEY_IN_LOCATION, (_mode.get() == Discoverability::Friends)); // if we have a session ID add it now, otherwise add a null value - rootObject[SESSION_ID_KEY] = _sessionID.isEmpty() ? QJsonValue() : _sessionID; + auto sessionID = accountManager->getSessionID(); + rootObject[SESSION_ID_KEY] = sessionID.isNull() ? QJsonValue() : sessionID.toString(); JSONCallbackParameters callbackParameters; callbackParameters.jsonCallbackReceiver = this; @@ -110,11 +111,8 @@ void DiscoverabilityManager::updateLocation() { callbackParameters.jsonCallbackMethod = "handleHeartbeatResponse"; QJsonObject heartbeatObject; - if (!_sessionID.isEmpty()) { - heartbeatObject[SESSION_ID_KEY] = _sessionID; - } else { - heartbeatObject[SESSION_ID_KEY] = QJsonValue(); - } + auto sessionID = accountManager->getSessionID(); + heartbeatObject[SESSION_ID_KEY] = sessionID.isNull() ? QJsonValue() : sessionID.toString(); accountManager->sendRequest(API_USER_HEARTBEAT_PATH, AccountManagerAuth::Optional, QNetworkAccessManager::PutOperation, callbackParameters, @@ -126,11 +124,11 @@ void DiscoverabilityManager::handleHeartbeatResponse(QNetworkReply& requestReply auto dataObject = AccountManager::dataObjectFromResponse(requestReply); if (!dataObject.isEmpty()) { - _sessionID = dataObject[SESSION_ID_KEY].toString(); + auto sessionID = dataObject[SESSION_ID_KEY].toString(); // give that session ID to the account manager auto accountManager = DependencyManager::get(); - accountManager->setSessionID(_sessionID); + accountManager->setSessionID(sessionID); } } diff --git a/interface/src/DiscoverabilityManager.h b/interface/src/DiscoverabilityManager.h index 9a1fa7b39c..196b0cdf81 100644 --- a/interface/src/DiscoverabilityManager.h +++ b/interface/src/DiscoverabilityManager.h @@ -49,7 +49,6 @@ private: DiscoverabilityManager(); Setting::Handle _mode; - QString _sessionID; QJsonObject _lastLocationObject; }; diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index bac031885f..2ee49455b7 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -44,6 +44,7 @@ Q_DECLARE_METATYPE(QNetworkAccessManager::Operation) Q_DECLARE_METATYPE(JSONCallbackParameters) const QString ACCOUNTS_GROUP = "accounts"; +static const auto METAVERSE_SESSION_ID_HEADER = QString("HFM-SessionID").toLocal8Bit(); JSONCallbackParameters::JSONCallbackParameters(QObject* jsonCallbackReceiver, const QString& jsonCallbackMethod, QObject* errorCallbackReceiver, const QString& errorCallbackMethod, @@ -221,8 +222,7 @@ void AccountManager::sendRequest(const QString& path, // if we're allowed to send usage data, include whatever the current session ID is with this request auto& activityLogger = UserActivityLogger::getInstance(); if (activityLogger.isEnabled()) { - static const QString METAVERSE_SESSION_ID_HEADER = "HFM-SessionID"; - networkRequest.setRawHeader(METAVERSE_SESSION_ID_HEADER.toLocal8Bit(), + networkRequest.setRawHeader(METAVERSE_SESSION_ID_HEADER, uuidStringWithoutCurlyBraces(_sessionID).toLocal8Bit()); } @@ -321,6 +321,9 @@ void AccountManager::processReply() { QNetworkReply* requestReply = reinterpret_cast(sender()); if (requestReply->error() == QNetworkReply::NoError) { + if (requestReply->hasRawHeader(METAVERSE_SESSION_ID_HEADER)) { + _sessionID = requestReply->rawHeader(METAVERSE_SESSION_ID_HEADER); + } passSuccessToCallback(requestReply); } else { passErrorToCallback(requestReply); diff --git a/libraries/networking/src/AccountManager.h b/libraries/networking/src/AccountManager.h index 4803d2625f..6e26a56739 100644 --- a/libraries/networking/src/AccountManager.h +++ b/libraries/networking/src/AccountManager.h @@ -86,6 +86,7 @@ public: static QJsonObject dataObjectFromResponse(QNetworkReply& requestReply); + QUuid getSessionID() const { return _sessionID; } void setSessionID(const QUuid& sessionID) { _sessionID = sessionID; } public slots: @@ -139,7 +140,7 @@ private: bool _isWaitingForKeypairResponse { false }; QByteArray _pendingPrivateKey; - QUuid _sessionID; + QUuid _sessionID { QUuid::createUuid() }; }; #endif // hifi_AccountManager_h From 8b3b62aad7ac3861f044fdaebf8ecdc5f6388de5 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 16 Jun 2016 10:25:38 -0700 Subject: [PATCH 02/34] Add UserActivityLogger scripting interface --- interface/src/Application.cpp | 3 +++ .../UserActivityLoggerScriptingInterface.cpp | 19 ++++++++++++++ .../UserActivityLoggerScriptingInterface.h | 26 +++++++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 libraries/networking/src/UserActivityLoggerScriptingInterface.cpp create mode 100644 libraries/networking/src/UserActivityLoggerScriptingInterface.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e789b7c508..e8effefd6e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -67,6 +67,7 @@ #include #include #include +#include #include #include #include @@ -4558,6 +4559,8 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("ScriptDiscoveryService", DependencyManager::get().data()); scriptEngine->registerGlobalObject("Reticle", getApplicationCompositor().getReticleInterface()); + + scriptEngine->registerGlobalObject("UserActivityLogger", new UserActivityLoggerScriptingInterface()); } bool Application::canAcceptURL(const QString& urlString) const { diff --git a/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp b/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp new file mode 100644 index 0000000000..c0ed4fce19 --- /dev/null +++ b/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp @@ -0,0 +1,19 @@ +// +// UserActivityLoggerScriptingInterface.h +// libraries/networking/src +// +// Created by Ryan Huffman on 6/06/16. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "UserActivityLoggerScriptingInterface.h" +#include "UserActivityLogger.h" + +void UserActivityLoggerScriptingInterface::logAction(QString action, QVariantMap details) const { + QMetaObject::invokeMethod(&UserActivityLogger::getInstance(), "logAction", + Q_ARG(QString, action), + Q_ARG(QJsonObject, QJsonObject::fromVariantMap(details))); +} diff --git a/libraries/networking/src/UserActivityLoggerScriptingInterface.h b/libraries/networking/src/UserActivityLoggerScriptingInterface.h new file mode 100644 index 0000000000..1e6043491e --- /dev/null +++ b/libraries/networking/src/UserActivityLoggerScriptingInterface.h @@ -0,0 +1,26 @@ +// +// UserActivityLoggerScriptingInterface.h +// libraries/networking/src +// +// Created by Ryan Huffman on 6/06/16. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_UserActivityLoggerScriptingInterface_h +#define hifi_UserActivityLoggerScriptingInterface_h + +#include +#include + +class QScriptValue; + +class UserActivityLoggerScriptingInterface : public QObject { + Q_OBJECT +public: + Q_INVOKABLE void logAction(QString action, QVariantMap details) const; +}; + +#endif // hifi_UserActivityLoggerScriptingInterface_h \ No newline at end of file From c7955900ab9c35a4f3da1dc5eaa35b77b495e8ad Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 16 Jun 2016 13:17:18 -0700 Subject: [PATCH 03/34] Add new user activity events --- interface/src/Application.cpp | 42 +++++++++++++++++++++++-- interface/src/Application.h | 2 ++ libraries/avatars/src/AvatarHashMap.cpp | 14 +++++++++ libraries/avatars/src/AvatarHashMap.h | 1 + 4 files changed, 57 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e8effefd6e..f2f265aae0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -435,7 +435,7 @@ bool setupEssentials(int& argc, char** argv) { DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); - + DependencyManager::set(); #if defined(Q_OS_MAC) || defined(Q_OS_WIN) DependencyManager::set(); @@ -1057,6 +1057,44 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : } }); + // Add periodic checks to send user activity data + static int CHECK_NEARBY_AVATARS_INTERVAL_MS = 10000; + static int SEND_FPS_INTERVAL_MS = 10000; + + // Periodically send fps as a user activity event + QTimer* sendFPSTimer = new QTimer(this); + sendFPSTimer->setInterval(SEND_FPS_INTERVAL_MS); + connect(sendFPSTimer, &QTimer::timeout, this, [this]() { + UserActivityLogger::getInstance().logAction("fps", { { "rate", _frameCounter.rate() } }); + }); + sendFPSTimer->start(); + + + // Periodically check for count of nearby avatars + static int lastCountOfNearbyAvatars = -1; + QTimer* checkNearbyAvatarsTimer = new QTimer(this); + checkNearbyAvatarsTimer->setInterval(CHECK_NEARBY_AVATARS_INTERVAL_MS); + connect(checkNearbyAvatarsTimer, &QTimer::timeout, this, [this]() { + auto avatarManager = DependencyManager::get(); + int nearbyAvatars = avatarManager->numberOfAvatarsInRange(avatarManager->getMyAvatar()->getPosition(), 10) - 1; + if (nearbyAvatars != lastCountOfNearbyAvatars) { + UserActivityLogger::getInstance().logAction("nearby_avatars", { { "count", nearbyAvatars } }); + } + }); + + // Track user activity event when we receive a mute packet + auto onMutedByMixer = []() { + UserActivityLogger::getInstance().logAction("received_mute_packet"); + }; + connect(DependencyManager::get().data(), &AudioClient::mutedByMixer, this, onMutedByMixer); + + // Track when the address bar is opened + auto onAddressBarToggled = [this]() { + // Record time + UserActivityLogger::getInstance().logAction("opened_address_bar", { { "uptime_ms", _sessionRunTimer.elapsed() } }); + }; + connect(DependencyManager::get().data(), &DialogsManager::addressBarToggled, this, onAddressBarToggled); + // Make sure we don't time out during slow operations at startup updateHeartbeat(); @@ -4560,7 +4598,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("ScriptDiscoveryService", DependencyManager::get().data()); scriptEngine->registerGlobalObject("Reticle", getApplicationCompositor().getReticleInterface()); - scriptEngine->registerGlobalObject("UserActivityLogger", new UserActivityLoggerScriptingInterface()); + scriptEngine->registerGlobalObject("UserActivityLogger", DependencyManager::get().data()); } bool Application::canAcceptURL(const QString& urlString) const { diff --git a/interface/src/Application.h b/interface/src/Application.h index a17250a58e..d728359ed1 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -195,6 +195,8 @@ public: float getRenderResolutionScale() const; + qint64 getCurrentSessionRuntime() const { return _sessionRunTimer.elapsed(); } + bool isAboutToQuit() const { return _aboutToQuit; } // the isHMDMode is true whenever we use the interface from an HMD and not a standard flat display diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index 9084fd837b..d153cfd977 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -44,6 +44,20 @@ bool AvatarHashMap::isAvatarInRange(const glm::vec3& position, const float range return false; } +int AvatarHashMap::numberOfAvatarsInRange(const glm::vec3& position, float rangeMeters) { + auto hashCopy = getHashCopy(); + auto rangeMeters2 = rangeMeters * rangeMeters; + int count = 0; + for (const AvatarSharedPointer& sharedAvatar : hashCopy) { + glm::vec3 avatarPosition = sharedAvatar->getPosition(); + auto distance2 = glm::distance2(avatarPosition, position); + if (distance2 < rangeMeters2) { + ++count; + } + } + return count; +} + AvatarSharedPointer AvatarHashMap::newSharedAvatar() { return std::make_shared(); } diff --git a/libraries/avatars/src/AvatarHashMap.h b/libraries/avatars/src/AvatarHashMap.h index 5f58074427..9d3ebb60f5 100644 --- a/libraries/avatars/src/AvatarHashMap.h +++ b/libraries/avatars/src/AvatarHashMap.h @@ -39,6 +39,7 @@ public: Q_INVOKABLE AvatarData* getAvatar(QUuid avatarID); virtual AvatarSharedPointer getAvatarBySessionID(const QUuid& sessionID) { return findAvatar(sessionID); } + int numberOfAvatarsInRange(const glm::vec3& position, float rangeMeters); signals: void avatarAddedEvent(const QUuid& sessionUUID); From 365037774570a28b1dd2f8883ac1290ad4a670e8 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 16 Jun 2016 13:17:31 -0700 Subject: [PATCH 04/34] Clean up NULL => nullptr --- libraries/networking/src/AccountManager.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/networking/src/AccountManager.h b/libraries/networking/src/AccountManager.h index 6e26a56739..d30a05fb2c 100644 --- a/libraries/networking/src/AccountManager.h +++ b/libraries/networking/src/AccountManager.h @@ -26,9 +26,9 @@ class JSONCallbackParameters { public: - JSONCallbackParameters(QObject* jsonCallbackReceiver = NULL, const QString& jsonCallbackMethod = QString(), - QObject* errorCallbackReceiver = NULL, const QString& errorCallbackMethod = QString(), - QObject* updateReceiver = NULL, const QString& updateSlot = QString()); + JSONCallbackParameters(QObject* jsonCallbackReceiver = nullptr, const QString& jsonCallbackMethod = QString(), + QObject* errorCallbackReceiver = nullptr, const QString& errorCallbackMethod = QString(), + QObject* updateReceiver = nullptr, const QString& updateSlot = QString()); bool isEmpty() const { return !jsonCallbackReceiver && !errorCallbackReceiver; } From 56c84bbc27cf34cf1a173d67b28e1c0fdc8cc871 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 16 Jun 2016 13:18:08 -0700 Subject: [PATCH 05/34] Add opened_marketplace and enabled_edit to edit.js --- scripts/system/edit.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index afbc679ec4..4c5d9bf4f0 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -150,6 +150,8 @@ function showMarketplace(marketplaceID) { marketplaceWindow.setURL(url); marketplaceWindow.setVisible(true); marketplaceWindow.raise(); + + UserActivityLogger.logAction("opened_marketplace"); } function hideMarketplace() { @@ -358,6 +360,9 @@ var toolBar = (function() { } that.showTools(isActive); } + if (active) { + UserActivityLogger.logAction("enabled_edit"); + } } toolBar.selectTool(activeButton, isActive); lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE)); From bce05df56b5718cc1f21a1238d8c77effe667800 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 16 Jun 2016 13:25:14 -0700 Subject: [PATCH 06/34] Update enabled_edit to only get sent when you have permission --- scripts/system/edit.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 4c5d9bf4f0..f20676efc2 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -340,6 +340,7 @@ var toolBar = (function() { Messages.sendLocalMessage("edit-events", JSON.stringify({ enabled: active })); + UserActivityLogger.logAction("enabled_edit"); isActive = active; if (!isActive) { entityListTool.setVisible(false); @@ -360,9 +361,6 @@ var toolBar = (function() { } that.showTools(isActive); } - if (active) { - UserActivityLogger.logAction("enabled_edit"); - } } toolBar.selectTool(activeButton, isActive); lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE)); From c2ebcd1f77234350a974a03b30c1aac1223e7f8a Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 16 Jun 2016 13:49:25 -0700 Subject: [PATCH 07/34] Make activity logging from scripts only available for certain events --- .../src/UserActivityLoggerScriptingInterface.cpp | 12 ++++++++++-- .../src/UserActivityLoggerScriptingInterface.h | 14 +++++++++----- scripts/system/edit.js | 2 +- scripts/system/examples.js | 2 ++ 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp b/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp index c0ed4fce19..012a569639 100644 --- a/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp +++ b/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp @@ -12,8 +12,16 @@ #include "UserActivityLoggerScriptingInterface.h" #include "UserActivityLogger.h" -void UserActivityLoggerScriptingInterface::logAction(QString action, QVariantMap details) const { +void UserActivityLoggerScriptingInterface::enabledEdit() { + logAction("enabled_edit"); +} + +void UserActivityLoggerScriptingInterface::openedMarketplace() { + logAction("opened_marketplace"); +} + +void UserActivityLoggerScriptingInterface::logAction(QString action, QJsonObject details) { QMetaObject::invokeMethod(&UserActivityLogger::getInstance(), "logAction", Q_ARG(QString, action), - Q_ARG(QJsonObject, QJsonObject::fromVariantMap(details))); + Q_ARG(QJsonObject, details)); } diff --git a/libraries/networking/src/UserActivityLoggerScriptingInterface.h b/libraries/networking/src/UserActivityLoggerScriptingInterface.h index 1e6043491e..cad24b1967 100644 --- a/libraries/networking/src/UserActivityLoggerScriptingInterface.h +++ b/libraries/networking/src/UserActivityLoggerScriptingInterface.h @@ -13,14 +13,18 @@ #define hifi_UserActivityLoggerScriptingInterface_h #include -#include +#include -class QScriptValue; +#include -class UserActivityLoggerScriptingInterface : public QObject { +class UserActivityLoggerScriptingInterface : public QObject, public Dependency { Q_OBJECT public: - Q_INVOKABLE void logAction(QString action, QVariantMap details) const; + Q_INVOKABLE void enabledEdit(); + Q_INVOKABLE void openedMarketplace(); + +private: + void logAction(QString action, QJsonObject details = {}); }; -#endif // hifi_UserActivityLoggerScriptingInterface_h \ No newline at end of file +#endif // hifi_UserActivityLoggerScriptingInterface_h diff --git a/scripts/system/edit.js b/scripts/system/edit.js index f20676efc2..64c6a06c58 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -340,7 +340,7 @@ var toolBar = (function() { Messages.sendLocalMessage("edit-events", JSON.stringify({ enabled: active })); - UserActivityLogger.logAction("enabled_edit"); + UserActivityLogger.enabledEdit(); isActive = active; if (!isActive) { entityListTool.setVisible(false); diff --git a/scripts/system/examples.js b/scripts/system/examples.js index 9d33e473af..fb5ba02441 100644 --- a/scripts/system/examples.js +++ b/scripts/system/examples.js @@ -37,6 +37,8 @@ function showExamples(marketplaceID) { print("setting examples URL to " + url); examplesWindow.setURL(url); examplesWindow.setVisible(true); + + UserActivityLogger.openedMarketplace(); } function hideExamples() { From 1fa274a5270f4154ee490cf10e3b919164d68808 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 20 Jun 2016 16:01:03 -0700 Subject: [PATCH 08/34] Fix GPUIdent name trailing whitespace --- libraries/shared/src/GPUIdent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/GPUIdent.cpp b/libraries/shared/src/GPUIdent.cpp index 19838964a4..02f92d87e7 100644 --- a/libraries/shared/src/GPUIdent.cpp +++ b/libraries/shared/src/GPUIdent.cpp @@ -122,7 +122,7 @@ GPUIdent* GPUIdent::ensureQuery(const QString& vendor, const QString& renderer) } if (count > bestCount) { bestCount = count; - _name = sString; + _name = QString(sString).trimmed(); hr = spInstance->Get(CComBSTR(_T("DriverVersion")), 0, &var, 0, 0); if (hr == S_OK) { From 0393777b036b7e17a16e8d7836027082ca204ae6 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 20 Jun 2016 16:01:44 -0700 Subject: [PATCH 09/34] Add getMemoryInfo helper function --- libraries/shared/src/SharedUtil.cpp | 25 +++++++++++++++++++++++++ libraries/shared/src/SharedUtil.h | 10 ++++++++++ 2 files changed, 35 insertions(+) diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index b80fac637c..a6866fdc93 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -28,6 +28,7 @@ #ifdef Q_OS_WIN #include "CPUIdent.h" +#include #endif @@ -843,3 +844,27 @@ void printSystemInformation() { (envVariables.contains(env) ? " = " + envVariables.value(env) : " NOT FOUND"); } } + +bool getMemoryInfo(MemoryInfo& info) { +#ifdef Q_OS_WIN + MEMORYSTATUSEX ms; + ms.dwLength = sizeof(ms); + if (!GlobalMemoryStatusEx(&ms)) { + return false; + } + + info.totalMemoryBytes = ms.ullTotalPhys; + info.availMemoryBytes = ms.ullAvailPhys; + info.usedMemoryBytes = ms.ullTotalPhys - ms.ullAvailPhys; + + + PROCESS_MEMORY_COUNTERS_EX pmc; + if (!GetProcessMemoryInfo(GetCurrentProcess(), reinterpret_cast(&pmc), sizeof(pmc))) { + return false; + } + info.processUsedMemoryBytes = pmc.PrivateUsage; + info.processPeakUsedMemoryBytes = pmc.PeakPagefileUsage; +#endif + + return true; +} \ No newline at end of file diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 042396f474..f3e5625484 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -204,4 +204,14 @@ void disableQtBearerPoll(); void printSystemInformation(); +struct MemoryInfo { + uint64_t totalMemoryBytes; + uint64_t availMemoryBytes; + uint64_t usedMemoryBytes; + uint64_t processUsedMemoryBytes; + uint64_t processPeakUsedMemoryBytes; +}; + +bool getMemoryInfo(MemoryInfo& info); + #endif // hifi_SharedUtil_h From 7b3b01a96a54b03099a3bc5d8d7a469ab0c5b5cf Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 20 Jun 2016 16:02:14 -0700 Subject: [PATCH 10/34] Add more values to launch UserActivity --- interface/src/Application.cpp | 39 +++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f2f265aae0..42cfa9484e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -151,6 +151,8 @@ #include "InterfaceParentFinder.h" #include "FrameTimingsScriptingInterface.h" +#include +#include // On Windows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU // FIXME seems to be broken. @@ -669,10 +671,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : accountManager->setIsAgent(true); accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL); - // sessionRunTime will be reset soon by loadSettings. Grab it now to get previous session value. - // The value will be 0 if the user blew away settings this session, which is both a feature and a bug. - UserActivityLogger::getInstance().launch(applicationVersion(), _previousSessionCrashed, sessionRunTime.get()); - auto addressManager = DependencyManager::get(); // use our MyAvatar position and quat for address manager path @@ -762,6 +760,39 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : // Make sure we don't time out during slow operations at startup updateHeartbeat(); + + // sessionRunTime will be reset soon by loadSettings. Grab it now to get previous session value. + // The value will be 0 if the user blew away settings this session, which is both a feature and a bug. + auto gpuIdent = GPUIdent::getInstance(); + auto glContextData = getGLContextData(); + QJsonObject properties = { + { "previousSessionCrashed", _previousSessionCrashed }, + { "previousSessionRuntime", sessionRunTime.get() }, + { "cpu_architecture", QSysInfo::currentCpuArchitecture() }, + { "kernel_type", QSysInfo::kernelType() }, + { "kernel_version", QSysInfo::kernelVersion() }, + { "os_type", QSysInfo::productType() }, + { "os_version", QSysInfo::productVersion() }, + { "gpu_name", gpuIdent->getName() }, + { "gpu_driver", gpuIdent->getDriver() }, + { "gpu_memory", static_cast(gpuIdent->getMemory()) }, + { "gl_version_int", glVersionToInteger(glContextData.value("version").toString()) }, + { "gl_version", glContextData["version"] }, + { "gl_vender", glContextData["vendor"] }, + { "gl_sl_version", glContextData["slVersion"] }, + { "gl_renderer", glContextData["renderer"] } + }; + auto macVersion = QSysInfo::macVersion(); + if (macVersion != QSysInfo::MV_None) { + properties["os_osx_version"] = QSysInfo::macVersion(); + } + auto windowsVersion = QSysInfo::windowsVersion(); + if (windowsVersion != QSysInfo::WV_None) { + properties["os_win_version"] = QSysInfo::windowsVersion(); + } + UserActivityLogger::getInstance().logAction("launch", properties); + + // Tell our entity edit sender about our known jurisdictions _entityEditSender.setServerJurisdictions(&_entityServerJurisdictions); _entityEditSender.setMyAvatar(getMyAvatar()); From 3aac0cc4fb17fce1b1c528e8a9c2fcfd02036397 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 20 Jun 2016 16:02:36 -0700 Subject: [PATCH 11/34] Update fps useractivity with more general stats --- interface/src/Application.cpp | 54 +++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 42cfa9484e..8071a46e5f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1090,15 +1090,57 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : // Add periodic checks to send user activity data static int CHECK_NEARBY_AVATARS_INTERVAL_MS = 10000; - static int SEND_FPS_INTERVAL_MS = 10000; + static int SEND_STATS_INTERVAL_MS = 10000; + static int NEARBY_AVATAR_RADIUS_METERS = 10; // Periodically send fps as a user activity event - QTimer* sendFPSTimer = new QTimer(this); - sendFPSTimer->setInterval(SEND_FPS_INTERVAL_MS); - connect(sendFPSTimer, &QTimer::timeout, this, [this]() { - UserActivityLogger::getInstance().logAction("fps", { { "rate", _frameCounter.rate() } }); + QTimer* sendStatsTimer = new QTimer(this); + sendStatsTimer->setInterval(SEND_STATS_INTERVAL_MS); + connect(sendStatsTimer, &QTimer::timeout, this, [this]() { + QJsonObject properties = {}; + MemoryInfo memInfo; + if (getMemoryInfo(memInfo)) { + properties["system_memory_total"] = static_cast(memInfo.totalMemoryBytes); + properties["system_memory_used"] = static_cast(memInfo.usedMemoryBytes); + properties["process_memory_used"] = static_cast(memInfo.processUsedMemoryBytes); + } + + auto displayPlugin = qApp->getActiveDisplayPlugin(); + + properties["fps"] = _frameCounter.rate(); + properties["present_rate"] = displayPlugin->presentRate(); + properties["new_frame_present_rate"] = displayPlugin->newFramePresentRate(); + properties["dropped_frame_rate"] = displayPlugin->droppedFrameRate(); + properties["sim_rate"] = getAverageSimsPerSecond(); + properties["avatar_sim_rate"] = getAvatarSimrate(); + + auto bandwidthRecorder = DependencyManager::get(); + properties["packet_rate_in"] = bandwidthRecorder->getCachedTotalAverageInputPacketsPerSecond(); + properties["packet_rate_out"] = bandwidthRecorder->getCachedTotalAverageOutputPacketsPerSecond(); + properties["kbps_in"] = bandwidthRecorder->getCachedTotalAverageInputKilobitsPerSecond(); + properties["kbps_out"] = bandwidthRecorder->getCachedTotalAverageOutputKilobitsPerSecond(); + + auto nodeList = DependencyManager::get(); + SharedNodePointer entityServerNode = nodeList->soloNodeOfType(NodeType::EntityServer); + SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer); + SharedNodePointer avatarMixerNode = nodeList->soloNodeOfType(NodeType::AvatarMixer); + SharedNodePointer assetServerNode = nodeList->soloNodeOfType(NodeType::AssetServer); + SharedNodePointer messagesMixerNode = nodeList->soloNodeOfType(NodeType::MessagesMixer); + properties["entity_ping"] = entityServerNode ? entityServerNode->getPingMs() : -1; + properties["audio_ping"] = audioMixerNode ? audioMixerNode->getPingMs() : -1; + properties["avatar_ping"] = avatarMixerNode ? avatarMixerNode->getPingMs() : -1; + properties["asset_ping"] = assetServerNode ? assetServerNode->getPingMs() : -1; + properties["messages_ping"] = messagesMixerNode ? messagesMixerNode->getPingMs() : -1; + + auto loadingRequests = ResourceCache::getLoadingRequests(); + properties["active_downloads"] = loadingRequests.size(); + properties["pending_downloads"] = ResourceCache::getPendingRequestCount(); + + properties["throttled"] = _displayPlugin ? _displayPlugin->isThrottled() : false; + + UserActivityLogger::getInstance().logAction("stats", properties); }); - sendFPSTimer->start(); + sendStatsTimer->start(); // Periodically check for count of nearby avatars From 1eaa9e40cdc8fc365843e18b30a92076735318b5 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 20 Jun 2016 16:09:17 -0700 Subject: [PATCH 12/34] Cleanup nearby avatar tracking --- interface/src/Application.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8071a46e5f..a3ab1ca8c0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1149,7 +1149,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : checkNearbyAvatarsTimer->setInterval(CHECK_NEARBY_AVATARS_INTERVAL_MS); connect(checkNearbyAvatarsTimer, &QTimer::timeout, this, [this]() { auto avatarManager = DependencyManager::get(); - int nearbyAvatars = avatarManager->numberOfAvatarsInRange(avatarManager->getMyAvatar()->getPosition(), 10) - 1; + int nearbyAvatars = avatarManager->numberOfAvatarsInRange(avatarManager->getMyAvatar()->getPosition(), + NEARBY_AVATAR_RADIUS_METERS) - 1; if (nearbyAvatars != lastCountOfNearbyAvatars) { UserActivityLogger::getInstance().logAction("nearby_avatars", { { "count", nearbyAvatars } }); } From ab057010d6c5c1c58880869ffc56b35c01edb135 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 20 Jun 2016 16:09:34 -0700 Subject: [PATCH 13/34] Add changed display mode tracking --- interface/src/Application.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a3ab1ca8c0..93a6df2d3b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5266,6 +5266,11 @@ void Application::updateDisplayMode() { return; } + UserActivityLogger::getInstance().logAction("changed_display_mode", { + { "previous_display_mode", _displayPlugin ? _displayPlugin->getName() : "" }, + { "display_mode", newDisplayPlugin ? newDisplayPlugin->getName() : "" } + }); + auto offscreenUi = DependencyManager::get(); // Make the switch atomic from the perspective of other threads From 154ccb8932095f2f180cda149eb912c68fef0348 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 20 Jun 2016 16:10:07 -0700 Subject: [PATCH 14/34] Add glVersionToInteger to GLHelpers --- libraries/gl/src/gl/GLHelpers.cpp | 8 ++++++++ libraries/gl/src/gl/GLHelpers.h | 1 + 2 files changed, 9 insertions(+) diff --git a/libraries/gl/src/gl/GLHelpers.cpp b/libraries/gl/src/gl/GLHelpers.cpp index 302e0b8515..79b39a2331 100644 --- a/libraries/gl/src/gl/GLHelpers.cpp +++ b/libraries/gl/src/gl/GLHelpers.cpp @@ -5,6 +5,7 @@ #include #include #include +#include const QSurfaceFormat& getDefaultOpenGLSurfaceFormat() { static QSurfaceFormat format; @@ -39,6 +40,13 @@ const QGLFormat& getDefaultGLFormat() { return glFormat; } +int glVersionToInteger(QString glVersion) { + QStringList versionParts = glVersion.split(QRegularExpression("[\\.\\s]")); + int majorNumber = versionParts[0].toInt(); + int minorNumber = versionParts[1].toInt(); + return majorNumber * 100 + minorNumber * 10; +} + QJsonObject getGLContextData() { if (!QOpenGLContext::currentContext()) { return QJsonObject(); diff --git a/libraries/gl/src/gl/GLHelpers.h b/libraries/gl/src/gl/GLHelpers.h index ddb254f1c5..477bf7abc8 100644 --- a/libraries/gl/src/gl/GLHelpers.h +++ b/libraries/gl/src/gl/GLHelpers.h @@ -27,5 +27,6 @@ void setGLFormatVersion(F& format, int major = 4, int minor = 5) { format.setVer const QSurfaceFormat& getDefaultOpenGLSurfaceFormat(); const QGLFormat& getDefaultGLFormat(); QJsonObject getGLContextData(); +int glVersionToInteger(QString glVersion); #endif From cee897d6d3e306a00704818336f4105c0377cc2a Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 20 Jun 2016 16:44:02 -0700 Subject: [PATCH 15/34] Fix osx warning --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 93a6df2d3b..b92fc2d3e6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -775,7 +775,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : { "os_version", QSysInfo::productVersion() }, { "gpu_name", gpuIdent->getName() }, { "gpu_driver", gpuIdent->getDriver() }, - { "gpu_memory", static_cast(gpuIdent->getMemory()) }, + { "gpu_memory", QJsonValue(static_cast(gpuIdent->getMemory())) }, { "gl_version_int", glVersionToInteger(glContextData.value("version").toString()) }, { "gl_version", glContextData["version"] }, { "gl_vender", glContextData["vendor"] }, From a77dea904876725d583638e8d382ff14917c3aef Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 21 Jun 2016 08:31:40 -0700 Subject: [PATCH 16/34] Fix osx warning --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b92fc2d3e6..17a6110ea2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -775,7 +775,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : { "os_version", QSysInfo::productVersion() }, { "gpu_name", gpuIdent->getName() }, { "gpu_driver", gpuIdent->getDriver() }, - { "gpu_memory", QJsonValue(static_cast(gpuIdent->getMemory())) }, + { "gpu_memory", QJsonValue(static_cast(gpuIdent->getMemory())) }, { "gl_version_int", glVersionToInteger(glContextData.value("version").toString()) }, { "gl_version", glContextData["version"] }, { "gl_vender", glContextData["vendor"] }, From 6d753e317b60dfb3ee9b6c5b3be826b11e999bbe Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 21 Jun 2016 10:51:31 -0700 Subject: [PATCH 17/34] Fix more osx warning --- interface/src/Application.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 17a6110ea2..0b6bc2e01a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -775,7 +775,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : { "os_version", QSysInfo::productVersion() }, { "gpu_name", gpuIdent->getName() }, { "gpu_driver", gpuIdent->getDriver() }, - { "gpu_memory", QJsonValue(static_cast(gpuIdent->getMemory())) }, + { "gpu_memory", static_cast(gpuIdent->getMemory()) }, { "gl_version_int", glVersionToInteger(glContextData.value("version").toString()) }, { "gl_version", glContextData["version"] }, { "gl_vender", glContextData["vendor"] }, @@ -1100,9 +1100,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : QJsonObject properties = {}; MemoryInfo memInfo; if (getMemoryInfo(memInfo)) { - properties["system_memory_total"] = static_cast(memInfo.totalMemoryBytes); - properties["system_memory_used"] = static_cast(memInfo.usedMemoryBytes); - properties["process_memory_used"] = static_cast(memInfo.processUsedMemoryBytes); + properties["system_memory_total"] = static_cast(memInfo.totalMemoryBytes); + properties["system_memory_used"] = static_cast(memInfo.usedMemoryBytes); + properties["process_memory_used"] = static_cast(memInfo.processUsedMemoryBytes); } auto displayPlugin = qApp->getActiveDisplayPlugin(); From 6c2c7f1eec2213affbcc82bf8f5ac32c6d2c0f74 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 21 Jun 2016 13:28:40 -0700 Subject: [PATCH 18/34] Fix connected_device user activity event --- libraries/networking/src/UserActivityLogger.cpp | 15 +++++++++++++++ libraries/plugins/src/plugins/PluginManager.cpp | 5 +++++ 2 files changed, 20 insertions(+) diff --git a/libraries/networking/src/UserActivityLogger.cpp b/libraries/networking/src/UserActivityLogger.cpp index 83c6eb304e..8b20420a34 100644 --- a/libraries/networking/src/UserActivityLogger.cpp +++ b/libraries/networking/src/UserActivityLogger.cpp @@ -125,6 +125,21 @@ void UserActivityLogger::changedDomain(QString domainURL) { } void UserActivityLogger::connectedDevice(QString typeOfDevice, QString deviceName) { + static QStringList DEVICE_BLACKLIST = { + "Desktop", + "NullDisplayPlugin", + "3D TV - Side by Side Stereo", + "3D TV - Interleaved", + + "Keyboard/Mouse", + "Neuron", + "SDL2" + }; + + if (DEVICE_BLACKLIST.contains(deviceName)) { + return; + } + const QString ACTION_NAME = "connected_device"; QJsonObject actionDetails; const QString TYPE_OF_DEVICE = "type_of_device"; diff --git a/libraries/plugins/src/plugins/PluginManager.cpp b/libraries/plugins/src/plugins/PluginManager.cpp index eb6465aab2..86bdcfe818 100644 --- a/libraries/plugins/src/plugins/PluginManager.cpp +++ b/libraries/plugins/src/plugins/PluginManager.cpp @@ -14,6 +14,9 @@ #include #include +#include +#include + #include "RuntimePlugin.h" #include "DisplayPlugin.h" #include "InputPlugin.h" @@ -81,6 +84,7 @@ const DisplayPluginList& PluginManager::getDisplayPlugins() { } auto& container = PluginContainer::getInstance(); for (auto plugin : displayPlugins) { + UserActivityLogger::getInstance().connectedDevice("display", plugin->getName()); plugin->setContainer(&container); plugin->init(); } @@ -117,6 +121,7 @@ const InputPluginList& PluginManager::getInputPlugins() { auto& container = PluginContainer::getInstance(); for (auto plugin : inputPlugins) { + UserActivityLogger::getInstance().connectedDevice("input", plugin->getName()); plugin->setContainer(&container); plugin->init(); } From 251e2137d33b285c6e3db9c10c1382cb8c240751 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 21 Jun 2016 13:31:10 -0700 Subject: [PATCH 19/34] Remove old use of connectedDevice --- plugins/hifiSpacemouse/src/SpacemouseManager.cpp | 2 -- plugins/openvr/src/ViveControllerManager.cpp | 1 - 2 files changed, 3 deletions(-) diff --git a/plugins/hifiSpacemouse/src/SpacemouseManager.cpp b/plugins/hifiSpacemouse/src/SpacemouseManager.cpp index 3d9b93ff44..dc60fe4cbb 100644 --- a/plugins/hifiSpacemouse/src/SpacemouseManager.cpp +++ b/plugins/hifiSpacemouse/src/SpacemouseManager.cpp @@ -59,7 +59,6 @@ bool SpacemouseManager::activate() { if (instance->getDeviceID() == controller::Input::INVALID_DEVICE) { auto userInputMapper = DependencyManager::get(); userInputMapper->registerDevice(instance); - UserActivityLogger::getInstance().connectedDevice("controller", NAME); } return true; } @@ -330,7 +329,6 @@ bool SpacemouseManager::RawInputEventFilter(void* msg, long* result) { auto userInputMapper = DependencyManager::get(); if (Is3dmouseAttached() && instance->getDeviceID() == controller::Input::INVALID_DEVICE) { userInputMapper->registerDevice(instance); - UserActivityLogger::getInstance().connectedDevice("controller", "Spacemouse"); } else if (!Is3dmouseAttached() && instance->getDeviceID() != controller::Input::INVALID_DEVICE) { userInputMapper->removeDevice(instance->getDeviceID()); diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 953501ccec..d3e1690155 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -234,7 +234,6 @@ void ViveControllerManager::pluginUpdate(float deltaTime, const controller::Inpu if (!_registeredWithInputMapper && _inputDevice->_trackedControllers > 0) { userInputMapper->registerDevice(_inputDevice); _registeredWithInputMapper = true; - UserActivityLogger::getInstance().connectedDevice("spatial_controller", "steamVR"); } } From 0ea9c5c26da41848f112d2fad62135aa073648a8 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 21 Jun 2016 13:32:17 -0700 Subject: [PATCH 20/34] Fix getMemoryInfo not returning false on non-Windows --- libraries/shared/src/SharedUtil.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index a6866fdc93..edb6fe437d 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -864,7 +864,9 @@ bool getMemoryInfo(MemoryInfo& info) { } info.processUsedMemoryBytes = pmc.PrivateUsage; info.processPeakUsedMemoryBytes = pmc.PeakPagefileUsage; -#endif return true; +#endif + + return false; } \ No newline at end of file From 9a17f5b439a49498377d48c77d069c5283331103 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 21 Jun 2016 14:12:27 -0700 Subject: [PATCH 21/34] update homebrew instructions --- BUILD_OSX.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BUILD_OSX.md b/BUILD_OSX.md index 44f27d3d02..ab84bc4711 100644 --- a/BUILD_OSX.md +++ b/BUILD_OSX.md @@ -13,11 +13,11 @@ We no longer require install of qt5 via our [homebrew formulas repository](https Assuming you've installed OpenSSL or Qt 5 using the homebrew instructions above, you'll need to set OPENSSL_ROOT_DIR and QT_CMAKE_PREFIX_PATH so CMake can find your installations. For OpenSSL installed via homebrew, set OPENSSL_ROOT_DIR: - export OPENSSL_ROOT_DIR=/usr/local/Cellar/openssl/1.0.2d_1 + export OPENSSL_ROOT_DIR=/usr/local/Cellar/openssl/1.0.2h_1/ For Qt 5.5.1 installed via homebrew, set QT_CMAKE_PREFIX_PATH as follows. - export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt5/5.5.1_2/lib/cmake + export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt55/5.5.1/lib/cmake Not that these use the versions from homebrew formulae at the time of this writing, and the version in the path will likely change. From da71fcb57fdffadcc320ab7092f8e0318746b929 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 21 Jun 2016 16:37:58 -0700 Subject: [PATCH 22/34] Update connected device detection implementation --- libraries/plugins/src/plugins/Plugin.h | 8 +++++++ .../plugins/src/plugins/PluginManager.cpp | 23 ++++++++++++++++++- plugins/hifiNeuron/src/NeuronPlugin.cpp | 2 ++ plugins/hifiSdl2/src/SDL2Manager.cpp | 2 ++ plugins/hifiSixense/src/SixenseManager.cpp | 6 +++++ plugins/oculus/src/OculusDisplayPlugin.cpp | 6 +++++ plugins/oculus/src/OculusDisplayPlugin.h | 2 ++ plugins/openvr/src/OpenVrDisplayPlugin.cpp | 6 +++++ plugins/openvr/src/OpenVrDisplayPlugin.h | 2 ++ 9 files changed, 56 insertions(+), 1 deletion(-) diff --git a/libraries/plugins/src/plugins/Plugin.h b/libraries/plugins/src/plugins/Plugin.h index fb5bf0ba55..0452c7fbfe 100644 --- a/libraries/plugins/src/plugins/Plugin.h +++ b/libraries/plugins/src/plugins/Plugin.h @@ -15,6 +15,7 @@ #include "Forward.h" class Plugin : public QObject { + Q_OBJECT public: /// \return human-readable name virtual const QString& getName() const = 0; @@ -63,6 +64,13 @@ public: virtual void saveSettings() const {} virtual void loadSettings() {} +signals: + // These signals should be emitted when a device is first known to be available. In some cases this will + // be in `init()`, in other cases, like Neuron, this isn't known until activation. + // SDL2 isn't a device itself, but can have 0+ subdevices. subdeviceConnected is used in this case. + void deviceConnected(QString pluginName) const; + void subdeviceConnected(QString pluginName, QString subdeviceName) const; + protected: bool _active { false }; PluginContainer* _container { nullptr }; diff --git a/libraries/plugins/src/plugins/PluginManager.cpp b/libraries/plugins/src/plugins/PluginManager.cpp index 86bdcfe818..64d771da6a 100644 --- a/libraries/plugins/src/plugins/PluginManager.cpp +++ b/libraries/plugins/src/plugins/PluginManager.cpp @@ -69,6 +69,15 @@ static DisplayPluginList displayPlugins; const DisplayPluginList& PluginManager::getDisplayPlugins() { static std::once_flag once; + static auto deviceAddedCallback = [](QString deviceName) { + qDebug() << "Added device: " << deviceName; + UserActivityLogger::getInstance().connectedDevice("display", deviceName); + }; + static auto subdeviceAddedCallback = [](QString pluginName, QString deviceName) { + qDebug() << "Added subdevice: " << deviceName; + UserActivityLogger::getInstance().connectedDevice("display", pluginName + " | " + deviceName); + }; + std::call_once(once, [&] { // Grab the built in plugins displayPlugins = ::getDisplayPlugins(); @@ -84,7 +93,8 @@ const DisplayPluginList& PluginManager::getDisplayPlugins() { } auto& container = PluginContainer::getInstance(); for (auto plugin : displayPlugins) { - UserActivityLogger::getInstance().connectedDevice("display", plugin->getName()); + connect(plugin.get(), &Plugin::deviceConnected, this, deviceAddedCallback); + connect(plugin.get(), &Plugin::subdeviceConnected, this, subdeviceAddedCallback); plugin->setContainer(&container); plugin->init(); } @@ -106,6 +116,15 @@ void PluginManager::disableDisplayPlugin(const QString& name) { const InputPluginList& PluginManager::getInputPlugins() { static InputPluginList inputPlugins; static std::once_flag once; + static auto deviceAddedCallback = [](QString deviceName) { + qDebug() << "Added device: " << deviceName; + UserActivityLogger::getInstance().connectedDevice("input", deviceName); + }; + static auto subdeviceAddedCallback = [](QString pluginName, QString deviceName) { + qDebug() << "Added subdevice: " << deviceName; + UserActivityLogger::getInstance().connectedDevice("input", pluginName + " | " + deviceName); + }; + std::call_once(once, [&] { inputPlugins = ::getInputPlugins(); @@ -122,6 +141,8 @@ const InputPluginList& PluginManager::getInputPlugins() { auto& container = PluginContainer::getInstance(); for (auto plugin : inputPlugins) { UserActivityLogger::getInstance().connectedDevice("input", plugin->getName()); + connect(plugin.get(), &Plugin::deviceConnected, this, deviceAddedCallback); + connect(plugin.get(), &Plugin::subdeviceConnected, this, subdeviceAddedCallback); plugin->setContainer(&container); plugin->init(); } diff --git a/plugins/hifiNeuron/src/NeuronPlugin.cpp b/plugins/hifiNeuron/src/NeuronPlugin.cpp index 0a4bc7f8d2..e41472a8c5 100644 --- a/plugins/hifiNeuron/src/NeuronPlugin.cpp +++ b/plugins/hifiNeuron/src/NeuronPlugin.cpp @@ -387,6 +387,8 @@ bool NeuronPlugin::activate() { } else { qCDebug(inputplugins) << "NeuronPlugin: success connecting to " << _serverAddress.c_str() << ":" << _serverPort; + emit deviceConnected(getName()); + BRRegisterAutoSyncParmeter(_socketRef, Cmd_CombinationMode); return true; } diff --git a/plugins/hifiSdl2/src/SDL2Manager.cpp b/plugins/hifiSdl2/src/SDL2Manager.cpp index 0bdb68f830..14a1b0fbac 100644 --- a/plugins/hifiSdl2/src/SDL2Manager.cpp +++ b/plugins/hifiSdl2/src/SDL2Manager.cpp @@ -66,6 +66,7 @@ void SDL2Manager::init() { auto userInputMapper = DependencyManager::get(); userInputMapper->registerDevice(joystick); emit joystickAdded(joystick.get()); + emit subdeviceConnected(getName(), SDL_GameControllerName(controller)); } } } @@ -157,6 +158,7 @@ void SDL2Manager::pluginUpdate(float deltaTime, const controller::InputCalibrati _openJoysticks[id] = joystick; userInputMapper->registerDevice(joystick); emit joystickAdded(joystick.get()); + emit subdeviceConnected(getName(), SDL_GameControllerName(controller)); } } else if (event.type == SDL_CONTROLLERDEVICEREMOVED) { if (_openJoysticks.contains(event.cdevice.which)) { diff --git a/plugins/hifiSixense/src/SixenseManager.cpp b/plugins/hifiSixense/src/SixenseManager.cpp index 9ea79a8b96..0993f9d12f 100644 --- a/plugins/hifiSixense/src/SixenseManager.cpp +++ b/plugins/hifiSixense/src/SixenseManager.cpp @@ -137,6 +137,12 @@ void SixenseManager::setSixenseFilter(bool filter) { void SixenseManager::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { BAIL_IF_NOT_LOADED + static bool sixenseHasBeenConnected { false }; + if (!sixenseHasBeenConnected && sixenseIsBaseConnected(0)) { + sixenseHasBeenConnected = true; + emit deviceConnected(getName()); + } + auto userInputMapper = DependencyManager::get(); userInputMapper->withLock([&, this]() { _inputDevice->update(deltaTime, inputCalibrationData); diff --git a/plugins/oculus/src/OculusDisplayPlugin.cpp b/plugins/oculus/src/OculusDisplayPlugin.cpp index 1006d69f06..2b2ec5bdb0 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDisplayPlugin.cpp @@ -28,6 +28,12 @@ bool OculusDisplayPlugin::internalActivate() { return result; } +void OculusDisplayPlugin::init() { + Plugin::init(); + + emit deviceConnected(getName()); +} + void OculusDisplayPlugin::cycleDebugOutput() { if (_session) { currentDebugMode = static_cast((currentDebugMode + 1) % ovrPerfHud_Count); diff --git a/plugins/oculus/src/OculusDisplayPlugin.h b/plugins/oculus/src/OculusDisplayPlugin.h index d6cd6f6f3d..ed6e0d13ea 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.h +++ b/plugins/oculus/src/OculusDisplayPlugin.h @@ -17,6 +17,8 @@ class OculusDisplayPlugin : public OculusBaseDisplayPlugin { public: const QString& getName() const override { return NAME; } + void init() override; + QString getPreferredAudioInDevice() const override; QString getPreferredAudioOutDevice() const override; diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index fe406cc29a..f805132edd 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -41,6 +41,12 @@ bool OpenVrDisplayPlugin::isSupported() const { return openVrSupported(); } +void OpenVrDisplayPlugin::init() { + Plugin::init(); + + emit deviceConnected(getName()); +} + bool OpenVrDisplayPlugin::internalActivate() { _container->setIsOptionChecked(StandingHMDSensorMode, true); diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.h b/plugins/openvr/src/OpenVrDisplayPlugin.h index fda5e37c2a..2e31bfa2c6 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.h +++ b/plugins/openvr/src/OpenVrDisplayPlugin.h @@ -21,6 +21,8 @@ public: bool isSupported() const override; const QString& getName() const override { return NAME; } + void init() override; + float getTargetFrameRate() const override { return TARGET_RATE_OpenVr; } void customizeContext() override; From 310adb0f45758db8a2ea7050a5d2d1a9b903a8ba Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 21 Jun 2016 16:42:39 -0700 Subject: [PATCH 23/34] Update spacemouse deviceConnected implementation --- plugins/hifiSpacemouse/src/SpacemouseManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/hifiSpacemouse/src/SpacemouseManager.cpp b/plugins/hifiSpacemouse/src/SpacemouseManager.cpp index dc60fe4cbb..b4c15e6571 100644 --- a/plugins/hifiSpacemouse/src/SpacemouseManager.cpp +++ b/plugins/hifiSpacemouse/src/SpacemouseManager.cpp @@ -855,7 +855,7 @@ void SpacemouseManager::init() { if (Is3dmouseAttached() && instance->getDeviceID() == controller::Input::INVALID_DEVICE) { auto userInputMapper = DependencyManager::get(); userInputMapper->registerDevice(instance); - UserActivityLogger::getInstance().connectedDevice("controller", "Spacemouse"); + emit deviceConnected(getName()); } //let one axis be dominant //ConnexionClientControl(fConnexionClientID, kConnexionCtlSetSwitches, kConnexionSwitchDominant | kConnexionSwitchEnableAll, NULL); From 4e52521f8cd05d4a30a0cc219c119d9f1fc37d79 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 21 Jun 2016 16:43:16 -0700 Subject: [PATCH 24/34] Update UserActivityLogger device blacklist --- libraries/networking/src/UserActivityLogger.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/networking/src/UserActivityLogger.cpp b/libraries/networking/src/UserActivityLogger.cpp index 8b20420a34..9a5f0541e5 100644 --- a/libraries/networking/src/UserActivityLogger.cpp +++ b/libraries/networking/src/UserActivityLogger.cpp @@ -131,9 +131,7 @@ void UserActivityLogger::connectedDevice(QString typeOfDevice, QString deviceNam "3D TV - Side by Side Stereo", "3D TV - Interleaved", - "Keyboard/Mouse", - "Neuron", - "SDL2" + "Keyboard/Mouse" }; if (DEVICE_BLACKLIST.contains(deviceName)) { From db8190ad4985fd43162119d5b97819f3d93c9440 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 21 Jun 2016 16:56:00 -0700 Subject: [PATCH 25/34] fix typo --- BUILD_OSX.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILD_OSX.md b/BUILD_OSX.md index ab84bc4711..1c9c5a9796 100644 --- a/BUILD_OSX.md +++ b/BUILD_OSX.md @@ -19,7 +19,7 @@ For Qt 5.5.1 installed via homebrew, set QT_CMAKE_PREFIX_PATH as follows. export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt55/5.5.1/lib/cmake -Not that these use the versions from homebrew formulae at the time of this writing, and the version in the path will likely change. +Note that these use the versions from homebrew formulae at the time of this writing, and the version in the path will likely change. ###Xcode If Xcode is your editor of choice, you can ask CMake to generate Xcode project files instead of Unix Makefiles. From e03974181acca42ee1a333ded811e09b2b951709 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 21 Jun 2016 17:13:47 -0700 Subject: [PATCH 26/34] reformat operating hours to [[open,close]] --- domain-server/src/DomainMetadata.cpp | 46 ++++++++++++++++------------ 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/domain-server/src/DomainMetadata.cpp b/domain-server/src/DomainMetadata.cpp index f18aa8c71b..c5048ea9d8 100644 --- a/domain-server/src/DomainMetadata.cpp +++ b/domain-server/src/DomainMetadata.cpp @@ -63,12 +63,16 @@ const QString DomainMetadata::Descriptors::Hours::CLOSE = "close"; DomainMetadata::DomainMetadata(QObject* domainServer) : QObject(domainServer) { // set up the structure necessary for casting during parsing (see parseHours, esp.) _metadata[USERS] = QVariantMap {}; - _metadata[DESCRIPTORS] = QVariantMap { - { Descriptors::HOURS, QVariantMap { - { Descriptors::Hours::WEEKDAY, QVariantList { QVariantMap{} } }, - { Descriptors::Hours::WEEKEND, QVariantList { QVariantMap{} } } - } } - }; + _metadata[DESCRIPTORS] = QVariantMap { { + Descriptors::HOURS, QVariantMap { + { Descriptors::Hours::WEEKDAY, QVariantList { + QVariantList{ QVariant{}, QVariant{} } } + }, + { Descriptors::Hours::WEEKEND, QVariantList { + QVariantList{ QVariant{}, QVariant{} } } + } + } + } }; assert(dynamic_cast(domainServer)); DomainServer* server = static_cast(domainServer); @@ -96,33 +100,37 @@ QJsonObject DomainMetadata::get(const QString& group) { return QJsonObject::fromVariantMap(_metadata[group].toMap()); } +// merge delta into target +// target should be of the form [ OpenTime, CloseTime ], +// delta should be of the form [ { open: Time, close: Time } ] void parseHours(QVariant delta, QVariant& target) { using Hours = DomainMetadata::Descriptors::Hours; - // hours should be of the form [ { open: Time, close: Time } ] assert(target.canConvert()); auto& targetList = *static_cast(target.data()); // if/when multiple ranges are allowed, this list will need to be iterated - assert(targetList[0].canConvert()); - auto& targetMap = *static_cast(targetList[0].data()); + assert(targetList[0].canConvert()); + auto& hours = *static_cast(targetList[0].data()); - auto deltaMap = delta.toList()[0].toMap(); - if (deltaMap.isEmpty()) { + auto deltaHours = delta.toList()[0].toMap(); + if (deltaHours.isEmpty()) { return; } // merge delta into base - auto open = deltaMap.find(Hours::OPEN); - if (open != deltaMap.end()) { - targetMap[Hours::OPEN] = open.value(); + static const int OPEN_INDEX = 0; + static const int CLOSE_INDEX = 1; + auto open = deltaHours.find(Hours::OPEN); + if (open != deltaHours.end()) { + hours[OPEN_INDEX] = open.value(); } - assert(targetMap[Hours::OPEN].canConvert()); - auto close = deltaMap.find(Hours::CLOSE); - if (close != deltaMap.end()) { - targetMap[Hours::CLOSE] = close.value(); + assert(hours[OPEN_INDEX].canConvert()); + auto close = deltaHours.find(Hours::CLOSE); + if (close != deltaHours.end()) { + hours[CLOSE_INDEX] = close.value(); } - assert(targetMap[Hours::CLOSE].canConvert()); + assert(hours[CLOSE_INDEX].canConvert()); } void DomainMetadata::descriptorsChanged() { From 89c50ab3df3585094c8752e341305c82b8d11dd7 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 21 Jun 2016 16:46:10 -0700 Subject: [PATCH 27/34] Update neuron archive in cmakelists --- cmake/externals/neuron/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/externals/neuron/CMakeLists.txt b/cmake/externals/neuron/CMakeLists.txt index 6936725571..76dda8f8c5 100644 --- a/cmake/externals/neuron/CMakeLists.txt +++ b/cmake/externals/neuron/CMakeLists.txt @@ -4,8 +4,8 @@ set(EXTERNAL_NAME neuron) string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) -set(NEURON_URL "https://s3.amazonaws.com/hifi-public/dependencies/neuron_datareader_b.12.zip") -set(NEURON_URL_MD5 "0ab54ca04c9cc8094e0fa046c226e574") +set(NEURON_URL "https://s3.amazonaws.com/hifi-public/dependencies/neuron_datareader_b.12.2.zip") +set(NEURON_URL_MD5 "84273ad2200bf86a9279d1f412a822ca") ExternalProject_Add(${EXTERNAL_NAME} URL ${NEURON_URL} From a7f30ced29516864b4c8f94367c1b02c3e23e534 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 21 Jun 2016 21:39:40 -0700 Subject: [PATCH 28/34] Fix infinite recursion in PluginManager --- libraries/plugins/src/plugins/PluginManager.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/libraries/plugins/src/plugins/PluginManager.cpp b/libraries/plugins/src/plugins/PluginManager.cpp index fcd17eeb9a..29658eeb6b 100644 --- a/libraries/plugins/src/plugins/PluginManager.cpp +++ b/libraries/plugins/src/plugins/PluginManager.cpp @@ -145,8 +145,8 @@ const DisplayPluginList& PluginManager::getDisplayPlugins() { } } for (auto plugin : displayPlugins) { - connect(plugin.get(), &Plugin::deviceConnected, this, deviceAddedCallback); - connect(plugin.get(), &Plugin::subdeviceConnected, this, subdeviceAddedCallback); + connect(plugin.get(), &Plugin::deviceConnected, this, deviceAddedCallback, Qt::QueuedConnection); + connect(plugin.get(), &Plugin::subdeviceConnected, this, subdeviceAddedCallback, Qt::QueuedConnection); plugin->setContainer(_container); plugin->init(); } @@ -193,9 +193,8 @@ const InputPluginList& PluginManager::getInputPlugins() { } for (auto plugin : inputPlugins) { - UserActivityLogger::getInstance().connectedDevice("input", plugin->getName()); - connect(plugin.get(), &Plugin::deviceConnected, this, deviceAddedCallback); - connect(plugin.get(), &Plugin::subdeviceConnected, this, subdeviceAddedCallback); + connect(plugin.get(), &Plugin::deviceConnected, this, deviceAddedCallback, Qt::QueuedConnection); + connect(plugin.get(), &Plugin::subdeviceConnected, this, subdeviceAddedCallback, Qt::QueuedConnection); plugin->setContainer(_container); plugin->init(); } From 1be30ccce9806ad8900ed97aa630e8f4a70cdde1 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 22 Jun 2016 08:24:50 -0700 Subject: [PATCH 29/34] Fix enabled_edit firing on disable --- scripts/system/edit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index bb24a3c7a4..c10f938bde 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -340,7 +340,6 @@ var toolBar = (function() { Messages.sendLocalMessage("edit-events", JSON.stringify({ enabled: active })); - UserActivityLogger.enabledEdit(); isActive = active; if (!isActive) { entityListTool.setVisible(false); @@ -350,6 +349,7 @@ var toolBar = (function() { selectionManager.clearSelections(); cameraManager.disable(); } else { + UserActivityLogger.enabledEdit(); hasShownPropertiesTool = false; entityListTool.setVisible(true); gridTool.setVisible(true); From 890de1bfea6569b8b569d012638a70641bc9a470 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 22 Jun 2016 08:54:58 -0700 Subject: [PATCH 30/34] Add went-to user activity back in --- libraries/networking/src/AddressManager.cpp | 13 ++++++++++ .../networking/src/UserActivityLogger.cpp | 25 ++++++++++++++++++- libraries/networking/src/UserActivityLogger.h | 3 ++- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 80989acd2c..df9b4094b0 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -23,6 +23,7 @@ #include "AddressManager.h" #include "NodeList.h" #include "NetworkLogging.h" +#include "UserActivityLogger.h" const QString ADDRESS_MANAGER_SETTINGS_GROUP = "AddressManager"; @@ -130,6 +131,10 @@ const JSONCallbackParameters& AddressManager::apiCallbackParameters() { } bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) { + static QString URL_TYPE_USER = "user"; + static QString URL_TYPE_DOMAIN_ID = "domain_id"; + static QString URL_TYPE_PLACE = "place"; + static QString URL_TYPE_NETWORK_ADDRESS = "network_address"; if (lookupUrl.scheme() == HIFI_URL_SCHEME) { qCDebug(networking) << "Trying to go to URL" << lookupUrl.toString(); @@ -147,6 +152,8 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) { if (handleUsername(lookupUrl.authority())) { // handled a username for lookup + UserActivityLogger::getInstance().wentTo(trigger, URL_TYPE_USER, lookupUrl.toString()); + // in case we're failing to connect to where we thought this user was // store their username as previous lookup so we can refresh their location via API _previousLookup = lookupUrl; @@ -157,6 +164,8 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) { if (handleNetworkAddress(lookupUrl.host() + (lookupUrl.port() == -1 ? "" : ":" + QString::number(lookupUrl.port())), trigger, hostChanged)) { + UserActivityLogger::getInstance().wentTo(trigger, URL_TYPE_NETWORK_ADDRESS, lookupUrl.toString()); + // a network address lookup clears the previous lookup since we don't expect to re-attempt it _previousLookup.clear(); @@ -174,6 +183,8 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) { // we may have a path that defines a relative viewpoint - if so we should jump to that now handlePath(path, trigger); } else if (handleDomainID(lookupUrl.host())){ + UserActivityLogger::getInstance().wentTo(trigger, URL_TYPE_DOMAIN_ID, lookupUrl.toString()); + // store this domain ID as the previous lookup in case we're failing to connect and want to refresh API info _previousLookup = lookupUrl; @@ -181,6 +192,8 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) { // try to look up the domain ID on the metaverse API attemptDomainIDLookup(lookupUrl.host(), lookupUrl.path(), trigger); } else { + UserActivityLogger::getInstance().wentTo(trigger, URL_TYPE_PLACE, lookupUrl.toString()); + // store this place name as the previous lookup in case we fail to connect and want to refresh API info _previousLookup = lookupUrl; diff --git a/libraries/networking/src/UserActivityLogger.cpp b/libraries/networking/src/UserActivityLogger.cpp index 9a5f0541e5..eba4d31167 100644 --- a/libraries/networking/src/UserActivityLogger.cpp +++ b/libraries/networking/src/UserActivityLogger.cpp @@ -18,6 +18,7 @@ #include "UserActivityLogger.h" #include +#include "AddressManager.h" static const QString USER_ACTIVITY_URL = "/api/v1/user_activities"; @@ -161,12 +162,34 @@ void UserActivityLogger::loadedScript(QString scriptName) { } -void UserActivityLogger::wentTo(QString destinationType, QString destinationName) { +void UserActivityLogger::wentTo(AddressManager::LookupTrigger lookupTrigger, QString destinationType, QString destinationName) { + // Only accept these types of triggers. Other triggers are usually used internally in AddressManager. + QString trigger; + switch (lookupTrigger) { + case AddressManager::UserInput: + trigger = "UserInput"; + break; + case AddressManager::Back: + trigger = "Back"; + break; + case AddressManager::Forward: + trigger = "Forward"; + break; + case AddressManager::StartupFromSettings: + trigger = "StartupFromSettings"; + break; + default: + return; + } + + const QString ACTION_NAME = "went_to"; QJsonObject actionDetails; + const QString TRIGGER_TYPE_KEY = "trigger"; const QString DESTINATION_TYPE_KEY = "destination_type"; const QString DESTINATION_NAME_KEY = "detination_name"; + actionDetails.insert(TRIGGER_TYPE_KEY, trigger); actionDetails.insert(DESTINATION_TYPE_KEY, destinationType); actionDetails.insert(DESTINATION_NAME_KEY, destinationName); diff --git a/libraries/networking/src/UserActivityLogger.h b/libraries/networking/src/UserActivityLogger.h index c2ab93db2f..b41960a8ad 100644 --- a/libraries/networking/src/UserActivityLogger.h +++ b/libraries/networking/src/UserActivityLogger.h @@ -20,6 +20,7 @@ #include #include +#include "AddressManager.h" class UserActivityLogger : public QObject { Q_OBJECT @@ -42,7 +43,7 @@ public slots: void changedDomain(QString domainURL); void connectedDevice(QString typeOfDevice, QString deviceName); void loadedScript(QString scriptName); - void wentTo(QString destinationType, QString destinationName); + void wentTo(AddressManager::LookupTrigger trigger, QString destinationType, QString destinationName); private slots: void requestError(QNetworkReply& errorReply); From 847685d2243bcf6dc50531f2b2788140925cfa7f Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 22 Jun 2016 09:06:59 -0700 Subject: [PATCH 31/34] Add tracking of away.js --- .../networking/src/UserActivityLoggerScriptingInterface.cpp | 4 ++++ .../networking/src/UserActivityLoggerScriptingInterface.h | 1 + scripts/system/away.js | 5 +++++ 3 files changed, 10 insertions(+) diff --git a/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp b/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp index 012a569639..8b22b8ff58 100644 --- a/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp +++ b/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp @@ -20,6 +20,10 @@ void UserActivityLoggerScriptingInterface::openedMarketplace() { logAction("opened_marketplace"); } +void UserActivityLoggerScriptingInterface::toggledAway(bool isAway) { + logAction("toggled_away", { { "is_away", isAway } }); +} + void UserActivityLoggerScriptingInterface::logAction(QString action, QJsonObject details) { QMetaObject::invokeMethod(&UserActivityLogger::getInstance(), "logAction", Q_ARG(QString, action), diff --git a/libraries/networking/src/UserActivityLoggerScriptingInterface.h b/libraries/networking/src/UserActivityLoggerScriptingInterface.h index cad24b1967..9d60d666e2 100644 --- a/libraries/networking/src/UserActivityLoggerScriptingInterface.h +++ b/libraries/networking/src/UserActivityLoggerScriptingInterface.h @@ -22,6 +22,7 @@ class UserActivityLoggerScriptingInterface : public QObject, public Dependency { public: Q_INVOKABLE void enabledEdit(); Q_INVOKABLE void openedMarketplace(); + Q_INVOKABLE void toggledAway(bool isAway); private: void logAction(QString action, QJsonObject details = {}); diff --git a/scripts/system/away.js b/scripts/system/away.js index 38b0f13c00..8f252cc449 100644 --- a/scripts/system/away.js +++ b/scripts/system/away.js @@ -158,6 +158,8 @@ function goAway() { return; } + UserActivityLogger.toggledAway(true); + isAway = true; print('going "away"'); wasMuted = AudioDevice.getMuted(); @@ -189,6 +191,9 @@ function goActive() { if (!isAway) { return; } + + UserActivityLogger.toggledAway(false); + isAway = false; print('going "active"'); if (!wasMuted) { From 2621add8e30b8a9d766c74f5eabdfe92acc14d64 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 22 Jun 2016 09:17:28 -0700 Subject: [PATCH 32/34] Fix nearby_avatars not tracking --- interface/src/Application.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 319da861dc..d20a62fc7b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1157,9 +1157,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : int nearbyAvatars = avatarManager->numberOfAvatarsInRange(avatarManager->getMyAvatar()->getPosition(), NEARBY_AVATAR_RADIUS_METERS) - 1; if (nearbyAvatars != lastCountOfNearbyAvatars) { + lastCountOfNearbyAvatars = nearbyAvatars; UserActivityLogger::getInstance().logAction("nearby_avatars", { { "count", nearbyAvatars } }); } }); + checkNearbyAvatarsTimer->start(); // Track user activity event when we receive a mute packet auto onMutedByMixer = []() { From 2233b5ba64f7c2339a802ccbb95dcc1fd831096c Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 22 Jun 2016 11:57:41 -0700 Subject: [PATCH 33/34] Add user activity tracking for OculusLegacyDisplayPlugin --- plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp | 6 ++++++ plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp index 4aadb890d5..efd9cbec88 100644 --- a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp +++ b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp @@ -36,6 +36,12 @@ const QString OculusLegacyDisplayPlugin::NAME("Oculus Rift"); OculusLegacyDisplayPlugin::OculusLegacyDisplayPlugin() { } +void OculusDisplayPlugin::init() { + Plugin::init(); + + emit deviceConnected(getName()); +} + void OculusLegacyDisplayPlugin::resetSensors() { ovrHmd_RecenterPose(_hmd); } diff --git a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h index 453a6f9168..6ffc1a7f44 100644 --- a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h +++ b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h @@ -23,6 +23,8 @@ public: bool isSupported() const override; const QString& getName() const override { return NAME; } + void init() override; + int getHmdScreen() const override; // Stereo specific methods From 9ff742c97c4c400a0eea97ed366389d8005843c9 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 22 Jun 2016 12:09:12 -0700 Subject: [PATCH 34/34] Fix typo --- plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp index efd9cbec88..f1a803ee19 100644 --- a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp +++ b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp @@ -36,7 +36,7 @@ const QString OculusLegacyDisplayPlugin::NAME("Oculus Rift"); OculusLegacyDisplayPlugin::OculusLegacyDisplayPlugin() { } -void OculusDisplayPlugin::init() { +void OculusLegacyDisplayPlugin::init() { Plugin::init(); emit deviceConnected(getName());