requests(general): ExecuteBatch WIP

This commit is contained in:
Stéphane Lepin
2021-02-02 11:26:22 +01:00
parent cb7c77d29e
commit 10910aa06d
7 changed files with 105 additions and 38 deletions

View File

@ -46,6 +46,8 @@ const QHash<QString, RpcMethodHandler> WSRequestHandler::messageMap{
{ "TriggerHotkeyByName", &WSRequestHandler::TriggerHotkeyByName },
{ "TriggerHotkeyBySequence", &WSRequestHandler::TriggerHotkeyBySequence },
{ "ExecuteBatch", &WSRequestHandler::ExecuteBatch },
{ "SetCurrentScene", &WSRequestHandler::SetCurrentScene },
{ "GetCurrentScene", &WSRequestHandler::GetCurrentScene },
{ "GetSceneList", &WSRequestHandler::GetSceneList },
@ -189,7 +191,7 @@ WSRequestHandler::WSRequestHandler(ConnectionProperties& connProperties) :
{
}
RpcResponse WSRequestHandler::processRequest(const RpcRequest& request){
RpcResponse WSRequestHandler::processRequest(const RpcRequest& request) {
if (GetConfig()->AuthRequired
&& (!authNotRequired.contains(request.methodName()))
&& (!_connProperties.isAuthenticated()))

View File

@ -64,6 +64,8 @@ class WSRequestHandler {
RpcResponse TriggerHotkeyByName(const RpcRequest&);
RpcResponse TriggerHotkeyBySequence(const RpcRequest&);
RpcResponse ExecuteBatch(const RpcRequest&);
RpcResponse SetCurrentScene(const RpcRequest&);
RpcResponse GetCurrentScene(const RpcRequest&);
RpcResponse GetSceneList(const RpcRequest&);

View File

@ -7,6 +7,7 @@
#include "Config.h"
#include "Utils.h"
#include "WSEvents.h"
#include "protocol/OBSRemoteProtocol.h"
#define CASE(x) case x: return #x;
const char *describe_output_format(int format) {
@ -415,3 +416,47 @@ RpcResponse WSRequestHandler::TriggerHotkeyBySequence(const RpcRequest& request)
return request.success();
}
/**
* Executes a list of requests sequentially.
*
* @param {Array<Object>} `requests`
*
* @return {Array<Object>} `results`
*
* @api requests
* @name ExecuteBatch
* @category general
* @since unreleased
*/
RpcResponse WSRequestHandler::ExecuteBatch(const RpcRequest& request) {
if (!request.hasField("requests")) {
return request.failed("missing request parameters");
}
OBSDataArrayAutoRelease results = obs_data_array_create();
OBSDataArrayAutoRelease requests = obs_data_get_array(request.parameters(), "requests");
size_t requestsCount = obs_data_array_count(requests);
for (size_t i = 0; i < requestsCount; i++) {
OBSDataAutoRelease requestData = obs_data_array_item(requests, i);
QString methodName = obs_data_get_string(requestData, "request-type");
obs_data_unset_user_value(requestData, "request-type");
obs_data_unset_user_value(requestData, "message-id");
// build RpcRequest from json data object
RpcRequest subRequest(QString::Null(), methodName, requestData);
// execute the request
RpcResponse subResponse = processRequest(subRequest);
// transform response into json data
OBSDataAutoRelease subResponseData = OBSRemoteProtocol::rpcResponseToJsonData(subResponse);
obs_data_array_push_back(results, subResponseData);
}
OBSDataAutoRelease response = obs_data_create();
obs_data_set_array(response, "results", results);
return request.success(response);
}

View File

@ -133,8 +133,7 @@ void WSServer::stop()
void WSServer::broadcast(const RpcEvent& event)
{
OBSRemoteProtocol protocol;
std::string message = protocol.encodeEvent(event);
std::string message = OBSRemoteProtocol::encodeEvent(event);
if (GetConfig()->DebugEnabled) {
blog(LOG_INFO, "Update << '%s'", message.c_str());
@ -190,8 +189,7 @@ void WSServer::onMessage(connection_hdl hdl, server::message_ptr message)
}
WSRequestHandler requestHandler(connProperties);
OBSRemoteProtocol protocol;
std::string response = protocol.processMessage(requestHandler, payload);
std::string response = OBSRemoteProtocol::processMessage(requestHandler, payload);
if (GetConfig()->DebugEnabled) {
blog(LOG_INFO, "Response << '%s'", response.c_str());

View File

@ -31,11 +31,15 @@ std::string OBSRemoteProtocol::processMessage(WSRequestHandler& requestHandler,
OBSDataAutoRelease data = obs_data_create_from_json(msg);
if (!data) {
blog(LOG_ERROR, "invalid JSON payload received for '%s'", msg);
return errorResponse(QString::Null(), "invalid JSON payload");
return jsonDataToString(
errorResponse(nullptr, "invalid JSON payload")
);
}
if (!obs_data_has_user_value(data, "request-type") || !obs_data_has_user_value(data, "message-id")) {
return errorResponse(QString::Null(), "missing request parameters");
return jsonDataToString(
errorResponse(nullptr, "missing request parameters")
);
}
QString methodName = obs_data_get_string(data, "request-type");
@ -49,15 +53,8 @@ std::string OBSRemoteProtocol::processMessage(WSRequestHandler& requestHandler,
RpcRequest request(messageId, methodName, params);
RpcResponse response = requestHandler.processRequest(request);
OBSData additionalFields = response.additionalFields();
switch (response.status()) {
case RpcResponse::Status::Ok:
return successResponse(messageId, additionalFields);
case RpcResponse::Status::Error:
return errorResponse(messageId, response.errorMessage(), additionalFields);
}
return std::string();
OBSData responseData = rpcResponseToJsonData(response);
return jsonDataToString(responseData);
}
std::string OBSRemoteProtocol::encodeEvent(const RpcEvent& event)
@ -87,33 +84,53 @@ std::string OBSRemoteProtocol::encodeEvent(const RpcEvent& event)
return std::string(obs_data_get_json(eventData));
}
std::string OBSRemoteProtocol::buildResponse(QString messageId, QString status, obs_data_t* fields)
obs_data_t* OBSRemoteProtocol::rpcResponseToJsonData(const RpcResponse& response)
{
OBSDataAutoRelease response = obs_data_create();
if (!messageId.isNull()) {
obs_data_set_string(response, "message-id", messageId.toUtf8().constData());
const char* messageId = response.messageId().toUtf8().constData();
OBSData additionalFields = response.additionalFields();
switch (response.status()) {
case RpcResponse::Status::Ok:
return successResponse(messageId, additionalFields);
case RpcResponse::Status::Error:
return errorResponse(messageId, response.errorMessage().toUtf8().constData(), additionalFields);
default:
assert(false);
}
obs_data_set_string(response, "status", status.toUtf8().constData());
if (fields) {
obs_data_apply(response, fields);
}
std::string responseString = obs_data_get_json(response);
return responseString;
}
std::string OBSRemoteProtocol::successResponse(QString messageId, obs_data_t* fields)
obs_data_t* OBSRemoteProtocol::successResponse(const char* messageId, obs_data_t* fields)
{
return buildResponse(messageId, "ok", fields);
}
std::string OBSRemoteProtocol::errorResponse(QString messageId, QString errorMessage, obs_data_t* additionalFields)
obs_data_t* OBSRemoteProtocol::errorResponse(const char* messageId, const char* errorMessage, obs_data_t* additionalFields)
{
OBSDataAutoRelease fields = obs_data_create();
if (additionalFields) {
obs_data_apply(fields, additionalFields);
}
obs_data_set_string(fields, "error", errorMessage.toUtf8().constData());
obs_data_set_string(fields, "error", errorMessage);
return buildResponse(messageId, "error", fields);
}
obs_data_t* OBSRemoteProtocol::buildResponse(const char* messageId, const char* status, obs_data_t* fields)
{
OBSDataAutoRelease response = obs_data_create();
if (messageId) {
obs_data_set_string(response, "message-id", messageId);
}
obs_data_set_string(response, "status", status);
if (fields) {
obs_data_apply(response, fields);
}
obs_data_addref(response);
return response;
}
std::string OBSRemoteProtocol::jsonDataToString(obs_data_t* data)
{
std::string responseString = obs_data_get_json(data);
return responseString;
}

View File

@ -20,7 +20,8 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#include <string>
#include <obs-data.h>
#include <QtCore/QString>
#include "../rpc/RpcResponse.h"
class WSRequestHandler;
class RpcEvent;
@ -28,11 +29,13 @@ class RpcEvent;
class OBSRemoteProtocol
{
public:
std::string processMessage(WSRequestHandler& requestHandler, std::string message);
std::string encodeEvent(const RpcEvent& event);
static std::string processMessage(WSRequestHandler& requestHandler, std::string message);
static std::string encodeEvent(const RpcEvent& event);
static obs_data_t* rpcResponseToJsonData(const RpcResponse& response);
private:
std::string buildResponse(QString messageId, QString status, obs_data_t* fields = nullptr);
std::string successResponse(QString messageId, obs_data_t* fields = nullptr);
std::string errorResponse(QString messageId, QString errorMessage, obs_data_t* additionalFields = nullptr);
static obs_data_t* successResponse(const char* messageId, obs_data_t* fields = nullptr);
static obs_data_t* errorResponse(const char* messageId, const char* errorMessage, obs_data_t* additionalFields = nullptr);
static obs_data_t* buildResponse(const char* messageId, const char*, obs_data_t* fields = nullptr);
static std::string jsonDataToString(obs_data_t* data);
};

View File

@ -36,7 +36,7 @@ public:
obs_data_t* additionalFields = nullptr
);
Status status() {
const Status status() const {
return _status;
}