diff --git a/src/WebSocketServer.cpp b/src/WebSocketServer.cpp index 1f1d24fd..d697ada7 100644 --- a/src/WebSocketServer.cpp +++ b/src/WebSocketServer.cpp @@ -51,6 +51,12 @@ WebSocketServer::WebSocketServer() : &WebSocketServer::BroadcastEvent, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4 ) ); + + eventHandler->SetObsLoadedCallback( + std::bind( + &WebSocketServer::onObsLoaded, this + ) + ); } WebSocketServer::~WebSocketServer() @@ -198,7 +204,20 @@ std::vector WebSocketServer::GetWebSocke return webSocketSessions; } -// It isn't consistent to directly call the WebSocketServer from the events system, but it would also be dumb to make it unnecessarily complicated. +void WebSocketServer::onObsLoaded() +{ + auto conf = GetConfig(); + if (!conf) { + blog(LOG_ERROR, "[WebSocketServer::onObsLoaded] Unable to retreive config!"); + return; + } + + if (conf->ServerEnabled) { + if (conf->DebugEnabled) + blog(LOG_INFO, "[WebSocketServer::onObsLoaded] Server is enabled in configuration. Starting server..."); + Start(); + } +} bool WebSocketServer::onValidate(websocketpp::connection_hdl hdl) { diff --git a/src/WebSocketServer.h b/src/WebSocketServer.h index 3a0e3f5c..359b84c4 100644 --- a/src/WebSocketServer.h +++ b/src/WebSocketServer.h @@ -95,15 +95,16 @@ class WebSocketServer : QObject void ServerRunner(); + void onObsLoaded(); bool onValidate(websocketpp::connection_hdl hdl); void onOpen(websocketpp::connection_hdl hdl); void onClose(websocketpp::connection_hdl hdl); void onMessage(websocketpp::connection_hdl hdl, websocketpp::server::message_ptr message); - void SetSessionParameters(SessionPtr session, WebSocketServer::ProcessResult &ret, json payloadData); - void ProcessMessage(SessionPtr session, ProcessResult &ret, const uint8_t opCode, json incomingMessage); + void SetSessionParameters(SessionPtr session, WebSocketServer::ProcessResult &ret, const json &payloadData); + void ProcessMessage(SessionPtr session, ProcessResult &ret, const uint8_t opCode, json &payloadData); - void ProcessRequestBatch(SessionPtr session, ObsWebSocketRequestBatchExecutionType executionType, std::vector &requests, std::vector &results); + void ProcessRequestBatch(SessionPtr session, ObsWebSocketRequestBatchExecutionType executionType, std::vector &requests, std::vector &results, json &variables); std::thread _serverThread; websocketpp::server _server; diff --git a/src/WebSocketServer_Protocol.cpp b/src/WebSocketServer_Protocol.cpp index 5b44e3f2..11e735b2 100644 --- a/src/WebSocketServer_Protocol.cpp +++ b/src/WebSocketServer_Protocol.cpp @@ -28,7 +28,7 @@ bool IsSupportedRpcVersion(uint8_t requestedVersion) return (requestedVersion == 1); } -void WebSocketServer::SetSessionParameters(SessionPtr session, ProcessResult &ret, json payloadData) +void WebSocketServer::SetSessionParameters(SessionPtr session, ProcessResult &ret, const json &payloadData) { if (payloadData.contains("ignoreInvalidMessages")) { if (!payloadData["ignoreInvalidMessages"].is_boolean()) { @@ -49,7 +49,7 @@ void WebSocketServer::SetSessionParameters(SessionPtr session, ProcessResult &re } } -void WebSocketServer::ProcessMessage(SessionPtr session, WebSocketServer::ProcessResult &ret, uint8_t opCode, json payloadData) +void WebSocketServer::ProcessMessage(SessionPtr session, WebSocketServer::ProcessResult &ret, uint8_t opCode, json &payloadData) { if (!payloadData.is_object()) { if (payloadData.is_null()) { @@ -236,6 +236,7 @@ void WebSocketServer::ProcessMessage(SessionPtr session, WebSocketServer::Proces } return; } + executionType = OBS_WEBSOCKET_REQUEST_BATCH_EXECUTION_TYPE_PARALLEL; } else { if (!session->IgnoreInvalidMessages()) { @@ -246,9 +247,28 @@ void WebSocketServer::ProcessMessage(SessionPtr session, WebSocketServer::Proces } } + if (payloadData.contains("variables") && !payloadData.is_null()) { + if (!payloadData.is_object()) { + if (!session->IgnoreInvalidMessages()) { + ret.closeCode = WebSocketCloseCode::InvalidDataKeyType; + ret.closeReason = "Your `variables` is not an object."; + } + return; + } + + if (executionType == OBS_WEBSOCKET_REQUEST_BATCH_EXECUTION_TYPE_PARALLEL) { + if (!session->IgnoreInvalidMessages()) { + ret.closeCode = WebSocketCloseCode::UnsupportedFeature; + ret.closeReason = "Variables are not supported in PARALLEL mode."; + } + return; + } + } + std::vector requests = payloadData["requests"]; + json variables = payloadData["variables"]; std::vector results; - ProcessRequestBatch(session, executionType, requests, results); + ProcessRequestBatch(session, executionType, requests, results, variables); ret.result["op"] = WebSocketOpCode::RequestBatchResponse; ret.result["d"]["requestId"] = payloadData["requestId"]; @@ -263,6 +283,7 @@ void WebSocketServer::ProcessMessage(SessionPtr session, WebSocketServer::Proces } } +// It isn't consistent to directly call the WebSocketServer from the events system, but it would also be dumb to make it unnecessarily complicated. void WebSocketServer::BroadcastEvent(uint64_t requiredIntent, std::string eventType, json eventData, uint8_t rpcVersion) { if (!_server.is_listening()) diff --git a/src/WebSocketServer_RequestBatchProcessing.cpp b/src/WebSocketServer_RequestBatchProcessing.cpp index 338e2b77..a0037c22 100644 --- a/src/WebSocketServer_RequestBatchProcessing.cpp +++ b/src/WebSocketServer_RequestBatchProcessing.cpp @@ -5,18 +5,33 @@ #include "obs-websocket.h" #include "utils/Compat.h" +struct SerialFrameRequest +{ + Request request; + const json inputVariables; + const json outputVariables; + + SerialFrameRequest(const std::string &requestType, const json &requestData, const json &inputVariables, const json &outputVariables) : + request(requestType, requestData, OBS_WEBSOCKET_REQUEST_BATCH_EXECUTION_TYPE_SERIAL_FRAME), + inputVariables(inputVariables), + outputVariables(outputVariables) + {} +}; + struct SerialFrameBatch { - RequestHandler *requestHandler; + RequestHandler &requestHandler; + json &variables; size_t frameCount; size_t sleepUntilFrame; - std::queue requests; + std::queue requests; std::vector results; std::mutex conditionMutex; std::condition_variable condition; - SerialFrameBatch(RequestHandler *requestHandler) : + SerialFrameBatch(RequestHandler &requestHandler, json &variables) : requestHandler(requestHandler), + variables(variables), frameCount(0), sleepUntilFrame(0) {} @@ -24,19 +39,73 @@ struct SerialFrameBatch struct ParallelBatchResults { - RequestHandler *requestHandler; + RequestHandler &requestHandler; size_t requestCount; std::mutex resultsMutex; std::vector results; std::condition_variable condition; - ParallelBatchResults(RequestHandler *requestHandler, size_t requestCount) : + ParallelBatchResults(RequestHandler &requestHandler, size_t requestCount) : requestHandler(requestHandler), requestCount(requestCount) {} }; -json ConstructRequestResult(RequestResult requestResult, json requestJson) + + +bool PreProcessVariables(const json &variables, const json &inputVariables, json &requestData) +{ + if (variables.empty() || inputVariables.empty() || !inputVariables.is_object() || !requestData.is_object()) + return !requestData.empty(); + + for (auto it = inputVariables.begin(); it != inputVariables.end(); ++it) { + std::string key = it.key(); + + if (!variables.contains(key)) { + if (IsDebugMode()) + blog(LOG_WARNING, "[WebSocketServer::ProcessRequestBatch] inputVariables requested variable `%s`, but it does not exist. Skipping!", key.c_str()); + continue; + } + + if (!it.value().is_string()) { + if (IsDebugMode()) + blog(LOG_WARNING, "[WebSocketServer::ProcessRequestBatch] Value of item `%s` in inputVariables is not a string. Skipping!", key.c_str()); + continue; + } + + std::string value = it.value(); + requestData[value] = variables[key]; + } + + return !requestData.empty(); +} + +void PostProcessVariables(json &variables, const json &outputVariables, const json &responseData) +{ + if (outputVariables.empty() || !outputVariables.is_object() || responseData.empty()) + return; + + for (auto it = outputVariables.begin(); it != outputVariables.end(); ++it) { + std::string key = it.key(); + + if (!responseData.contains(key)) { + if (IsDebugMode()) + blog(LOG_WARNING, "[WebSocketServer::ProcessRequestBatch] outputVariables requested responseData item `%s`, but it does not exist. Skipping!", key.c_str()); + continue; + } + + if (!it.value().is_string()) { + if (IsDebugMode()) + blog(LOG_WARNING, "[WebSocketServer::ProcessRequestBatch] Value of item `%s` in outputVariables is not a string. Skipping!", key.c_str()); + continue; + } + + std::string value = it.value(); + variables[key] = responseData[value]; + } +} + +json ConstructRequestResult(RequestResult requestResult, const json &requestJson) { json ret; @@ -82,9 +151,13 @@ void ObsTickCallback(void *param, float) // Begin recursing any unprocessed requests while (!serialFrameBatch->requests.empty()) { // Fetch first in queue - Request request = serialFrameBatch->requests.front(); + SerialFrameRequest frameRequest = serialFrameBatch->requests.front(); + // Pre-process batch variables + frameRequest.request.HasRequestData = PreProcessVariables(serialFrameBatch->variables, frameRequest.inputVariables, frameRequest.request.RequestData); // Process request and get result - RequestResult requestResult = serialFrameBatch->requestHandler->ProcessRequest(request); + RequestResult requestResult = serialFrameBatch->requestHandler.ProcessRequest(frameRequest.request); + // Post-process batch variables + PostProcessVariables(serialFrameBatch->variables, frameRequest.outputVariables, requestResult.ResponseData); // Add to results vector serialFrameBatch->results.push_back(requestResult); // Remove from front of queue @@ -105,27 +178,31 @@ void ObsTickCallback(void *param, float) profile_end("obs-websocket-request-batch-frame-tick"); } -void WebSocketServer::ProcessRequestBatch(SessionPtr session, ObsWebSocketRequestBatchExecutionType executionType, std::vector &requests, std::vector &results) +void WebSocketServer::ProcessRequestBatch(SessionPtr session, ObsWebSocketRequestBatchExecutionType executionType, std::vector &requests, std::vector &results, json &variables) { RequestHandler requestHandler(session); if (executionType == OBS_WEBSOCKET_REQUEST_BATCH_EXECUTION_TYPE_SERIAL_REALTIME) { // Recurse all requests in batch serially, processing the request then moving to the next one for (auto requestJson : requests) { - Request request(requestJson["requestType"], requestJson["requestData"], executionType); + Request request(requestJson["requestType"], requestJson["requestData"], OBS_WEBSOCKET_REQUEST_BATCH_EXECUTION_TYPE_SERIAL_REALTIME); + + request.HasRequestData = PreProcessVariables(variables, requestJson["inputVariables"], request.RequestData); RequestResult requestResult = requestHandler.ProcessRequest(request); + PostProcessVariables(variables, requestJson["outputVariables"], requestResult.ResponseData); + json result = ConstructRequestResult(requestResult, requestJson); results.push_back(result); } } else if (executionType == OBS_WEBSOCKET_REQUEST_BATCH_EXECUTION_TYPE_SERIAL_FRAME) { - SerialFrameBatch serialFrameBatch(&requestHandler); + SerialFrameBatch serialFrameBatch(requestHandler, variables); // Create Request objects in the worker thread (avoid unnecessary processing in graphics thread) for (auto requestJson : requests) { - Request request(requestJson["requestType"], requestJson["requestData"], executionType); - serialFrameBatch.requests.push(request); + SerialFrameRequest frameRequest(requestJson["requestType"], requestJson["requestData"], requestJson["inputVariables"], requestJson["outputVariables"]); + serialFrameBatch.requests.push(frameRequest); } // Create a callback entry for the graphics thread to execute on each video frame @@ -145,14 +222,14 @@ void WebSocketServer::ProcessRequestBatch(SessionPtr session, ObsWebSocketReques i++; } } else if (executionType == OBS_WEBSOCKET_REQUEST_BATCH_EXECUTION_TYPE_PARALLEL) { - ParallelBatchResults parallelResults(&requestHandler, requests.size()); + ParallelBatchResults parallelResults(requestHandler, requests.size()); // Submit each request as a task to the thread pool to be processed ASAP for (auto requestJson : requests) { _threadPool.start(Utils::Compat::CreateFunctionRunnable([¶llelResults, &executionType, requestJson]() { - Request request(requestJson["requestType"], requestJson["requestData"], executionType); + Request request(requestJson["requestType"], requestJson["requestData"], OBS_WEBSOCKET_REQUEST_BATCH_EXECUTION_TYPE_PARALLEL); - RequestResult requestResult = parallelResults.requestHandler->ProcessRequest(request); + RequestResult requestResult = parallelResults.requestHandler.ProcessRequest(request); json result = ConstructRequestResult(requestResult, requestJson); diff --git a/src/eventhandler/EventHandler.cpp b/src/eventhandler/EventHandler.cpp index 25eaccc7..954abae9 100644 --- a/src/eventhandler/EventHandler.cpp +++ b/src/eventhandler/EventHandler.cpp @@ -48,6 +48,11 @@ void EventHandler::SetBroadcastCallback(EventHandler::BroadcastCallback cb) _broadcastCallback = cb; } +void EventHandler::SetObsLoadedCallback(EventHandler::ObsLoadedCallback cb) +{ + _obsLoadedCallback = cb; +} + // Function to increment refcounts for high volume event subscriptions void EventHandler::ProcessSubscription(uint64_t eventSubscriptions) { @@ -189,6 +194,9 @@ void EventHandler::OnFrontendEvent(enum obs_frontend_event event, void *private_ }, private_data); blog(LOG_INFO, "[EventHandler::OnFrontendEvent] Finished."); + + if (eventHandler->_obsLoadedCallback) + eventHandler->_obsLoadedCallback(); } else { return; } diff --git a/src/eventhandler/EventHandler.h b/src/eventhandler/EventHandler.h index a12da6fb..3ef2f4f8 100644 --- a/src/eventhandler/EventHandler.h +++ b/src/eventhandler/EventHandler.h @@ -24,12 +24,15 @@ class EventHandler typedef std::function BroadcastCallback; void SetBroadcastCallback(BroadcastCallback cb); + typedef std::function ObsLoadedCallback; + void SetObsLoadedCallback(ObsLoadedCallback cb); void ProcessSubscription(uint64_t eventSubscriptions); void ProcessUnsubscription(uint64_t eventSubscriptions); private: BroadcastCallback _broadcastCallback; + ObsLoadedCallback _obsLoadedCallback; std::atomic _obsLoaded; diff --git a/src/obs-websocket.cpp b/src/obs-websocket.cpp index 2241c028..61aafcd2 100644 --- a/src/obs-websocket.cpp +++ b/src/obs-websocket.cpp @@ -54,9 +54,6 @@ bool obs_module_load(void) _cpuUsageInfo = os_cpu_usage_info_start(); - if (_config->ServerEnabled) - _webSocketServer->Start(); - // Loading finished blog(LOG_INFO, "[obs_module_load] Module loaded."); diff --git a/src/requesthandler/rpc/Request.cpp b/src/requesthandler/rpc/Request.cpp index 2ca60870..f6a5bf80 100644 --- a/src/requesthandler/rpc/Request.cpp +++ b/src/requesthandler/rpc/Request.cpp @@ -2,7 +2,7 @@ #include "../../obs-websocket.h" #include "../../plugin-macros.generated.h" -json GetDefaultJsonObject(json requestData) +json GetDefaultJsonObject(const json &requestData) { // Always provide an object to prevent exceptions while running checks in requests if (!requestData.is_object()) @@ -11,20 +11,28 @@ json GetDefaultJsonObject(json requestData) return requestData; } -Request::Request(std::string requestType, json requestData, ObsWebSocketRequestBatchExecutionType requestBatchExecutionType) : - HasRequestData(requestData.is_object()), +Request::Request(const std::string &requestType, const json &requestData) : RequestType(requestType), + HasRequestData(requestData.is_object()), + RequestData(GetDefaultJsonObject(requestData)), + RequestBatchExecutionType(OBS_WEBSOCKET_REQUEST_BATCH_EXECUTION_TYPE_NONE) +{ +} + +Request::Request(const std::string &requestType, const json &requestData, const ObsWebSocketRequestBatchExecutionType requestBatchExecutionType) : + RequestType(requestType), + HasRequestData(requestData.is_object()), RequestData(GetDefaultJsonObject(requestData)), RequestBatchExecutionType(requestBatchExecutionType) { } -const bool Request::Contains(const std::string keyName) const +const bool Request::Contains(const std::string &keyName) const { return (RequestData.contains(keyName) && !RequestData[keyName].is_null()); } -const bool Request::ValidateBasic(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const +const bool Request::ValidateBasic(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const { if (!HasRequestData) { statusCode = RequestStatus::MissingRequestData; @@ -41,7 +49,7 @@ const bool Request::ValidateBasic(const std::string keyName, RequestStatus::Requ return true; } -const bool Request::ValidateOptionalNumber(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const double minValue, const double maxValue) const +const bool Request::ValidateOptionalNumber(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const double minValue, const double maxValue) const { if (!RequestData[keyName].is_number()) { statusCode = RequestStatus::InvalidRequestParameterType; @@ -64,7 +72,7 @@ const bool Request::ValidateOptionalNumber(const std::string keyName, RequestSta return true; } -const bool Request::ValidateNumber(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const double minValue, const double maxValue) const +const bool Request::ValidateNumber(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const double minValue, const double maxValue) const { if (!ValidateBasic(keyName, statusCode, comment)) return false; @@ -75,7 +83,7 @@ const bool Request::ValidateNumber(const std::string keyName, RequestStatus::Req return true; } -const bool Request::ValidateOptionalString(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty) const +const bool Request::ValidateOptionalString(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty) const { if (!RequestData[keyName].is_string()) { statusCode = RequestStatus::InvalidRequestParameterType; @@ -92,7 +100,7 @@ const bool Request::ValidateOptionalString(const std::string keyName, RequestSta return true; } -const bool Request::ValidateString(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty) const +const bool Request::ValidateString(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty) const { if (!ValidateBasic(keyName, statusCode, comment)) return false; @@ -103,7 +111,7 @@ const bool Request::ValidateString(const std::string keyName, RequestStatus::Req return true; } -const bool Request::ValidateOptionalBoolean(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const +const bool Request::ValidateOptionalBoolean(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const { if (!RequestData[keyName].is_boolean()) { statusCode = RequestStatus::InvalidRequestParameterType; @@ -114,7 +122,7 @@ const bool Request::ValidateOptionalBoolean(const std::string keyName, RequestSt return true; } -const bool Request::ValidateBoolean(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const +const bool Request::ValidateBoolean(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const { if (!ValidateBasic(keyName, statusCode, comment)) return false; @@ -125,7 +133,7 @@ const bool Request::ValidateBoolean(const std::string keyName, RequestStatus::Re return true; } -const bool Request::ValidateOptionalObject(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty) const +const bool Request::ValidateOptionalObject(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty) const { if (!RequestData[keyName].is_object()) { statusCode = RequestStatus::InvalidRequestParameterType; @@ -142,7 +150,7 @@ const bool Request::ValidateOptionalObject(const std::string keyName, RequestSta return true; } -const bool Request::ValidateObject(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty) const +const bool Request::ValidateObject(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty) const { if (!ValidateBasic(keyName, statusCode, comment)) return false; @@ -153,7 +161,7 @@ const bool Request::ValidateObject(const std::string keyName, RequestStatus::Req return true; } -const bool Request::ValidateOptionalArray(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty) const +const bool Request::ValidateOptionalArray(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty) const { if (!RequestData[keyName].is_array()) { statusCode = RequestStatus::InvalidRequestParameterType; @@ -170,7 +178,7 @@ const bool Request::ValidateOptionalArray(const std::string keyName, RequestStat return true; } -const bool Request::ValidateArray(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty) const +const bool Request::ValidateArray(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty) const { if (!ValidateBasic(keyName, statusCode, comment)) return false; @@ -181,7 +189,7 @@ const bool Request::ValidateArray(const std::string keyName, RequestStatus::Requ return true; } -obs_source_t *Request::ValidateSource(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const +obs_source_t *Request::ValidateSource(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const { if (!ValidateString(keyName, statusCode, comment)) return nullptr; @@ -198,7 +206,7 @@ obs_source_t *Request::ValidateSource(const std::string keyName, RequestStatus:: return ret; } -obs_source_t *Request::ValidateScene(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const ObsWebSocketSceneFilter filter) const +obs_source_t *Request::ValidateScene(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const ObsWebSocketSceneFilter filter) const { obs_source_t *ret = ValidateSource(keyName, statusCode, comment); if (!ret) @@ -227,7 +235,7 @@ obs_source_t *Request::ValidateScene(const std::string keyName, RequestStatus::R return ret; } -obs_source_t *Request::ValidateInput(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const +obs_source_t *Request::ValidateInput(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const { obs_source_t *ret = ValidateSource(keyName, statusCode, comment); if (!ret) @@ -243,7 +251,7 @@ obs_source_t *Request::ValidateInput(const std::string keyName, RequestStatus::R return ret; } -obs_sceneitem_t *Request::ValidateSceneItem(const std::string sceneKeyName, const std::string sceneItemIdKeyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const ObsWebSocketSceneFilter filter) const +obs_sceneitem_t *Request::ValidateSceneItem(const std::string &sceneKeyName, const std::string &sceneItemIdKeyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const ObsWebSocketSceneFilter filter) const { OBSSourceAutoRelease sceneSource = ValidateScene(sceneKeyName, statusCode, comment, filter); if (!sceneSource) diff --git a/src/requesthandler/rpc/Request.h b/src/requesthandler/rpc/Request.h index 417c988e..06d04dbc 100644 --- a/src/requesthandler/rpc/Request.h +++ b/src/requesthandler/rpc/Request.h @@ -4,6 +4,7 @@ #include "../../utils/Json.h" enum ObsWebSocketRequestBatchExecutionType { + OBS_WEBSOCKET_REQUEST_BATCH_EXECUTION_TYPE_NONE, OBS_WEBSOCKET_REQUEST_BATCH_EXECUTION_TYPE_SERIAL_REALTIME, OBS_WEBSOCKET_REQUEST_BATCH_EXECUTION_TYPE_SERIAL_FRAME, OBS_WEBSOCKET_REQUEST_BATCH_EXECUTION_TYPE_PARALLEL @@ -17,31 +18,32 @@ enum ObsWebSocketSceneFilter { struct Request { - Request(const std::string requestType, const json requestData = nullptr, const ObsWebSocketRequestBatchExecutionType requestBatchExecutionType = OBS_WEBSOCKET_REQUEST_BATCH_EXECUTION_TYPE_SERIAL_REALTIME); + Request(const std::string &requestType, const json &requestData = nullptr); + Request(const std::string &requestType, const json &requestData, const ObsWebSocketRequestBatchExecutionType requestBatchExecutionType); // Contains the key and is not null - const bool Contains(const std::string keyName) const; + const bool Contains(const std::string &keyName) const; - const bool ValidateBasic(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const; - const bool ValidateOptionalNumber(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const double minValue = -INFINITY, const double maxValue = INFINITY) const; - const bool ValidateNumber(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const double minValue = -INFINITY, const double maxValue = INFINITY) const; - const bool ValidateOptionalString(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty = false) const; - const bool ValidateString(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty = false) const; - const bool ValidateOptionalBoolean(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const; - const bool ValidateBoolean(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const; - const bool ValidateOptionalObject(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty = false) const; - const bool ValidateObject(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty = false) const; - const bool ValidateOptionalArray(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty = false) const; - const bool ValidateArray(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty = false) const; + const bool ValidateBasic(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const; + const bool ValidateOptionalNumber(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const double minValue = -INFINITY, const double maxValue = INFINITY) const; + const bool ValidateNumber(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const double minValue = -INFINITY, const double maxValue = INFINITY) const; + const bool ValidateOptionalString(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty = false) const; + const bool ValidateString(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty = false) const; + const bool ValidateOptionalBoolean(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const; + const bool ValidateBoolean(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const; + const bool ValidateOptionalObject(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty = false) const; + const bool ValidateObject(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty = false) const; + const bool ValidateOptionalArray(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty = false) const; + const bool ValidateArray(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty = false) const; // All return values have incremented refcounts - obs_source_t *ValidateSource(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const; - obs_source_t *ValidateScene(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const ObsWebSocketSceneFilter filter = OBS_WEBSOCKET_SCENE_FILTER_SCENE_ONLY) const; - obs_source_t *ValidateInput(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const; - obs_sceneitem_t *ValidateSceneItem(const std::string sceneKeyName, const std::string sceneItemIdKeyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const ObsWebSocketSceneFilter filter = OBS_WEBSOCKET_SCENE_FILTER_SCENE_ONLY) const; + obs_source_t *ValidateSource(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const; + obs_source_t *ValidateScene(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const ObsWebSocketSceneFilter filter = OBS_WEBSOCKET_SCENE_FILTER_SCENE_ONLY) const; + obs_source_t *ValidateInput(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const; + obs_sceneitem_t *ValidateSceneItem(const std::string &sceneKeyName, const std::string &sceneItemIdKeyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const ObsWebSocketSceneFilter filter = OBS_WEBSOCKET_SCENE_FILTER_SCENE_ONLY) const; - const bool HasRequestData; const std::string RequestType; - const json RequestData; + bool HasRequestData; + json RequestData; const ObsWebSocketRequestBatchExecutionType RequestBatchExecutionType; };