Showing the changes to interface/src/scripting/ScreenshareScriptingInterface.cpp (1 of 2 files). Show all
Unified · Split
| @@ -2,7 +2,7 @@ · 1 unmodified line | |||
| 2 | // ScreenshareScriptingInterface.cpp | 2 | // ScreenshareScriptingInterface.cpp |
| 3 | // interface/src/scripting/ | 3 | // interface/src/scripting/ |
| 4 | // | 4 | // |
| 5 | // Created by Milad Nazeri on 2019-10-23. | 5 | // Created by Milad Nazeri and Zach Fox on 2019-10-23. |
| 6 | // Copyright 2019 High Fidelity, Inc. | 6 | // Copyright 2019 High Fidelity, Inc. |
| 7 | // | 7 | // |
| 8 | // Distributed under the Apache License, Version 2.0. | 8 | // Distributed under the Apache License, Version 2.0. |
| @@ -14,12 +14,23 @@ · 5 unmodified lines | |||
| 14 | #include <QJsonDocument> | 14 | #include <QJsonDocument> |
| 15 | #include <QThread> | 15 | #include <QThread> |
| 16 | #include <QUrl> | 16 | #include <QUrl> |
| 17 | #include <QObject> | ||
| 18 | #include <QNetworkAccessManager> | ||
| 19 | #include <QNetworkReply> | ||
| 20 | #include <QNetworkRequest> | ||
| 21 | #include <QProcessEnvironment> | ||
| 17 | 22 | ||
| 18 | #include <AddressManager.h> | 23 | #include <AddressManager.h> |
| 24 | #include <EntityTreeRenderer.h> | ||
| 25 | #include <EntityTree.h> | ||
| 19 | 26 | ||
| 20 | #include "EntityScriptingInterface.h" | 27 | #include "EntityScriptingInterface.h" |
| 21 | #include "ScreenshareScriptingInterface.h" | 28 | #include "ScreenshareScriptingInterface.h" |
| 22 | 29 | ||
| 30 | #include <RenderableEntityItem.h> | ||
| 31 | #include <RenderableTextEntityItem.h> | ||
| 32 | #include <RenderableWebEntityItem.h> | ||
| 33 | |||
| 23 | ScreenshareScriptingInterface::ScreenshareScriptingInterface() { | 34 | ScreenshareScriptingInterface::ScreenshareScriptingInterface() { |
| 24 | }; | 35 | }; |
| 25 | 36 | ||
| @@ -29,8 +40,9 @@ ScreenshareScriptingInterface::~ScreenshareScriptingInterface() { · 3 unmodified lines | |||
| 29 | 40 | ||
| 30 | static const EntityTypes::EntityType LOCAL_SCREENSHARE_WEB_ENTITY_TYPE = EntityTypes::Web; | 41 | static const EntityTypes::EntityType LOCAL_SCREENSHARE_WEB_ENTITY_TYPE = EntityTypes::Web; |
| 31 | static const uint8_t LOCAL_SCREENSHARE_WEB_ENTITY_FPS = 30; | 42 | static const uint8_t LOCAL_SCREENSHARE_WEB_ENTITY_FPS = 30; |
| 32 | static const glm::vec3 LOCAL_SCREENSHARE_WEB_ENTITY_LOCAL_POSITION(0.0f, 0.0f, 0.1f); | 43 | static const glm::vec3 LOCAL_SCREENSHARE_WEB_ENTITY_LOCAL_POSITION(0.0f, -0.0862f, 0.0311f); |
| 33 | static const QString LOCAL_SCREENSHARE_WEB_ENTITY_URL = "https://hifi-content.s3.amazonaws.com/Experiences/Releases/usefulUtilities/smartBoard/screenshareViewer/screenshareClient.html?1"; | 44 | static const QString LOCAL_SCREENSHARE_WEB_ENTITY_URL = "https://hifi-content.s3.amazonaws.com/Experiences/Releases/usefulUtilities/smartBoard/screenshareViewer/screenshareClient.html?1"; |
| 45 | static const glm::vec3 LOCAL_SCREENSHARE_WEB_ENTITY_DIMENSIONS(4.0419f, 2.2735f, 0.0100f); | ||
| 34 | void ScreenshareScriptingInterface::startScreenshare(const QUuid& screenshareZoneID, const QUuid& smartboardEntityID, const bool& isPresenter) { | 46 | void ScreenshareScriptingInterface::startScreenshare(const QUuid& screenshareZoneID, const QUuid& smartboardEntityID, const bool& isPresenter) { |
| 35 | if (QThread::currentThread() != thread()) { | 47 | if (QThread::currentThread() != thread()) { |
| 36 | // We must start a new QProcess from the main thread. | 48 | // We must start a new QProcess from the main thread. |
| @@ -59,99 +71,120 @@ void ScreenshareScriptingInterface::startScreenshare(const QUuid& screenshareZon · 22 unmodified lines | |||
| 59 | } | 71 | } |
| 60 | 72 | ||
| 61 | QUuid currentDomainID = DependencyManager::get<AddressManager>()->getDomainID(); | 73 | QUuid currentDomainID = DependencyManager::get<AddressManager>()->getDomainID(); |
| 62 | |||
| 63 | // Make HTTP GET request to: | ||
| 64 | // `https://metaverse.highfidelity.com/api/v1/domain/:domain_id/screenshare`, | 74 | // `https://metaverse.highfidelity.com/api/v1/domain/:domain_id/screenshare`, |
| 65 | // passing the Domain ID that the user is connected to, as well as the `roomName`. | 75 | // passing the Domain ID that the user is connected to, as well as the `roomName`. |
| 66 | // The server will respond with the relevant OpenTok Token, Session ID, and API Key. | 76 | // The server will respond with the relevant OpenTok Token, Session ID, and API Key. |
| 67 | // Upon error-free response, do the logic below, passing in that info as necessary. | 77 | // Upon error-free response, do the logic below, passing in that info as necessary. |
| 68 | QString token = ""; | 78 | QNetworkAccessManager* manager = new QNetworkAccessManager(); |
| 69 | QString apiKey = ""; | 79 | QObject::connect(manager, &QNetworkAccessManager::finished, this, [=](QNetworkReply *reply) { |
| 70 | QString sessionID = ""; | 80 | if (reply->error()) { |
| 71 | 81 | qDebug() << "\n\n MN HERE: REPLY" << reply->errorString(); | |
| 72 | if (isPresenter) { | 82 | return; |
| 73 | QStringList arguments; | 83 | } |
| 74 | arguments << "--token=" + token; | ||
| 75 | arguments << "--apiKey=" + apiKey; | ||
| 76 | arguments << "--sessionID=" + sessionID; | ||
| 77 | |||
| 78 | connect(_screenshareProcess.get(), &QProcess::errorOccurred, | ||
| 79 | [=](QProcess::ProcessError error) { qDebug() << "ZRF QProcess::errorOccurred. `error`:" << error; }); | ||
| 80 | connect(_screenshareProcess.get(), &QProcess::started, [=]() { qDebug() << "ZRF QProcess::started"; }); | ||
| 81 | connect(_screenshareProcess.get(), &QProcess::stateChanged, | ||
| 82 | [=](QProcess::ProcessState newState) { qDebug() << "ZRF QProcess::stateChanged. `newState`:" << newState; }); | ||
| 83 | connect(_screenshareProcess.get(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), | ||
| 84 | [=](int exitCode, QProcess::ExitStatus exitStatus) { | ||
| 85 | qDebug() << "ZRF QProcess::finished. `exitCode`:" << exitCode << "`exitStatus`:" << exitStatus; | ||
| 86 | emit screenshareStopped(); | ||
| 87 | }); | ||
| 88 | |||
| 89 | _screenshareProcess->start(SCREENSHARE_EXE_PATH, arguments); | ||
| 90 | } | ||
| 91 | |||
| 92 | if (!_screenshareViewerLocalWebEntityUUID.isNull()) { | ||
| 93 | return; | ||
| 94 | } | ||
| 95 | |||
| 96 | auto esi = DependencyManager::get<EntityScriptingInterface>(); | ||
| 97 | if (!esi) { | ||
| 98 | return; | ||
| 99 | } | ||
| 100 | |||
| 101 | EntityItemProperties localScreenshareWebEntityProps; | ||
| 102 | localScreenshareWebEntityProps.setType(LOCAL_SCREENSHARE_WEB_ENTITY_TYPE); | ||
| 103 | localScreenshareWebEntityProps.setMaxFPS(LOCAL_SCREENSHARE_WEB_ENTITY_FPS); | ||
| 104 | localScreenshareWebEntityProps.setLocalPosition(LOCAL_SCREENSHARE_WEB_ENTITY_LOCAL_POSITION); | ||
| 105 | localScreenshareWebEntityProps.setSourceUrl(LOCAL_SCREENSHARE_WEB_ENTITY_URL); | ||
| 106 | localScreenshareWebEntityProps.setParentID(smartboardEntityID); | ||
| 107 | |||
| 108 | EntityPropertyFlags desiredSmartboardProperties; | ||
| 109 | desiredSmartboardProperties += PROP_POSITION; | ||
| 110 | desiredSmartboardProperties += PROP_DIMENSIONS; | ||
| 111 | EntityItemProperties smartboardProps = esi->getEntityProperties(smartboardEntityID, desiredSmartboardProperties); | ||
| 112 | |||
| 113 | localScreenshareWebEntityProps.setPosition(smartboardProps.getPosition()); | ||
| 114 | localScreenshareWebEntityProps.setDimensions(smartboardProps.getDimensions()); | ||
| 115 | |||
| 116 | QString hostType = "local"; | ||
| 117 | _screenshareViewerLocalWebEntityUUID = esi->addEntity(localScreenshareWebEntityProps, hostType); | ||
| 118 | |||
| 119 | QObject::connect(esi.data(), &EntityScriptingInterface::webEventReceived, this, [&](const QUuid& entityID, const QVariant& message) { | ||
| 120 | if (entityID == _screenshareViewerLocalWebEntityUUID) { | ||
| 121 | qDebug() << "ZRF HERE! Inside `webEventReceived(). `entityID`:" << entityID << "`_screenshareViewerLocalWebEntityUUID`:" << _screenshareViewerLocalWebEntityUUID; | ||
| 122 | |||
| 123 | auto esi = DependencyManager::get<EntityScriptingInterface>(); | ||
| 124 | if (!esi) { | ||
| 125 | return; | ||
| 126 | } | ||
| 127 | |||
| 128 | QJsonDocument jsonMessage = QJsonDocument::fromVariant(message); | ||
| 129 | QJsonObject jsonObject = jsonMessage.object(); | ||
| 130 | |||
| 131 | qDebug() << "ZRF HERE! Inside `webEventReceived(). `message`:" << message << "`jsonMessage`:" << jsonMessage; | ||
| 132 | 84 | ||
| 133 | if (jsonObject["app"] != "screenshare") { | 85 | QString answer = reply->readAll(); |
| 134 | return; | 86 | qDebug() << "\n\n MN HERE: REPLY" << answer; |
| 135 | } | ||
| 136 | 87 | ||
| 137 | qDebug() << "ZRF HERE! Inside `webEventReceived(). we're still here!"; | 88 | |
| 89 | QString token = ""; | ||
| 90 | QString apiKey = ""; | ||
| 91 | QString sessionID = ""; | ||
| 92 | |||
| 93 | if (isPresenter) { | ||
| 94 | QStringList arguments; | ||
| 95 | arguments << "--token=" + token; | ||
| 96 | arguments << "--apiKey=" + apiKey; | ||
| 97 | arguments << "--sessionID=" + sessionID; | ||
| 98 | |||
| 99 | connect(_screenshareProcess.get(), &QProcess::errorOccurred, | ||
| 100 | [=](QProcess::ProcessError error) { qDebug() << "ZRF QProcess::errorOccurred. `error`:" << error; }); | ||
| 101 | connect(_screenshareProcess.get(), &QProcess::started, [=]() { qDebug() << "ZRF QProcess::started"; }); | ||
| 102 | connect(_screenshareProcess.get(), &QProcess::stateChanged, | ||
| 103 | [=](QProcess::ProcessState newState) { qDebug() << "ZRF QProcess::stateChanged. `newState`:" << newState; }); | ||
| 104 | connect(_screenshareProcess.get(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), | ||
| 105 | [=](int exitCode, QProcess::ExitStatus exitStatus) { | ||
| 106 | qDebug() << "ZRF QProcess::finished. `exitCode`:" << exitCode << "`exitStatus`:" << exitStatus; | ||
| 107 | emit screenshareStopped(); | ||
| 108 | }); | ||
| 109 | |||
| 110 | _screenshareProcess->start(SCREENSHARE_EXE_PATH, arguments); | ||
| 111 | } | ||
| 138 | 112 | ||
| 139 | if (jsonObject["method"] == "eventBridgeReady") { | 113 | if (!_screenshareViewerLocalWebEntityUUID.isNull()) { |
| 140 | QJsonObject responseObject; | 114 | return; |
| 141 | responseObject.insert("app", "screenshare"); | 115 | } |
| 142 | responseObject.insert("method", "receiveConnectionInfo"); | ||
| 143 | QJsonObject responseObjectData; | ||
| 144 | responseObjectData.insert("token", token); | ||
| 145 | responseObjectData.insert("projectAPIKey", apiKey); | ||
| 146 | responseObjectData.insert("sessionID", sessionID); | ||
| 147 | responseObject.insert("data", responseObjectData); | ||
| 148 | 116 | ||
| 149 | qDebug() << "ZRF HERE! Inside `webEventReceived(). `responseObject.toVariantMap()`:" << responseObject.toVariantMap(); | 117 | auto esi = DependencyManager::get<EntityScriptingInterface>(); |
| 118 | if (!esi) { | ||
| 119 | return; | ||
| 120 | } | ||
| 150 | 121 | ||
| 151 | esi->emitScriptEvent(_screenshareViewerLocalWebEntityUUID, responseObject.toVariantMap()); | 122 | EntityItemProperties localScreenshareWebEntityProps; |
| 123 | localScreenshareWebEntityProps.setType(LOCAL_SCREENSHARE_WEB_ENTITY_TYPE); | ||
| 124 | localScreenshareWebEntityProps.setMaxFPS(LOCAL_SCREENSHARE_WEB_ENTITY_FPS); | ||
| 125 | localScreenshareWebEntityProps.setLocalPosition(LOCAL_SCREENSHARE_WEB_ENTITY_LOCAL_POSITION); | ||
| 126 | localScreenshareWebEntityProps.setSourceUrl(LOCAL_SCREENSHARE_WEB_ENTITY_URL); | ||
| 127 | localScreenshareWebEntityProps.setParentID(smartboardEntityID); | ||
| 128 | localScreenshareWebEntityProps.setDimensions(LOCAL_SCREENSHARE_WEB_ENTITY_DIMENSIONS); | ||
| 129 | |||
| 130 | // EntityPropertyFlags desiredSmartboardProperties; | ||
| 131 | // desiredSmartboardProperties += PROP_POSITION; | ||
| 132 | // desiredSmartboardProperties += PROP_DIMENSIONS; | ||
| 133 | // EntityItemProperties smartboardProps = esi->getEntityProperties(smartboardEntityID, desiredSmartboardProperties); | ||
| 134 | |||
| 135 | QString hostType = "local"; | ||
| 136 | _screenshareViewerLocalWebEntityUUID = esi->addEntity(localScreenshareWebEntityProps, hostType); | ||
| 137 | |||
| 138 | QObject::connect(esi.data(), &EntityScriptingInterface::webEventReceived, this, [&](const QUuid& entityID, const QVariant& message) { | ||
| 139 | if (entityID == _screenshareViewerLocalWebEntityUUID) { | ||
| 140 | qDebug() << "ZRF HERE! Inside `webEventReceived(). `entityID`:" << entityID << "`_screenshareViewerLocalWebEntityUUID`:" << _screenshareViewerLocalWebEntityUUID; | ||
| 141 | |||
| 142 | auto esi = DependencyManager::get<EntityScriptingInterface>(); | ||
| 143 | if (!esi) { | ||
| 144 | return; | ||
| 145 | } | ||
| 146 | |||
| 147 | QJsonDocument jsonMessage = QJsonDocument::fromVariant(message); | ||
| 148 | QJsonObject jsonObject = jsonMessage.object(); | ||
| 149 | |||
| 150 | qDebug() << "ZRF HERE! Inside `webEventReceived(). `message`:" << message << "`jsonMessage`:" << jsonMessage; | ||
| 151 | |||
| 152 | if (jsonObject["app"] != "screenshare") { | ||
| 153 | return; | ||
| 154 | } | ||
| 155 | |||
| 156 | qDebug() << "ZRF HERE! Inside `webEventReceived(). we're still here!"; | ||
| 157 | |||
| 158 | if (jsonObject["method"] == "eventBridgeReady") { | ||
| 159 | QJsonObject responseObject; | ||
| 160 | responseObject.insert("app", "screenshare"); | ||
| 161 | responseObject.insert("method", "receiveConnectionInfo"); | ||
| 162 | QJsonObject responseObjectData; | ||
| 163 | responseObjectData.insert("token", token); | ||
| 164 | responseObjectData.insert("projectAPIKey", apiKey); | ||
| 165 | responseObjectData.insert("sessionID", sessionID); | ||
| 166 | responseObject.insert("data", responseObjectData); | ||
| 167 | |||
| 168 | qDebug() << "ZRF HERE! Inside `webEventReceived(). `responseObject.toVariantMap()`:" << responseObject.toVariantMap(); | ||
| 169 | |||
| 170 | // Attempt 1, we receive the eventBridge message, but this won't send a message | ||
| 171 | // to that js | ||
| 172 | auto esi = DependencyManager::get<EntityScriptingInterface>(); | ||
| 173 | esi->emitScriptEvent(_screenshareViewerLocalWebEntityUUID, responseObject.toVariantMap()); | ||
| 174 | |||
| 175 | // atempt 2, same outcome | ||
| 176 | auto entityTreeRenderer = DependencyManager::get<EntityTreeRenderer>(); | ||
| 177 | auto webEntityRenderable = entityTreeRenderer->renderableForEntityId(_screenshareViewerLocalWebEntityUUID); | ||
| 178 | webEntityRenderable->emitScriptEvent(responseObject.toVariantMap()); | ||
| 179 | } | ||
| 152 | } | 180 | } |
| 153 | } | 181 | }); |
| 154 | }); | 182 | }); |
| 183 | |||
| 184 | QNetworkRequest request; | ||
| 185 | QString tokboxURL = QProcessEnvironment::systemEnvironment().value("hifiScreenshareUrl"); | ||
| 186 | request.setUrl(QUrl(tokboxURL)); | ||
| 187 | manager->get(request); | ||
| 155 | }; | 188 | }; |
| 156 | 189 | ||
| 157 | void ScreenshareScriptingInterface::stopScreenshare() { | 190 | void ScreenshareScriptingInterface::stopScreenshare() { |