diff --git a/CMakeLists.txt b/CMakeLists.txt
index 435a4e37..520d4254 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -46,6 +46,10 @@ set(obs-websocket_SOURCES
src/WSEvents.cpp
src/Config.cpp
src/Utils.cpp
+ src/rpc/RpcRequest.cpp
+ src/rpc/RpcResponse.cpp
+ src/rpc/RpcEvent.cpp
+ src/protocol/OBSRemoteProtocol.cpp
src/forms/settings-dialog.cpp)
set(obs-websocket_HEADERS
@@ -56,6 +60,10 @@ set(obs-websocket_HEADERS
src/WSEvents.h
src/Config.h
src/Utils.h
+ src/rpc/RpcRequest.h
+ src/rpc/RpcResponse.h
+ src/rpc/RpcEvent.h
+ src/protocol/OBSRemoteProtocol.h
src/forms/settings-dialog.h)
# --- Platform-independent build settings ---
@@ -174,8 +182,8 @@ if(UNIX AND NOT APPLE)
install(TARGETS obs-websocket
LIBRARY DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/obs-plugins")
# Dirty fix for Ubuntu
- install(TARGETS obs-websocket
- LIBRARY DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/${UNAME_MACHINE}-linux-gnu/obs-plugins")
+ install(TARGETS obs-websocket
+ LIBRARY DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/${UNAME_MACHINE}-linux-gnu/obs-plugins")
install(FILES ${locale_files}
DESTINATION "${CMAKE_INSTALL_PREFIX}/share/obs/obs-plugins/obs-websocket/locale")
diff --git a/src/Utils.cpp b/src/Utils.cpp
index b1b08d5c..cb381d0f 100644
--- a/src/Utils.cpp
+++ b/src/Utils.cpp
@@ -16,6 +16,7 @@ You should have received a copy of the GNU General Public License along
with this program. If not, see
*/
+#include
#include
#include
#include
@@ -822,3 +823,17 @@ void Utils::PauseRecording(bool pause)
pauseRecording(pause);
}
+
+QString Utils::nsToTimestamp(uint64_t ns)
+{
+ uint64_t ms = ns / 1000000ULL;
+ uint64_t secs = ms / 1000ULL;
+ uint64_t minutes = secs / 60ULL;
+
+ uint64_t hoursPart = minutes / 60ULL;
+ uint64_t minutesPart = minutes % 60ULL;
+ uint64_t secsPart = secs % 60ULL;
+ uint64_t msPart = ms % 1000ULL;
+
+ return QString::asprintf("%02" PRIu64 ":%02" PRIu64 ":%02" PRIu64 ".%03" PRIu64, hoursPart, minutesPart, secsPart, msPart);
+}
diff --git a/src/Utils.h b/src/Utils.h
index 89f01acc..bdd5da20 100644
--- a/src/Utils.h
+++ b/src/Utils.h
@@ -86,4 +86,6 @@ class Utils {
static bool RecordingPauseSupported();
static bool RecordingPaused();
static void PauseRecording(bool pause);
+
+ static QString nsToTimestamp(uint64_t ns);
};
diff --git a/src/WSEvents.cpp b/src/WSEvents.cpp
index d7d04055..4c48e683 100644
--- a/src/WSEvents.cpp
+++ b/src/WSEvents.cpp
@@ -23,27 +23,15 @@
#include
-#include "Config.h"
-#include "Utils.h"
#include "WSEvents.h"
#include "obs-websocket.h"
+#include "Config.h"
+#include "Utils.h"
+#include "rpc/RpcEvent.h"
#define STATUS_INTERVAL 2000
-QString nsToTimestamp(uint64_t ns) {
- uint64_t ms = ns / 1000000ULL;
- uint64_t secs = ms / 1000ULL;
- uint64_t minutes = secs / 60ULL;
-
- uint64_t hoursPart = minutes / 60ULL;
- uint64_t minutesPart = minutes % 60ULL;
- uint64_t secsPart = secs % 60ULL;
- uint64_t msPart = ms % 1000ULL;
-
- return QString::asprintf("%02" PRIu64 ":%02" PRIu64 ":%02" PRIu64 ".%03" PRIu64, hoursPart, minutesPart, secsPart, msPart);
-}
-
const char* sourceTypeToString(obs_source_type type) {
switch (type) {
case OBS_SOURCE_TYPE_INPUT:
@@ -252,28 +240,11 @@ void WSEvents::FrontendEventHandler(enum obs_frontend_event event, void* private
void WSEvents::broadcastUpdate(const char* updateType,
obs_data_t* additionalFields = nullptr)
{
- OBSDataAutoRelease update = obs_data_create();
- obs_data_set_string(update, "update-type", updateType);
+ uint64_t streamTime = getStreamingTime();
+ uint64_t recordingTime = getStreamingTime();
+ RpcEvent event(QString(updateType), streamTime, recordingTime, additionalFields);
- if (obs_frontend_streaming_active()) {
- QString streamingTimecode = getStreamingTimecode();
- obs_data_set_string(update, "stream-timecode", streamingTimecode.toUtf8().constData());
- }
-
- if (obs_frontend_recording_active()) {
- QString recordingTimecode = getRecordingTimecode();
- obs_data_set_string(update, "rec-timecode", recordingTimecode.toUtf8().constData());
- }
-
- if (additionalFields)
- obs_data_apply(update, additionalFields);
-
- QString json = obs_data_get_json(update);
- _srv->broadcast(json.toStdString());
-
- if (GetConfig()->DebugEnabled) {
- blog(LOG_INFO, "Update << '%s'", json.toUtf8().constData());
- }
+ _srv->broadcast(event);
}
void WSEvents::connectSourceSignals(obs_source_t* source) {
@@ -410,11 +381,11 @@ uint64_t WSEvents::getRecordingTime() {
}
QString WSEvents::getStreamingTimecode() {
- return nsToTimestamp(getStreamingTime());
+ return Utils::nsToTimestamp(getStreamingTime());
}
QString WSEvents::getRecordingTimecode() {
- return nsToTimestamp(getRecordingTime());
+ return Utils::nsToTimestamp(getRecordingTime());
}
/**
diff --git a/src/WSRequestHandler.cpp b/src/WSRequestHandler.cpp
index 8b31c0b7..0f10fad6 100644
--- a/src/WSRequestHandler.cpp
+++ b/src/WSRequestHandler.cpp
@@ -17,6 +17,8 @@
* with this program. If not, see
*/
+#include
+
#include
#include "Config.h"
@@ -24,265 +26,148 @@
#include "WSRequestHandler.h"
-QHash WSRequestHandler::messageMap{
- { "GetVersion", WSRequestHandler::HandleGetVersion },
- { "GetAuthRequired", WSRequestHandler::HandleGetAuthRequired },
- { "Authenticate", WSRequestHandler::HandleAuthenticate },
+using namespace std::placeholders;
- { "GetStats", WSRequestHandler::HandleGetStats },
- { "SetHeartbeat", WSRequestHandler::HandleSetHeartbeat },
- { "GetVideoInfo", WSRequestHandler::HandleGetVideoInfo },
+const QHash WSRequestHandler::messageMap {
+ { "GetVersion", &WSRequestHandler::GetVersion },
+ { "GetAuthRequired", &WSRequestHandler::GetAuthRequired },
+ { "Authenticate", &WSRequestHandler::Authenticate },
- { "SetFilenameFormatting", WSRequestHandler::HandleSetFilenameFormatting },
- { "GetFilenameFormatting", WSRequestHandler::HandleGetFilenameFormatting },
+ { "GetStats", &WSRequestHandler::GetStats },
+ { "SetHeartbeat", &WSRequestHandler::SetHeartbeat },
+ { "GetVideoInfo", &WSRequestHandler::GetVideoInfo },
- { "BroadcastCustomMessage", WSRequestHandler::HandleBroadcastCustomMessage },
+ { "SetFilenameFormatting", &WSRequestHandler::SetFilenameFormatting },
+ { "GetFilenameFormatting", &WSRequestHandler::GetFilenameFormatting },
- { "SetCurrentScene", WSRequestHandler::HandleSetCurrentScene },
- { "GetCurrentScene", WSRequestHandler::HandleGetCurrentScene },
- { "GetSceneList", WSRequestHandler::HandleGetSceneList },
+ { "BroadcastCustomMessage", &WSRequestHandler::BroadcastCustomMessage },
- { "SetSourceRender", WSRequestHandler::HandleSetSceneItemRender }, // Retrocompat
- { "SetSceneItemRender", WSRequestHandler::HandleSetSceneItemRender },
- { "SetSceneItemPosition", WSRequestHandler::HandleSetSceneItemPosition },
- { "SetSceneItemTransform", WSRequestHandler::HandleSetSceneItemTransform },
- { "SetSceneItemCrop", WSRequestHandler::HandleSetSceneItemCrop },
- { "GetSceneItemProperties", WSRequestHandler::HandleGetSceneItemProperties },
- { "SetSceneItemProperties", WSRequestHandler::HandleSetSceneItemProperties },
- { "ResetSceneItem", WSRequestHandler::HandleResetSceneItem },
- { "DeleteSceneItem", WSRequestHandler::HandleDeleteSceneItem },
- { "DuplicateSceneItem", WSRequestHandler::HandleDuplicateSceneItem },
- { "ReorderSceneItems", WSRequestHandler::HandleReorderSceneItems },
+ { "SetCurrentScene", &WSRequestHandler::SetCurrentScene },
+ { "GetCurrentScene", &WSRequestHandler::GetCurrentScene },
+ { "GetSceneList", &WSRequestHandler::GetSceneList },
- { "GetStreamingStatus", WSRequestHandler::HandleGetStreamingStatus },
- { "StartStopStreaming", WSRequestHandler::HandleStartStopStreaming },
- { "StartStopRecording", WSRequestHandler::HandleStartStopRecording },
+ { "SetSourceRender", &WSRequestHandler::SetSceneItemRender }, // Retrocompat
+ { "SetSceneItemRender", &WSRequestHandler::SetSceneItemRender },
+ { "SetSceneItemPosition", &WSRequestHandler::SetSceneItemPosition },
+ { "SetSceneItemTransform", &WSRequestHandler::SetSceneItemTransform },
+ { "SetSceneItemCrop", &WSRequestHandler::SetSceneItemCrop },
+ { "GetSceneItemProperties", &WSRequestHandler::GetSceneItemProperties },
+ { "SetSceneItemProperties", &WSRequestHandler::SetSceneItemProperties },
+ { "ResetSceneItem", &WSRequestHandler::ResetSceneItem },
+ { "DeleteSceneItem", &WSRequestHandler::DeleteSceneItem },
+ { "DuplicateSceneItem", &WSRequestHandler::DuplicateSceneItem },
+ { "ReorderSceneItems", &WSRequestHandler::ReorderSceneItems },
- { "StartStreaming", WSRequestHandler::HandleStartStreaming },
- { "StopStreaming", WSRequestHandler::HandleStopStreaming },
+ { "GetStreamingStatus", &WSRequestHandler::GetStreamingStatus },
+ { "StartStopStreaming", &WSRequestHandler::StartStopStreaming },
+ { "StartStopRecording", &WSRequestHandler::StartStopRecording },
- { "StartRecording", WSRequestHandler::HandleStartRecording },
- { "StopRecording", WSRequestHandler::HandleStopRecording },
- { "PauseRecording", WSRequestHandler::HandlePauseRecording },
- { "ResumeRecording", WSRequestHandler::HandleResumeRecording },
+ { "StartStreaming", &WSRequestHandler::StartStreaming },
+ { "StopStreaming", &WSRequestHandler::StopStreaming },
- { "StartStopReplayBuffer", WSRequestHandler::HandleStartStopReplayBuffer },
- { "StartReplayBuffer", WSRequestHandler::HandleStartReplayBuffer },
- { "StopReplayBuffer", WSRequestHandler::HandleStopReplayBuffer },
- { "SaveReplayBuffer", WSRequestHandler::HandleSaveReplayBuffer },
+ { "StartRecording", &WSRequestHandler::StartRecording },
+ { "StopRecording", &WSRequestHandler::StopRecording },
+ { "PauseRecording", &WSRequestHandler::PauseRecording },
+ { "ResumeRecording", &WSRequestHandler::ResumeRecording },
- { "SetRecordingFolder", WSRequestHandler::HandleSetRecordingFolder },
- { "GetRecordingFolder", WSRequestHandler::HandleGetRecordingFolder },
+ { "StartStopReplayBuffer", &WSRequestHandler::StartStopReplayBuffer },
+ { "StartReplayBuffer", &WSRequestHandler::StartReplayBuffer },
+ { "StopReplayBuffer", &WSRequestHandler::StopReplayBuffer },
+ { "SaveReplayBuffer", &WSRequestHandler::SaveReplayBuffer },
- { "GetTransitionList", WSRequestHandler::HandleGetTransitionList },
- { "GetCurrentTransition", WSRequestHandler::HandleGetCurrentTransition },
- { "SetCurrentTransition", WSRequestHandler::HandleSetCurrentTransition },
- { "SetTransitionDuration", WSRequestHandler::HandleSetTransitionDuration },
- { "GetTransitionDuration", WSRequestHandler::HandleGetTransitionDuration },
+ { "SetRecordingFolder", &WSRequestHandler::SetRecordingFolder },
+ { "GetRecordingFolder", &WSRequestHandler::GetRecordingFolder },
- { "SetVolume", WSRequestHandler::HandleSetVolume },
- { "GetVolume", WSRequestHandler::HandleGetVolume },
- { "ToggleMute", WSRequestHandler::HandleToggleMute },
- { "SetMute", WSRequestHandler::HandleSetMute },
- { "GetMute", WSRequestHandler::HandleGetMute },
- { "SetSyncOffset", WSRequestHandler::HandleSetSyncOffset },
- { "GetSyncOffset", WSRequestHandler::HandleGetSyncOffset },
- { "GetSpecialSources", WSRequestHandler::HandleGetSpecialSources },
- { "GetSourcesList", WSRequestHandler::HandleGetSourcesList },
- { "GetSourceTypesList", WSRequestHandler::HandleGetSourceTypesList },
- { "GetSourceSettings", WSRequestHandler::HandleGetSourceSettings },
- { "SetSourceSettings", WSRequestHandler::HandleSetSourceSettings },
- { "TakeSourceScreenshot", WSRequestHandler::HandleTakeSourceScreenshot },
+ { "GetTransitionList", &WSRequestHandler::GetTransitionList },
+ { "GetCurrentTransition", &WSRequestHandler::GetCurrentTransition },
+ { "SetCurrentTransition", &WSRequestHandler::SetCurrentTransition },
+ { "SetTransitionDuration", &WSRequestHandler::SetTransitionDuration },
+ { "GetTransitionDuration", &WSRequestHandler::GetTransitionDuration },
- { "GetSourceFilters", WSRequestHandler::HandleGetSourceFilters },
- { "GetSourceFilterInfo", WSRequestHandler::HandleGetSourceFilterInfo },
- { "AddFilterToSource", WSRequestHandler::HandleAddFilterToSource },
- { "RemoveFilterFromSource", WSRequestHandler::HandleRemoveFilterFromSource },
- { "ReorderSourceFilter", WSRequestHandler::HandleReorderSourceFilter },
- { "MoveSourceFilter", WSRequestHandler::HandleMoveSourceFilter },
- { "SetSourceFilterSettings", WSRequestHandler::HandleSetSourceFilterSettings },
- { "SetSourceFilterVisibility", WSRequestHandler::HandleSetSourceFilterVisibility },
+ { "SetVolume", &WSRequestHandler::SetVolume },
+ { "GetVolume", &WSRequestHandler::GetVolume },
+ { "ToggleMute", &WSRequestHandler::ToggleMute },
+ { "SetMute", &WSRequestHandler::SetMute },
+ { "GetMute", &WSRequestHandler::GetMute },
+ { "SetSyncOffset", &WSRequestHandler::SetSyncOffset },
+ { "GetSyncOffset", &WSRequestHandler::GetSyncOffset },
+ { "GetSpecialSources", &WSRequestHandler::GetSpecialSources },
+ { "GetSourcesList", &WSRequestHandler::GetSourcesList },
+ { "GetSourceTypesList", &WSRequestHandler::GetSourceTypesList },
+ { "GetSourceSettings", &WSRequestHandler::GetSourceSettings },
+ { "SetSourceSettings", &WSRequestHandler::SetSourceSettings },
+ { "TakeSourceScreenshot", &WSRequestHandler::TakeSourceScreenshot },
- { "SetCurrentSceneCollection", WSRequestHandler::HandleSetCurrentSceneCollection },
- { "GetCurrentSceneCollection", WSRequestHandler::HandleGetCurrentSceneCollection },
- { "ListSceneCollections", WSRequestHandler::HandleListSceneCollections },
+ { "GetSourceFilters", &WSRequestHandler::GetSourceFilters },
+ { "GetSourceFilterInfo", &WSRequestHandler::GetSourceFilterInfo },
+ { "AddFilterToSource", &WSRequestHandler::AddFilterToSource },
+ { "RemoveFilterFromSource", &WSRequestHandler::RemoveFilterFromSource },
+ { "ReorderSourceFilter", &WSRequestHandler::ReorderSourceFilter },
+ { "MoveSourceFilter", &WSRequestHandler::MoveSourceFilter },
+ { "SetSourceFilterSettings", &WSRequestHandler::SetSourceFilterSettings },
+ { "SetSourceFilterVisibility", &WSRequestHandler::SetSourceFilterVisibility },
- { "SetCurrentProfile", WSRequestHandler::HandleSetCurrentProfile },
- { "GetCurrentProfile", WSRequestHandler::HandleGetCurrentProfile },
- { "ListProfiles", WSRequestHandler::HandleListProfiles },
+ { "SetCurrentSceneCollection", &WSRequestHandler::SetCurrentSceneCollection },
+ { "GetCurrentSceneCollection", &WSRequestHandler::GetCurrentSceneCollection },
+ { "ListSceneCollections", &WSRequestHandler::ListSceneCollections },
- { "SetStreamSettings", WSRequestHandler::HandleSetStreamSettings },
- { "GetStreamSettings", WSRequestHandler::HandleGetStreamSettings },
- { "SaveStreamSettings", WSRequestHandler::HandleSaveStreamSettings },
+ { "SetCurrentProfile", &WSRequestHandler::SetCurrentProfile },
+ { "GetCurrentProfile", &WSRequestHandler::GetCurrentProfile },
+ { "ListProfiles", &WSRequestHandler::ListProfiles },
+
+ { "SetStreamSettings", &WSRequestHandler::SetStreamSettings },
+ { "GetStreamSettings", &WSRequestHandler::GetStreamSettings },
+ { "SaveStreamSettings", &WSRequestHandler::SaveStreamSettings },
#if BUILD_CAPTIONS
- { "SendCaptions", WSRequestHandler::HandleSendCaptions },
+ { "SendCaptions", &WSRequestHandler::SendCaptions },
#endif
- { "GetStudioModeStatus", WSRequestHandler::HandleGetStudioModeStatus },
- { "GetPreviewScene", WSRequestHandler::HandleGetPreviewScene },
- { "SetPreviewScene", WSRequestHandler::HandleSetPreviewScene },
- { "TransitionToProgram", WSRequestHandler::HandleTransitionToProgram },
- { "EnableStudioMode", WSRequestHandler::HandleEnableStudioMode },
- { "DisableStudioMode", WSRequestHandler::HandleDisableStudioMode },
- { "ToggleStudioMode", WSRequestHandler::HandleToggleStudioMode },
+ { "GetStudioModeStatus", &WSRequestHandler::GetStudioModeStatus },
+ { "GetPreviewScene", &WSRequestHandler::GetPreviewScene },
+ { "SetPreviewScene", &WSRequestHandler::SetPreviewScene },
+ { "TransitionToProgram", &WSRequestHandler::TransitionToProgram },
+ { "EnableStudioMode", &WSRequestHandler::EnableStudioMode },
+ { "DisableStudioMode", &WSRequestHandler::DisableStudioMode },
+ { "ToggleStudioMode", &WSRequestHandler::ToggleStudioMode },
- { "SetTextGDIPlusProperties", WSRequestHandler::HandleSetTextGDIPlusProperties },
- { "GetTextGDIPlusProperties", WSRequestHandler::HandleGetTextGDIPlusProperties },
+ { "SetTextGDIPlusProperties", &WSRequestHandler::SetTextGDIPlusProperties },
+ { "GetTextGDIPlusProperties", &WSRequestHandler::GetTextGDIPlusProperties },
- { "SetTextFreetype2Properties", WSRequestHandler::HandleSetTextFreetype2Properties },
- { "GetTextFreetype2Properties", WSRequestHandler::HandleGetTextFreetype2Properties },
+ { "SetTextFreetype2Properties", &WSRequestHandler::SetTextFreetype2Properties },
+ { "GetTextFreetype2Properties", &WSRequestHandler::GetTextFreetype2Properties },
- { "GetBrowserSourceProperties", WSRequestHandler::HandleGetBrowserSourceProperties },
- { "SetBrowserSourceProperties", WSRequestHandler::HandleSetBrowserSourceProperties },
+ { "GetBrowserSourceProperties", &WSRequestHandler::GetBrowserSourceProperties },
+ { "SetBrowserSourceProperties", &WSRequestHandler::SetBrowserSourceProperties },
- { "ListOutputs", WSRequestHandler::HandleListOutputs },
- { "GetOutputInfo", WSRequestHandler::HandleGetOutputInfo },
- { "StartOutput", WSRequestHandler::HandleStartOutput },
- { "StopOutput", WSRequestHandler::HandleStopOutput }
+ { "ListOutputs", &WSRequestHandler::ListOutputs },
+ { "GetOutputInfo", &WSRequestHandler::GetOutputInfo },
+ { "StartOutput", &WSRequestHandler::StartOutput },
+ { "StopOutput", &WSRequestHandler::StopOutput }
};
-QSet WSRequestHandler::authNotRequired {
+const QSet WSRequestHandler::authNotRequired {
"GetVersion",
"GetAuthRequired",
"Authenticate"
};
WSRequestHandler::WSRequestHandler(ConnectionProperties& connProperties) :
- _messageId(0),
- _requestType(""),
- data(nullptr),
_connProperties(connProperties)
{
}
-std::string WSRequestHandler::processIncomingMessage(std::string& textMessage) {
- if (GetConfig()->DebugEnabled) {
- blog(LOG_INFO, "Request >> '%s'", textMessage.c_str());
- }
-
- OBSDataAutoRelease responseData = processRequest(textMessage);
- std::string response = obs_data_get_json(responseData);
-
- if (GetConfig()->DebugEnabled) {
- blog(LOG_INFO, "Response << '%s'", response.c_str());
- }
-
- return response;
-}
-
-HandlerResponse WSRequestHandler::processRequest(std::string& textMessage){
- std::string msgContainer(textMessage);
- const char* msg = msgContainer.c_str();
-
- data = obs_data_create_from_json(msg);
- if (!data) {
- blog(LOG_ERROR, "invalid JSON payload received for '%s'", msg);
- return SendErrorResponse("invalid JSON payload");
- }
-
- if (!hasField("request-type") || !hasField("message-id")) {
- return SendErrorResponse("missing request parameters");
- }
-
- _requestType = obs_data_get_string(data, "request-type");
- _messageId = obs_data_get_string(data, "message-id");
-
+RpcResponse WSRequestHandler::processRequest(const RpcRequest& request){
if (GetConfig()->AuthRequired
- && (!authNotRequired.contains(_requestType))
+ && (!authNotRequired.contains(request.methodName()))
&& (!_connProperties.isAuthenticated()))
{
- return SendErrorResponse("Not Authenticated");
+ return RpcResponse::fail(request, "Not Authenticated");
}
- HandlerResponse (*handlerFunc)(WSRequestHandler*) = (messageMap[_requestType]);
+ RpcMethodHandler handlerFunc = messageMap[request.methodName()];
if (!handlerFunc) {
- return SendErrorResponse("invalid request type");
+ return RpcResponse::fail(request, "invalid request type");
}
- return handlerFunc(this);
-}
-
-WSRequestHandler::~WSRequestHandler() {
-}
-
-HandlerResponse WSRequestHandler::SendOKResponse(obs_data_t* additionalFields) {
- return SendResponse("ok", additionalFields);
-}
-
-HandlerResponse WSRequestHandler::SendErrorResponse(QString errorMessage) {
- OBSDataAutoRelease fields = obs_data_create();
- obs_data_set_string(fields, "error", errorMessage.toUtf8().constData());
-
- return SendResponse("error", fields);
-}
-
-HandlerResponse WSRequestHandler::SendErrorResponse(obs_data_t* additionalFields) {
- return SendResponse("error", additionalFields);
-}
-
-HandlerResponse WSRequestHandler::SendResponse(const char* status, obs_data_t* fields) {
- obs_data_t* response = obs_data_create();
- obs_data_set_string(response, "message-id", _messageId);
- obs_data_set_string(response, "status", status);
-
- if (fields) {
- obs_data_apply(response, fields);
- }
-
- return response;
-}
-
-bool WSRequestHandler::hasField(QString name, obs_data_type expectedFieldType, obs_data_number_type expectedNumberType) {
- if (!data || name.isEmpty() || name.isNull()) {
- return false;
- }
-
- OBSDataItemAutoRelease dataItem = obs_data_item_byname(data, name.toUtf8());
- if (!dataItem) {
- return false;
- }
-
- if (expectedFieldType != OBS_DATA_NULL) {
- obs_data_type fieldType = obs_data_item_gettype(dataItem);
- if (fieldType != expectedFieldType) {
- return false;
- }
-
- if (fieldType == OBS_DATA_NUMBER && expectedNumberType != OBS_DATA_NUM_INVALID) {
- obs_data_number_type numberType = obs_data_item_numtype(dataItem);
- if (numberType != expectedNumberType) {
- return false;
- }
- }
- }
-
- return true;
-}
-
-bool WSRequestHandler::hasBool(QString fieldName) {
- return this->hasField(fieldName, OBS_DATA_BOOLEAN);
-}
-
-bool WSRequestHandler::hasString(QString fieldName) {
- return this->hasField(fieldName, OBS_DATA_STRING);
-}
-
-bool WSRequestHandler::hasNumber(QString fieldName, obs_data_number_type expectedNumberType) {
- return this->hasField(fieldName, OBS_DATA_NUMBER, expectedNumberType);
-}
-
-bool WSRequestHandler::hasInteger(QString fieldName) {
- return this->hasNumber(fieldName, OBS_DATA_NUM_INT);
-}
-
-bool WSRequestHandler::hasDouble(QString fieldName) {
- return this->hasNumber(fieldName, OBS_DATA_NUM_DOUBLE);
-}
-
-bool WSRequestHandler::hasArray(QString fieldName) {
- return this->hasField(fieldName, OBS_DATA_ARRAY);
-}
-
-bool WSRequestHandler::hasObject(QString fieldName) {
- return this->hasField(fieldName, OBS_DATA_OBJECT);
+ return std::bind(handlerFunc, this, _1)(request);
}
diff --git a/src/WSRequestHandler.h b/src/WSRequestHandler.h
index 0e729e55..da93330b 100644
--- a/src/WSRequestHandler.h
+++ b/src/WSRequestHandler.h
@@ -19,171 +19,146 @@ with this program. If not, see
#pragma once
+#include
#include
#include
-#include
-#include
-#include
#include
#include
#include "ConnectionProperties.h"
+#include "rpc/RpcRequest.h"
+#include "rpc/RpcResponse.h"
+
#include "obs-websocket.h"
-typedef obs_data_t* HandlerResponse;
-
-class WSRequestHandler : public QObject {
- Q_OBJECT
+class WSRequestHandler;
+typedef RpcResponse(WSRequestHandler::*RpcMethodHandler)(const RpcRequest&);
+class WSRequestHandler {
public:
explicit WSRequestHandler(ConnectionProperties& connProperties);
- ~WSRequestHandler();
- std::string processIncomingMessage(std::string& textMessage);
-
- bool hasField(QString fieldName, obs_data_type expectedFieldType = OBS_DATA_NULL,
- obs_data_number_type expectedNumberType = OBS_DATA_NUM_INVALID);
- bool hasBool(QString fieldName);
- bool hasString(QString fieldName);
- bool hasNumber(QString fieldName, obs_data_number_type expectedNumberType = OBS_DATA_NUM_INVALID);
- bool hasInteger(QString fieldName);
- bool hasDouble(QString fieldName);
- bool hasArray(QString fieldName);
- bool hasObject(QString fieldName);
-
- HandlerResponse SendOKResponse(obs_data_t* additionalFields = nullptr);
- HandlerResponse SendErrorResponse(QString errorMessage);
- HandlerResponse SendErrorResponse(obs_data_t* additionalFields = nullptr);
- HandlerResponse SendResponse(const char* status, obs_data_t* additionalFields = nullptr);
-
- obs_data_t* parameters() {
- return this->data;
- }
+ RpcResponse processRequest(const RpcRequest& textMessage);
private:
- const char* _messageId;
- const char* _requestType;
ConnectionProperties& _connProperties;
- OBSDataAutoRelease data;
- HandlerResponse processRequest(std::string& textMessage);
+ static const QHash messageMap;
+ static const QSet authNotRequired;
- static QHash messageMap;
- static QSet authNotRequired;
+ RpcResponse GetVersion(const RpcRequest&);
+ RpcResponse GetAuthRequired(const RpcRequest&);
+ RpcResponse Authenticate(const RpcRequest&);
- static HandlerResponse HandleGetVersion(WSRequestHandler* req);
- static HandlerResponse HandleGetAuthRequired(WSRequestHandler* req);
- static HandlerResponse HandleAuthenticate(WSRequestHandler* req);
+ RpcResponse GetStats(const RpcRequest&);
+ RpcResponse SetHeartbeat(const RpcRequest&);
+ RpcResponse GetVideoInfo(const RpcRequest&);
- static HandlerResponse HandleGetStats(WSRequestHandler* req);
- static HandlerResponse HandleSetHeartbeat(WSRequestHandler* req);
- static HandlerResponse HandleGetVideoInfo(WSRequestHandler* req);
+ RpcResponse SetFilenameFormatting(const RpcRequest&);
+ RpcResponse GetFilenameFormatting(const RpcRequest&);
- static HandlerResponse HandleSetFilenameFormatting(WSRequestHandler* req);
- static HandlerResponse HandleGetFilenameFormatting(WSRequestHandler* req);
+ RpcResponse BroadcastCustomMessage(const RpcRequest&);
- static HandlerResponse HandleBroadcastCustomMessage(WSRequestHandler* req);
+ RpcResponse SetCurrentScene(const RpcRequest&);
+ RpcResponse GetCurrentScene(const RpcRequest&);
+ RpcResponse GetSceneList(const RpcRequest&);
- static HandlerResponse HandleSetCurrentScene(WSRequestHandler* req);
- static HandlerResponse HandleGetCurrentScene(WSRequestHandler* req);
- static HandlerResponse HandleGetSceneList(WSRequestHandler* req);
+ RpcResponse SetSceneItemRender(const RpcRequest&);
+ RpcResponse SetSceneItemPosition(const RpcRequest&);
+ RpcResponse SetSceneItemTransform(const RpcRequest&);
+ RpcResponse SetSceneItemCrop(const RpcRequest&);
+ RpcResponse GetSceneItemProperties(const RpcRequest&);
+ RpcResponse SetSceneItemProperties(const RpcRequest&);
+ RpcResponse ResetSceneItem(const RpcRequest&);
+ RpcResponse DuplicateSceneItem(const RpcRequest&);
+ RpcResponse DeleteSceneItem(const RpcRequest&);
+ RpcResponse ReorderSceneItems(const RpcRequest&);
- static HandlerResponse HandleSetSceneItemRender(WSRequestHandler* req);
- static HandlerResponse HandleSetSceneItemPosition(WSRequestHandler* req);
- static HandlerResponse HandleSetSceneItemTransform(WSRequestHandler* req);
- static HandlerResponse HandleSetSceneItemCrop(WSRequestHandler* req);
- static HandlerResponse HandleGetSceneItemProperties(WSRequestHandler* req);
- static HandlerResponse HandleSetSceneItemProperties(WSRequestHandler* req);
- static HandlerResponse HandleResetSceneItem(WSRequestHandler* req);
- static HandlerResponse HandleDuplicateSceneItem(WSRequestHandler* req);
- static HandlerResponse HandleDeleteSceneItem(WSRequestHandler* req);
- static HandlerResponse HandleReorderSceneItems(WSRequestHandler* req);
+ RpcResponse GetStreamingStatus(const RpcRequest&);
+ RpcResponse StartStopStreaming(const RpcRequest&);
+ RpcResponse StartStopRecording(const RpcRequest&);
- static HandlerResponse HandleGetStreamingStatus(WSRequestHandler* req);
- static HandlerResponse HandleStartStopStreaming(WSRequestHandler* req);
- static HandlerResponse HandleStartStopRecording(WSRequestHandler* req);
+ RpcResponse StartStreaming(const RpcRequest&);
+ RpcResponse StopStreaming(const RpcRequest&);
- static HandlerResponse HandleStartStreaming(WSRequestHandler* req);
- static HandlerResponse HandleStopStreaming(WSRequestHandler* req);
+ RpcResponse StartRecording(const RpcRequest&);
+ RpcResponse StopRecording(const RpcRequest&);
+ RpcResponse PauseRecording(const RpcRequest&);
+ RpcResponse ResumeRecording(const RpcRequest&);
- static HandlerResponse HandleStartRecording(WSRequestHandler* req);
- static HandlerResponse HandleStopRecording(WSRequestHandler* req);
- static HandlerResponse HandlePauseRecording(WSRequestHandler* req);
- static HandlerResponse HandleResumeRecording(WSRequestHandler* req);
+ RpcResponse StartStopReplayBuffer(const RpcRequest&);
+ RpcResponse StartReplayBuffer(const RpcRequest&);
+ RpcResponse StopReplayBuffer(const RpcRequest&);
+ RpcResponse SaveReplayBuffer(const RpcRequest&);
- static HandlerResponse HandleStartStopReplayBuffer(WSRequestHandler* req);
- static HandlerResponse HandleStartReplayBuffer(WSRequestHandler* req);
- static HandlerResponse HandleStopReplayBuffer(WSRequestHandler* req);
- static HandlerResponse HandleSaveReplayBuffer(WSRequestHandler* req);
+ RpcResponse SetRecordingFolder(const RpcRequest&);
+ RpcResponse GetRecordingFolder(const RpcRequest&);
- static HandlerResponse HandleSetRecordingFolder(WSRequestHandler* req);
- static HandlerResponse HandleGetRecordingFolder(WSRequestHandler* req);
+ RpcResponse GetTransitionList(const RpcRequest&);
+ RpcResponse GetCurrentTransition(const RpcRequest&);
+ RpcResponse SetCurrentTransition(const RpcRequest&);
- static HandlerResponse HandleGetTransitionList(WSRequestHandler* req);
- static HandlerResponse HandleGetCurrentTransition(WSRequestHandler* req);
- static HandlerResponse HandleSetCurrentTransition(WSRequestHandler* req);
+ RpcResponse SetVolume(const RpcRequest&);
+ RpcResponse GetVolume(const RpcRequest&);
+ RpcResponse ToggleMute(const RpcRequest&);
+ RpcResponse SetMute(const RpcRequest&);
+ RpcResponse GetMute(const RpcRequest&);
+ RpcResponse SetSyncOffset(const RpcRequest&);
+ RpcResponse GetSyncOffset(const RpcRequest&);
+ RpcResponse GetSpecialSources(const RpcRequest&);
+ RpcResponse GetSourcesList(const RpcRequest&);
+ RpcResponse GetSourceTypesList(const RpcRequest&);
+ RpcResponse GetSourceSettings(const RpcRequest&);
+ RpcResponse SetSourceSettings(const RpcRequest&);
+ RpcResponse TakeSourceScreenshot(const RpcRequest&);
- static HandlerResponse HandleSetVolume(WSRequestHandler* req);
- static HandlerResponse HandleGetVolume(WSRequestHandler* req);
- static HandlerResponse HandleToggleMute(WSRequestHandler* req);
- static HandlerResponse HandleSetMute(WSRequestHandler* req);
- static HandlerResponse HandleGetMute(WSRequestHandler* req);
- static HandlerResponse HandleSetSyncOffset(WSRequestHandler* req);
- static HandlerResponse HandleGetSyncOffset(WSRequestHandler* req);
- static HandlerResponse HandleGetSpecialSources(WSRequestHandler* req);
- static HandlerResponse HandleGetSourcesList(WSRequestHandler* req);
- static HandlerResponse HandleGetSourceTypesList(WSRequestHandler* req);
- static HandlerResponse HandleGetSourceSettings(WSRequestHandler* req);
- static HandlerResponse HandleSetSourceSettings(WSRequestHandler* req);
- static HandlerResponse HandleTakeSourceScreenshot(WSRequestHandler* req);
+ RpcResponse GetSourceFilters(const RpcRequest&);
+ RpcResponse GetSourceFilterInfo(const RpcRequest&);
+ RpcResponse AddFilterToSource(const RpcRequest&);
+ RpcResponse RemoveFilterFromSource(const RpcRequest&);
+ RpcResponse ReorderSourceFilter(const RpcRequest&);
+ RpcResponse MoveSourceFilter(const RpcRequest&);
+ RpcResponse SetSourceFilterSettings(const RpcRequest&);
+ RpcResponse SetSourceFilterVisibility(const RpcRequest&);
- static HandlerResponse HandleGetSourceFilters(WSRequestHandler* req);
- static HandlerResponse HandleGetSourceFilterInfo(WSRequestHandler* req);
- static HandlerResponse HandleAddFilterToSource(WSRequestHandler* req);
- static HandlerResponse HandleRemoveFilterFromSource(WSRequestHandler* req);
- static HandlerResponse HandleReorderSourceFilter(WSRequestHandler* req);
- static HandlerResponse HandleMoveSourceFilter(WSRequestHandler* req);
- static HandlerResponse HandleSetSourceFilterSettings(WSRequestHandler* req);
- static HandlerResponse HandleSetSourceFilterVisibility(WSRequestHandler* req);
+ RpcResponse SetCurrentSceneCollection(const RpcRequest&);
+ RpcResponse GetCurrentSceneCollection(const RpcRequest&);
+ RpcResponse ListSceneCollections(const RpcRequest&);
- static HandlerResponse HandleSetCurrentSceneCollection(WSRequestHandler* req);
- static HandlerResponse HandleGetCurrentSceneCollection(WSRequestHandler* req);
- static HandlerResponse HandleListSceneCollections(WSRequestHandler* req);
+ RpcResponse SetCurrentProfile(const RpcRequest&);
+ RpcResponse GetCurrentProfile(const RpcRequest&);
+ RpcResponse ListProfiles(const RpcRequest&);
- static HandlerResponse HandleSetCurrentProfile(WSRequestHandler* req);
- static HandlerResponse HandleGetCurrentProfile(WSRequestHandler* req);
- static HandlerResponse HandleListProfiles(WSRequestHandler* req);
-
- static HandlerResponse HandleSetStreamSettings(WSRequestHandler* req);
- static HandlerResponse HandleGetStreamSettings(WSRequestHandler* req);
- static HandlerResponse HandleSaveStreamSettings(WSRequestHandler* req);
+ RpcResponse SetStreamSettings(const RpcRequest&);
+ RpcResponse GetStreamSettings(const RpcRequest&);
+ RpcResponse SaveStreamSettings(const RpcRequest&);
#if BUILD_CAPTIONS
- static HandlerResponse HandleSendCaptions(WSRequestHandler * req);
+ RpcResponse SendCaptions(const RpcRequest&);
#endif
- static HandlerResponse HandleSetTransitionDuration(WSRequestHandler* req);
- static HandlerResponse HandleGetTransitionDuration(WSRequestHandler* req);
+ RpcResponse SetTransitionDuration(const RpcRequest&);
+ RpcResponse GetTransitionDuration(const RpcRequest&);
- static HandlerResponse HandleGetStudioModeStatus(WSRequestHandler* req);
- static HandlerResponse HandleGetPreviewScene(WSRequestHandler* req);
- static HandlerResponse HandleSetPreviewScene(WSRequestHandler* req);
- static HandlerResponse HandleTransitionToProgram(WSRequestHandler* req);
- static HandlerResponse HandleEnableStudioMode(WSRequestHandler* req);
- static HandlerResponse HandleDisableStudioMode(WSRequestHandler* req);
- static HandlerResponse HandleToggleStudioMode(WSRequestHandler* req);
+ RpcResponse GetStudioModeStatus(const RpcRequest&);
+ RpcResponse GetPreviewScene(const RpcRequest&);
+ RpcResponse SetPreviewScene(const RpcRequest&);
+ RpcResponse TransitionToProgram(const RpcRequest&);
+ RpcResponse EnableStudioMode(const RpcRequest&);
+ RpcResponse DisableStudioMode(const RpcRequest&);
+ RpcResponse ToggleStudioMode(const RpcRequest&);
- static HandlerResponse HandleSetTextGDIPlusProperties(WSRequestHandler* req);
- static HandlerResponse HandleGetTextGDIPlusProperties(WSRequestHandler* req);
+ RpcResponse SetTextGDIPlusProperties(const RpcRequest&);
+ RpcResponse GetTextGDIPlusProperties(const RpcRequest&);
- static HandlerResponse HandleSetTextFreetype2Properties(WSRequestHandler* req);
- static HandlerResponse HandleGetTextFreetype2Properties(WSRequestHandler* req);
+ RpcResponse SetTextFreetype2Properties(const RpcRequest&);
+ RpcResponse GetTextFreetype2Properties(const RpcRequest&);
- static HandlerResponse HandleSetBrowserSourceProperties(WSRequestHandler* req);
- static HandlerResponse HandleGetBrowserSourceProperties(WSRequestHandler* req);
+ RpcResponse SetBrowserSourceProperties(const RpcRequest&);
+ RpcResponse GetBrowserSourceProperties(const RpcRequest&);
- static HandlerResponse HandleListOutputs(WSRequestHandler* req);
- static HandlerResponse HandleGetOutputInfo(WSRequestHandler* req);
- static HandlerResponse HandleStartOutput(WSRequestHandler* req);
- static HandlerResponse HandleStopOutput(WSRequestHandler* req);
+ RpcResponse ListOutputs(const RpcRequest&);
+ RpcResponse GetOutputInfo(const RpcRequest&);
+ RpcResponse StartOutput(const RpcRequest&);
+ RpcResponse StopOutput(const RpcRequest&);
};
diff --git a/src/WSRequestHandler_General.cpp b/src/WSRequestHandler_General.cpp
index ecb3f48f..bab1a6e0 100644
--- a/src/WSRequestHandler_General.cpp
+++ b/src/WSRequestHandler_General.cpp
@@ -66,10 +66,10 @@ const char *describe_scale_type(int scale) {
* @category general
* @since 0.3
*/
-HandlerResponse WSRequestHandler::HandleGetVersion(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::GetVersion(const RpcRequest& request) {
QString obsVersion = Utils::OBSVersionString();
- QList names = req->messageMap.keys();
+ QList names = messageMap.keys();
names.sort(Qt::CaseInsensitive);
// (Palakis) OBS' data arrays only support object arrays, so I improvised.
@@ -85,7 +85,7 @@ HandlerResponse WSRequestHandler::HandleGetVersion(WSRequestHandler* req) {
obs_data_set_string(data, "obs-studio-version", obsVersion.toUtf8());
obs_data_set_string(data, "available-requests", requests.toUtf8());
- return req->SendOKResponse(data);
+ return request.success(data);
}
/**
@@ -101,7 +101,7 @@ HandlerResponse WSRequestHandler::HandleGetVersion(WSRequestHandler* req) {
* @category general
* @since 0.3
*/
-HandlerResponse WSRequestHandler::HandleGetAuthRequired(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::GetAuthRequired(const RpcRequest& request) {
bool authRequired = GetConfig()->AuthRequired;
OBSDataAutoRelease data = obs_data_create();
@@ -115,7 +115,7 @@ HandlerResponse WSRequestHandler::HandleGetAuthRequired(WSRequestHandler* req) {
config->Salt.toUtf8());
}
- return req->SendOKResponse(data);
+ return request.success(data);
}
/**
@@ -128,26 +128,26 @@ HandlerResponse WSRequestHandler::HandleGetAuthRequired(WSRequestHandler* req) {
* @category general
* @since 0.3
*/
-HandlerResponse WSRequestHandler::HandleAuthenticate(WSRequestHandler* req) {
- if (!req->hasField("auth")) {
- return req->SendErrorResponse("missing request parameters");
+RpcResponse WSRequestHandler::Authenticate(const RpcRequest& request) {
+ if (!request.hasField("auth")) {
+ return request.failed("missing request parameters");
}
- if (req->_connProperties.isAuthenticated()) {
- return req->SendErrorResponse("already authenticated");
+ if (_connProperties.isAuthenticated()) {
+ return request.failed("already authenticated");
}
- QString auth = obs_data_get_string(req->data, "auth");
+ QString auth = obs_data_get_string(request.parameters(), "auth");
if (auth.isEmpty()) {
- return req->SendErrorResponse("auth not specified!");
+ return request.failed("auth not specified!");
}
if (GetConfig()->CheckAuth(auth) == false) {
- return req->SendErrorResponse("Authentication Failed.");
+ return request.failed("Authentication Failed.");
}
- req->_connProperties.setAuthenticated(true);
- return req->SendOKResponse();
+ _connProperties.setAuthenticated(true);
+ return request.success();
}
/**
@@ -160,17 +160,18 @@ HandlerResponse WSRequestHandler::HandleAuthenticate(WSRequestHandler* req) {
* @category general
* @since 4.3.0
*/
-HandlerResponse WSRequestHandler::HandleSetHeartbeat(WSRequestHandler* req) {
- if (!req->hasField("enable")) {
- return req->SendErrorResponse("Heartbeat parameter missing");
+RpcResponse WSRequestHandler::SetHeartbeat(const RpcRequest& request) {
+ if (!request.hasField("enable")) {
+ return request.failed("Heartbeat parameter missing");
}
auto events = GetEventsSystem();
- events->HeartbeatIsActive = obs_data_get_bool(req->data, "enable");
+ events->HeartbeatIsActive = obs_data_get_bool(request.parameters(), "enable");
OBSDataAutoRelease response = obs_data_create();
obs_data_set_bool(response, "enable", events->HeartbeatIsActive);
- return req->SendOKResponse(response);
+
+ return request.success(response);
}
/**
@@ -183,18 +184,19 @@ HandlerResponse WSRequestHandler::HandleSetHeartbeat(WSRequestHandler* req) {
* @category general
* @since 4.3.0
*/
-HandlerResponse WSRequestHandler::HandleSetFilenameFormatting(WSRequestHandler* req) {
- if (!req->hasField("filename-formatting")) {
- return req->SendErrorResponse(" parameter missing");
+RpcResponse WSRequestHandler::SetFilenameFormatting(const RpcRequest& request) {
+ if (!request.hasField("filename-formatting")) {
+ return request.failed(" parameter missing");
}
- QString filenameFormatting = obs_data_get_string(req->data, "filename-formatting");
+ QString filenameFormatting = obs_data_get_string(request.parameters(), "filename-formatting");
if (filenameFormatting.isEmpty()) {
- return req->SendErrorResponse("invalid request parameters");
+ return request.failed("invalid request parameters");
}
Utils::SetFilenameFormatting(filenameFormatting.toUtf8());
- return req->SendOKResponse();
+
+ return request.success();
}
/**
@@ -207,10 +209,11 @@ HandlerResponse WSRequestHandler::HandleSetFilenameFormatting(WSRequestHandler*
* @category general
* @since 4.3.0
*/
-HandlerResponse WSRequestHandler::HandleGetFilenameFormatting(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::GetFilenameFormatting(const RpcRequest& request) {
OBSDataAutoRelease response = obs_data_create();
obs_data_set_string(response, "filename-formatting", Utils::GetFilenameFormatting());
- return req->SendOKResponse(response);
+
+ return request.success(response);
}
/**
@@ -223,12 +226,13 @@ HandlerResponse WSRequestHandler::HandleGetFilenameFormatting(WSRequestHandler*
* @category general
* @since 4.6.0
*/
-HandlerResponse WSRequestHandler::HandleGetStats(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::GetStats(const RpcRequest& request) {
OBSDataAutoRelease stats = GetEventsSystem()->GetStats();
OBSDataAutoRelease response = obs_data_create();
obs_data_set_obj(response, "stats", stats);
- return req->SendOKResponse(response);
+
+ return request.success(response);
}
/**
@@ -242,26 +246,26 @@ HandlerResponse WSRequestHandler::HandleGetStats(WSRequestHandler* req) {
* @category general
* @since 4.7.0
*/
-HandlerResponse WSRequestHandler::HandleBroadcastCustomMessage(WSRequestHandler* req) {
- if (!req->hasField("realm") || !req->hasField("data")) {
- return req->SendErrorResponse("missing request parameters");
+RpcResponse WSRequestHandler::BroadcastCustomMessage(const RpcRequest& request) {
+ if (!request.hasField("realm") || !request.hasField("data")) {
+ return request.failed("missing request parameters");
}
- QString realm = obs_data_get_string(req->data, "realm");
- OBSDataAutoRelease data = obs_data_get_obj(req->data, "data");
+ QString realm = obs_data_get_string(request.parameters(), "realm");
+ OBSDataAutoRelease data = obs_data_get_obj(request.parameters(), "data");
if (realm.isEmpty()) {
- return req->SendErrorResponse("realm not specified!");
+ return request.failed("realm not specified!");
}
if (!data) {
- return req->SendErrorResponse("data not specified!");
+ return request.failed("data not specified!");
}
auto events = GetEventsSystem();
events->OnBroadcastCustomMessage(realm, data);
- return req->SendOKResponse();
+ return request.success();
}
@@ -283,9 +287,10 @@ HandlerResponse WSRequestHandler::HandleBroadcastCustomMessage(WSRequestHandler*
* @category general
* @since 4.6.0
*/
-HandlerResponse WSRequestHandler::HandleGetVideoInfo(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::GetVideoInfo(const RpcRequest& request) {
obs_video_info ovi;
obs_get_video_info(&ovi);
+
OBSDataAutoRelease response = obs_data_create();
obs_data_set_int(response, "baseWidth", ovi.base_width);
obs_data_set_int(response, "baseHeight", ovi.base_height);
@@ -296,5 +301,6 @@ HandlerResponse WSRequestHandler::HandleGetVideoInfo(WSRequestHandler* req) {
obs_data_set_string(response, "colorSpace", describe_color_space(ovi.colorspace));
obs_data_set_string(response, "colorRange", describe_color_range(ovi.range));
obs_data_set_string(response, "scaleType", describe_scale_type(ovi.scale_type));
- return req->SendOKResponse(response);
+
+ return request.success(response);
}
diff --git a/src/WSRequestHandler_Outputs.cpp b/src/WSRequestHandler_Outputs.cpp
index 45469411..dad0bf19 100644
--- a/src/WSRequestHandler_Outputs.cpp
+++ b/src/WSRequestHandler_Outputs.cpp
@@ -1,3 +1,5 @@
+#include
+
#include "WSRequestHandler.h"
/**
@@ -57,16 +59,16 @@ obs_data_t* getOutputInfo(obs_output_t* output)
return data;
}
-HandlerResponse findOutputOrFail(WSRequestHandler* req, std::function callback)
+RpcResponse findOutputOrFail(const RpcRequest& request, std::function callback)
{
- if (!req->hasField("outputName")) {
- return req->SendErrorResponse("missing request parameters");
+ if (!request.hasField("outputName")) {
+ return request.failed("missing request parameters");
}
- const char* outputName = obs_data_get_string(req->parameters(), "outputName");
+ const char* outputName = obs_data_get_string(request.parameters(), "outputName");
OBSOutputAutoRelease output = obs_get_output_by_name(outputName);
if (!output) {
- return req->SendErrorResponse("specified output doesn't exist");
+ return request.failed("specified output doesn't exist");
}
return callback(output);
@@ -82,7 +84,7 @@ HandlerResponse findOutputOrFail(WSRequestHandler* req, std::functionSendOKResponse(fields);
+
+ return request.success(fields);
}
/**
@@ -112,14 +115,14 @@ HandlerResponse WSRequestHandler::HandleListOutputs(WSRequestHandler* req)
* @category outputs
* @since 4.7.0
*/
-HandlerResponse WSRequestHandler::HandleGetOutputInfo(WSRequestHandler* req)
+RpcResponse WSRequestHandler::GetOutputInfo(const RpcRequest& request)
{
- return findOutputOrFail(req, [req](obs_output_t* output) {
+ return findOutputOrFail(request, [request](obs_output_t* output) {
OBSDataAutoRelease outputInfo = getOutputInfo(output);
OBSDataAutoRelease fields = obs_data_create();
obs_data_set_obj(fields, "outputInfo", outputInfo);
- return req->SendOKResponse(fields);
+ return request.success(fields);
});
}
@@ -133,21 +136,21 @@ HandlerResponse WSRequestHandler::HandleGetOutputInfo(WSRequestHandler* req)
* @category outputs
* @since 4.7.0
*/
-HandlerResponse WSRequestHandler::HandleStartOutput(WSRequestHandler* req)
+RpcResponse WSRequestHandler::StartOutput(const RpcRequest& request)
{
- return findOutputOrFail(req, [req](obs_output_t* output) {
+ return findOutputOrFail(request, [request](obs_output_t* output) {
if (obs_output_active(output)) {
- return req->SendErrorResponse("output already active");
+ return request.failed("output already active");
}
bool success = obs_output_start(output);
if (!success) {
QString lastError = obs_output_get_last_error(output);
QString errorMessage = QString("output start failed: %1").arg(lastError);
- return req->SendErrorResponse(errorMessage);
+ return request.failed(errorMessage);
}
- return req->SendOKResponse();
+ return request.success();
});
}
@@ -162,20 +165,20 @@ HandlerResponse WSRequestHandler::HandleStartOutput(WSRequestHandler* req)
* @category outputs
* @since 4.7.0
*/
-HandlerResponse WSRequestHandler::HandleStopOutput(WSRequestHandler* req)
+RpcResponse WSRequestHandler::StopOutput(const RpcRequest& request)
{
- return findOutputOrFail(req, [req](obs_output_t* output) {
+ return findOutputOrFail(request, [request](obs_output_t* output) {
if (!obs_output_active(output)) {
- return req->SendErrorResponse("output not active");
+ return request.failed("output not active");
}
- bool forceStop = obs_data_get_bool(req->data, "force");
+ bool forceStop = obs_data_get_bool(request.parameters(), "force");
if (forceStop) {
obs_output_force_stop(output);
} else {
obs_output_stop(output);
}
- return req->SendOKResponse();
+ return request.success();
});
}
diff --git a/src/WSRequestHandler_Profiles.cpp b/src/WSRequestHandler_Profiles.cpp
index 3b78d40b..78e3ce2d 100644
--- a/src/WSRequestHandler_Profiles.cpp
+++ b/src/WSRequestHandler_Profiles.cpp
@@ -12,19 +12,19 @@
* @category profiles
* @since 4.0.0
*/
-HandlerResponse WSRequestHandler::HandleSetCurrentProfile(WSRequestHandler* req) {
- if (!req->hasField("profile-name")) {
- return req->SendErrorResponse("missing request parameters");
+RpcResponse WSRequestHandler::SetCurrentProfile(const RpcRequest& request) {
+ if (!request.hasField("profile-name")) {
+ return request.failed("missing request parameters");
}
- QString profileName = obs_data_get_string(req->data, "profile-name");
+ QString profileName = obs_data_get_string(request.parameters(), "profile-name");
if (profileName.isEmpty()) {
- return req->SendErrorResponse("invalid request parameters");
+ return request.failed("invalid request parameters");
}
// TODO : check if profile exists
obs_frontend_set_current_profile(profileName.toUtf8());
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -37,12 +37,12 @@ HandlerResponse WSRequestHandler::HandleSetCurrentProfile(WSRequestHandler* req)
* @category profiles
* @since 4.0.0
*/
-HandlerResponse WSRequestHandler::HandleGetCurrentProfile(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::GetCurrentProfile(const RpcRequest& request) {
OBSDataAutoRelease response = obs_data_create();
char* currentProfile = obs_frontend_get_current_profile();
obs_data_set_string(response, "profile-name", currentProfile);
bfree(currentProfile);
- return req->SendOKResponse(response);
+ return request.success(response);
}
/**
@@ -55,7 +55,7 @@ HandlerResponse WSRequestHandler::HandleGetCurrentProfile(WSRequestHandler* req)
* @category profiles
* @since 4.0.0
*/
-HandlerResponse WSRequestHandler::HandleListProfiles(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::ListProfiles(const RpcRequest& request) {
char** profiles = obs_frontend_get_profiles();
OBSDataArrayAutoRelease list = Utils::StringListToArray(profiles, "profile-name");
bfree(profiles);
@@ -63,5 +63,5 @@ HandlerResponse WSRequestHandler::HandleListProfiles(WSRequestHandler* req) {
OBSDataAutoRelease response = obs_data_create();
obs_data_set_array(response, "profiles", list);
- return req->SendOKResponse(response);
+ return request.success(response);
}
diff --git a/src/WSRequestHandler_Recording.cpp b/src/WSRequestHandler_Recording.cpp
index 9164a404..330843d3 100644
--- a/src/WSRequestHandler_Recording.cpp
+++ b/src/WSRequestHandler_Recording.cpp
@@ -1,16 +1,17 @@
#include "WSRequestHandler.h"
+#include
#include
#include "Utils.h"
-HandlerResponse ifCanPause(WSRequestHandler* req, std::function callback)
+RpcResponse ifCanPause(const RpcRequest& request, std::function callback)
{
if (!obs_frontend_recording_active()) {
- return req->SendErrorResponse("recording is not active");
+ return request.failed("recording is not active");
}
if (!Utils::RecordingPauseSupported()) {
- return req->SendErrorResponse("recording pauses are not available in this version of OBS Studio");
+ return request.failed("recording pauses are not available in this version of OBS Studio");
}
return callback();
@@ -24,9 +25,9 @@ HandlerResponse ifCanPause(WSRequestHandler* req, std::functionSendOKResponse();
+ return request.success();
}
/**
@@ -38,13 +39,13 @@ HandlerResponse WSRequestHandler::HandleStartStopRecording(WSRequestHandler* req
* @category recording
* @since 4.1.0
*/
-HandlerResponse WSRequestHandler::HandleStartRecording(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::StartRecording(const RpcRequest& request) {
if (obs_frontend_recording_active()) {
- return req->SendErrorResponse("recording already active");
+ return request.failed("recording already active");
}
obs_frontend_recording_start();
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -56,13 +57,13 @@ HandlerResponse WSRequestHandler::HandleStartRecording(WSRequestHandler* req) {
* @category recording
* @since 4.1.0
*/
- HandlerResponse WSRequestHandler::HandleStopRecording(WSRequestHandler* req) {
+ RpcResponse WSRequestHandler::StopRecording(const RpcRequest& request) {
if (!obs_frontend_recording_active()) {
- return req->SendErrorResponse("recording not active");
+ return request.failed("recording not active");
}
obs_frontend_recording_stop();
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -74,14 +75,14 @@ HandlerResponse WSRequestHandler::HandleStartRecording(WSRequestHandler* req) {
* @category recording
* @since 4.7.0
*/
-HandlerResponse WSRequestHandler::HandlePauseRecording(WSRequestHandler* req) {
- return ifCanPause(req, [req]() {
+RpcResponse WSRequestHandler::PauseRecording(const RpcRequest& request) {
+ return ifCanPause(request, [request]() {
if (Utils::RecordingPaused()) {
- return req->SendErrorResponse("recording already paused");
+ return request.failed("recording already paused");
}
Utils::PauseRecording(true);
- return req->SendOKResponse();
+ return request.success();
});
}
@@ -94,14 +95,14 @@ HandlerResponse WSRequestHandler::HandlePauseRecording(WSRequestHandler* req) {
* @category recording
* @since 4.7.0
*/
-HandlerResponse WSRequestHandler::HandleResumeRecording(WSRequestHandler* req) {
- return ifCanPause(req, [req]() {
+RpcResponse WSRequestHandler::ResumeRecording(const RpcRequest& request) {
+ return ifCanPause(request, [request]() {
if (!Utils::RecordingPaused()) {
- return req->SendErrorResponse("recording is not paused");
+ return request.failed("recording is not paused");
}
Utils::PauseRecording(false);
- return req->SendOKResponse();
+ return request.success();
});
}
@@ -120,18 +121,18 @@ HandlerResponse WSRequestHandler::HandleResumeRecording(WSRequestHandler* req) {
* @category recording
* @since 4.1.0
*/
-HandlerResponse WSRequestHandler::HandleSetRecordingFolder(WSRequestHandler* req) {
- if (!req->hasField("rec-folder")) {
- return req->SendErrorResponse("missing request parameters");
+RpcResponse WSRequestHandler::SetRecordingFolder(const RpcRequest& request) {
+ if (!request.hasField("rec-folder")) {
+ return request.failed("missing request parameters");
}
- const char* newRecFolder = obs_data_get_string(req->data, "rec-folder");
+ const char* newRecFolder = obs_data_get_string(request.parameters(), "rec-folder");
bool success = Utils::SetRecordingFolder(newRecFolder);
if (!success) {
- return req->SendErrorResponse("invalid request parameters");
+ return request.failed("invalid request parameters");
}
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -144,11 +145,11 @@ HandlerResponse WSRequestHandler::HandleSetRecordingFolder(WSRequestHandler* req
* @category recording
* @since 4.1.0
*/
-HandlerResponse WSRequestHandler::HandleGetRecordingFolder(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::GetRecordingFolder(const RpcRequest& request) {
const char* recFolder = Utils::GetRecordingFolder();
OBSDataAutoRelease response = obs_data_create();
obs_data_set_string(response, "rec-folder", recFolder);
- return req->SendOKResponse(response);
+ return request.success(response);
}
diff --git a/src/WSRequestHandler_ReplayBuffer.cpp b/src/WSRequestHandler_ReplayBuffer.cpp
index 86add84a..510b8f05 100644
--- a/src/WSRequestHandler_ReplayBuffer.cpp
+++ b/src/WSRequestHandler_ReplayBuffer.cpp
@@ -10,13 +10,13 @@
* @category replay buffer
* @since 4.2.0
*/
-HandlerResponse WSRequestHandler::HandleStartStopReplayBuffer(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::StartStopReplayBuffer(const RpcRequest& request) {
if (obs_frontend_replay_buffer_active()) {
obs_frontend_replay_buffer_stop();
} else {
Utils::StartReplayBuffer();
}
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -31,17 +31,17 @@ HandlerResponse WSRequestHandler::HandleStartStopReplayBuffer(WSRequestHandler*
* @category replay buffer
* @since 4.2.0
*/
-HandlerResponse WSRequestHandler::HandleStartReplayBuffer(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::StartReplayBuffer(const RpcRequest& request) {
if (!Utils::ReplayBufferEnabled()) {
- return req->SendErrorResponse("replay buffer disabled in settings");
+ return request.failed("replay buffer disabled in settings");
}
if (obs_frontend_replay_buffer_active() == true) {
- return req->SendErrorResponse("replay buffer already active");
+ return request.failed("replay buffer already active");
}
Utils::StartReplayBuffer();
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -53,12 +53,12 @@ HandlerResponse WSRequestHandler::HandleStartReplayBuffer(WSRequestHandler* req)
* @category replay buffer
* @since 4.2.0
*/
-HandlerResponse WSRequestHandler::HandleStopReplayBuffer(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::StopReplayBuffer(const RpcRequest& request) {
if (obs_frontend_replay_buffer_active() == true) {
obs_frontend_replay_buffer_stop();
- return req->SendOKResponse();
+ return request.success();
} else {
- return req->SendErrorResponse("replay buffer not active");
+ return request.failed("replay buffer not active");
}
}
@@ -72,9 +72,9 @@ HandlerResponse WSRequestHandler::HandleStopReplayBuffer(WSRequestHandler* req)
* @category replay buffer
* @since 4.2.0
*/
-HandlerResponse WSRequestHandler::HandleSaveReplayBuffer(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::SaveReplayBuffer(const RpcRequest& request) {
if (!obs_frontend_replay_buffer_active()) {
- return req->SendErrorResponse("replay buffer not active");
+ return request.failed("replay buffer not active");
}
OBSOutputAutoRelease replayOutput = obs_frontend_get_replay_buffer_output();
@@ -84,5 +84,5 @@ HandlerResponse WSRequestHandler::HandleSaveReplayBuffer(WSRequestHandler* req)
proc_handler_call(ph, "save", &cd);
calldata_free(&cd);
- return req->SendOKResponse();
+ return request.success();
}
diff --git a/src/WSRequestHandler_SceneCollections.cpp b/src/WSRequestHandler_SceneCollections.cpp
index ccc411a1..1f87996b 100644
--- a/src/WSRequestHandler_SceneCollections.cpp
+++ b/src/WSRequestHandler_SceneCollections.cpp
@@ -12,19 +12,19 @@
* @category scene collections
* @since 4.0.0
*/
-HandlerResponse WSRequestHandler::HandleSetCurrentSceneCollection(WSRequestHandler* req) {
- if (!req->hasField("sc-name")) {
- return req->SendErrorResponse("missing request parameters");
+RpcResponse WSRequestHandler::SetCurrentSceneCollection(const RpcRequest& request) {
+ if (!request.hasField("sc-name")) {
+ return request.failed("missing request parameters");
}
- QString sceneCollection = obs_data_get_string(req->data, "sc-name");
+ QString sceneCollection = obs_data_get_string(request.parameters(), "sc-name");
if (sceneCollection.isEmpty()) {
- return req->SendErrorResponse("invalid request parameters");
+ return request.failed("invalid request parameters");
}
// TODO : Check if specified profile exists and if changing is allowed
obs_frontend_set_current_scene_collection(sceneCollection.toUtf8());
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -37,14 +37,14 @@ HandlerResponse WSRequestHandler::HandleSetCurrentSceneCollection(WSRequestHandl
* @category scene collections
* @since 4.0.0
*/
-HandlerResponse WSRequestHandler::HandleGetCurrentSceneCollection(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::GetCurrentSceneCollection(const RpcRequest& request) {
OBSDataAutoRelease response = obs_data_create();
char* sceneCollection = obs_frontend_get_current_scene_collection();
obs_data_set_string(response, "sc-name", sceneCollection);
bfree(sceneCollection);
- return req->SendOKResponse(response);
+ return request.success(response);
}
/**
@@ -57,7 +57,7 @@ HandlerResponse WSRequestHandler::HandleGetCurrentSceneCollection(WSRequestHandl
* @category scene collections
* @since 4.0.0
*/
-HandlerResponse WSRequestHandler::HandleListSceneCollections(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::ListSceneCollections(const RpcRequest& request) {
char** sceneCollections = obs_frontend_get_scene_collections();
OBSDataArrayAutoRelease list =
Utils::StringListToArray(sceneCollections, "sc-name");
@@ -66,5 +66,5 @@ HandlerResponse WSRequestHandler::HandleListSceneCollections(WSRequestHandler* r
OBSDataAutoRelease response = obs_data_create();
obs_data_set_array(response, "scene-collections", list);
- return req->SendOKResponse(response);
+ return request.success(response);
}
diff --git a/src/WSRequestHandler_SceneItems.cpp b/src/WSRequestHandler_SceneItems.cpp
index e2e6d188..cd54de16 100644
--- a/src/WSRequestHandler_SceneItems.cpp
+++ b/src/WSRequestHandler_SceneItems.cpp
@@ -38,31 +38,31 @@
* @category scene items
* @since 4.3.0
*/
-HandlerResponse WSRequestHandler::HandleGetSceneItemProperties(WSRequestHandler* req) {
- if (!req->hasField("item")) {
- return req->SendErrorResponse("missing request parameters");
+RpcResponse WSRequestHandler::GetSceneItemProperties(const RpcRequest& request) {
+ if (!request.hasField("item")) {
+ return request.failed("missing request parameters");
}
- QString itemName = obs_data_get_string(req->data, "item");
+ QString itemName = obs_data_get_string(request.parameters(), "item");
if (itemName.isEmpty()) {
- return req->SendErrorResponse("invalid request parameters");
+ return request.failed("invalid request parameters");
}
- QString sceneName = obs_data_get_string(req->data, "scene-name");
+ QString sceneName = obs_data_get_string(request.parameters(), "scene-name");
OBSScene scene = Utils::GetSceneFromNameOrCurrent(sceneName);
if (!scene) {
- return req->SendErrorResponse("requested scene doesn't exist");
+ return request.failed("requested scene doesn't exist");
}
OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromName(scene, itemName);
if (!sceneItem) {
- return req->SendErrorResponse("specified scene item doesn't exist");
+ return request.failed("specified scene item doesn't exist");
}
OBSDataAutoRelease data = Utils::GetSceneItemPropertiesData(sceneItem);
obs_data_set_string(data, "name", itemName.toUtf8());
- return req->SendOKResponse(data);
+ return request.success(data);
}
/**
@@ -93,38 +93,38 @@ HandlerResponse WSRequestHandler::HandleGetSceneItemProperties(WSRequestHandler*
* @category scene items
* @since 4.3.0
*/
-HandlerResponse WSRequestHandler::HandleSetSceneItemProperties(WSRequestHandler* req) {
- if (!req->hasField("item")) {
- return req->SendErrorResponse("missing request parameters");
+RpcResponse WSRequestHandler::SetSceneItemProperties(const RpcRequest& request) {
+ if (!request.hasField("item")) {
+ return request.failed("missing request parameters");
}
- QString itemName = obs_data_get_string(req->data, "item");
+ QString itemName = obs_data_get_string(request.parameters(), "item");
if (itemName.isEmpty()) {
- return req->SendErrorResponse("invalid request parameters");
+ return request.failed("invalid request parameters");
}
- QString sceneName = obs_data_get_string(req->data, "scene-name");
+ QString sceneName = obs_data_get_string(request.parameters(), "scene-name");
OBSScene scene = Utils::GetSceneFromNameOrCurrent(sceneName);
if (!scene) {
- return req->SendErrorResponse("requested scene doesn't exist");
+ return request.failed("requested scene doesn't exist");
}
OBSSceneItemAutoRelease sceneItem =
Utils::GetSceneItemFromName(scene, itemName);
if (!sceneItem) {
- return req->SendErrorResponse("specified scene item doesn't exist");
+ return request.failed("specified scene item doesn't exist");
}
bool badRequest = false;
- OBSDataAutoRelease errorMessage = obs_data_create();
+ OBSDataAutoRelease errorData = obs_data_create();
obs_sceneitem_defer_update_begin(sceneItem);
- if (req->hasField("position")) {
+ if (request.hasField("position")) {
vec2 oldPosition;
OBSDataAutoRelease positionError = obs_data_create();
obs_sceneitem_get_pos(sceneItem, &oldPosition);
- OBSDataAutoRelease reqPosition = obs_data_get_obj(req->data, "position");
+ OBSDataAutoRelease reqPosition = obs_data_get_obj(request.parameters(), "position");
vec2 newPosition = oldPosition;
if (obs_data_has_user_value(reqPosition, "x")) {
newPosition.x = obs_data_get_int(reqPosition, "x");
@@ -140,20 +140,20 @@ HandlerResponse WSRequestHandler::HandleSetSceneItemProperties(WSRequestHandler*
else {
badRequest = true;
obs_data_set_string(positionError, "alignment", "invalid");
- obs_data_set_obj(errorMessage, "position", positionError);
+ obs_data_set_obj(errorData, "position", positionError);
}
}
obs_sceneitem_set_pos(sceneItem, &newPosition);
}
- if (req->hasField("rotation")) {
- obs_sceneitem_set_rot(sceneItem, (float)obs_data_get_double(req->data, "rotation"));
+ if (request.hasField("rotation")) {
+ obs_sceneitem_set_rot(sceneItem, (float)obs_data_get_double(request.parameters(), "rotation"));
}
- if (req->hasField("scale")) {
+ if (request.hasField("scale")) {
vec2 oldScale;
obs_sceneitem_get_scale(sceneItem, &oldScale);
- OBSDataAutoRelease reqScale = obs_data_get_obj(req->data, "scale");
+ OBSDataAutoRelease reqScale = obs_data_get_obj(request.parameters(), "scale");
vec2 newScale = oldScale;
if (obs_data_has_user_value(reqScale, "x")) {
newScale.x = obs_data_get_double(reqScale, "x");
@@ -164,10 +164,10 @@ HandlerResponse WSRequestHandler::HandleSetSceneItemProperties(WSRequestHandler*
obs_sceneitem_set_scale(sceneItem, &newScale);
}
- if (req->hasField("crop")) {
+ if (request.hasField("crop")) {
obs_sceneitem_crop oldCrop;
obs_sceneitem_get_crop(sceneItem, &oldCrop);
- OBSDataAutoRelease reqCrop = obs_data_get_obj(req->data, "crop");
+ OBSDataAutoRelease reqCrop = obs_data_get_obj(request.parameters(), "crop");
obs_sceneitem_crop newCrop = oldCrop;
if (obs_data_has_user_value(reqCrop, "top")) {
newCrop.top = obs_data_get_int(reqCrop, "top");
@@ -184,18 +184,18 @@ HandlerResponse WSRequestHandler::HandleSetSceneItemProperties(WSRequestHandler*
obs_sceneitem_set_crop(sceneItem, &newCrop);
}
- if (req->hasField("visible")) {
- obs_sceneitem_set_visible(sceneItem, obs_data_get_bool(req->data, "visible"));
+ if (request.hasField("visible")) {
+ obs_sceneitem_set_visible(sceneItem, obs_data_get_bool(request.parameters(), "visible"));
}
- if (req->hasField("locked")) {
- obs_sceneitem_set_locked(sceneItem, obs_data_get_bool(req->data, "locked"));
+ if (request.hasField("locked")) {
+ obs_sceneitem_set_locked(sceneItem, obs_data_get_bool(request.parameters(), "locked"));
}
- if (req->hasField("bounds")) {
+ if (request.hasField("bounds")) {
bool badBounds = false;
OBSDataAutoRelease boundsError = obs_data_create();
- OBSDataAutoRelease reqBounds = obs_data_get_obj(req->data, "bounds");
+ OBSDataAutoRelease reqBounds = obs_data_get_obj(request.parameters(), "bounds");
if (obs_data_has_user_value(reqBounds, "type")) {
QString newBoundsType = obs_data_get_string(reqBounds, "type");
if (newBoundsType == "OBS_BOUNDS_NONE") {
@@ -245,17 +245,17 @@ HandlerResponse WSRequestHandler::HandleSetSceneItemProperties(WSRequestHandler*
}
}
if (badBounds) {
- obs_data_set_obj(errorMessage, "bounds", boundsError);
+ obs_data_set_obj(errorData, "bounds", boundsError);
}
}
obs_sceneitem_defer_update_end(sceneItem);
if (badRequest) {
- return req->SendErrorResponse(errorMessage);
+ return request.failed("error", errorData);
}
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -269,27 +269,27 @@ HandlerResponse WSRequestHandler::HandleSetSceneItemProperties(WSRequestHandler*
* @category scene items
* @since 4.2.0
*/
-HandlerResponse WSRequestHandler::HandleResetSceneItem(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::ResetSceneItem(const RpcRequest& request) {
// TODO: remove this request, or refactor it to ResetSource
- if (!req->hasField("item")) {
- return req->SendErrorResponse("missing request parameters");
+ if (!request.hasField("item")) {
+ return request.failed("missing request parameters");
}
- const char* itemName = obs_data_get_string(req->data, "item");
+ const char* itemName = obs_data_get_string(request.parameters(), "item");
if (!itemName) {
- return req->SendErrorResponse("invalid request parameters");
+ return request.failed("invalid request parameters");
}
- const char* sceneName = obs_data_get_string(req->data, "scene-name");
+ const char* sceneName = obs_data_get_string(request.parameters(), "scene-name");
OBSScene scene = Utils::GetSceneFromNameOrCurrent(sceneName);
if (!scene) {
- return req->SendErrorResponse("requested scene doesn't exist");
+ return request.failed("requested scene doesn't exist");
}
OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromName(scene, itemName);
if (!sceneItem) {
- return req->SendErrorResponse("specified scene item doesn't exist");
+ return request.failed("specified scene item doesn't exist");
}
OBSSource sceneItemSource = obs_sceneitem_get_source(sceneItem);
@@ -297,7 +297,7 @@ HandlerResponse WSRequestHandler::HandleResetSceneItem(WSRequestHandler* req) {
OBSDataAutoRelease settings = obs_source_get_settings(sceneItemSource);
obs_source_update(sceneItemSource, settings);
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -313,34 +313,34 @@ HandlerResponse WSRequestHandler::HandleResetSceneItem(WSRequestHandler* req) {
* @since 0.3
* @deprecated Since 4.3.0. Prefer the use of SetSceneItemProperties.
*/
-HandlerResponse WSRequestHandler::HandleSetSceneItemRender(WSRequestHandler* req) {
- if (!req->hasField("source") ||
- !req->hasField("render"))
+RpcResponse WSRequestHandler::SetSceneItemRender(const RpcRequest& request) {
+ if (!request.hasField("source") ||
+ !request.hasField("render"))
{
- return req->SendErrorResponse("missing request parameters");
+ return request.failed("missing request parameters");
}
- const char* itemName = obs_data_get_string(req->data, "source");
- bool isVisible = obs_data_get_bool(req->data, "render");
+ const char* itemName = obs_data_get_string(request.parameters(), "source");
+ bool isVisible = obs_data_get_bool(request.parameters(), "render");
if (!itemName) {
- return req->SendErrorResponse("invalid request parameters");
+ return request.failed("invalid request parameters");
}
- const char* sceneName = obs_data_get_string(req->data, "scene-name");
+ const char* sceneName = obs_data_get_string(request.parameters(), "scene-name");
OBSScene scene = Utils::GetSceneFromNameOrCurrent(sceneName);
if (!scene) {
- return req->SendErrorResponse("requested scene doesn't exist");
+ return request.failed("requested scene doesn't exist");
}
OBSSceneItemAutoRelease sceneItem =
Utils::GetSceneItemFromName(scene, itemName);
if (!sceneItem) {
- return req->SendErrorResponse("specified scene item doesn't exist");
+ return request.failed("specified scene item doesn't exist");
}
obs_sceneitem_set_visible(sceneItem, isVisible);
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -358,34 +358,34 @@ HandlerResponse WSRequestHandler::HandleSetSceneItemRender(WSRequestHandler* req
* @since 4.0.0
* @deprecated Since 4.3.0. Prefer the use of SetSceneItemProperties.
*/
-HandlerResponse WSRequestHandler::HandleSetSceneItemPosition(WSRequestHandler* req) {
- if (!req->hasField("item") ||
- !req->hasField("x") || !req->hasField("y")) {
- return req->SendErrorResponse("missing request parameters");
+RpcResponse WSRequestHandler::SetSceneItemPosition(const RpcRequest& request) {
+ if (!request.hasField("item") ||
+ !request.hasField("x") || !request.hasField("y")) {
+ return request.failed("missing request parameters");
}
- QString itemName = obs_data_get_string(req->data, "item");
+ QString itemName = obs_data_get_string(request.parameters(), "item");
if (itemName.isEmpty()) {
- return req->SendErrorResponse("invalid request parameters");
+ return request.failed("invalid request parameters");
}
- QString sceneName = obs_data_get_string(req->data, "scene-name");
+ QString sceneName = obs_data_get_string(request.parameters(), "scene-name");
OBSScene scene = Utils::GetSceneFromNameOrCurrent(sceneName);
if (!scene) {
- return req->SendErrorResponse("requested scene could not be found");
+ return request.failed("requested scene could not be found");
}
OBSSceneItem sceneItem = Utils::GetSceneItemFromName(scene, itemName);
if (!sceneItem) {
- return req->SendErrorResponse("specified scene item doesn't exist");
+ return request.failed("specified scene item doesn't exist");
}
vec2 item_position = { 0 };
- item_position.x = obs_data_get_double(req->data, "x");
- item_position.y = obs_data_get_double(req->data, "y");
+ item_position.x = obs_data_get_double(request.parameters(), "x");
+ item_position.y = obs_data_get_double(request.parameters(), "y");
obs_sceneitem_set_pos(sceneItem, &item_position);
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -403,34 +403,34 @@ HandlerResponse WSRequestHandler::HandleSetSceneItemPosition(WSRequestHandler* r
* @since 4.0.0
* @deprecated Since 4.3.0. Prefer the use of SetSceneItemProperties.
*/
-HandlerResponse WSRequestHandler::HandleSetSceneItemTransform(WSRequestHandler* req) {
- if (!req->hasField("item") ||
- !req->hasField("x-scale") ||
- !req->hasField("y-scale") ||
- !req->hasField("rotation"))
+RpcResponse WSRequestHandler::SetSceneItemTransform(const RpcRequest& request) {
+ if (!request.hasField("item") ||
+ !request.hasField("x-scale") ||
+ !request.hasField("y-scale") ||
+ !request.hasField("rotation"))
{
- return req->SendErrorResponse("missing request parameters");
+ return request.failed("missing request parameters");
}
- QString itemName = obs_data_get_string(req->data, "item");
+ QString itemName = obs_data_get_string(request.parameters(), "item");
if (itemName.isEmpty()) {
- return req->SendErrorResponse("invalid request parameters");
+ return request.failed("invalid request parameters");
}
- QString sceneName = obs_data_get_string(req->data, "scene-name");
+ QString sceneName = obs_data_get_string(request.parameters(), "scene-name");
OBSScene scene = Utils::GetSceneFromNameOrCurrent(sceneName);
if (!scene) {
- return req->SendErrorResponse("requested scene doesn't exist");
+ return request.failed("requested scene doesn't exist");
}
vec2 scale;
- scale.x = obs_data_get_double(req->data, "x-scale");
- scale.y = obs_data_get_double(req->data, "y-scale");
- float rotation = obs_data_get_double(req->data, "rotation");
+ scale.x = obs_data_get_double(request.parameters(), "x-scale");
+ scale.y = obs_data_get_double(request.parameters(), "y-scale");
+ float rotation = obs_data_get_double(request.parameters(), "rotation");
OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromName(scene, itemName);
if (!sceneItem) {
- return req->SendErrorResponse("specified scene item doesn't exist");
+ return request.failed("specified scene item doesn't exist");
}
obs_sceneitem_defer_update_begin(sceneItem);
@@ -440,7 +440,7 @@ HandlerResponse WSRequestHandler::HandleSetSceneItemTransform(WSRequestHandler*
obs_sceneitem_defer_update_end(sceneItem);
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -459,36 +459,36 @@ HandlerResponse WSRequestHandler::HandleSetSceneItemTransform(WSRequestHandler*
* @since 4.1.0
* @deprecated Since 4.3.0. Prefer the use of SetSceneItemProperties.
*/
-HandlerResponse WSRequestHandler::HandleSetSceneItemCrop(WSRequestHandler* req) {
- if (!req->hasField("item")) {
- return req->SendErrorResponse("missing request parameters");
+RpcResponse WSRequestHandler::SetSceneItemCrop(const RpcRequest& request) {
+ if (!request.hasField("item")) {
+ return request.failed("missing request parameters");
}
- QString itemName = obs_data_get_string(req->data, "item");
+ QString itemName = obs_data_get_string(request.parameters(), "item");
if (itemName.isEmpty()) {
- return req->SendErrorResponse("invalid request parameters");
+ return request.failed("invalid request parameters");
}
- QString sceneName = obs_data_get_string(req->data, "scene-name");
+ QString sceneName = obs_data_get_string(request.parameters(), "scene-name");
OBSScene scene = Utils::GetSceneFromNameOrCurrent(sceneName);
if (!scene) {
- return req->SendErrorResponse("requested scene doesn't exist");
+ return request.failed("requested scene doesn't exist");
}
OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromName(scene, itemName);
if (!sceneItem) {
- return req->SendErrorResponse("specified scene item doesn't exist");
+ return request.failed("specified scene item doesn't exist");
}
struct obs_sceneitem_crop crop = { 0 };
- crop.top = obs_data_get_int(req->data, "top");
- crop.bottom = obs_data_get_int(req->data, "bottom");
- crop.left = obs_data_get_int(req->data, "left");
- crop.right = obs_data_get_int(req->data, "right");
+ crop.top = obs_data_get_int(request.parameters(), "top");
+ crop.bottom = obs_data_get_int(request.parameters(), "bottom");
+ crop.left = obs_data_get_int(request.parameters(), "left");
+ crop.right = obs_data_get_int(request.parameters(), "right");
obs_sceneitem_set_crop(sceneItem, &crop);
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -504,38 +504,26 @@ HandlerResponse WSRequestHandler::HandleSetSceneItemCrop(WSRequestHandler* req)
* @category scene items
* @since 4.5.0
*/
-HandlerResponse WSRequestHandler::HandleDeleteSceneItem(WSRequestHandler* req) {
- if (!req->hasField("item")) {
- return req->SendErrorResponse("missing request parameters");
+RpcResponse WSRequestHandler::DeleteSceneItem(const RpcRequest& request) {
+ if (!request.hasField("item")) {
+ return request.failed("missing request parameters");
}
- const char* sceneName = obs_data_get_string(req->data, "scene");
+ const char* sceneName = obs_data_get_string(request.parameters(), "scene");
OBSScene scene = Utils::GetSceneFromNameOrCurrent(sceneName);
if (!scene) {
- return req->SendErrorResponse("requested scene doesn't exist");
+ return request.failed("requested scene doesn't exist");
}
- OBSDataAutoRelease item = obs_data_get_obj(req->data, "item");
+ OBSDataAutoRelease item = obs_data_get_obj(request.parameters(), "item");
OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromItem(scene, item);
if (!sceneItem) {
- return req->SendErrorResponse("item with id/name combination not found in specified scene");
+ return request.failed("item with id/name combination not found in specified scene");
}
obs_sceneitem_remove(sceneItem);
- return req->SendOKResponse();
-}
-
-struct DuplicateSceneItemData {
- obs_sceneitem_t *referenceItem;
- obs_source_t *fromSource;
- obs_sceneitem_t *newItem;
-};
-
-static void DuplicateSceneItem(void *_data, obs_scene_t *scene) {
- DuplicateSceneItemData *data = (DuplicateSceneItemData *)_data;
- data->newItem = obs_scene_add(scene, data->fromSource);
- obs_sceneitem_set_visible(data->newItem, obs_sceneitem_visible(data->referenceItem));
+ return request.success();
}
/**
@@ -557,27 +545,33 @@ static void DuplicateSceneItem(void *_data, obs_scene_t *scene) {
* @category scene items
* @since 4.5.0
*/
-HandlerResponse WSRequestHandler::HandleDuplicateSceneItem(WSRequestHandler* req) {
- if (!req->hasField("item")) {
- return req->SendErrorResponse("missing request parameters");
+RpcResponse WSRequestHandler::DuplicateSceneItem(const RpcRequest& request) {
+ struct DuplicateSceneItemData {
+ obs_sceneitem_t *referenceItem;
+ obs_source_t *fromSource;
+ obs_sceneitem_t *newItem;
+ };
+
+ if (!request.hasField("item")) {
+ return request.failed("missing request parameters");
}
- const char* fromSceneName = obs_data_get_string(req->data, "fromScene");
+ const char* fromSceneName = obs_data_get_string(request.parameters(), "fromScene");
OBSScene fromScene = Utils::GetSceneFromNameOrCurrent(fromSceneName);
if (!fromScene) {
- return req->SendErrorResponse("requested fromScene doesn't exist");
+ return request.failed("requested fromScene doesn't exist");
}
- const char* toSceneName = obs_data_get_string(req->data, "toScene");
+ const char* toSceneName = obs_data_get_string(request.parameters(), "toScene");
OBSScene toScene = Utils::GetSceneFromNameOrCurrent(toSceneName);
if (!toScene) {
- return req->SendErrorResponse("requested toScene doesn't exist");
+ return request.failed("requested toScene doesn't exist");
}
- OBSDataAutoRelease item = obs_data_get_obj(req->data, "item");
+ OBSDataAutoRelease item = obs_data_get_obj(request.parameters(), "item");
OBSSceneItemAutoRelease referenceItem = Utils::GetSceneItemFromItem(fromScene, item);
if (!referenceItem) {
- return req->SendErrorResponse("item with id/name combination not found in specified scene");
+ return request.failed("item with id/name combination not found in specified scene");
}
DuplicateSceneItemData data;
@@ -585,12 +579,16 @@ HandlerResponse WSRequestHandler::HandleDuplicateSceneItem(WSRequestHandler* req
data.referenceItem = referenceItem;
obs_enter_graphics();
- obs_scene_atomic_update(toScene, DuplicateSceneItem, &data);
+ obs_scene_atomic_update(toScene, [](void *_data, obs_scene_t *scene) {
+ auto data = reinterpret_cast(_data);
+ data->newItem = obs_scene_add(scene, data->fromSource);
+ obs_sceneitem_set_visible(data->newItem, obs_sceneitem_visible(data->referenceItem));
+ }, &data);
obs_leave_graphics();
obs_sceneitem_t *newItem = data.newItem;
if (!newItem) {
- return req->SendErrorResponse("Error duplicating scene item");
+ return request.failed("Error duplicating scene item");
}
OBSDataAutoRelease itemData = obs_data_create();
@@ -601,5 +599,5 @@ HandlerResponse WSRequestHandler::HandleDuplicateSceneItem(WSRequestHandler* req
obs_data_set_obj(responseData, "item", itemData);
obs_data_set_string(responseData, "scene", obs_source_get_name(obs_scene_get_source(toScene)));
- return req->SendOKResponse(responseData);
+ return request.success(responseData);
}
diff --git a/src/WSRequestHandler_Scenes.cpp b/src/WSRequestHandler_Scenes.cpp
index 3a8754b4..9399ac5d 100644
--- a/src/WSRequestHandler_Scenes.cpp
+++ b/src/WSRequestHandler_Scenes.cpp
@@ -18,19 +18,19 @@
* @category scenes
* @since 0.3
*/
-HandlerResponse WSRequestHandler::HandleSetCurrentScene(WSRequestHandler* req) {
- if (!req->hasField("scene-name")) {
- return req->SendErrorResponse("missing request parameters");
+RpcResponse WSRequestHandler::SetCurrentScene(const RpcRequest& request) {
+ if (!request.hasField("scene-name")) {
+ return request.failed("missing request parameters");
}
- const char* sceneName = obs_data_get_string(req->data, "scene-name");
+ const char* sceneName = obs_data_get_string(request.parameters(), "scene-name");
OBSSourceAutoRelease source = obs_get_source_by_name(sceneName);
if (source) {
obs_frontend_set_current_scene(source);
- return req->SendOKResponse();
+ return request.success();
} else {
- return req->SendErrorResponse("requested scene does not exist");
+ return request.failed("requested scene does not exist");
}
}
@@ -45,7 +45,7 @@ HandlerResponse WSRequestHandler::HandleSetCurrentScene(WSRequestHandler* req) {
* @category scenes
* @since 0.3
*/
-HandlerResponse WSRequestHandler::HandleGetCurrentScene(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::GetCurrentScene(const RpcRequest& request) {
OBSSourceAutoRelease currentScene = obs_frontend_get_current_scene();
OBSDataArrayAutoRelease sceneItems = Utils::GetSceneItems(currentScene);
@@ -53,7 +53,7 @@ HandlerResponse WSRequestHandler::HandleGetCurrentScene(WSRequestHandler* req) {
obs_data_set_string(data, "name", obs_source_get_name(currentScene));
obs_data_set_array(data, "sources", sceneItems);
- return req->SendOKResponse(data);
+ return request.success(data);
}
/**
@@ -67,7 +67,7 @@ HandlerResponse WSRequestHandler::HandleGetCurrentScene(WSRequestHandler* req) {
* @category scenes
* @since 0.3
*/
-HandlerResponse WSRequestHandler::HandleGetSceneList(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::GetSceneList(const RpcRequest& request) {
OBSSourceAutoRelease currentScene = obs_frontend_get_current_scene();
OBSDataArrayAutoRelease scenes = Utils::GetScenes();
@@ -76,7 +76,7 @@ HandlerResponse WSRequestHandler::HandleGetSceneList(WSRequestHandler* req) {
obs_source_get_name(currentScene));
obs_data_set_array(data, "scenes", scenes);
- return req->SendOKResponse(data);
+ return request.success(data);
}
/**
@@ -92,16 +92,16 @@ HandlerResponse WSRequestHandler::HandleGetSceneList(WSRequestHandler* req) {
* @category scenes
* @since 4.5.0
*/
-HandlerResponse WSRequestHandler::HandleReorderSceneItems(WSRequestHandler* req) {
- QString sceneName = obs_data_get_string(req->data, "scene");
+RpcResponse WSRequestHandler::ReorderSceneItems(const RpcRequest& request) {
+ QString sceneName = obs_data_get_string(request.parameters(), "scene");
OBSScene scene = Utils::GetSceneFromNameOrCurrent(sceneName);
if (!scene) {
- return req->SendErrorResponse("requested scene doesn't exist");
+ return request.failed("requested scene doesn't exist");
}
- OBSDataArrayAutoRelease items = obs_data_get_array(req->data, "items");
+ OBSDataArrayAutoRelease items = obs_data_get_array(request.parameters(), "items");
if (!items) {
- return req->SendErrorResponse("sceneItem order not specified");
+ return request.failed("sceneItem order not specified");
}
struct reorder_context {
@@ -143,8 +143,8 @@ HandlerResponse WSRequestHandler::HandleReorderSceneItems(WSRequestHandler* req)
}, &ctx);
if (!ctx.success) {
- return req->SendErrorResponse(ctx.errorMessage);
+ return request.failed(ctx.errorMessage);
}
- return req->SendOKResponse();
+ return request.success();
}
diff --git a/src/WSRequestHandler_Sources.cpp b/src/WSRequestHandler_Sources.cpp
index 23207139..2feca185 100644
--- a/src/WSRequestHandler_Sources.cpp
+++ b/src/WSRequestHandler_Sources.cpp
@@ -21,7 +21,7 @@
* @category sources
* @since 4.3.0
*/
-HandlerResponse WSRequestHandler::HandleGetSourcesList(WSRequestHandler* req)
+RpcResponse WSRequestHandler::GetSourcesList(const RpcRequest& request)
{
OBSDataArrayAutoRelease sourcesArray = obs_data_array_create();
@@ -64,7 +64,7 @@ HandlerResponse WSRequestHandler::HandleGetSourcesList(WSRequestHandler* req)
OBSDataAutoRelease response = obs_data_create();
obs_data_set_array(response, "sources", sourcesArray);
- return req->SendOKResponse(response);
+ return request.success(response);
}
/**
@@ -89,7 +89,7 @@ HandlerResponse WSRequestHandler::HandleGetSourcesList(WSRequestHandler* req)
* @category sources
* @since 4.3.0
*/
-HandlerResponse WSRequestHandler::HandleGetSourceTypesList(WSRequestHandler* req)
+RpcResponse WSRequestHandler::GetSourceTypesList(const RpcRequest& request)
{
OBSDataArrayAutoRelease idsArray = obs_data_array_create();
@@ -142,7 +142,7 @@ HandlerResponse WSRequestHandler::HandleGetSourceTypesList(WSRequestHandler* req
OBSDataAutoRelease response = obs_data_create();
obs_data_set_array(response, "types", idsArray);
- return req->SendOKResponse(response);
+ return request.success(response);
}
/**
@@ -159,20 +159,20 @@ HandlerResponse WSRequestHandler::HandleGetSourceTypesList(WSRequestHandler* req
* @category sources
* @since 4.0.0
*/
-HandlerResponse WSRequestHandler::HandleGetVolume(WSRequestHandler* req)
+RpcResponse WSRequestHandler::GetVolume(const RpcRequest& request)
{
- if (!req->hasField("source")) {
- return req->SendErrorResponse("missing request parameters");
+ if (!request.hasField("source")) {
+ return request.failed("missing request parameters");
}
- QString sourceName = obs_data_get_string(req->data, "source");
+ QString sourceName = obs_data_get_string(request.parameters(), "source");
if (sourceName.isEmpty()) {
- return req->SendErrorResponse("invalid request parameters");
+ return request.failed("invalid request parameters");
}
OBSSourceAutoRelease source = obs_get_source_by_name(sourceName.toUtf8());
if (!source) {
- return req->SendErrorResponse("specified source doesn't exist");
+ return request.failed("specified source doesn't exist");
}
OBSDataAutoRelease response = obs_data_create();
@@ -180,7 +180,7 @@ HandlerResponse WSRequestHandler::HandleGetVolume(WSRequestHandler* req)
obs_data_set_double(response, "volume", obs_source_get_volume(source));
obs_data_set_bool(response, "muted", obs_source_muted(source));
- return req->SendOKResponse(response);
+ return request.success(response);
}
/**
@@ -194,26 +194,26 @@ HandlerResponse WSRequestHandler::HandleGetVolume(WSRequestHandler* req)
* @category sources
* @since 4.0.0
*/
-HandlerResponse WSRequestHandler::HandleSetVolume(WSRequestHandler* req)
+RpcResponse WSRequestHandler::SetVolume(const RpcRequest& request)
{
- if (!req->hasField("source") || !req->hasField("volume")) {
- return req->SendErrorResponse("missing request parameters");
+ if (!request.hasField("source") || !request.hasField("volume")) {
+ return request.failed("missing request parameters");
}
- QString sourceName = obs_data_get_string(req->data, "source");
- float sourceVolume = obs_data_get_double(req->data, "volume");
+ QString sourceName = obs_data_get_string(request.parameters(), "source");
+ float sourceVolume = obs_data_get_double(request.parameters(), "volume");
if (sourceName.isEmpty() || sourceVolume < 0.0 || sourceVolume > 1.0) {
- return req->SendErrorResponse("invalid request parameters");
+ return request.failed("invalid request parameters");
}
OBSSourceAutoRelease source = obs_get_source_by_name(sourceName.toUtf8());
if (!source) {
- return req->SendErrorResponse("specified source doesn't exist");
+ return request.failed("specified source doesn't exist");
}
obs_source_set_volume(source, sourceVolume);
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -229,27 +229,27 @@ HandlerResponse WSRequestHandler::HandleSetVolume(WSRequestHandler* req)
* @category sources
* @since 4.0.0
*/
-HandlerResponse WSRequestHandler::HandleGetMute(WSRequestHandler* req)
+RpcResponse WSRequestHandler::GetMute(const RpcRequest& request)
{
- if (!req->hasField("source")) {
- return req->SendErrorResponse("missing request parameters");
+ if (!request.hasField("source")) {
+ return request.failed("missing request parameters");
}
- QString sourceName = obs_data_get_string(req->data, "source");
+ QString sourceName = obs_data_get_string(request.parameters(), "source");
if (sourceName.isEmpty()) {
- return req->SendErrorResponse("invalid request parameters");
+ return request.failed("invalid request parameters");
}
OBSSourceAutoRelease source = obs_get_source_by_name(sourceName.toUtf8());
if (!source) {
- return req->SendErrorResponse("specified source doesn't exist");
+ return request.failed("specified source doesn't exist");
}
OBSDataAutoRelease response = obs_data_create();
obs_data_set_string(response, "name", obs_source_get_name(source));
obs_data_set_bool(response, "muted", obs_source_muted(source));
- return req->SendOKResponse(response);
+ return request.success(response);
}
/**
@@ -263,26 +263,26 @@ HandlerResponse WSRequestHandler::HandleGetMute(WSRequestHandler* req)
* @category sources
* @since 4.0.0
*/
-HandlerResponse WSRequestHandler::HandleSetMute(WSRequestHandler* req)
+RpcResponse WSRequestHandler::SetMute(const RpcRequest& request)
{
- if (!req->hasField("source") || !req->hasField("mute")) {
- return req->SendErrorResponse("missing request parameters");
+ if (!request.hasField("source") || !request.hasField("mute")) {
+ return request.failed("missing request parameters");
}
- QString sourceName = obs_data_get_string(req->data, "source");
- bool mute = obs_data_get_bool(req->data, "mute");
+ QString sourceName = obs_data_get_string(request.parameters(), "source");
+ bool mute = obs_data_get_bool(request.parameters(), "mute");
if (sourceName.isEmpty()) {
- return req->SendErrorResponse("invalid request parameters");
+ return request.failed("invalid request parameters");
}
OBSSourceAutoRelease source = obs_get_source_by_name(sourceName.toUtf8());
if (!source) {
- return req->SendErrorResponse("specified source doesn't exist");
+ return request.failed("specified source doesn't exist");
}
obs_source_set_muted(source, mute);
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -295,24 +295,24 @@ HandlerResponse WSRequestHandler::HandleSetMute(WSRequestHandler* req)
* @category sources
* @since 4.0.0
*/
-HandlerResponse WSRequestHandler::HandleToggleMute(WSRequestHandler* req)
+RpcResponse WSRequestHandler::ToggleMute(const RpcRequest& request)
{
- if (!req->hasField("source")) {
- return req->SendErrorResponse("missing request parameters");
+ if (!request.hasField("source")) {
+ return request.failed("missing request parameters");
}
- QString sourceName = obs_data_get_string(req->data, "source");
+ QString sourceName = obs_data_get_string(request.parameters(), "source");
if (sourceName.isEmpty()) {
- return req->SendErrorResponse("invalid request parameters");
+ return request.failed("invalid request parameters");
}
OBSSourceAutoRelease source = obs_get_source_by_name(sourceName.toUtf8());
if (!source) {
- return req->SendErrorResponse("invalid request parameters");
+ return request.failed("invalid request parameters");
}
obs_source_set_muted(source, !obs_source_muted(source));
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -326,26 +326,26 @@ HandlerResponse WSRequestHandler::HandleToggleMute(WSRequestHandler* req)
* @category sources
* @since 4.2.0
*/
-HandlerResponse WSRequestHandler::HandleSetSyncOffset(WSRequestHandler* req)
+RpcResponse WSRequestHandler::SetSyncOffset(const RpcRequest& request)
{
- if (!req->hasField("source") || !req->hasField("offset")) {
- return req->SendErrorResponse("missing request parameters");
+ if (!request.hasField("source") || !request.hasField("offset")) {
+ return request.failed("missing request parameters");
}
- QString sourceName = obs_data_get_string(req->data, "source");
- int64_t sourceSyncOffset = (int64_t)obs_data_get_int(req->data, "offset");
+ QString sourceName = obs_data_get_string(request.parameters(), "source");
+ int64_t sourceSyncOffset = (int64_t)obs_data_get_int(request.parameters(), "offset");
if (sourceName.isEmpty() || sourceSyncOffset < 0) {
- return req->SendErrorResponse("invalid request parameters");
+ return request.failed("invalid request parameters");
}
OBSSourceAutoRelease source = obs_get_source_by_name(sourceName.toUtf8());
if (!source) {
- return req->SendErrorResponse("specified source doesn't exist");
+ return request.failed("specified source doesn't exist");
}
obs_source_set_sync_offset(source, sourceSyncOffset);
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -361,27 +361,27 @@ HandlerResponse WSRequestHandler::HandleSetSyncOffset(WSRequestHandler* req)
* @category sources
* @since 4.2.0
*/
-HandlerResponse WSRequestHandler::HandleGetSyncOffset(WSRequestHandler* req)
+RpcResponse WSRequestHandler::GetSyncOffset(const RpcRequest& request)
{
- if (!req->hasField("source")) {
- return req->SendErrorResponse("missing request parameters");
+ if (!request.hasField("source")) {
+ return request.failed("missing request parameters");
}
- QString sourceName = obs_data_get_string(req->data, "source");
+ QString sourceName = obs_data_get_string(request.parameters(), "source");
if (sourceName.isEmpty()) {
- return req->SendErrorResponse("invalid request parameters");
+ return request.failed("invalid request parameters");
}
OBSSourceAutoRelease source = obs_get_source_by_name(sourceName.toUtf8());
if (!source) {
- return req->SendErrorResponse("specified source doesn't exist");
+ return request.failed("specified source doesn't exist");
}
OBSDataAutoRelease response = obs_data_create();
obs_data_set_string(response, "name", obs_source_get_name(source));
obs_data_set_int(response, "offset", obs_source_get_sync_offset(source));
- return req->SendOKResponse(response);
+ return request.success(response);
}
/**
@@ -399,24 +399,24 @@ HandlerResponse WSRequestHandler::HandleGetSyncOffset(WSRequestHandler* req)
* @category sources
* @since 4.3.0
*/
-HandlerResponse WSRequestHandler::HandleGetSourceSettings(WSRequestHandler* req)
+RpcResponse WSRequestHandler::GetSourceSettings(const RpcRequest& request)
{
- if (!req->hasField("sourceName")) {
- return req->SendErrorResponse("missing request parameters");
+ if (!request.hasField("sourceName")) {
+ return request.failed("missing request parameters");
}
- const char* sourceName = obs_data_get_string(req->data, "sourceName");
+ const char* sourceName = obs_data_get_string(request.parameters(), "sourceName");
OBSSourceAutoRelease source = obs_get_source_by_name(sourceName);
if (!source) {
- return req->SendErrorResponse("specified source doesn't exist");
+ return request.failed("specified source doesn't exist");
}
- if (req->hasField("sourceType")) {
+ if (request.hasField("sourceType")) {
QString actualSourceType = obs_source_get_id(source);
- QString requestedType = obs_data_get_string(req->data, "sourceType");
+ QString requestedType = obs_data_get_string(request.parameters(), "sourceType");
if (actualSourceType != requestedType) {
- return req->SendErrorResponse("specified source exists but is not of expected type");
+ return request.failed("specified source exists but is not of expected type");
}
}
@@ -427,7 +427,7 @@ HandlerResponse WSRequestHandler::HandleGetSourceSettings(WSRequestHandler* req)
obs_data_set_string(response, "sourceType", obs_source_get_id(source));
obs_data_set_obj(response, "sourceSettings", sourceSettings);
- return req->SendOKResponse(response);
+ return request.success(response);
}
/**
@@ -446,29 +446,29 @@ HandlerResponse WSRequestHandler::HandleGetSourceSettings(WSRequestHandler* req)
* @category sources
* @since 4.3.0
*/
-HandlerResponse WSRequestHandler::HandleSetSourceSettings(WSRequestHandler* req)
+RpcResponse WSRequestHandler::SetSourceSettings(const RpcRequest& request)
{
- if (!req->hasField("sourceName") || !req->hasField("sourceSettings")) {
- return req->SendErrorResponse("missing request parameters");
+ if (!request.hasField("sourceName") || !request.hasField("sourceSettings")) {
+ return request.failed("missing request parameters");
}
- const char* sourceName = obs_data_get_string(req->data, "sourceName");
+ const char* sourceName = obs_data_get_string(request.parameters(), "sourceName");
OBSSourceAutoRelease source = obs_get_source_by_name(sourceName);
if (!source) {
- return req->SendErrorResponse("specified source doesn't exist");
+ return request.failed("specified source doesn't exist");
}
- if (req->hasField("sourceType")) {
+ if (request.hasField("sourceType")) {
QString actualSourceType = obs_source_get_id(source);
- QString requestedType = obs_data_get_string(req->data, "sourceType");
+ QString requestedType = obs_data_get_string(request.parameters(), "sourceType");
if (actualSourceType != requestedType) {
- return req->SendErrorResponse("specified source exists but is not of expected type");
+ return request.failed("specified source exists but is not of expected type");
}
}
OBSDataAutoRelease currentSettings = obs_source_get_settings(source);
- OBSDataAutoRelease newSettings = obs_data_get_obj(req->data, "sourceSettings");
+ OBSDataAutoRelease newSettings = obs_data_get_obj(request.parameters(), "sourceSettings");
OBSDataAutoRelease sourceSettings = obs_data_create();
obs_data_apply(sourceSettings, currentSettings);
@@ -482,7 +482,7 @@ HandlerResponse WSRequestHandler::HandleSetSourceSettings(WSRequestHandler* req)
obs_data_set_string(response, "sourceType", obs_source_get_id(source));
obs_data_set_obj(response, "sourceSettings", sourceSettings);
- return req->SendOKResponse(response);
+ return request.success(response);
}
/**
@@ -524,27 +524,27 @@ HandlerResponse WSRequestHandler::HandleSetSourceSettings(WSRequestHandler* req)
* @category sources
* @since 4.1.0
*/
-HandlerResponse WSRequestHandler::HandleGetTextGDIPlusProperties(WSRequestHandler* req)
+RpcResponse WSRequestHandler::GetTextGDIPlusProperties(const RpcRequest& request)
{
- const char* sourceName = obs_data_get_string(req->data, "source");
+ const char* sourceName = obs_data_get_string(request.parameters(), "source");
if (!sourceName) {
- return req->SendErrorResponse("invalid request parameters");
+ return request.failed("invalid request parameters");
}
OBSSourceAutoRelease source = obs_get_source_by_name(sourceName);
if (!source) {
- return req->SendErrorResponse("specified source doesn't exist");
+ return request.failed("specified source doesn't exist");
}
QString sourceId = obs_source_get_id(source);
if (sourceId != "text_gdiplus") {
- return req->SendErrorResponse("not a text gdi plus source");
+ return request.failed("not a text gdi plus source");
}
OBSDataAutoRelease response = obs_source_get_settings(source);
obs_data_set_string(response, "source", obs_source_get_name(source));
- return req->SendOKResponse(response);
+ return request.success(response);
}
/**
@@ -585,77 +585,77 @@ HandlerResponse WSRequestHandler::HandleGetTextGDIPlusProperties(WSRequestHandle
* @category sources
* @since 4.1.0
*/
-HandlerResponse WSRequestHandler::HandleSetTextGDIPlusProperties(WSRequestHandler* req)
+RpcResponse WSRequestHandler::SetTextGDIPlusProperties(const RpcRequest& request)
{
- if (!req->hasField("source")) {
- return req->SendErrorResponse("missing request parameters");
+ if (!request.hasField("source")) {
+ return request.failed("missing request parameters");
}
- const char* sourceName = obs_data_get_string(req->data, "source");
+ const char* sourceName = obs_data_get_string(request.parameters(), "source");
if (!sourceName) {
- return req->SendErrorResponse("invalid request parameters");
+ return request.failed("invalid request parameters");
}
OBSSourceAutoRelease source = obs_get_source_by_name(sourceName);
if (!source) {
- return req->SendErrorResponse("specified source doesn't exist");
+ return request.failed("specified source doesn't exist");
}
QString sourceId = obs_source_get_id(source);
if (sourceId != "text_gdiplus") {
- return req->SendErrorResponse("not a text gdi plus source");
+ return request.failed("not a text gdi plus source");
}
OBSDataAutoRelease settings = obs_source_get_settings(source);
- if (req->hasField("align")) {
- obs_data_set_string(settings, "align", obs_data_get_string(req->data, "align"));
+ if (request.hasField("align")) {
+ obs_data_set_string(settings, "align", obs_data_get_string(request.parameters(), "align"));
}
- if (req->hasField("bk_color")) {
- obs_data_set_int(settings, "bk_color", obs_data_get_int(req->data, "bk_color"));
+ if (request.hasField("bk_color")) {
+ obs_data_set_int(settings, "bk_color", obs_data_get_int(request.parameters(), "bk_color"));
}
- if (req->hasField("bk-opacity")) {
- obs_data_set_int(settings, "bk_opacity", obs_data_get_int(req->data, "bk_opacity"));
+ if (request.hasField("bk-opacity")) {
+ obs_data_set_int(settings, "bk_opacity", obs_data_get_int(request.parameters(), "bk_opacity"));
}
- if (req->hasField("chatlog")) {
- obs_data_set_bool(settings, "chatlog", obs_data_get_bool(req->data, "chatlog"));
+ if (request.hasField("chatlog")) {
+ obs_data_set_bool(settings, "chatlog", obs_data_get_bool(request.parameters(), "chatlog"));
}
- if (req->hasField("chatlog_lines")) {
- obs_data_set_int(settings, "chatlog_lines", obs_data_get_int(req->data, "chatlog_lines"));
+ if (request.hasField("chatlog_lines")) {
+ obs_data_set_int(settings, "chatlog_lines", obs_data_get_int(request.parameters(), "chatlog_lines"));
}
- if (req->hasField("color")) {
- obs_data_set_int(settings, "color", obs_data_get_int(req->data, "color"));
+ if (request.hasField("color")) {
+ obs_data_set_int(settings, "color", obs_data_get_int(request.parameters(), "color"));
}
- if (req->hasField("extents")) {
- obs_data_set_bool(settings, "extents", obs_data_get_bool(req->data, "extents"));
+ if (request.hasField("extents")) {
+ obs_data_set_bool(settings, "extents", obs_data_get_bool(request.parameters(), "extents"));
}
- if (req->hasField("extents_wrap")) {
- obs_data_set_bool(settings, "extents_wrap", obs_data_get_bool(req->data, "extents_wrap"));
+ if (request.hasField("extents_wrap")) {
+ obs_data_set_bool(settings, "extents_wrap", obs_data_get_bool(request.parameters(), "extents_wrap"));
}
- if (req->hasField("extents_cx")) {
- obs_data_set_int(settings, "extents_cx", obs_data_get_int(req->data, "extents_cx"));
+ if (request.hasField("extents_cx")) {
+ obs_data_set_int(settings, "extents_cx", obs_data_get_int(request.parameters(), "extents_cx"));
}
- if (req->hasField("extents_cy")) {
- obs_data_set_int(settings, "extents_cy", obs_data_get_int(req->data, "extents_cy"));
+ if (request.hasField("extents_cy")) {
+ obs_data_set_int(settings, "extents_cy", obs_data_get_int(request.parameters(), "extents_cy"));
}
- if (req->hasField("file")) {
- obs_data_set_string(settings, "file", obs_data_get_string(req->data, "file"));
+ if (request.hasField("file")) {
+ obs_data_set_string(settings, "file", obs_data_get_string(request.parameters(), "file"));
}
- if (req->hasField("font")) {
+ if (request.hasField("font")) {
OBSDataAutoRelease font_obj = obs_data_get_obj(settings, "font");
if (font_obj) {
- OBSDataAutoRelease req_font_obj = obs_data_get_obj(req->data, "font");
+ OBSDataAutoRelease req_font_obj = obs_data_get_obj(request.parameters(), "font");
if (obs_data_has_user_value(req_font_obj, "face")) {
obs_data_set_string(font_obj, "face", obs_data_get_string(req_font_obj, "face"));
@@ -675,57 +675,57 @@ HandlerResponse WSRequestHandler::HandleSetTextGDIPlusProperties(WSRequestHandle
}
}
- if (req->hasField("gradient")) {
- obs_data_set_bool(settings, "gradient", obs_data_get_bool(req->data, "gradient"));
+ if (request.hasField("gradient")) {
+ obs_data_set_bool(settings, "gradient", obs_data_get_bool(request.parameters(), "gradient"));
}
- if (req->hasField("gradient_color")) {
- obs_data_set_int(settings, "gradient_color", obs_data_get_int(req->data, "gradient_color"));
+ if (request.hasField("gradient_color")) {
+ obs_data_set_int(settings, "gradient_color", obs_data_get_int(request.parameters(), "gradient_color"));
}
- if (req->hasField("gradient_dir")) {
- obs_data_set_double(settings, "gradient_dir", obs_data_get_double(req->data, "gradient_dir"));
+ if (request.hasField("gradient_dir")) {
+ obs_data_set_double(settings, "gradient_dir", obs_data_get_double(request.parameters(), "gradient_dir"));
}
- if (req->hasField("gradient_opacity")) {
- obs_data_set_int(settings, "gradient_opacity", obs_data_get_int(req->data, "gradient_opacity"));
+ if (request.hasField("gradient_opacity")) {
+ obs_data_set_int(settings, "gradient_opacity", obs_data_get_int(request.parameters(), "gradient_opacity"));
}
- if (req->hasField("outline")) {
- obs_data_set_bool(settings, "outline", obs_data_get_bool(req->data, "outline"));
+ if (request.hasField("outline")) {
+ obs_data_set_bool(settings, "outline", obs_data_get_bool(request.parameters(), "outline"));
}
- if (req->hasField("outline_size")) {
- obs_data_set_int(settings, "outline_size", obs_data_get_int(req->data, "outline_size"));
+ if (request.hasField("outline_size")) {
+ obs_data_set_int(settings, "outline_size", obs_data_get_int(request.parameters(), "outline_size"));
}
- if (req->hasField("outline_color")) {
- obs_data_set_int(settings, "outline_color", obs_data_get_int(req->data, "outline_color"));
+ if (request.hasField("outline_color")) {
+ obs_data_set_int(settings, "outline_color", obs_data_get_int(request.parameters(), "outline_color"));
}
- if (req->hasField("outline_opacity")) {
- obs_data_set_int(settings, "outline_opacity", obs_data_get_int(req->data, "outline_opacity"));
+ if (request.hasField("outline_opacity")) {
+ obs_data_set_int(settings, "outline_opacity", obs_data_get_int(request.parameters(), "outline_opacity"));
}
- if (req->hasField("read_from_file")) {
- obs_data_set_bool(settings, "read_from_file", obs_data_get_bool(req->data, "read_from_file"));
+ if (request.hasField("read_from_file")) {
+ obs_data_set_bool(settings, "read_from_file", obs_data_get_bool(request.parameters(), "read_from_file"));
}
- if (req->hasField("text")) {
- obs_data_set_string(settings, "text", obs_data_get_string(req->data, "text"));
+ if (request.hasField("text")) {
+ obs_data_set_string(settings, "text", obs_data_get_string(request.parameters(), "text"));
}
- if (req->hasField("valign")) {
- obs_data_set_string(settings, "valign", obs_data_get_string(req->data, "valign"));
+ if (request.hasField("valign")) {
+ obs_data_set_string(settings, "valign", obs_data_get_string(request.parameters(), "valign"));
}
- if (req->hasField("vertical")) {
- obs_data_set_bool(settings, "vertical", obs_data_get_bool(req->data, "vertical"));
+ if (request.hasField("vertical")) {
+ obs_data_set_bool(settings, "vertical", obs_data_get_bool(request.parameters(), "vertical"));
}
obs_source_update(source, settings);
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -755,27 +755,27 @@ HandlerResponse WSRequestHandler::HandleSetTextGDIPlusProperties(WSRequestHandle
* @category sources
* @since 4.5.0
*/
-HandlerResponse WSRequestHandler::HandleGetTextFreetype2Properties(WSRequestHandler* req)
+RpcResponse WSRequestHandler::GetTextFreetype2Properties(const RpcRequest& request)
{
- const char* sourceName = obs_data_get_string(req->data, "source");
+ const char* sourceName = obs_data_get_string(request.parameters(), "source");
if (!sourceName) {
- return req->SendErrorResponse("invalid request parameters");
+ return request.failed("invalid request parameters");
}
OBSSourceAutoRelease source = obs_get_source_by_name(sourceName);
if (!source) {
- return req->SendErrorResponse("specified source doesn't exist");
+ return request.failed("specified source doesn't exist");
}
QString sourceId = obs_source_get_id(source);
if (sourceId != "text_ft2_source") {
- return req->SendErrorResponse("not a freetype 2 source");
+ return request.failed("not a freetype 2 source");
}
OBSDataAutoRelease response = obs_source_get_settings(source);
obs_data_set_string(response, "source", sourceName);
- return req->SendOKResponse(response);
+ return request.success(response);
}
/**
@@ -803,45 +803,45 @@ HandlerResponse WSRequestHandler::HandleGetTextFreetype2Properties(WSRequestHand
* @category sources
* @since 4.5.0
*/
-HandlerResponse WSRequestHandler::HandleSetTextFreetype2Properties(WSRequestHandler* req)
+RpcResponse WSRequestHandler::SetTextFreetype2Properties(const RpcRequest& request)
{
- const char* sourceName = obs_data_get_string(req->data, "source");
+ const char* sourceName = obs_data_get_string(request.parameters(), "source");
if (!sourceName) {
- return req->SendErrorResponse("invalid request parameters");
+ return request.failed("invalid request parameters");
}
OBSSourceAutoRelease source = obs_get_source_by_name(sourceName);
if (!source) {
- return req->SendErrorResponse("specified source doesn't exist");
+ return request.failed("specified source doesn't exist");
}
QString sourceId = obs_source_get_id(source);
if (sourceId != "text_ft2_source") {
- return req->SendErrorResponse("not text freetype 2 source");
+ return request.failed("not text freetype 2 source");
}
OBSDataAutoRelease settings = obs_source_get_settings(source);
- if (req->hasField("color1")) {
- obs_data_set_int(settings, "color1", obs_data_get_int(req->data, "color1"));
+ if (request.hasField("color1")) {
+ obs_data_set_int(settings, "color1", obs_data_get_int(request.parameters(), "color1"));
}
- if (req->hasField("color2")) {
- obs_data_set_int(settings, "color2", obs_data_get_int(req->data, "color2"));
+ if (request.hasField("color2")) {
+ obs_data_set_int(settings, "color2", obs_data_get_int(request.parameters(), "color2"));
}
- if (req->hasField("custom_width")) {
- obs_data_set_int(settings, "custom_width", obs_data_get_int(req->data, "custom_width"));
+ if (request.hasField("custom_width")) {
+ obs_data_set_int(settings, "custom_width", obs_data_get_int(request.parameters(), "custom_width"));
}
- if (req->hasField("drop_shadow")) {
- obs_data_set_bool(settings, "drop_shadow", obs_data_get_bool(req->data, "drop_shadow"));
+ if (request.hasField("drop_shadow")) {
+ obs_data_set_bool(settings, "drop_shadow", obs_data_get_bool(request.parameters(), "drop_shadow"));
}
- if (req->hasField("font")) {
+ if (request.hasField("font")) {
OBSDataAutoRelease font_obj = obs_data_get_obj(settings, "font");
if (font_obj) {
- OBSDataAutoRelease req_font_obj = obs_data_get_obj(req->data, "font");
+ OBSDataAutoRelease req_font_obj = obs_data_get_obj(request.parameters(), "font");
if (obs_data_has_user_value(req_font_obj, "face")) {
obs_data_set_string(font_obj, "face", obs_data_get_string(req_font_obj, "face"));
@@ -861,33 +861,33 @@ HandlerResponse WSRequestHandler::HandleSetTextFreetype2Properties(WSRequestHand
}
}
- if (req->hasField("from_file")) {
- obs_data_set_bool(settings, "from_file", obs_data_get_bool(req->data, "from_file"));
+ if (request.hasField("from_file")) {
+ obs_data_set_bool(settings, "from_file", obs_data_get_bool(request.parameters(), "from_file"));
}
- if (req->hasField("log_mode")) {
- obs_data_set_bool(settings, "log_mode", obs_data_get_bool(req->data, "log_mode"));
+ if (request.hasField("log_mode")) {
+ obs_data_set_bool(settings, "log_mode", obs_data_get_bool(request.parameters(), "log_mode"));
}
- if (req->hasField("outline")) {
- obs_data_set_bool(settings, "outline", obs_data_get_bool(req->data, "outline"));
+ if (request.hasField("outline")) {
+ obs_data_set_bool(settings, "outline", obs_data_get_bool(request.parameters(), "outline"));
}
- if (req->hasField("text")) {
- obs_data_set_string(settings, "text", obs_data_get_string(req->data, "text"));
+ if (request.hasField("text")) {
+ obs_data_set_string(settings, "text", obs_data_get_string(request.parameters(), "text"));
}
- if (req->hasField("text_file")) {
- obs_data_set_string(settings, "text_file", obs_data_get_string(req->data, "text_file"));
+ if (request.hasField("text_file")) {
+ obs_data_set_string(settings, "text_file", obs_data_get_string(request.parameters(), "text_file"));
}
- if (req->hasField("word_wrap")) {
- obs_data_set_bool(settings, "word_wrap", obs_data_get_bool(req->data, "word_wrap"));
+ if (request.hasField("word_wrap")) {
+ obs_data_set_bool(settings, "word_wrap", obs_data_get_bool(request.parameters(), "word_wrap"));
}
obs_source_update(source, settings);
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -910,27 +910,27 @@ HandlerResponse WSRequestHandler::HandleSetTextFreetype2Properties(WSRequestHand
* @category sources
* @since 4.1.0
*/
-HandlerResponse WSRequestHandler::HandleGetBrowserSourceProperties(WSRequestHandler* req)
+RpcResponse WSRequestHandler::GetBrowserSourceProperties(const RpcRequest& request)
{
- const char* sourceName = obs_data_get_string(req->data, "source");
+ const char* sourceName = obs_data_get_string(request.parameters(), "source");
if (!sourceName) {
- return req->SendErrorResponse("invalid request parameters");
+ return request.failed("invalid request parameters");
}
OBSSourceAutoRelease source = obs_get_source_by_name(sourceName);
if (!source) {
- return req->SendErrorResponse("specified source doesn't exist");
+ return request.failed("specified source doesn't exist");
}
QString sourceId = obs_source_get_id(source);
if (sourceId != "browser_source" && sourceId != "linuxbrowser-source") {
- return req->SendErrorResponse("not a browser source");
+ return request.failed("not a browser source");
}
OBSDataAutoRelease response = obs_source_get_settings(source);
obs_data_set_string(response, "source", obs_source_get_name(source));
- return req->SendOKResponse(response);
+ return request.success(response);
}
/**
@@ -952,68 +952,68 @@ HandlerResponse WSRequestHandler::HandleGetBrowserSourceProperties(WSRequestHand
* @category sources
* @since 4.1.0
*/
-HandlerResponse WSRequestHandler::HandleSetBrowserSourceProperties(WSRequestHandler* req)
+RpcResponse WSRequestHandler::SetBrowserSourceProperties(const RpcRequest& request)
{
- if (!req->hasField("source")) {
- return req->SendErrorResponse("missing request parameters");
+ if (!request.hasField("source")) {
+ return request.failed("missing request parameters");
}
- const char* sourceName = obs_data_get_string(req->data, "source");
+ const char* sourceName = obs_data_get_string(request.parameters(), "source");
if (!sourceName) {
- return req->SendErrorResponse("invalid request parameters");
+ return request.failed("invalid request parameters");
}
OBSSourceAutoRelease source = obs_get_source_by_name(sourceName);
if (!source) {
- return req->SendErrorResponse("specified source doesn't exist");
+ return request.failed("specified source doesn't exist");
}
QString sourceId = obs_source_get_id(source);
if(sourceId != "browser_source" && sourceId != "linuxbrowser-source") {
- return req->SendErrorResponse("not a browser source");
+ return request.failed("not a browser source");
}
OBSDataAutoRelease settings = obs_source_get_settings(source);
- if (req->hasField("restart_when_active")) {
- obs_data_set_bool(settings, "restart_when_active", obs_data_get_bool(req->data, "restart_when_active"));
+ if (request.hasField("restart_when_active")) {
+ obs_data_set_bool(settings, "restart_when_active", obs_data_get_bool(request.parameters(), "restart_when_active"));
}
- if (req->hasField("shutdown")) {
- obs_data_set_bool(settings, "shutdown", obs_data_get_bool(req->data, "shutdown"));
+ if (request.hasField("shutdown")) {
+ obs_data_set_bool(settings, "shutdown", obs_data_get_bool(request.parameters(), "shutdown"));
}
- if (req->hasField("is_local_file")) {
- obs_data_set_bool(settings, "is_local_file", obs_data_get_bool(req->data, "is_local_file"));
+ if (request.hasField("is_local_file")) {
+ obs_data_set_bool(settings, "is_local_file", obs_data_get_bool(request.parameters(), "is_local_file"));
}
- if (req->hasField("local_file")) {
- obs_data_set_string(settings, "local_file", obs_data_get_string(req->data, "local_file"));
+ if (request.hasField("local_file")) {
+ obs_data_set_string(settings, "local_file", obs_data_get_string(request.parameters(), "local_file"));
}
- if (req->hasField("url")) {
- obs_data_set_string(settings, "url", obs_data_get_string(req->data, "url"));
+ if (request.hasField("url")) {
+ obs_data_set_string(settings, "url", obs_data_get_string(request.parameters(), "url"));
}
- if (req->hasField("css")) {
- obs_data_set_string(settings, "css", obs_data_get_string(req->data, "css"));
+ if (request.hasField("css")) {
+ obs_data_set_string(settings, "css", obs_data_get_string(request.parameters(), "css"));
}
- if (req->hasField("width")) {
- obs_data_set_int(settings, "width", obs_data_get_int(req->data, "width"));
+ if (request.hasField("width")) {
+ obs_data_set_int(settings, "width", obs_data_get_int(request.parameters(), "width"));
}
- if (req->hasField("height")) {
- obs_data_set_int(settings, "height", obs_data_get_int(req->data, "height"));
+ if (request.hasField("height")) {
+ obs_data_set_int(settings, "height", obs_data_get_int(request.parameters(), "height"));
}
- if (req->hasField("fps")) {
- obs_data_set_int(settings, "fps", obs_data_get_int(req->data, "fps"));
+ if (request.hasField("fps")) {
+ obs_data_set_int(settings, "fps", obs_data_get_int(request.parameters(), "fps"));
}
obs_source_update(source, settings);
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -1030,7 +1030,7 @@ HandlerResponse WSRequestHandler::HandleSetBrowserSourceProperties(WSRequestHand
* @category sources
* @since 4.1.0
*/
-HandlerResponse WSRequestHandler::HandleGetSpecialSources(WSRequestHandler* req)
+RpcResponse WSRequestHandler::GetSpecialSources(const RpcRequest& request)
{
OBSDataAutoRelease response = obs_data_create();
@@ -1052,7 +1052,7 @@ HandlerResponse WSRequestHandler::HandleGetSpecialSources(WSRequestHandler* req)
}
}
- return req->SendOKResponse(response);
+ return request.success(response);
}
/**
@@ -1071,23 +1071,23 @@ HandlerResponse WSRequestHandler::HandleGetSpecialSources(WSRequestHandler* req)
* @category sources
* @since 4.5.0
*/
-HandlerResponse WSRequestHandler::HandleGetSourceFilters(WSRequestHandler* req)
+RpcResponse WSRequestHandler::GetSourceFilters(const RpcRequest& request)
{
- if (!req->hasField("sourceName")) {
- return req->SendErrorResponse("missing request parameters");
+ if (!request.hasField("sourceName")) {
+ return request.failed("missing request parameters");
}
- const char* sourceName = obs_data_get_string(req->data, "sourceName");
+ const char* sourceName = obs_data_get_string(request.parameters(), "sourceName");
OBSSourceAutoRelease source = obs_get_source_by_name(sourceName);
if (!source) {
- return req->SendErrorResponse("specified source doesn't exist");
+ return request.failed("specified source doesn't exist");
}
OBSDataArrayAutoRelease filters = Utils::GetSourceFiltersList(source, true);
OBSDataAutoRelease response = obs_data_create();
obs_data_set_array(response, "filters", filters);
- return req->SendOKResponse(response);
+ return request.success(response);
}
/**
@@ -1106,26 +1106,26 @@ HandlerResponse WSRequestHandler::HandleGetSourceFilters(WSRequestHandler* req)
* @category sources
* @since 4.7.0
*/
-HandlerResponse WSRequestHandler::HandleGetSourceFilterInfo(WSRequestHandler* req)
+RpcResponse WSRequestHandler::GetSourceFilterInfo(const RpcRequest& request)
{
- if (!req->hasField("sourceName") || !req->hasField("filterName")) {
- return req->SendErrorResponse("missing request parameters");
+ if (!request.hasField("sourceName") || !request.hasField("filterName")) {
+ return request.failed("missing request parameters");
}
- const char* sourceName = obs_data_get_string(req->data, "sourceName");
+ const char* sourceName = obs_data_get_string(request.parameters(), "sourceName");
OBSSourceAutoRelease source = obs_get_source_by_name(sourceName);
if (!source) {
- return req->SendErrorResponse("specified source doesn't exist");
+ return request.failed("specified source doesn't exist");
}
- const char* filterName = obs_data_get_string(req->data, "filterName");
+ const char* filterName = obs_data_get_string(request.parameters(), "filterName");
OBSSourceAutoRelease filter = obs_source_get_filter_by_name(source, filterName);
if (!filter) {
- return req->SendErrorResponse("specified filter doesn't exist on specified source");
+ return request.failed("specified filter doesn't exist on specified source");
}
OBSDataAutoRelease response = Utils::GetSourceFilterInfo(filter, true);
- return req->SendOKResponse(response);
+ return request.success(response);
}
/**
@@ -1141,40 +1141,40 @@ HandlerResponse WSRequestHandler::HandleGetSourceFilterInfo(WSRequestHandler* re
* @category sources
* @since 4.5.0
*/
-HandlerResponse WSRequestHandler::HandleAddFilterToSource(WSRequestHandler* req)
+RpcResponse WSRequestHandler::AddFilterToSource(const RpcRequest& request)
{
- if (!req->hasField("sourceName") || !req->hasField("filterName") ||
- !req->hasField("filterType") || !req->hasField("filterSettings"))
+ if (!request.hasField("sourceName") || !request.hasField("filterName") ||
+ !request.hasField("filterType") || !request.hasField("filterSettings"))
{
- return req->SendErrorResponse("missing request parameters");
+ return request.failed("missing request parameters");
}
- const char* sourceName = obs_data_get_string(req->data, "sourceName");
- const char* filterName = obs_data_get_string(req->data, "filterName");
- const char* filterType = obs_data_get_string(req->data, "filterType");
- OBSDataAutoRelease filterSettings = obs_data_get_obj(req->data, "filterSettings");
+ const char* sourceName = obs_data_get_string(request.parameters(), "sourceName");
+ const char* filterName = obs_data_get_string(request.parameters(), "filterName");
+ const char* filterType = obs_data_get_string(request.parameters(), "filterType");
+ OBSDataAutoRelease filterSettings = obs_data_get_obj(request.parameters(), "filterSettings");
OBSSourceAutoRelease source = obs_get_source_by_name(sourceName);
if (!source) {
- return req->SendErrorResponse("specified source doesn't exist");
+ return request.failed("specified source doesn't exist");
}
OBSSourceAutoRelease existingFilter = obs_source_get_filter_by_name(source, filterName);
if (existingFilter) {
- return req->SendErrorResponse("filter name already taken");
+ return request.failed("filter name already taken");
}
OBSSourceAutoRelease filter = obs_source_create_private(filterType, filterName, filterSettings);
if (!filter) {
- return req->SendErrorResponse("filter creation failed");
+ return request.failed("filter creation failed");
}
if (obs_source_get_type(filter) != OBS_SOURCE_TYPE_FILTER) {
- return req->SendErrorResponse("invalid filter type");
+ return request.failed("invalid filter type");
}
obs_source_filter_add(source, filter);
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -1188,28 +1188,28 @@ HandlerResponse WSRequestHandler::HandleAddFilterToSource(WSRequestHandler* req)
* @category sources
* @since 4.5.0
*/
-HandlerResponse WSRequestHandler::HandleRemoveFilterFromSource(WSRequestHandler* req)
+RpcResponse WSRequestHandler::RemoveFilterFromSource(const RpcRequest& request)
{
- if (!req->hasField("sourceName") || !req->hasField("filterName")) {
- return req->SendErrorResponse("missing request parameters");
+ if (!request.hasField("sourceName") || !request.hasField("filterName")) {
+ return request.failed("missing request parameters");
}
- const char* sourceName = obs_data_get_string(req->data, "sourceName");
- const char* filterName = obs_data_get_string(req->data, "filterName");
+ const char* sourceName = obs_data_get_string(request.parameters(), "sourceName");
+ const char* filterName = obs_data_get_string(request.parameters(), "filterName");
OBSSourceAutoRelease source = obs_get_source_by_name(sourceName);
if (!source) {
- return req->SendErrorResponse("specified source doesn't exist");
+ return request.failed("specified source doesn't exist");
}
OBSSourceAutoRelease filter = obs_source_get_filter_by_name(source, filterName);
if (!filter) {
- return req->SendErrorResponse("specified filter doesn't exist");
+ return request.failed("specified filter doesn't exist");
}
obs_source_filter_remove(source, filter);
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -1224,28 +1224,28 @@ HandlerResponse WSRequestHandler::HandleRemoveFilterFromSource(WSRequestHandler*
* @category sources
* @since 4.5.0
*/
-HandlerResponse WSRequestHandler::HandleReorderSourceFilter(WSRequestHandler* req)
+RpcResponse WSRequestHandler::ReorderSourceFilter(const RpcRequest& request)
{
- if (!req->hasField("sourceName") || !req->hasField("filterName") || !req->hasField("newIndex")) {
- return req->SendErrorResponse("missing request parameters");
+ if (!request.hasField("sourceName") || !request.hasField("filterName") || !request.hasField("newIndex")) {
+ return request.failed("missing request parameters");
}
- const char* sourceName = obs_data_get_string(req->data, "sourceName");
- const char* filterName = obs_data_get_string(req->data, "filterName");
- int newIndex = obs_data_get_int(req->data, "newIndex");
+ const char* sourceName = obs_data_get_string(request.parameters(), "sourceName");
+ const char* filterName = obs_data_get_string(request.parameters(), "filterName");
+ int newIndex = obs_data_get_int(request.parameters(), "newIndex");
if (newIndex < 0) {
- return req->SendErrorResponse("invalid index");
+ return request.failed("invalid index");
}
OBSSourceAutoRelease source = obs_get_source_by_name(sourceName);
if (!source) {
- return req->SendErrorResponse("specified source doesn't exist");
+ return request.failed("specified source doesn't exist");
}
OBSSourceAutoRelease filter = obs_source_get_filter_by_name(source, filterName);
if (!filter) {
- return req->SendErrorResponse("specified filter doesn't exist");
+ return request.failed("specified filter doesn't exist");
}
struct filterSearch {
@@ -1265,7 +1265,7 @@ HandlerResponse WSRequestHandler::HandleReorderSourceFilter(WSRequestHandler* re
int lastFilterIndex = ctx.i + 1;
if (newIndex > lastFilterIndex) {
- return req->SendErrorResponse("index out of bounds");
+ return request.failed("index out of bounds");
}
int currentIndex = ctx.filterIndex;
@@ -1282,7 +1282,7 @@ HandlerResponse WSRequestHandler::HandleReorderSourceFilter(WSRequestHandler* re
}
}
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -1297,24 +1297,24 @@ HandlerResponse WSRequestHandler::HandleReorderSourceFilter(WSRequestHandler* re
* @category sources
* @since 4.5.0
*/
-HandlerResponse WSRequestHandler::HandleMoveSourceFilter(WSRequestHandler* req)
+RpcResponse WSRequestHandler::MoveSourceFilter(const RpcRequest& request)
{
- if (!req->hasField("sourceName") || !req->hasField("filterName") || !req->hasField("movementType")) {
- return req->SendErrorResponse("missing request parameters");
+ if (!request.hasField("sourceName") || !request.hasField("filterName") || !request.hasField("movementType")) {
+ return request.failed("missing request parameters");
}
- const char* sourceName = obs_data_get_string(req->data, "sourceName");
- const char* filterName = obs_data_get_string(req->data, "filterName");
- QString movementType(obs_data_get_string(req->data, "movementType"));
+ const char* sourceName = obs_data_get_string(request.parameters(), "sourceName");
+ const char* filterName = obs_data_get_string(request.parameters(), "filterName");
+ QString movementType(obs_data_get_string(request.parameters(), "movementType"));
OBSSourceAutoRelease source = obs_get_source_by_name(sourceName);
if (!source) {
- return req->SendErrorResponse("specified source doesn't exist");
+ return request.failed("specified source doesn't exist");
}
OBSSourceAutoRelease filter = obs_source_get_filter_by_name(source, filterName);
if (!filter) {
- return req->SendErrorResponse("specified filter doesn't exist");
+ return request.failed("specified filter doesn't exist");
}
obs_order_movement movement;
@@ -1331,12 +1331,12 @@ HandlerResponse WSRequestHandler::HandleMoveSourceFilter(WSRequestHandler* req)
movement = OBS_ORDER_MOVE_BOTTOM;
}
else {
- return req->SendErrorResponse("invalid value for movementType: must be either 'up', 'down', 'top' or 'bottom'.");
+ return request.failed("invalid value for movementType: must be either 'up', 'down', 'top' or 'bottom'.");
}
obs_source_filter_set_order(source, filter, movement);
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -1351,31 +1351,31 @@ HandlerResponse WSRequestHandler::HandleMoveSourceFilter(WSRequestHandler* req)
* @category sources
* @since 4.5.0
*/
-HandlerResponse WSRequestHandler::HandleSetSourceFilterSettings(WSRequestHandler* req)
+RpcResponse WSRequestHandler::SetSourceFilterSettings(const RpcRequest& request)
{
- if (!req->hasField("sourceName") || !req->hasField("filterName") || !req->hasField("filterSettings")) {
- return req->SendErrorResponse("missing request parameters");
+ if (!request.hasField("sourceName") || !request.hasField("filterName") || !request.hasField("filterSettings")) {
+ return request.failed("missing request parameters");
}
- const char* sourceName = obs_data_get_string(req->data, "sourceName");
- const char* filterName = obs_data_get_string(req->data, "filterName");
- OBSDataAutoRelease newFilterSettings = obs_data_get_obj(req->data, "filterSettings");
+ const char* sourceName = obs_data_get_string(request.parameters(), "sourceName");
+ const char* filterName = obs_data_get_string(request.parameters(), "filterName");
+ OBSDataAutoRelease newFilterSettings = obs_data_get_obj(request.parameters(), "filterSettings");
OBSSourceAutoRelease source = obs_get_source_by_name(sourceName);
if (!source) {
- return req->SendErrorResponse("specified source doesn't exist");
+ return request.failed("specified source doesn't exist");
}
OBSSourceAutoRelease filter = obs_source_get_filter_by_name(source, filterName);
if (!filter) {
- return req->SendErrorResponse("specified filter doesn't exist");
+ return request.failed("specified filter doesn't exist");
}
OBSDataAutoRelease settings = obs_source_get_settings(filter);
obs_data_apply(settings, newFilterSettings);
obs_source_update(filter, settings);
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -1390,28 +1390,28 @@ HandlerResponse WSRequestHandler::HandleSetSourceFilterSettings(WSRequestHandler
* @category sources
* @since 4.7.0
*/
-HandlerResponse WSRequestHandler::HandleSetSourceFilterVisibility(WSRequestHandler* req)
+RpcResponse WSRequestHandler::SetSourceFilterVisibility(const RpcRequest& request)
{
- if (!req->hasField("sourceName") || !req->hasField("filterName") || !req->hasField("filterEnabled")) {
- return req->SendErrorResponse("missing request parameters");
+ if (!request.hasField("sourceName") || !request.hasField("filterName") || !request.hasField("filterEnabled")) {
+ return request.failed("missing request parameters");
}
- const char* sourceName = obs_data_get_string(req->data, "sourceName");
+ const char* sourceName = obs_data_get_string(request.parameters(), "sourceName");
OBSSourceAutoRelease source = obs_get_source_by_name(sourceName);
if (!source) {
- return req->SendErrorResponse("specified source doesn't exist");
+ return request.failed("specified source doesn't exist");
}
- const char* filterName = obs_data_get_string(req->data, "filterName");
+ const char* filterName = obs_data_get_string(request.parameters(), "filterName");
OBSSourceAutoRelease filter = obs_source_get_filter_by_name(source, filterName);
if (!filter) {
- return req->SendErrorResponse("specified filter doesn't exist on specified source");
+ return request.failed("specified filter doesn't exist on specified source");
}
- bool filterEnabled = obs_data_get_bool(req->data, "filterEnabled");
+ bool filterEnabled = obs_data_get_bool(request.parameters(), "filterEnabled");
obs_source_set_enabled(filter, filterEnabled);
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -1439,19 +1439,19 @@ HandlerResponse WSRequestHandler::HandleSetSourceFilterVisibility(WSRequestHandl
* @category sources
* @since 4.6.0
*/
-HandlerResponse WSRequestHandler::HandleTakeSourceScreenshot(WSRequestHandler* req) {
- if (!req->hasField("sourceName")) {
- return req->SendErrorResponse("missing request parameters");
+RpcResponse WSRequestHandler::TakeSourceScreenshot(const RpcRequest& request) {
+ if (!request.hasField("sourceName")) {
+ return request.failed("missing request parameters");
}
- if (!req->hasField("embedPictureFormat") && !req->hasField("saveToFilePath")) {
- return req->SendErrorResponse("At least 'embedPictureFormat' or 'saveToFilePath' must be specified");
+ if (!request.hasField("embedPictureFormat") && !request.hasField("saveToFilePath")) {
+ return request.failed("At least 'embedPictureFormat' or 'saveToFilePath' must be specified");
}
- const char* sourceName = obs_data_get_string(req->data, "sourceName");
+ const char* sourceName = obs_data_get_string(request.parameters(), "sourceName");
OBSSourceAutoRelease source = obs_get_source_by_name(sourceName);
if (!source) {
- return req->SendErrorResponse("specified source doesn't exist");;
+ return request.failed("specified source doesn't exist");;
}
const uint32_t sourceWidth = obs_source_get_base_width(source);
@@ -1461,18 +1461,18 @@ HandlerResponse WSRequestHandler::HandleTakeSourceScreenshot(WSRequestHandler* r
uint32_t imgWidth = sourceWidth;
uint32_t imgHeight = sourceHeight;
- if (req->hasField("width")) {
- imgWidth = obs_data_get_int(req->data, "width");
+ if (request.hasField("width")) {
+ imgWidth = obs_data_get_int(request.parameters(), "width");
- if (!req->hasField("height")) {
+ if (!request.hasField("height")) {
imgHeight = ((double)imgWidth / sourceAspectRatio);
}
}
- if (req->hasField("height")) {
- imgHeight = obs_data_get_int(req->data, "height");
+ if (request.hasField("height")) {
+ imgHeight = obs_data_get_int(request.parameters(), "height");
- if (!req->hasField("width")) {
+ if (!request.hasField("width")) {
imgWidth = ((double)imgHeight * sourceAspectRatio);
}
}
@@ -1524,25 +1524,25 @@ HandlerResponse WSRequestHandler::HandleTakeSourceScreenshot(WSRequestHandler* r
obs_leave_graphics();
if (!renderSuccess) {
- return req->SendErrorResponse("Source render failed");
+ return request.failed("Source render failed");
}
OBSDataAutoRelease response = obs_data_create();
- if (req->hasField("embedPictureFormat")) {
- const char* pictureFormat = obs_data_get_string(req->data, "embedPictureFormat");
+ if (request.hasField("embedPictureFormat")) {
+ const char* pictureFormat = obs_data_get_string(request.parameters(), "embedPictureFormat");
QByteArrayList supportedFormats = QImageWriter::supportedImageFormats();
if (!supportedFormats.contains(pictureFormat)) {
QString errorMessage = QString("Unsupported picture format: %1").arg(pictureFormat);
- return req->SendErrorResponse(errorMessage.toUtf8());
+ return request.failed(errorMessage.toUtf8());
}
QByteArray encodedImgBytes;
QBuffer buffer(&encodedImgBytes);
buffer.open(QBuffer::WriteOnly);
if (!sourceImage.save(&buffer, pictureFormat)) {
- return req->SendErrorResponse("Embed image encoding failed");
+ return request.failed("Embed image encoding failed");
}
buffer.close();
@@ -1554,17 +1554,17 @@ HandlerResponse WSRequestHandler::HandleTakeSourceScreenshot(WSRequestHandler* r
obs_data_set_string(response, "img", imgBase64.toUtf8());
}
- if (req->hasField("saveToFilePath")) {
- QString filePathStr = obs_data_get_string(req->data, "saveToFilePath");
+ if (request.hasField("saveToFilePath")) {
+ QString filePathStr = obs_data_get_string(request.parameters(), "saveToFilePath");
QFileInfo filePathInfo(filePathStr);
QString absoluteFilePath = filePathInfo.absoluteFilePath();
if (!sourceImage.save(absoluteFilePath)) {
- return req->SendErrorResponse("Image save failed");
+ return request.failed("Image save failed");
}
obs_data_set_string(response, "imageFile", absoluteFilePath.toUtf8());
}
obs_data_set_string(response, "sourceName", obs_source_get_name(source));
- return req->SendOKResponse(response);
+ return request.success(response);
}
diff --git a/src/WSRequestHandler_Streaming.cpp b/src/WSRequestHandler_Streaming.cpp
index 45bb5f44..4ee77d8b 100644
--- a/src/WSRequestHandler_Streaming.cpp
+++ b/src/WSRequestHandler_Streaming.cpp
@@ -20,7 +20,7 @@
* @category streaming
* @since 0.3
*/
-HandlerResponse WSRequestHandler::HandleGetStreamingStatus(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::GetStreamingStatus(const RpcRequest& request) {
auto events = GetEventsSystem();
OBSDataAutoRelease data = obs_data_create();
@@ -39,7 +39,7 @@ HandlerResponse WSRequestHandler::HandleGetStreamingStatus(WSRequestHandler* req
obs_data_set_string(data, "rec-timecode", recordingTimecode.toUtf8().constData());
}
- return req->SendOKResponse(data);
+ return request.success(data);
}
/**
@@ -50,11 +50,11 @@ HandlerResponse WSRequestHandler::HandleGetStreamingStatus(WSRequestHandler* req
* @category streaming
* @since 0.3
*/
-HandlerResponse WSRequestHandler::HandleStartStopStreaming(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::StartStopStreaming(const RpcRequest& request) {
if (obs_frontend_streaming_active())
- return HandleStopStreaming(req);
+ return StopStreaming(request);
else
- return HandleStartStreaming(req);
+ return StartStreaming(request);
}
/**
@@ -76,15 +76,15 @@ HandlerResponse WSRequestHandler::HandleStartStopStreaming(WSRequestHandler* req
* @category streaming
* @since 4.1.0
*/
-HandlerResponse WSRequestHandler::HandleStartStreaming(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::StartStreaming(const RpcRequest& request) {
if (obs_frontend_streaming_active() == false) {
OBSService configuredService = obs_frontend_get_streaming_service();
OBSService newService = nullptr;
// TODO: fix service memory leak
- if (req->hasField("stream")) {
- OBSDataAutoRelease streamData = obs_data_get_obj(req->data, "stream");
+ if (request.hasField("stream")) {
+ OBSDataAutoRelease streamData = obs_data_get_obj(request.parameters(), "stream");
OBSDataAutoRelease newSettings = obs_data_get_obj(streamData, "settings");
OBSDataAutoRelease newMetadata = obs_data_get_obj(streamData, "metadata");
@@ -157,9 +157,9 @@ HandlerResponse WSRequestHandler::HandleStartStreaming(WSRequestHandler* req) {
obs_frontend_set_streaming_service(configuredService);
}
- return req->SendOKResponse();
+ return request.success();
} else {
- return req->SendErrorResponse("streaming already active");
+ return request.failed("streaming already active");
}
}
@@ -172,12 +172,12 @@ HandlerResponse WSRequestHandler::HandleStartStreaming(WSRequestHandler* req) {
* @category streaming
* @since 4.1.0
*/
-HandlerResponse WSRequestHandler::HandleStopStreaming(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::StopStreaming(const RpcRequest& request) {
if (obs_frontend_streaming_active() == true) {
obs_frontend_streaming_stop();
- return req->SendOKResponse();
+ return request.success();
} else {
- return req->SendErrorResponse("streaming not active");
+ return request.failed("streaming not active");
}
}
@@ -198,16 +198,16 @@ HandlerResponse WSRequestHandler::HandleStopStreaming(WSRequestHandler* req) {
* @category streaming
* @since 4.1.0
*/
-HandlerResponse WSRequestHandler::HandleSetStreamSettings(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::SetStreamSettings(const RpcRequest& request) {
OBSService service = obs_frontend_get_streaming_service();
- OBSDataAutoRelease requestSettings = obs_data_get_obj(req->data, "settings");
+ OBSDataAutoRelease requestSettings = obs_data_get_obj(request.parameters(), "settings");
if (!requestSettings) {
- return req->SendErrorResponse("'settings' are required'");
+ return request.failed("'settings' are required'");
}
QString serviceType = obs_service_get_type(service);
- QString requestedType = obs_data_get_string(req->data, "type");
+ QString requestedType = obs_data_get_string(request.parameters(), "type");
if (requestedType != nullptr && requestedType != serviceType) {
OBSDataAutoRelease hotkeys = obs_hotkeys_save_service(service);
@@ -231,7 +231,7 @@ HandlerResponse WSRequestHandler::HandleSetStreamSettings(WSRequestHandler* req)
}
//if save is specified we should immediately save the streaming service
- if (obs_data_get_bool(req->data, "save")) {
+ if (obs_data_get_bool(request.parameters(), "save")) {
obs_frontend_save_streaming_service();
}
@@ -241,7 +241,7 @@ HandlerResponse WSRequestHandler::HandleSetStreamSettings(WSRequestHandler* req)
obs_data_set_string(response, "type", requestedType.toUtf8());
obs_data_set_obj(response, "settings", serviceSettings);
- return req->SendOKResponse(response);
+ return request.success(response);
}
/**
@@ -260,7 +260,7 @@ HandlerResponse WSRequestHandler::HandleSetStreamSettings(WSRequestHandler* req)
* @category streaming
* @since 4.1.0
*/
-HandlerResponse WSRequestHandler::HandleGetStreamSettings(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::GetStreamSettings(const RpcRequest& request) {
OBSService service = obs_frontend_get_streaming_service();
const char* serviceType = obs_service_get_type(service);
@@ -270,7 +270,7 @@ HandlerResponse WSRequestHandler::HandleGetStreamSettings(WSRequestHandler* req)
obs_data_set_string(response, "type", serviceType);
obs_data_set_obj(response, "settings", settings);
- return req->SendOKResponse(response);
+ return request.success(response);
}
/**
@@ -281,9 +281,9 @@ HandlerResponse WSRequestHandler::HandleGetStreamSettings(WSRequestHandler* req)
* @category streaming
* @since 4.1.0
*/
-HandlerResponse WSRequestHandler::HandleSaveStreamSettings(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::SaveStreamSettings(const RpcRequest& request) {
obs_frontend_save_streaming_service();
- return req->SendOKResponse();
+ return request.success();
}
@@ -299,19 +299,19 @@ HandlerResponse WSRequestHandler::HandleSaveStreamSettings(WSRequestHandler* req
* @since 4.6.0
*/
#if BUILD_CAPTIONS
-HandlerResponse WSRequestHandler::HandleSendCaptions(WSRequestHandler* req) {
- if (!req->hasField("text")) {
- return req->SendErrorResponse("missing request parameters");
+RpcResponse WSRequestHandler::SendCaptions(const RpcRequest& request) {
+ if (!request.hasField("text")) {
+ return request.failed("missing request parameters");
}
OBSOutputAutoRelease output = obs_frontend_get_streaming_output();
if (output) {
- const char* caption = obs_data_get_string(req->data, "text");
+ const char* caption = obs_data_get_string(request.parameters(), "text");
// Send caption text with immediately (0 second delay)
obs_output_output_caption_text2(output, caption, 0.0);
}
- return req->SendOKResponse();
+ return request.success();
}
#endif
diff --git a/src/WSRequestHandler_StudioMode.cpp b/src/WSRequestHandler_StudioMode.cpp
index bfcdae4e..67928ee4 100644
--- a/src/WSRequestHandler_StudioMode.cpp
+++ b/src/WSRequestHandler_StudioMode.cpp
@@ -12,13 +12,13 @@
* @category studio mode
* @since 4.1.0
*/
-HandlerResponse WSRequestHandler::HandleGetStudioModeStatus(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::GetStudioModeStatus(const RpcRequest& request) {
bool previewActive = obs_frontend_preview_program_mode_active();
OBSDataAutoRelease response = obs_data_create();
obs_data_set_bool(response, "studio-mode", previewActive);
- return req->SendOKResponse(response);
+ return request.success(response);
}
/**
@@ -33,9 +33,9 @@ HandlerResponse WSRequestHandler::HandleGetStudioModeStatus(WSRequestHandler* re
* @category studio mode
* @since 4.1.0
*/
-HandlerResponse WSRequestHandler::HandleGetPreviewScene(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::GetPreviewScene(const RpcRequest& request) {
if (!obs_frontend_preview_program_mode_active()) {
- return req->SendErrorResponse("studio mode not enabled");
+ return request.failed("studio mode not enabled");
}
OBSSourceAutoRelease scene = obs_frontend_get_current_preview_scene();
@@ -45,7 +45,7 @@ HandlerResponse WSRequestHandler::HandleGetPreviewScene(WSRequestHandler* req) {
obs_data_set_string(data, "name", obs_source_get_name(scene));
obs_data_set_array(data, "sources", sceneItems);
- return req->SendOKResponse(data);
+ return request.success(data);
}
/**
@@ -59,23 +59,23 @@ HandlerResponse WSRequestHandler::HandleGetPreviewScene(WSRequestHandler* req) {
* @category studio mode
* @since 4.1.0
*/
-HandlerResponse WSRequestHandler::HandleSetPreviewScene(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::SetPreviewScene(const RpcRequest& request) {
if (!obs_frontend_preview_program_mode_active()) {
- return req->SendErrorResponse("studio mode not enabled");
+ return request.failed("studio mode not enabled");
}
- if (!req->hasField("scene-name")) {
- return req->SendErrorResponse("missing request parameters");
+ if (!request.hasField("scene-name")) {
+ return request.failed("missing request parameters");
}
- const char* scene_name = obs_data_get_string(req->data, "scene-name");
+ const char* scene_name = obs_data_get_string(request.parameters(), "scene-name");
OBSScene scene = Utils::GetSceneFromNameOrCurrent(scene_name);
if (!scene) {
- return req->SendErrorResponse("specified scene doesn't exist");
+ return request.failed("specified scene doesn't exist");
}
obs_frontend_set_current_preview_scene(obs_scene_get_source(scene));
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -91,25 +91,25 @@ HandlerResponse WSRequestHandler::HandleSetPreviewScene(WSRequestHandler* req) {
* @category studio mode
* @since 4.1.0
*/
-HandlerResponse WSRequestHandler::HandleTransitionToProgram(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::TransitionToProgram(const RpcRequest& request) {
if (!obs_frontend_preview_program_mode_active()) {
- return req->SendErrorResponse("studio mode not enabled");
+ return request.failed("studio mode not enabled");
}
- if (req->hasField("with-transition")) {
+ if (request.hasField("with-transition")) {
OBSDataAutoRelease transitionInfo =
- obs_data_get_obj(req->data, "with-transition");
+ obs_data_get_obj(request.parameters(), "with-transition");
if (obs_data_has_user_value(transitionInfo, "name")) {
QString transitionName =
obs_data_get_string(transitionInfo, "name");
if (transitionName.isEmpty()) {
- return req->SendErrorResponse("invalid request parameters");
+ return request.failed("invalid request parameters");
}
bool success = Utils::SetTransitionByName(transitionName);
if (!success) {
- return req->SendErrorResponse("specified transition doesn't exist");
+ return request.failed("specified transition doesn't exist");
}
}
@@ -121,7 +121,7 @@ HandlerResponse WSRequestHandler::HandleTransitionToProgram(WSRequestHandler* re
}
obs_frontend_preview_program_trigger_transition();
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -132,9 +132,9 @@ HandlerResponse WSRequestHandler::HandleTransitionToProgram(WSRequestHandler* re
* @category studio mode
* @since 4.1.0
*/
-HandlerResponse WSRequestHandler::HandleEnableStudioMode(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::EnableStudioMode(const RpcRequest& request) {
obs_frontend_set_preview_program_mode(true);
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -145,9 +145,9 @@ HandlerResponse WSRequestHandler::HandleEnableStudioMode(WSRequestHandler* req)
* @category studio mode
* @since 4.1.0
*/
-HandlerResponse WSRequestHandler::HandleDisableStudioMode(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::DisableStudioMode(const RpcRequest& request) {
obs_frontend_set_preview_program_mode(false);
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -158,8 +158,8 @@ HandlerResponse WSRequestHandler::HandleDisableStudioMode(WSRequestHandler* req)
* @category studio mode
* @since 4.1.0
*/
-HandlerResponse WSRequestHandler::HandleToggleStudioMode(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::ToggleStudioMode(const RpcRequest& request) {
bool previewProgramMode = obs_frontend_preview_program_mode_active();
obs_frontend_set_preview_program_mode(!previewProgramMode);
- return req->SendOKResponse();
+ return request.success();
}
diff --git a/src/WSRequestHandler_Transitions.cpp b/src/WSRequestHandler_Transitions.cpp
index 7295736b..7c22687c 100644
--- a/src/WSRequestHandler_Transitions.cpp
+++ b/src/WSRequestHandler_Transitions.cpp
@@ -14,7 +14,7 @@
* @category transitions
* @since 4.1.0
*/
-HandlerResponse WSRequestHandler::HandleGetTransitionList(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::GetTransitionList(const RpcRequest& request) {
OBSSourceAutoRelease currentTransition = obs_frontend_get_current_transition();
obs_frontend_source_list transitionList = {};
obs_frontend_get_transitions(&transitionList);
@@ -34,7 +34,7 @@ HandlerResponse WSRequestHandler::HandleGetTransitionList(WSRequestHandler* req)
obs_source_get_name(currentTransition));
obs_data_set_array(response, "transitions", transitions);
- return req->SendOKResponse(response);
+ return request.success(response);
}
/**
@@ -48,7 +48,7 @@ HandlerResponse WSRequestHandler::HandleGetTransitionList(WSRequestHandler* req)
* @category transitions
* @since 0.3
*/
-HandlerResponse WSRequestHandler::HandleGetCurrentTransition(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::GetCurrentTransition(const RpcRequest& request) {
OBSSourceAutoRelease currentTransition = obs_frontend_get_current_transition();
OBSDataAutoRelease response = obs_data_create();
@@ -58,7 +58,7 @@ HandlerResponse WSRequestHandler::HandleGetCurrentTransition(WSRequestHandler* r
if (!obs_transition_fixed(currentTransition))
obs_data_set_int(response, "duration", obs_frontend_get_transition_duration());
- return req->SendOKResponse(response);
+ return request.success(response);
}
/**
@@ -71,18 +71,18 @@ HandlerResponse WSRequestHandler::HandleGetCurrentTransition(WSRequestHandler* r
* @category transitions
* @since 0.3
*/
-HandlerResponse WSRequestHandler::HandleSetCurrentTransition(WSRequestHandler* req) {
- if (!req->hasField("transition-name")) {
- return req->SendErrorResponse("missing request parameters");
+RpcResponse WSRequestHandler::SetCurrentTransition(const RpcRequest& request) {
+ if (!request.hasField("transition-name")) {
+ return request.failed("missing request parameters");
}
- QString name = obs_data_get_string(req->data, "transition-name");
+ QString name = obs_data_get_string(request.parameters(), "transition-name");
bool success = Utils::SetTransitionByName(name);
if (!success) {
- return req->SendErrorResponse("requested transition does not exist");
+ return request.failed("requested transition does not exist");
}
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -95,14 +95,14 @@ HandlerResponse WSRequestHandler::HandleSetCurrentTransition(WSRequestHandler* r
* @category transitions
* @since 4.0.0
*/
-HandlerResponse WSRequestHandler::HandleSetTransitionDuration(WSRequestHandler* req) {
- if (!req->hasField("duration")) {
- return req->SendErrorResponse("missing request parameters");
+RpcResponse WSRequestHandler::SetTransitionDuration(const RpcRequest& request) {
+ if (!request.hasField("duration")) {
+ return request.failed("missing request parameters");
}
- int ms = obs_data_get_int(req->data, "duration");
+ int ms = obs_data_get_int(request.parameters(), "duration");
obs_frontend_set_transition_duration(ms);
- return req->SendOKResponse();
+ return request.success();
}
/**
@@ -115,8 +115,8 @@ HandlerResponse WSRequestHandler::HandleSetTransitionDuration(WSRequestHandler*
* @category transitions
* @since 4.1.0
*/
-HandlerResponse WSRequestHandler::HandleGetTransitionDuration(WSRequestHandler* req) {
+RpcResponse WSRequestHandler::GetTransitionDuration(const RpcRequest& request) {
OBSDataAutoRelease response = obs_data_create();
obs_data_set_int(response, "transition-duration", obs_frontend_get_transition_duration());
- return req->SendOKResponse(response);
+ return request.success(response);
}
diff --git a/src/WSServer.cpp b/src/WSServer.cpp
index 1b062b97..c9f09362 100644
--- a/src/WSServer.cpp
+++ b/src/WSServer.cpp
@@ -31,6 +31,7 @@ with this program. If not, see
#include "obs-websocket.h"
#include "Config.h"
#include "Utils.h"
+#include "protocol/OBSRemoteProtocol.h"
QT_USE_NAMESPACE
@@ -124,8 +125,15 @@ void WSServer::stop()
blog(LOG_INFO, "server stopped successfully");
}
-void WSServer::broadcast(std::string message)
+void WSServer::broadcast(const RpcEvent& event)
{
+ OBSRemoteProtocol protocol;
+ std::string message = protocol.encodeEvent(event);
+
+ if (GetConfig()->DebugEnabled) {
+ blog(LOG_INFO, "Update << '%s'", message.c_str());
+ }
+
QMutexLocker locker(&_clMutex);
for (connection_hdl hdl : _connections) {
if (GetConfig()->AuthRequired) {
@@ -171,8 +179,17 @@ void WSServer::onMessage(connection_hdl hdl, server::message_ptr message)
ConnectionProperties& connProperties = _connectionProperties[hdl];
locker.unlock();
- WSRequestHandler handler(connProperties);
- std::string response = handler.processIncomingMessage(payload);
+ if (GetConfig()->DebugEnabled) {
+ blog(LOG_INFO, "Request >> '%s'", payload.c_str());
+ }
+
+ WSRequestHandler requestHandler(connProperties);
+ OBSRemoteProtocol protocol;
+ std::string response = protocol.processMessage(requestHandler, payload);
+
+ if (GetConfig()->DebugEnabled) {
+ blog(LOG_INFO, "Response << '%s'", response.c_str());
+ }
websocketpp::lib::error_code errorCode;
_server.send(hdl, response, websocketpp::frame::opcode::text, errorCode);
diff --git a/src/WSServer.h b/src/WSServer.h
index 76e978e3..723f51af 100644
--- a/src/WSServer.h
+++ b/src/WSServer.h
@@ -30,8 +30,8 @@ with this program. If not, see
#include
#include "ConnectionProperties.h"
-
#include "WSRequestHandler.h"
+#include "rpc/RpcEvent.h"
using websocketpp::connection_hdl;
@@ -46,7 +46,7 @@ public:
virtual ~WSServer();
void start(quint16 port);
void stop();
- void broadcast(std::string message);
+ void broadcast(const RpcEvent& event);
QThreadPool* threadPool() {
return &_threadPool;
}
diff --git a/src/protocol/OBSRemoteProtocol.cpp b/src/protocol/OBSRemoteProtocol.cpp
new file mode 100644
index 00000000..e5b1da1a
--- /dev/null
+++ b/src/protocol/OBSRemoteProtocol.cpp
@@ -0,0 +1,117 @@
+/*
+obs-websocket
+Copyright (C) 2016-2019 Stéphane Lepin
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program. If not, see
+*/
+
+#include
+
+#include "OBSRemoteProtocol.h"
+#include "../WSRequestHandler.h"
+#include "../rpc/RpcEvent.h"
+#include "../Utils.h"
+
+std::string OBSRemoteProtocol::processMessage(WSRequestHandler& requestHandler, std::string message)
+{
+ std::string msgContainer(message);
+ const char* msg = msgContainer.c_str();
+
+ 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");
+ }
+
+ if (!obs_data_has_user_value(data, "request-type") || !obs_data_has_user_value(data, "message-id")) {
+ return errorResponse(QString::Null(), "missing request parameters");
+ }
+
+ QString methodName = obs_data_get_string(data, "request-type");
+ QString messageId = obs_data_get_string(data, "message-id");
+
+ OBSDataAutoRelease params = obs_data_create();
+ obs_data_apply(params, data);
+ obs_data_unset_user_value(params, "request-type");
+ obs_data_unset_user_value(params, "message-id");
+
+ 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();
+}
+
+std::string OBSRemoteProtocol::encodeEvent(const RpcEvent& event)
+{
+ OBSDataAutoRelease eventData = obs_data_create();
+
+ QString updateType = event.updateType();
+ obs_data_set_string(eventData, "update-type", updateType.toUtf8().constData());
+
+ if (obs_frontend_streaming_active()) {
+ QString streamingTimecode = Utils::nsToTimestamp(event.streamTime());
+ obs_data_set_string(eventData, "stream-timecode", streamingTimecode.toUtf8().constData());
+ }
+
+ if (obs_frontend_recording_active()) {
+ QString recordingTimecode = Utils::nsToTimestamp(event.recordingTime());
+ obs_data_set_string(eventData, "rec-timecode", recordingTimecode.toUtf8().constData());
+ }
+
+ OBSData additionalFields = event.additionalFields();
+ if (additionalFields) {
+ obs_data_apply(eventData, additionalFields);
+ }
+
+ return std::string(obs_data_get_json(eventData));
+}
+
+std::string OBSRemoteProtocol::buildResponse(QString messageId, QString status, obs_data_t* fields)
+{
+ OBSDataAutoRelease response = obs_data_create();
+ if (!messageId.isNull()) {
+ obs_data_set_string(response, "message-id", messageId.toUtf8().constData());
+ }
+ 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)
+{
+ return buildResponse(messageId, "ok", fields);
+}
+
+std::string OBSRemoteProtocol::errorResponse(QString messageId, QString 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());
+ return buildResponse(messageId, "error", fields);
+}
diff --git a/src/protocol/OBSRemoteProtocol.h b/src/protocol/OBSRemoteProtocol.h
new file mode 100644
index 00000000..03d8aa7d
--- /dev/null
+++ b/src/protocol/OBSRemoteProtocol.h
@@ -0,0 +1,38 @@
+/*
+obs-websocket
+Copyright (C) 2016-2019 Stéphane Lepin
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program. If not, see
+*/
+
+#pragma once
+
+#include
+#include
+#include
+
+class WSRequestHandler;
+class RpcEvent;
+
+class OBSRemoteProtocol
+{
+public:
+ std::string processMessage(WSRequestHandler& requestHandler, std::string message);
+ std::string encodeEvent(const RpcEvent& event);
+
+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);
+};
diff --git a/src/rpc/RpcEvent.cpp b/src/rpc/RpcEvent.cpp
new file mode 100644
index 00000000..a8d3b06b
--- /dev/null
+++ b/src/rpc/RpcEvent.cpp
@@ -0,0 +1,35 @@
+/*
+obs-websocket
+Copyright (C) 2016-2020 Stéphane Lepin
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program. If not, see
+*/
+
+#include "RpcEvent.h"
+
+RpcEvent::RpcEvent(
+ const QString& updateType,
+ uint64_t streamTime, uint64_t recordingTime,
+ obs_data_t* additionalFields
+) :
+ _updateType(updateType),
+ _streamTime(streamTime),
+ _recordingTime(recordingTime),
+ _additionalFields(nullptr)
+{
+ if (additionalFields) {
+ _additionalFields = obs_data_create();
+ obs_data_apply(_additionalFields, additionalFields);
+ }
+}
\ No newline at end of file
diff --git a/src/rpc/RpcEvent.h b/src/rpc/RpcEvent.h
new file mode 100644
index 00000000..6dd0df99
--- /dev/null
+++ b/src/rpc/RpcEvent.h
@@ -0,0 +1,60 @@
+/*
+obs-websocket
+Copyright (C) 2016-2020 Stéphane Lepin
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program. If not, see
+*/
+
+#pragma once
+
+#include
+#include
+
+#include "../obs-websocket.h"
+
+class RpcEvent
+{
+public:
+ explicit RpcEvent(
+ const QString& updateType,
+ uint64_t streamTime, uint64_t recordingTime,
+ obs_data_t* additionalFields = nullptr
+ );
+
+ const QString& updateType() const
+ {
+ return _updateType;
+ }
+
+ const uint64_t streamTime() const
+ {
+ return _streamTime;
+ }
+
+ const uint64_t recordingTime() const
+ {
+ return _recordingTime;
+ }
+
+ const OBSData additionalFields() const
+ {
+ return OBSData(_additionalFields);
+ }
+
+private:
+ QString _updateType;
+ uint64_t _streamTime;
+ uint64_t _recordingTime;
+ OBSDataAutoRelease _additionalFields;
+};
diff --git a/src/rpc/RpcRequest.cpp b/src/rpc/RpcRequest.cpp
new file mode 100644
index 00000000..04d62cb9
--- /dev/null
+++ b/src/rpc/RpcRequest.cpp
@@ -0,0 +1,104 @@
+/*
+obs-websocket
+Copyright (C) 2016-2019 Stéphane Lepin
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program. If not, see
+*/
+
+#include "RpcRequest.h"
+#include "RpcResponse.h"
+
+RpcRequest::RpcRequest(const QString& messageId, const QString& methodName, obs_data_t* params) :
+ _messageId(messageId),
+ _methodName(methodName),
+ _parameters(nullptr)
+{
+ if (params) {
+ _parameters = obs_data_create();
+ obs_data_apply(_parameters, params);
+ }
+}
+
+const RpcResponse RpcRequest::success(obs_data_t* additionalFields) const
+{
+ return RpcResponse::ok(*this, additionalFields);
+}
+
+const RpcResponse RpcRequest::failed(const QString& errorMessage, obs_data_t* additionalFields) const
+{
+ return RpcResponse::fail(*this, errorMessage, additionalFields);
+}
+
+const bool RpcRequest::hasField(QString name, obs_data_type expectedFieldType, obs_data_number_type expectedNumberType) const
+{
+ if (!_parameters || name.isEmpty() || name.isNull()) {
+ return false;
+ }
+
+ OBSDataItemAutoRelease dataItem = obs_data_item_byname(_parameters, name.toUtf8());
+ if (!dataItem) {
+ return false;
+ }
+
+ if (expectedFieldType != OBS_DATA_NULL) {
+ obs_data_type fieldType = obs_data_item_gettype(dataItem);
+ if (fieldType != expectedFieldType) {
+ return false;
+ }
+
+ if (fieldType == OBS_DATA_NUMBER && expectedNumberType != OBS_DATA_NUM_INVALID) {
+ obs_data_number_type numberType = obs_data_item_numtype(dataItem);
+ if (numberType != expectedNumberType) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+const bool RpcRequest::hasBool(QString fieldName) const
+{
+ return this->hasField(fieldName, OBS_DATA_BOOLEAN);
+}
+
+const bool RpcRequest::hasString(QString fieldName) const
+{
+ return this->hasField(fieldName, OBS_DATA_STRING);
+}
+
+const bool RpcRequest::hasNumber(QString fieldName, obs_data_number_type expectedNumberType) const
+{
+ return this->hasField(fieldName, OBS_DATA_NUMBER, expectedNumberType);
+}
+
+const bool RpcRequest::hasInteger(QString fieldName) const
+{
+ return this->hasNumber(fieldName, OBS_DATA_NUM_INT);
+}
+
+const bool RpcRequest::hasDouble(QString fieldName) const
+{
+ return this->hasNumber(fieldName, OBS_DATA_NUM_DOUBLE);
+}
+
+const bool RpcRequest::hasArray(QString fieldName) const
+{
+ return this->hasField(fieldName, OBS_DATA_ARRAY);
+}
+
+const bool RpcRequest::hasObject(QString fieldName) const
+{
+ return this->hasField(fieldName, OBS_DATA_OBJECT);
+}
diff --git a/src/rpc/RpcRequest.h b/src/rpc/RpcRequest.h
new file mode 100644
index 00000000..3e360150
--- /dev/null
+++ b/src/rpc/RpcRequest.h
@@ -0,0 +1,65 @@
+/*
+obs-websocket
+Copyright (C) 2016-2019 Stéphane Lepin
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program. If not, see
+*/
+
+#pragma once
+
+#include
+#include
+#include "../obs-websocket.h"
+
+// forward declarations
+class RpcResponse;
+
+class RpcRequest
+{
+public:
+ explicit RpcRequest(const QString& messageId, const QString& methodName, obs_data_t* params);
+
+ const QString& messageId() const
+ {
+ return _messageId;
+ }
+
+ const QString& methodName() const
+ {
+ return _methodName;
+ }
+
+ const OBSData parameters() const
+ {
+ return OBSData(_parameters);
+ }
+
+ const RpcResponse success(obs_data_t* additionalFields = nullptr) const;
+ const RpcResponse failed(const QString& errorMessage, obs_data_t* additionalFields = nullptr) const;
+
+ const bool hasField(QString fieldName, obs_data_type expectedFieldType = OBS_DATA_NULL,
+ obs_data_number_type expectedNumberType = OBS_DATA_NUM_INVALID) const;
+ const bool hasBool(QString fieldName) const;
+ const bool hasString(QString fieldName) const;
+ const bool hasNumber(QString fieldName, obs_data_number_type expectedNumberType = OBS_DATA_NUM_INVALID) const;
+ const bool hasInteger(QString fieldName) const;
+ const bool hasDouble(QString fieldName) const;
+ const bool hasArray(QString fieldName) const;
+ const bool hasObject(QString fieldName) const;
+
+private:
+ const QString _messageId;
+ const QString _methodName;
+ OBSDataAutoRelease _parameters;
+};
diff --git a/src/rpc/RpcResponse.cpp b/src/rpc/RpcResponse.cpp
new file mode 100644
index 00000000..17f9f6e9
--- /dev/null
+++ b/src/rpc/RpcResponse.cpp
@@ -0,0 +1,48 @@
+/*
+obs-websocket
+Copyright (C) 2016-2019 Stéphane Lepin
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program. If not, see
+*/
+
+#include "RpcResponse.h"
+#include "RpcRequest.h"
+
+RpcResponse::RpcResponse(
+ Status status, const QString& messageId,
+ const QString& methodName, obs_data_t* additionalFields
+) :
+ _status(status),
+ _messageId(messageId),
+ _methodName(methodName),
+ _additionalFields(nullptr)
+{
+ if (additionalFields) {
+ _additionalFields = obs_data_create();
+ obs_data_apply(_additionalFields, additionalFields);
+ }
+}
+
+const RpcResponse RpcResponse::ok(const RpcRequest& request, obs_data_t* additionalFields)
+{
+ RpcResponse response(Status::Ok, request.messageId(), request.methodName(), additionalFields);
+ return response;
+}
+
+const RpcResponse RpcResponse::fail(const RpcRequest& request, const QString& errorMessage, obs_data_t* additionalFields)
+{
+ RpcResponse response(Status::Error, request.messageId(), request.methodName(), additionalFields);
+ response._errorMessage = errorMessage;
+ return response;
+}
diff --git a/src/rpc/RpcResponse.h b/src/rpc/RpcResponse.h
new file mode 100644
index 00000000..a6381bfd
--- /dev/null
+++ b/src/rpc/RpcResponse.h
@@ -0,0 +1,70 @@
+/*
+obs-websocket
+Copyright (C) 2016-2019 Stéphane Lepin
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program. If not, see
+*/
+
+#pragma once
+
+#include
+#include
+#include "../obs-websocket.h"
+
+class RpcRequest;
+
+class RpcResponse
+{
+public:
+ enum Status { Unknown, Ok, Error };
+
+ static RpcResponse ofRequest(const RpcRequest& request);
+ static const RpcResponse ok(const RpcRequest& request, obs_data_t* additionalFields = nullptr);
+ static const RpcResponse fail(
+ const RpcRequest& request, const QString& errorMessage,
+ obs_data_t* additionalFields = nullptr
+ );
+
+ Status status() {
+ return _status;
+ }
+
+ const QString& messageId() const {
+ return _messageId;
+ }
+
+ const QString& methodName() const {
+ return _methodName;
+ }
+
+ const QString& errorMessage() const {
+ return _errorMessage;
+ }
+
+ const OBSData additionalFields() const {
+ return OBSData(_additionalFields);
+ }
+
+private:
+ explicit RpcResponse(
+ Status status,
+ const QString& messageId, const QString& methodName,
+ obs_data_t* additionalFields = nullptr
+ );
+ const Status _status;
+ const QString _messageId;
+ const QString _methodName;
+ QString _errorMessage;
+ OBSDataAutoRelease _additionalFields;
+};