mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-08 20:42:12 +02:00
comment updates and extra includes removed
This commit is contained in:
parent
82c85b51df
commit
a4ad78c337
2 changed files with 65 additions and 33 deletions
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue