diff --git a/src/Utils.cpp b/src/Utils.cpp
index 5140a7ae..2752b8ab 100644
--- a/src/Utils.cpp
+++ b/src/Utils.cpp
@@ -24,6 +24,7 @@ with this program. If not, see
#include
#include
#include
+#include
#include "obs-websocket.h"
@@ -905,3 +906,52 @@ void Utils::AddSourceHelper(void *_data, obs_scene_t *scene)
data->sceneItem = obs_scene_add(scene, data->source);
obs_sceneitem_set_visible(data->sceneItem, data->setVisible);
}
+
+struct obs_data_item { // Used for OBSDataGetDefaults
+ volatile long ref;
+ struct obs_data *parent;
+ struct obs_data_item *next;
+ enum obs_data_type type;
+ size_t name_len;
+ size_t data_len;
+ size_t data_size;
+ size_t default_len;
+ size_t default_size;
+ size_t autoselect_size;
+ size_t capacity;
+};
+
+obs_data_t *Utils::OBSDataGetDefaults(obs_data_t *data)
+{
+ obs_data_t *returnData = obs_data_create();
+ obs_data_item_t *item = NULL;
+
+ for (item = obs_data_first(data); item; obs_data_item_next(&item)) {
+ enum obs_data_type type = obs_data_item_gettype(item);
+ const char *name = (char *)item + sizeof(struct obs_data_item);
+
+ if (type == OBS_DATA_STRING) {
+ const char *val = obs_data_item_get_string(item);
+ obs_data_set_string(returnData, name, val);
+ } else if (type == OBS_DATA_NUMBER) {
+ enum obs_data_number_type type = obs_data_item_numtype(item);
+ if (type == OBS_DATA_NUM_INT) {
+ long long val = obs_data_item_get_int(item);
+ obs_data_set_int(returnData, name, val);
+ } else {
+ double val = obs_data_item_get_double(item);
+ obs_data_set_double(returnData, name, val);
+ }
+ } else if (type == OBS_DATA_BOOLEAN) {
+ bool val = obs_data_item_get_bool(item);
+ obs_data_set_bool(returnData, name, val);
+ } else if (type == OBS_DATA_OBJECT) {
+ OBSDataAutoRelease obj = obs_data_item_get_obj(item);
+ obs_data_set_obj(returnData, name, obj);
+ } else if (type == OBS_DATA_ARRAY) {
+ OBSDataArrayAutoRelease array = obs_data_item_get_array(item);
+ obs_data_set_array(returnData, name, array);
+ }
+ }
+ return returnData;
+}
diff --git a/src/Utils.h b/src/Utils.h
index 47a19f2d..d15427b5 100644
--- a/src/Utils.h
+++ b/src/Utils.h
@@ -94,4 +94,6 @@ namespace Utils {
bool setVisible;
};
void AddSourceHelper(void *_data, obs_scene_t *scene);
+
+ obs_data_t *OBSDataGetDefaults(obs_data_t *data);
};
diff --git a/src/WSRequestHandler.cpp b/src/WSRequestHandler.cpp
index d3427885..0b366761 100644
--- a/src/WSRequestHandler.cpp
+++ b/src/WSRequestHandler.cpp
@@ -118,6 +118,7 @@ const QHash WSRequestHandler::messageMap{
{ "SetSourceSettings", &WSRequestHandler::SetSourceSettings },
{ "GetAudioMonitorType", &WSRequestHandler::GetAudioMonitorType },
{ "SetAudioMonitorType", &WSRequestHandler::SetAudioMonitorType },
+ { "GetSourceDefaultSettings", &WSRequestHandler::GetSourceDefaultSettings },
{ "TakeSourceScreenshot", &WSRequestHandler::TakeSourceScreenshot },
{ "GetSourceFilters", &WSRequestHandler::GetSourceFilters },
diff --git a/src/WSRequestHandler.h b/src/WSRequestHandler.h
index d2da4439..16a64742 100644
--- a/src/WSRequestHandler.h
+++ b/src/WSRequestHandler.h
@@ -135,6 +135,7 @@ class WSRequestHandler {
RpcResponse SetSourceSettings(const RpcRequest&);
RpcResponse GetAudioMonitorType(const RpcRequest&);
RpcResponse SetAudioMonitorType(const RpcRequest&);
+ RpcResponse GetSourceDefaultSettings(const RpcRequest&);
RpcResponse TakeSourceScreenshot(const RpcRequest&);
RpcResponse GetSourceFilters(const RpcRequest&);
diff --git a/src/WSRequestHandler_Sources.cpp b/src/WSRequestHandler_Sources.cpp
index 94e9a06c..8df1bf5c 100644
--- a/src/WSRequestHandler_Sources.cpp
+++ b/src/WSRequestHandler_Sources.cpp
@@ -1679,6 +1679,40 @@ RpcResponse WSRequestHandler::SetAudioMonitorType(const RpcRequest& request)
return request.success();
}
+/**
+* Get the default settings for a given source type.
+*
+* @param {String} `sourceKind` Source name.
+*
+* @api requests
+* @name GetSourceDefaultSettings
+* @category sources
+* @since 4.9.0
+*/
+RpcResponse WSRequestHandler::GetSourceDefaultSettings(const RpcRequest& request)
+{
+ if (!request.hasField("sourceKind")) {
+ return request.failed("missing request parameters");
+ }
+
+ QString sourceKind = obs_data_get_string(request.parameters(), "sourceKind");
+
+ if (sourceKind.isEmpty()) {
+ return request.failed("invalid request parameters");
+ }
+
+ OBSDataAutoRelease defaultData = obs_get_source_defaults(sourceKind.toUtf8());
+ if (!defaultData) {
+ return request.failed("invalid sourceKind");
+ }
+
+ OBSDataAutoRelease defaultSettings = Utils::OBSDataGetDefaults(defaultData);
+
+ OBSDataAutoRelease response = obs_data_create();
+ obs_data_set_obj(response, "defaultSettings", defaultSettings);
+ return request.success(response);
+}
+
/**
* Takes a picture snapshot of a source and then can either or both:
* - Send it over as a Data URI (base64-encoded data) in the response (by specifying `embedPictureFormat` in the request)