mirror of
https://github.com/Palakis/obs-websocket.git
synced 2024-08-30 18:12:16 +00:00
requesthandler: Filter requests & events (#888)
* Implement filter requests * Fix CreateSourceFilter * Implement most Filter events * build against 27.1.3 * Update main.yml * SourceFilterNameChanged rename * revert main.yml changes * rename SourceFilterCreated and revert CI changes * cleanup * Base: Various cleanups + fix -Werror * Base: A few nitpicks/fixes * requesthandler: Fix CreateSourceFilter * utils: Fix CreateSourceFilter Use obs_source_t* instead of OBSSourceAutoRelease to prevent double release * requesthandler: Remove filterIndex from CreateSourceFilter The purpose of sceneItemEnabled in CreateSceneItem is to hide the scene item while we still hold the scene mutex (guaranteeing the input will never be shown). Since we don't hold a mutex when creating filters, there's no reason to do any extra steps. * requesthandler: Validate input/filter kinds in *DefaultSettings Co-authored-by: tt2468 <tt2468@gmail.com>
This commit is contained in:
parent
b3a5c55bef
commit
361547a96d
1
.gitignore
vendored
1
.gitignore
vendored
@ -11,3 +11,4 @@
|
||||
/docs/node_modules/
|
||||
/src/plugin-macros.generated.h
|
||||
/installer/installer-windows.generated.iss
|
||||
/cmake-build-debug/
|
||||
|
@ -135,9 +135,12 @@ void EventHandler::ConnectSourceSignals(obs_source_t *source) // Applies to inpu
|
||||
signal_handler_connect(sh, "mute", HandleInputMuteStateChanged, this);
|
||||
signal_handler_connect(sh, "volume", HandleInputVolumeChanged, this);
|
||||
signal_handler_connect(sh, "audio_balance", HandleInputAudioBalanceChanged, this);
|
||||
signal_handler_connect(sh, "audio_sync", HandleInputAudioSyncOffsetChanged, this);
|
||||
signal_handler_connect(sh, "audio_mixers", HandleInputAudioTracksChanged, this);
|
||||
signal_handler_connect(sh, "audio_monitoring", HandleInputAudioMonitorTypeChanged, this);
|
||||
signal_handler_connect(sh, "audio_sync", HandleInputAudioSyncOffsetChanged, this);
|
||||
signal_handler_connect(sh, "audio_mixers", HandleInputAudioTracksChanged, this);
|
||||
signal_handler_connect(sh, "audio_monitoring", HandleInputAudioMonitorTypeChanged, this);
|
||||
signal_handler_connect(sh, "filter_add", HandleSourceFilterCreated, this);
|
||||
signal_handler_connect(sh, "filter_remove", HandleSourceFilterRemoved, this);
|
||||
signal_handler_connect(sh, "reorder_filters", HandleSourceFilterListReindexed, this);
|
||||
|
||||
if (sourceType == OBS_SOURCE_TYPE_INPUT) {
|
||||
signal_handler_connect(sh, "media_started", HandleMediaInputPlaybackStarted, this);
|
||||
@ -188,6 +191,9 @@ void EventHandler::DisconnectSourceSignals(obs_source_t *source)
|
||||
signal_handler_disconnect(sh, "media_stopped", SourceMediaStopMultiHandler, this);
|
||||
signal_handler_disconnect(sh, "media_next", SourceMediaNextMultiHandler, this);
|
||||
signal_handler_disconnect(sh, "media_previous", SourceMediaPreviousMultiHandler, this);
|
||||
signal_handler_disconnect(sh, "filter_add", HandleSourceFilterCreated, this);
|
||||
signal_handler_disconnect(sh, "filter_remove", HandleSourceFilterRemoved, this);
|
||||
signal_handler_disconnect(sh, "reorder_filters", HandleSourceFilterListReindexed, this);
|
||||
|
||||
// Scenes
|
||||
signal_handler_disconnect(sh, "item_add", HandleSceneItemCreated, this);
|
||||
@ -199,6 +205,30 @@ void EventHandler::DisconnectSourceSignals(obs_source_t *source)
|
||||
signal_handler_disconnect(sh, "item_transform", HandleSceneItemTransformChanged, this);
|
||||
}
|
||||
|
||||
void EventHandler::ConnectFilterSignals(obs_source_t *filter)
|
||||
{
|
||||
if (!filter || obs_source_removed(filter))
|
||||
return;
|
||||
|
||||
DisconnectFilterSignals(filter);
|
||||
|
||||
signal_handler_t* sh = obs_source_get_signal_handler(filter);
|
||||
|
||||
signal_handler_connect(sh, "enable", HandleSourceFilterEnableStateChanged, this);
|
||||
signal_handler_connect(sh, "rename", HandleSourceFilterNameChanged, this);
|
||||
}
|
||||
|
||||
void EventHandler::DisconnectFilterSignals(obs_source_t *filter)
|
||||
{
|
||||
if (!filter)
|
||||
return;
|
||||
|
||||
signal_handler_t* sh = obs_source_get_signal_handler(filter);
|
||||
|
||||
signal_handler_disconnect(sh, "enable", HandleSourceFilterEnableStateChanged, this);
|
||||
signal_handler_disconnect(sh, "rename", HandleSourceFilterNameChanged, this);
|
||||
}
|
||||
|
||||
void EventHandler::OnFrontendEvent(enum obs_frontend_event event, void *private_data)
|
||||
{
|
||||
auto eventHandler = static_cast<EventHandler*>(private_data);
|
||||
@ -211,18 +241,38 @@ void EventHandler::OnFrontendEvent(enum obs_frontend_event event, void *private_
|
||||
|
||||
// In the case that plugins become hotloadable, this will have to go back into `EventHandler::EventHandler()`
|
||||
// Enumerate inputs and connect each one
|
||||
obs_enum_sources([](void* param, obs_source_t* source) {
|
||||
auto eventHandler = static_cast<EventHandler*>(param);
|
||||
eventHandler->ConnectSourceSignals(source);
|
||||
return true;
|
||||
}, private_data);
|
||||
{
|
||||
auto enumInputs = [](void *param, obs_source_t *source) {
|
||||
auto eventHandler = static_cast<EventHandler*>(param);
|
||||
eventHandler->ConnectSourceSignals(source);
|
||||
|
||||
auto enumFilters = [](obs_source_t *, obs_source_t *filter, void *param){
|
||||
auto eventHandler = static_cast<EventHandler*>(param);
|
||||
eventHandler->ConnectFilterSignals(filter);
|
||||
};
|
||||
obs_source_enum_filters(source, enumFilters, param);
|
||||
|
||||
return true;
|
||||
};
|
||||
obs_enum_sources(enumInputs, private_data);
|
||||
}
|
||||
|
||||
// Enumerate scenes and connect each one
|
||||
obs_enum_scenes([](void* param, obs_source_t* source) {
|
||||
auto eventHandler = static_cast<EventHandler*>(param);
|
||||
eventHandler->ConnectSourceSignals(source);
|
||||
return true;
|
||||
}, private_data);
|
||||
{
|
||||
auto enumScenes = [](void *param, obs_source_t *source) {
|
||||
auto eventHandler = static_cast<EventHandler*>(param);
|
||||
eventHandler->ConnectSourceSignals(source);
|
||||
|
||||
auto enumFilters = [](obs_source_t *, obs_source_t *filter, void *param){
|
||||
auto eventHandler = static_cast<EventHandler*>(param);
|
||||
eventHandler->ConnectFilterSignals(filter);
|
||||
};
|
||||
obs_source_enum_filters(source, enumFilters, param);
|
||||
|
||||
return true;
|
||||
};
|
||||
obs_enum_scenes(enumScenes, private_data);
|
||||
}
|
||||
|
||||
blog_debug("[EventHandler::OnFrontendEvent] Finished.");
|
||||
|
||||
@ -244,18 +294,38 @@ void EventHandler::OnFrontendEvent(enum obs_frontend_event event, void *private_
|
||||
|
||||
// In the case that plugins become hotloadable, this will have to go back into `EventHandler::~EventHandler()`
|
||||
// Enumerate inputs and disconnect each one
|
||||
obs_enum_sources([](void* param, obs_source_t* source) {
|
||||
auto eventHandler = static_cast<EventHandler*>(param);
|
||||
eventHandler->DisconnectSourceSignals(source);
|
||||
return true;
|
||||
}, private_data);
|
||||
{
|
||||
auto enumInputs = [](void *param, obs_source_t *source) {
|
||||
auto eventHandler = static_cast<EventHandler*>(param);
|
||||
eventHandler->DisconnectSourceSignals(source);
|
||||
|
||||
auto enumFilters = [](obs_source_t *, obs_source_t *filter, void *param){
|
||||
auto eventHandler = static_cast<EventHandler*>(param);
|
||||
eventHandler->ConnectFilterSignals(filter);
|
||||
};
|
||||
obs_source_enum_filters(source, enumFilters, param);
|
||||
|
||||
return true;
|
||||
};
|
||||
obs_enum_sources(enumInputs, private_data);
|
||||
}
|
||||
|
||||
// Enumerate scenes and disconnect each one
|
||||
obs_enum_scenes([](void* param, obs_source_t* source) {
|
||||
auto eventHandler = static_cast<EventHandler*>(param);
|
||||
eventHandler->DisconnectSourceSignals(source);
|
||||
return true;
|
||||
}, private_data);
|
||||
{
|
||||
auto enumScenes = [](void *param, obs_source_t *source) {
|
||||
auto eventHandler = static_cast<EventHandler*>(param);
|
||||
eventHandler->DisconnectSourceSignals(source);
|
||||
|
||||
auto enumFilters = [](obs_source_t *, obs_source_t *filter, void *param){
|
||||
auto eventHandler = static_cast<EventHandler*>(param);
|
||||
eventHandler->ConnectFilterSignals(filter);
|
||||
};
|
||||
obs_source_enum_filters(source, enumFilters, param);
|
||||
|
||||
return true;
|
||||
};
|
||||
obs_enum_scenes(enumScenes, private_data);
|
||||
}
|
||||
|
||||
blog_debug("[EventHandler::OnFrontendEvent] Finished.");
|
||||
|
||||
@ -465,8 +535,6 @@ void EventHandler::SourceRenamedMultiHandler(void *param, calldata_t *data)
|
||||
case OBS_SOURCE_TYPE_INPUT:
|
||||
eventHandler->HandleInputNameChanged(source, oldSourceName, sourceName);
|
||||
break;
|
||||
case OBS_SOURCE_TYPE_FILTER:
|
||||
break;
|
||||
case OBS_SOURCE_TYPE_TRANSITION:
|
||||
break;
|
||||
case OBS_SOURCE_TYPE_SCENE:
|
||||
|
@ -58,6 +58,9 @@ class EventHandler
|
||||
void ConnectSourceSignals(obs_source_t *source);
|
||||
void DisconnectSourceSignals(obs_source_t *source);
|
||||
|
||||
void ConnectFilterSignals(obs_source_t *filter);
|
||||
void DisconnectFilterSignals(obs_source_t *filter);
|
||||
|
||||
void BroadcastEvent(uint64_t requiredIntent, std::string eventType, json eventData = nullptr, uint8_t rpcVersion = 0);
|
||||
|
||||
// Signal handler: frontend
|
||||
@ -136,4 +139,11 @@ class EventHandler
|
||||
static void HandleMediaInputPlaybackStarted(void *param, calldata_t *data); // Direct callback
|
||||
static void HandleMediaInputPlaybackEnded(void *param, calldata_t *data); // Direct callback
|
||||
void HandleMediaInputActionTriggered(obs_source_t *source, ObsMediaInputAction action);
|
||||
|
||||
// Filters
|
||||
static void HandleSourceFilterNameChanged(void *param, calldata_t *data); // Direct callback
|
||||
static void HandleSourceFilterCreated(void *param, calldata_t *data); // Direct callback
|
||||
static void HandleSourceFilterRemoved(void *param, calldata_t *data); // Direct callback
|
||||
static void HandleSourceFilterListReindexed(void *param, calldata_t *data); // Direct callback
|
||||
static void HandleSourceFilterEnableStateChanged(void *param, calldata_t *data); // Direct callback
|
||||
};
|
||||
|
@ -18,3 +18,174 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#include "EventHandler.h"
|
||||
|
||||
/**
|
||||
* A filter has been added to a source.
|
||||
*
|
||||
* @dataField sourceName | String | Name of the source the filter was added to
|
||||
* @dataField filterName | String | Name of the filter
|
||||
* @dataField filterKind | String | The kind of the filter
|
||||
* @dataField filterIndex | Number | Index position of the filter
|
||||
* @dataField filterSettings | Object | The settings configured to the filter when it was created
|
||||
* @dataField defaultFilterSettings | Object | The default settings for the filter
|
||||
*
|
||||
* @eventType SourceFilterCreated
|
||||
* @eventSubscription Filters
|
||||
* @complexity 2
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api events
|
||||
* @category filters
|
||||
*/
|
||||
void EventHandler::HandleSourceFilterCreated(void *param, calldata_t *data)
|
||||
{
|
||||
auto eventHandler = static_cast<EventHandler*>(param);
|
||||
|
||||
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
|
||||
obs_source_t *filter = GetCalldataPointer<obs_source_t>(data, "filter");
|
||||
|
||||
if (!(source && filter))
|
||||
return;
|
||||
|
||||
eventHandler->ConnectFilterSignals(filter);
|
||||
|
||||
std::string filterKind = obs_source_get_id(filter);
|
||||
OBSDataAutoRelease filterSettings = obs_source_get_settings(filter);
|
||||
OBSDataAutoRelease defaultFilterSettings = obs_get_source_defaults(filterKind.c_str());
|
||||
|
||||
json eventData;
|
||||
eventData["sourceName"] = obs_source_get_name(source);
|
||||
eventData["filterName"] = obs_source_get_name(filter);
|
||||
eventData["filterKind"] = filterKind;
|
||||
eventData["filterIndex"] = Utils::Obs::NumberHelper::GetSourceFilterIndex(source, filter);
|
||||
eventData["filterSettings"] = Utils::Json::ObsDataToJson(filterSettings);
|
||||
eventData["defaultFilterSettings"] = Utils::Json::ObsDataToJson(defaultFilterSettings, true);
|
||||
eventHandler->BroadcastEvent(EventSubscription::Filters, "SourceFilterCreated", eventData);
|
||||
}
|
||||
|
||||
/**
|
||||
* A filter has been removed from a source.
|
||||
*
|
||||
* @dataField sourceName | String | Name of the source the filter was on
|
||||
* @dataField filterName | String | Name of the filter
|
||||
*
|
||||
* @eventType SourceFilterRemoved
|
||||
* @eventSubscription Filters
|
||||
* @complexity 2
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api events
|
||||
* @category filters
|
||||
*/
|
||||
void EventHandler::HandleSourceFilterRemoved(void *param, calldata_t *data)
|
||||
{
|
||||
auto eventHandler = static_cast<EventHandler*>(param);
|
||||
|
||||
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
|
||||
obs_source_t *filter = GetCalldataPointer<obs_source_t>(data, "filter");
|
||||
|
||||
if (!(source && filter))
|
||||
return;
|
||||
|
||||
eventHandler->DisconnectFilterSignals(filter);
|
||||
|
||||
json eventData;
|
||||
eventData["sourceName"] = obs_source_get_name(source);
|
||||
eventData["filterName"] = obs_source_get_name(filter);
|
||||
eventHandler->BroadcastEvent(EventSubscription::Filters, "SourceFilterRemoved", eventData);
|
||||
}
|
||||
|
||||
/**
|
||||
* A source's filter list has been reindexed.
|
||||
*
|
||||
* @dataField sourceName | String | Name of the source
|
||||
* @dataField filters | Array<Object> | Array of filter objects
|
||||
*
|
||||
* @eventType SourceFilterListReindexed
|
||||
* @eventSubscription Filters
|
||||
* @complexity 3
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api events
|
||||
* @category filters
|
||||
*/
|
||||
void EventHandler::HandleSourceFilterListReindexed(void *param, calldata_t *data)
|
||||
{
|
||||
auto eventHandler = static_cast<EventHandler*>(param);
|
||||
|
||||
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
|
||||
if (!source)
|
||||
return;
|
||||
|
||||
json eventData;
|
||||
eventData["sourceName"] = obs_source_get_name(source);
|
||||
eventData["filters"] = Utils::Obs::ArrayHelper::GetSourceFilterList(source);
|
||||
eventHandler->BroadcastEvent(EventSubscription::Filters, "SourceFilterListReindexed", eventData);
|
||||
}
|
||||
|
||||
/**
|
||||
* A source filter's enable state has changed.
|
||||
*
|
||||
* @dataField sourceName | String | Name of the source the filter is on
|
||||
* @dataField filterName | String | Name of the filter
|
||||
* @dataField filterEnabled | Boolean | Whether the filter is enabled
|
||||
*
|
||||
* @eventType SourceFilterEnableStateChanged
|
||||
* @eventSubscription Filters
|
||||
* @complexity 3
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api events
|
||||
* @category filters
|
||||
*/
|
||||
void EventHandler::HandleSourceFilterEnableStateChanged(void *param, calldata_t *data)
|
||||
{
|
||||
auto eventHandler = static_cast<EventHandler*>(param);
|
||||
|
||||
obs_source_t *filter = GetCalldataPointer<obs_source_t>(data, "source");
|
||||
if (!filter)
|
||||
return;
|
||||
|
||||
// Not OBSSourceAutoRelease as get_parent doesn't increment refcount
|
||||
obs_source_t *source = obs_filter_get_parent(filter);
|
||||
if (!source)
|
||||
return;
|
||||
|
||||
bool filterEnabled = calldata_bool(data, "enabled");
|
||||
|
||||
json eventData;
|
||||
eventData["sourceName"] = obs_source_get_name(source);
|
||||
eventData["filterName"] = obs_source_get_name(filter);
|
||||
eventData["filterEnabled"] = filterEnabled;
|
||||
eventHandler->BroadcastEvent(EventSubscription::Filters, "SourceFilterEnableStateChanged", eventData);
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of a source filter has changed.
|
||||
*
|
||||
* @dataField sourceName | String | The source the filter is on
|
||||
* @dataField oldFilterName | String | Old name of the filter
|
||||
* @dataField filterName | String | New name of the filter
|
||||
*
|
||||
* @eventType SourceFilterNameChanged
|
||||
* @eventSubscription Filters
|
||||
* @complexity 2
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api events
|
||||
* @category filters
|
||||
*/
|
||||
void EventHandler::HandleSourceFilterNameChanged(void *param, calldata_t *data)
|
||||
{
|
||||
auto eventHandler = static_cast<EventHandler*>(param);
|
||||
|
||||
obs_source_t *filter = GetCalldataPointer<obs_source_t>(data, "source");
|
||||
if (!filter)
|
||||
return;
|
||||
|
||||
json eventData;
|
||||
eventData["sourceName"] = obs_source_get_name(obs_filter_get_parent(filter));
|
||||
eventData["oldFilterName"] = calldata_string(data, "prev_name");
|
||||
eventData["filterName"] = calldata_string(data, "new_name");
|
||||
eventHandler->BroadcastEvent(EventSubscription::Filters, "SourceFilterNameChanged", eventData);
|
||||
}
|
||||
|
@ -111,7 +111,14 @@ const std::unordered_map<std::string, RequestMethodHandler> RequestHandler::_han
|
||||
{"SetTBarPosition", &RequestHandler::SetTBarPosition},
|
||||
|
||||
// Filters
|
||||
{"GetSourceFilterList", &RequestHandler::GetSourceFilterList},
|
||||
{"CreateSourceFilter", &RequestHandler::CreateSourceFilter},
|
||||
{"RemoveSourceFilter", &RequestHandler::RemoveSourceFilter},
|
||||
{"GetSourceFilterDefaultSettings", &RequestHandler::GetSourceFilterDefaultSettings},
|
||||
{"GetSourceFilter", &RequestHandler::GetSourceFilter},
|
||||
{"SetSourceFilterIndex", &RequestHandler::SetSourceFilterIndex},
|
||||
{"SetSourceFilterSettings", &RequestHandler::SetSourceFilterSettings},
|
||||
{"SetSourceFilterEnabled", &RequestHandler::SetSourceFilterEnabled},
|
||||
|
||||
// Scene Items
|
||||
{"GetSceneItemList", &RequestHandler::GetSceneItemList},
|
||||
|
@ -129,7 +129,14 @@ class RequestHandler {
|
||||
RequestResult SetTBarPosition(const Request&);
|
||||
|
||||
// Filters
|
||||
RequestResult GetSourceFilterList(const Request&);
|
||||
RequestResult CreateSourceFilter(const Request&);
|
||||
RequestResult RemoveSourceFilter(const Request&);
|
||||
RequestResult GetSourceFilterDefaultSettings(const Request&);
|
||||
RequestResult GetSourceFilter(const Request&);
|
||||
RequestResult SetSourceFilterIndex(const Request&);
|
||||
RequestResult SetSourceFilterSettings(const Request&);
|
||||
RequestResult SetSourceFilterEnabled(const Request&);
|
||||
|
||||
// Scene Items
|
||||
RequestResult GetSceneItemList(const Request&);
|
||||
|
@ -19,6 +19,145 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
|
||||
#include "RequestHandler.h"
|
||||
|
||||
/**
|
||||
* Gets an array of all of a source's filters.
|
||||
*
|
||||
* @requestField sourceName | String | Name of the source
|
||||
*
|
||||
* @responseField filters | Array<Object> | Array of filters
|
||||
*
|
||||
* @requestType GetSourceFilterList
|
||||
* @complexity 2
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api requests
|
||||
* @category filters
|
||||
*/
|
||||
RequestResult RequestHandler::GetSourceFilterList(const Request& request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSSourceAutoRelease source = request.ValidateSource("sourceName", statusCode, comment);
|
||||
if(!source)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
json responseData;
|
||||
responseData["filters"] = Utils::Obs::ArrayHelper::GetSourceFilterList(source);
|
||||
|
||||
return RequestResult::Success(responseData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new filter, adding it to the specified source.
|
||||
*
|
||||
* @requestField sourceName | String | Name of the source to add the filter to
|
||||
* @requestField filterName | String | Name of the new filter to be created
|
||||
* @requestField filterKind | String | The kind of filter to be created
|
||||
* @requestField ?filterSettings | Object | Settings object to initialize the filter with | Default settings used
|
||||
*
|
||||
* @requestType CreateSourceFilter
|
||||
* @complexity 3
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api requests
|
||||
* @category filters
|
||||
*/
|
||||
RequestResult RequestHandler::CreateSourceFilter(const Request& request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
|
||||
OBSSourceAutoRelease source = request.ValidateSource("sourceName", statusCode, comment);
|
||||
if (!(source && request.ValidateString("filterName", statusCode, comment) && request.ValidateString("filterKind", statusCode, comment)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
std::string filterName = request.RequestData["filterName"];
|
||||
OBSSourceAutoRelease existingFilter = obs_source_get_filter_by_name(source, filterName.c_str());
|
||||
if (existingFilter)
|
||||
return RequestResult::Error(RequestStatus::ResourceAlreadyExists, "A filter already exists by that name.");
|
||||
|
||||
std::string filterKind = request.RequestData["filterKind"];
|
||||
auto kinds = Utils::Obs::ArrayHelper::GetFilterKindList();
|
||||
if (std::find(kinds.begin(), kinds.end(), filterKind) == kinds.end())
|
||||
return RequestResult::Error(RequestStatus::InvalidFilterKind, "Your specified filter kind is not supported by OBS. Check that any necessary plugins are loaded.");
|
||||
|
||||
OBSDataAutoRelease filterSettings = nullptr;
|
||||
if (request.Contains("filterSettings")) {
|
||||
if (!request.ValidateOptionalObject("filterSettings", statusCode, comment, true))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
filterSettings = Utils::Json::JsonToObsData(request.RequestData["filterSettings"]);
|
||||
}
|
||||
|
||||
OBSSourceAutoRelease filter = Utils::Obs::ActionHelper::CreateSourceFilter(source, filterName, filterKind, filterSettings);
|
||||
|
||||
if(!filter)
|
||||
return RequestResult::Error(RequestStatus::ResourceCreationFailed, "Creation of the filter failed.");
|
||||
|
||||
return RequestResult::Success();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a filter from a source.
|
||||
*
|
||||
* @requestField sourceName | String | Name of the source the filter is on
|
||||
* @requestField filterName | String | Name of the filter to remove
|
||||
*
|
||||
* @requestType RemoveSourceFilter
|
||||
* @complexity 2
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api requests
|
||||
* @category filters
|
||||
*/
|
||||
RequestResult RequestHandler::RemoveSourceFilter(const Request& request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
FilterPair pair = request.ValidateFilter("sourceName", "filterName", statusCode, comment);
|
||||
if (!pair.filter)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
obs_source_filter_remove(pair.source, pair.filter);
|
||||
|
||||
return RequestResult::Success();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default settings for a filter kind.
|
||||
*
|
||||
* @requestField filterKind | String | Filter kind to get the default settings for
|
||||
*
|
||||
* @responseField defaultFilterSettings | Object | Object of default settings for the filter kind
|
||||
*
|
||||
* @requestType GetSourceFilterDefaultSettings
|
||||
* @complexity 3
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api requests
|
||||
* @category filters
|
||||
*/
|
||||
RequestResult RequestHandler::GetSourceFilterDefaultSettings(const Request& request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
if (!request.ValidateString("filterKind", statusCode, comment))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
std::string filterKind = request.RequestData["filterKind"];
|
||||
auto kinds = Utils::Obs::ArrayHelper::GetFilterKindList();
|
||||
if (std::find(kinds.begin(), kinds.end(), filterKind) == kinds.end())
|
||||
return RequestResult::Error(RequestStatus::InvalidFilterKind);
|
||||
|
||||
OBSDataAutoRelease defaultSettings = obs_get_source_defaults(filterKind.c_str());
|
||||
if (!defaultSettings)
|
||||
return RequestResult::Error(RequestStatus::InvalidFilterKind);
|
||||
|
||||
json responseData;
|
||||
responseData["defaultFilterSettings"] = Utils::Json::ObsDataToJson(defaultSettings, true);
|
||||
return RequestResult::Success(responseData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the info for a specific source filter.
|
||||
*
|
||||
@ -55,3 +194,108 @@ RequestResult RequestHandler::GetSourceFilter(const Request& request)
|
||||
|
||||
return RequestResult::Success(responseData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the index position of a filter on a source.
|
||||
*
|
||||
* @requestField sourceName | String | Name of the source the filter is on
|
||||
* @requestField filterName | String | Name of the filter
|
||||
* @requestField filterIndex | Number | New index position of the filter | >= 0
|
||||
*
|
||||
* @requestType SetSourceFilterIndex
|
||||
* @complexity 3
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api requests
|
||||
* @category filters
|
||||
*/
|
||||
RequestResult RequestHandler::SetSourceFilterIndex(const Request& request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
FilterPair pair = request.ValidateFilter("sourceName", "filterName", statusCode, comment);
|
||||
if (!(pair.filter && request.ValidateNumber("filterIndex", statusCode, comment, 0, 8192)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
int filterIndex = request.RequestData["filterIndex"];
|
||||
|
||||
Utils::Obs::ActionHelper::SetSourceFilterIndex(pair.source, pair.filter, filterIndex);
|
||||
|
||||
return RequestResult::Success();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the settings of a source filter.
|
||||
*
|
||||
* @requestField sourceName | String | Name of the source the filter is on
|
||||
* @requestField filterName | String | Name of the filter to set the settings of
|
||||
* @requestField filterSettings | Object | Object of settings to apply
|
||||
* @requestField ?overlay | Boolean | True == apply the settings on top of existing ones, False == reset the input to its defaults, then apply settings. | true
|
||||
*
|
||||
* @requestType SetSourceFilterSettings
|
||||
* @complexity 3
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api requests
|
||||
* @category filters
|
||||
*/
|
||||
RequestResult RequestHandler::SetSourceFilterSettings(const Request& request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
FilterPair pair = request.ValidateFilter("sourceName", "filterName", statusCode, comment);
|
||||
if (!(pair.filter && request.ValidateObject("filterSettings", statusCode, comment, true)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
// Almost identical to SetInputSettings
|
||||
|
||||
bool overlay = true;
|
||||
if (request.Contains("overlay")) {
|
||||
if (!request.ValidateOptionalBoolean("overlay", statusCode, comment))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
overlay = request.RequestData["overlay"];
|
||||
}
|
||||
|
||||
OBSDataAutoRelease newSettings = Utils::Json::JsonToObsData(request.RequestData["filterSettings"]);
|
||||
if (!newSettings)
|
||||
return RequestResult::Error(RequestStatus::RequestProcessingFailed, "An internal data conversion operation failed. Please report this!");
|
||||
|
||||
if (overlay)
|
||||
obs_source_update(pair.filter, newSettings);
|
||||
else
|
||||
obs_source_reset_settings(pair.filter, newSettings);
|
||||
|
||||
obs_source_update_properties(pair.filter);
|
||||
|
||||
return RequestResult::Success();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the enable state of a source filter.
|
||||
*
|
||||
* @requestField sourceName | String | Name of the source the filter is on
|
||||
* @requestField filterName | Number | Name of the filter
|
||||
* @requestField filterEnabled | Boolean | New enable state of the filter
|
||||
*
|
||||
* @requestType SetSourceFilterEnabled
|
||||
* @complexity 3
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api requests
|
||||
* @category filters
|
||||
*/
|
||||
RequestResult RequestHandler::SetSourceFilterEnabled(const Request& request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
FilterPair pair = request.ValidateFilter("sourceName", "filterName", statusCode, comment);
|
||||
if (!(pair.filter && request.ValidateBoolean("filterEnabled", statusCode, comment)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
bool filterEnabled = request.RequestData["filterEnabled"];
|
||||
|
||||
obs_source_set_enabled(pair.filter, filterEnabled);
|
||||
|
||||
return RequestResult::Success();
|
||||
}
|
||||
|
@ -269,6 +269,9 @@ RequestResult RequestHandler::GetInputDefaultSettings(const Request& request)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
std::string inputKind = request.RequestData["inputKind"];
|
||||
auto kinds = Utils::Obs::ArrayHelper::GetInputKindList();
|
||||
if (std::find(kinds.begin(), kinds.end(), inputKind) == kinds.end())
|
||||
return RequestResult::Error(RequestStatus::InvalidInputKind);
|
||||
|
||||
OBSDataAutoRelease defaultSettings = obs_get_source_defaults(inputKind.c_str());
|
||||
if (!defaultSettings)
|
||||
|
@ -345,6 +345,17 @@ namespace RequestStatus {
|
||||
* @api enums
|
||||
*/
|
||||
ResourceNotConfigurable = 606,
|
||||
/**
|
||||
* The specified filter (obs_source_t-OBS_SOURCE_TYPE_FILTER) had the wrong kind.
|
||||
*
|
||||
* @enumIdentifier InvalidFilterKind
|
||||
* @enumValue 607
|
||||
* @enumType RequestStatus
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api enums
|
||||
*/
|
||||
InvalidFilterKind = 607,
|
||||
|
||||
/**
|
||||
* Creating the resource failed.
|
||||
|
@ -193,6 +193,8 @@ namespace Utils {
|
||||
std::vector<json> GetListPropertyItems(obs_property_t *property);
|
||||
std::vector<std::string> GetTransitionKindList();
|
||||
std::vector<json> GetSceneTransitionList();
|
||||
std::vector<json> GetSourceFilterList(obs_source_t *source);
|
||||
std::vector<std::string> GetFilterKindList();
|
||||
}
|
||||
|
||||
namespace ObjectHelper {
|
||||
@ -209,6 +211,8 @@ namespace Utils {
|
||||
namespace ActionHelper {
|
||||
obs_sceneitem_t *CreateSceneItem(obs_source_t *source, obs_scene_t *scene, bool sceneItemEnabled = true, obs_transform_info *sceneItemTransform = nullptr, obs_sceneitem_crop *sceneItemCrop = nullptr); // Increments ref. Use OBSSceneItemAutoRelease
|
||||
obs_sceneitem_t *CreateInput(std::string inputName, std::string inputKind, obs_data_t *inputSettings, obs_scene_t *scene, bool sceneItemEnabled = true); // Increments ref. Use OBSSceneItemAutoRelease
|
||||
obs_source_t *CreateSourceFilter(obs_source_t *source, std::string filterName, std::string filterKind, obs_data_t *filterSettings); // Increments source ref. Use OBSSourceAutoRelease
|
||||
void SetSourceFilterIndex(obs_source_t *source, obs_source_t *filter, size_t index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -87,3 +87,30 @@ obs_sceneitem_t *Utils::Obs::ActionHelper::CreateInput(std::string inputName, st
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
obs_source_t *Utils::Obs::ActionHelper::CreateSourceFilter(obs_source_t *source, std::string filterName, std::string filterKind, obs_data_t *filterSettings)
|
||||
{
|
||||
obs_source_t *filter = obs_source_create_private(filterKind.c_str(), filterName.c_str(), filterSettings);
|
||||
|
||||
if (!filter)
|
||||
return nullptr;
|
||||
|
||||
obs_source_filter_add(source, filter);
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
void Utils::Obs::ActionHelper::SetSourceFilterIndex(obs_source_t *source, obs_source_t *filter, size_t index)
|
||||
{
|
||||
size_t currentIndex = Utils::Obs::NumberHelper::GetSourceFilterIndex(source, filter);
|
||||
obs_order_movement direction = index > currentIndex ? OBS_ORDER_MOVE_DOWN : OBS_ORDER_MOVE_UP;
|
||||
|
||||
while(currentIndex != index) {
|
||||
obs_source_filter_set_order(source, filter, direction);
|
||||
|
||||
if (direction == OBS_ORDER_MOVE_DOWN)
|
||||
currentIndex++;
|
||||
else
|
||||
currentIndex--;
|
||||
}
|
||||
}
|
||||
|
@ -276,3 +276,38 @@ std::vector<json> Utils::Obs::ArrayHelper::GetSceneTransitionList()
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<std::string> Utils::Obs::ArrayHelper::GetFilterKindList()
|
||||
{
|
||||
std::vector<std::string> ret;
|
||||
|
||||
size_t idx = 0;
|
||||
const char *kind;
|
||||
while(obs_enum_filter_types(idx++, &kind))
|
||||
ret.push_back(kind);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<json> Utils::Obs::ArrayHelper::GetSourceFilterList(obs_source_t *source)
|
||||
{
|
||||
std::vector<json> filters;
|
||||
|
||||
auto enumFilters = [](obs_source_t *, obs_source_t *filter, void *param) {
|
||||
auto filters = reinterpret_cast<std::vector<json>*>(param);
|
||||
|
||||
json filterJson;
|
||||
filterJson["filterEnabled"] = obs_source_enabled(filter);
|
||||
filterJson["filterIndex"] = filters->size();
|
||||
filterJson["filterKind"] = obs_source_get_id(filter);
|
||||
filterJson["filterName"] = obs_source_get_name(filter);
|
||||
|
||||
OBSDataAutoRelease filterSettings = obs_source_get_settings(filter);
|
||||
filterJson["filterSettings"] = Utils::Json::ObsDataToJson(filterSettings);
|
||||
|
||||
filters->push_back(filterJson);
|
||||
};
|
||||
obs_source_enum_filters(source, enumFilters, &filters);
|
||||
|
||||
return filters;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user