comment updates and extra includes removed

This commit is contained in:
milad 2019-11-14 11:28:37 -08:00
parent 82c85b51df
commit a4ad78c337
2 changed files with 65 additions and 33 deletions

View file

@ -9,37 +9,27 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QCoreApplication>
#include <QDesktopServices>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkAccessManager>
#include <QThread>
#include <QUrl>
#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QProcessEnvironment>
#include <AccountManager.h>
#include <AddressManager.h>
#include <EntityTreeRenderer.h>
#include <EntityTree.h>
#include <DependencyManager.h>
#include <UUID.h>
#include "EntityScriptingInterface.h"
#include "ScreenshareScriptingInterface.h"
#include <RenderableEntityItem.h>
#include <RenderableTextEntityItem.h>
#include <RenderableWebEntityItem.h>
ScreenshareScriptingInterface::ScreenshareScriptingInterface() {
auto esi = DependencyManager::get<EntityScriptingInterface>();
if (!esi) {
return;
}
// This signal/slot connection is used when the screen share local web entity sends an event bridge message.
QObject::connect(esi.data(), &EntityScriptingInterface::webEventReceived, this, &ScreenshareScriptingInterface::onWebEventReceived);
};
@ -55,27 +45,35 @@ static const glm::vec3 LOCAL_SCREENSHARE_WEB_ENTITY_LOCAL_POSITION(0.0f, -0.0862
static const glm::vec3 LOCAL_SCREENSHARE_WEB_ENTITY_DIMENSIONS(4.0419f, 2.2735f, 0.0100f);
static const QString LOCAL_SCREENSHARE_WEB_ENTITY_URL =
"https://hifi-content.s3.amazonaws.com/Experiences/Releases/usefulUtilities/smartBoard/screenshareViewer/screenshareClient.html";
static const QString LOCAL_SCREENSHARE_WEB_ENTITY_HOST_TYPE ="local";
void ScreenshareScriptingInterface::startScreenshare(const QUuid& screenshareZoneID,
const QUuid& smartboardEntityID,
const bool& isPresenter) {
// We must start a new QProcess from the main thread.
if (QThread::currentThread() != thread()) {
// We must start a new QProcess from the main thread.
QMetaObject::invokeMethod(this, "startScreenshare", Q_ARG(const QUuid&, screenshareZoneID),
Q_ARG(const QUuid&, smartboardEntityID), Q_ARG(const bool&, isPresenter));
return;
}
// These three private member variables are set now so that they may be used later during asynchronous
// callbacks.
_screenshareZoneID = screenshareZoneID;
_smartboardEntityID = smartboardEntityID;
_isPresenter = isPresenter;
// If we are presenting, and the screenshare process is already running, don't do anything else here.
if (_isPresenter && _screenshareProcess && _screenshareProcess->state() != QProcess::NotRunning) {
return;
}
// If we're presenting...
if (_isPresenter) {
// ...make sure we first reset this `std::unique_ptr`.
_screenshareProcess.reset(new QProcess(this));
// Ensure that the screenshare executable exists where we expect it to.
// Error out and reset the screen share state machine if the executable doesn't exist.
QFileInfo screenshareExecutable(SCREENSHARE_EXE_PATH);
if (!screenshareExecutable.exists() || !screenshareExecutable.isFile()) {
qDebug() << "Screenshare executable doesn't exist at" << SCREENSHARE_EXE_PATH;
@ -85,6 +83,7 @@ void ScreenshareScriptingInterface::startScreenshare(const QUuid& screenshareZon
}
}
// Don't continue with any more of this logic if we can't get the `AccountManager` or `AddressManager`.
auto accountManager = DependencyManager::get<AccountManager>();
if (!accountManager) {
return;
@ -94,9 +93,17 @@ void ScreenshareScriptingInterface::startScreenshare(const QUuid& screenshareZon
return;
}
// Construct and send a request to the Metaverse to obtain the information
// necessary to start the screen sharing process.
// This request requires:
// 1. The domain ID of the domain in which the user's avatar is present
// 2. User authentication information that is automatically included when `sendRequest()` is passed
// with the `AccountManagerAuth::Required` argument.
// Note that this request will only return successfully if the Domain Server has already registered
// the user paired with the current domain with the Metaverse.
// See `DomainServer::screensharePresence()` for more info about that.
QString currentDomainID = uuidStringWithoutCurlyBraces(addressManager->getDomainID());
QString requestURLPath = "api/v1/domains/%1/screenshare";
JSONCallbackParameters callbackParams;
callbackParams.callbackReceiver = this;
callbackParams.jsonCallbackMethod = "handleSuccessfulScreenshareInfoGet";
@ -110,22 +117,29 @@ void ScreenshareScriptingInterface::startScreenshare(const QUuid& screenshareZon
}
void ScreenshareScriptingInterface::stopScreenshare() {
// We can only deal with our Screen Share `QProcess` on the main thread.
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "stopScreenshare");
return;
}
// If the Screen Share process is running...
if (_screenshareProcess && _screenshareProcess->state() != QProcess::NotRunning) {
//...terminate it and make sure that scripts know we terminated it by emitting
// `screenshareProcessTerminated()`.
_screenshareProcess->terminate();
emit screenshareProcessTerminated();
}
// Delete the local web entity if we know about it here.
if (!_screenshareViewerLocalWebEntityUUID.isNull()) {
auto esi = DependencyManager::get<EntityScriptingInterface>();
if (esi) {
esi->deleteEntity(_screenshareViewerLocalWebEntityUUID);
}
}
// Reset all private member variables related to screen share here.
_screenshareViewerLocalWebEntityUUID = "{00000000-0000-0000-0000-000000000000}";
_token = "";
_projectAPIKey = "";
@ -133,12 +147,14 @@ void ScreenshareScriptingInterface::stopScreenshare() {
_isPresenter = false;
}
// Called when the Metaverse returns the information necessary to start/view a screen share.
void ScreenshareScriptingInterface::handleSuccessfulScreenshareInfoGet(QNetworkReply* reply) {
// Read the reply and get it into a format we understand.
QString answer = reply->readAll();
QByteArray answerByteArray = answer.toUtf8();
QJsonDocument answerJSONObject = QJsonDocument::fromJson(answerByteArray);
// This Metaverse endpoint will always return a status key/value pair of "success" if things went well.
QString status = answerJSONObject["status"].toString();
if (status != "success") {
qDebug() << "Error when retrieving screenshare info via HTTP. Error:" << reply->errorString();
@ -147,10 +163,12 @@ void ScreenshareScriptingInterface::handleSuccessfulScreenshareInfoGet(QNetworkR
return;
}
// Store the information necessary to start/view a screen share in these private member variables.
_token = answerJSONObject["token"].toString();
_projectAPIKey = answerJSONObject["projectApiKey"].toString();
_sessionID = answerJSONObject["sessionID"].toString();
// Make sure we have all of the info that we need.
if (_token.isEmpty() || _projectAPIKey.isEmpty() || _sessionID.isEmpty()) {
qDebug() << "Not all Screen Share information was retrieved from the backend. Stopping...";
stopScreenshare();
@ -158,6 +176,10 @@ void ScreenshareScriptingInterface::handleSuccessfulScreenshareInfoGet(QNetworkR
return;
}
// If we're presenting:
// 1. Build a list of arguments that we're going to pass to the screen share Electron app.
// 2. Make sure we connect a signal/slot to know when the user quits the Electron app.
// 3. Start the screen share Electron app with the list of args from (1).
if (_isPresenter) {
QStringList arguments;
arguments << " ";
@ -174,12 +196,7 @@ void ScreenshareScriptingInterface::handleSuccessfulScreenshareInfoGet(QNetworkR
_screenshareProcess->start(SCREENSHARE_EXE_PATH, arguments);
}
if (!_screenshareViewerLocalWebEntityUUID.isNull()) {
stopScreenshare();
emit screenshareError();
return;
}
// Make sure we can grab the entity scripting interface. Error out if we can't.
auto esi = DependencyManager::get<EntityScriptingInterface>();
if (!esi) {
stopScreenshare();
@ -187,6 +204,12 @@ void ScreenshareScriptingInterface::handleSuccessfulScreenshareInfoGet(QNetworkR
return;
}
// If, for some reason, we already have a record of a screen share local Web entity, delete it.
if (!_screenshareViewerLocalWebEntityUUID.isNull()) {
esi->deleteEntity(_screenshareViewerLocalWebEntityUUID);
}
// Set up the entity properties associated with the screen share local Web entity.
EntityItemProperties localScreenshareWebEntityProps;
localScreenshareWebEntityProps.setType(LOCAL_SCREENSHARE_WEB_ENTITY_TYPE);
localScreenshareWebEntityProps.setMaxFPS(LOCAL_SCREENSHARE_WEB_ENTITY_FPS);
@ -195,14 +218,16 @@ void ScreenshareScriptingInterface::handleSuccessfulScreenshareInfoGet(QNetworkR
localScreenshareWebEntityProps.setParentID(_smartboardEntityID);
localScreenshareWebEntityProps.setDimensions(LOCAL_SCREENSHARE_WEB_ENTITY_DIMENSIONS);
// The lines below will be used when writing the feature to ensure that the smartboard can be of any arbitrary size.
// The lines below will be used when writing the feature to support scaling the Smartboard entity to any arbitrary size.
//EntityPropertyFlags desiredSmartboardProperties;
//desiredSmartboardProperties += PROP_POSITION;
//desiredSmartboardProperties += PROP_DIMENSIONS;
//EntityItemProperties smartboardProps = esi->getEntityProperties(smartboardEntityID, desiredSmartboardProperties);
QString hostType = "local";
_screenshareViewerLocalWebEntityUUID = esi->addEntity(localScreenshareWebEntityProps, hostType);
//EntityItemProperties smartboardProps = esi->getEntityProperties(_smartboardEntityID, desiredSmartboardProperties);
// Add the screen share local Web entity to Interface's entity tree.
// When the Web entity loads the page specified by `LOCAL_SCREENSHARE_WEB_ENTITY_URL`, it will broadcast an Event Bridge
// message, which we will consume inside `ScreenshareScriptingInterface::onWebEventReceived()`.
_screenshareViewerLocalWebEntityUUID = esi->addEntity(localScreenshareWebEntityProps, LOCAL_SCREENSHARE_WEB_ENTITY_HOST_TYPE);
}
void ScreenshareScriptingInterface::handleFailedScreenshareInfoGet(QNetworkReply* reply) {
@ -211,21 +236,31 @@ void ScreenshareScriptingInterface::handleFailedScreenshareInfoGet(QNetworkReply
emit screenshareError();
}
// This function will handle _all_ web events received via `EntityScriptingInterface::webEventReceived()`, including
// those not related to screen sharing.
void ScreenshareScriptingInterface::onWebEventReceived(const QUuid& entityID, const QVariant& message) {
// Bail early if the entity that sent the Web event isn't the one we care about.
if (entityID == _screenshareViewerLocalWebEntityUUID) {
// Bail early if we can't grab the Entity Scripting Interface.
auto esi = DependencyManager::get<EntityScriptingInterface>();
if (!esi) {
return;
}
// Web events received from the screen share Web JS will always be in stringified JSON format.
QByteArray jsonByteArray = QVariant(message).toString().toUtf8();
QJsonDocument jsonObject = QJsonDocument::fromJson(jsonByteArray);
// It should never happen where the screen share Web JS sends a message without the `app` key's value
// set to "screenshare".
if (jsonObject["app"] != "screenshare") {
return;
}
// The screen share Web JS only sends a message with one method: "eventBridgeReady". Handle it here.
if (jsonObject["method"] == "eventBridgeReady") {
// Stuff a JSON object full of information necessary for the screen share local Web entity
// to connect to the screen share session associated with the room in which the user's avatar is standing.
QJsonObject responseObject;
responseObject.insert("app", "screenshare");
responseObject.insert("method", "receiveConnectionInfo");
@ -235,7 +270,6 @@ void ScreenshareScriptingInterface::onWebEventReceived(const QUuid& entityID, co
responseObjectData.insert("sessionID", _sessionID);
responseObject.insert("data", responseObjectData);
auto esi = DependencyManager::get<EntityScriptingInterface>();
esi->emitScriptEvent(_screenshareViewerLocalWebEntityUUID, responseObject.toVariantMap());
}
}

View file

@ -12,13 +12,11 @@
#ifndef hifi_ScreenshareScriptingInterface_h
#define hifi_ScreenshareScriptingInterface_h
// #include <QObject>
#include <QObject>
#include <QProcess>
#include <QtCore/QCoreApplication>
// #include <QNetworkAccessManager>
// #include <QNetworkReply>
// #include <QNetworkRequest>
#include <DependencyManager.h>
#include <QNetworkReply>
#include <PathUtils.h>
class ScreenshareScriptingInterface : public QObject, public Dependency {