diff --git a/.clang-format.json b/.cmake-format.json similarity index 100% rename from .clang-format.json rename to .cmake-format.json diff --git a/lib/example/simplest-plugin.c b/lib/example/simplest-plugin.c index bb50db2b..a937360a 100644 --- a/lib/example/simplest-plugin.c +++ b/lib/example/simplest-plugin.c @@ -1,78 +1,89 @@ -/* -obs-websocket -Copyright (C) 2020-2021 Kyle Manning - -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 -*/ - -// Similar example code can be found in ../../src/obs-websocket.cpp -// You can test that sample code by specifying -DPLUGIN_TESTS=TRUE - -#include - -#include "../obs-websocket-api.h" - -OBS_DECLARE_MODULE() -OBS_MODULE_USE_DEFAULT_LOCALE(PLUGIN_NAME, "en-US") - -obs_websocket_vendor vendor; - -bool obs_module_load(void) -{ - blog(LOG_INFO, "Example obs-websocket-api plugin loaded!"); - return true; -} - -void example_request_cb(obs_data_t *request_data, obs_data_t *response_data, void *priv_data); -void obs_module_post_load(void) -{ - vendor = obs_websocket_register_vendor("api_example_plugin"); - if (!vendor) { - blog(LOG_ERROR, "Vendor registration failed! (obs-websocket should have logged something if installed properly.)"); - return; - } - - if (!obs_websocket_vendor_register_request(vendor, "example_request", example_request_cb, NULL)) - blog(LOG_ERROR, "Failed to register `example_request` request with obs-websocket."); - - uint api_version = obs_websocket_get_api_version(); - if (api_version == 0) { - blog(LOG_ERROR, "Unable to fetch obs-websocket plugin API version."); - return; - } else if (api_version == 1) { - blog(LOG_WARNING, "Unsupported obs-websocket plugin API version for calling requests."); - return; - } - - struct obs_websocket_request_response *response = obs_websocket_call_request("GetVersion"); - if (!response) { - blog(LOG_ERROR, "Failed to call GetVersion due to obs-websocket not being installed."); - return; - } - blog(LOG_INFO, "[obs_module_post_load] Called GetVersion. Status Code: %u | Comment: %s | Response Data: %s", response->status_code, response->comment, response->response_data); - obs_websocket_request_response_free(response); -} - -void obs_module_unload(void) -{ - blog(LOG_INFO, "Example obs-websocket-api plugin unloaded!"); -} - -void example_request_cb(obs_data_t *request_data, obs_data_t *response_data, void *priv_data) -{ - if (obs_data_has_user_value(request_data, "ping")) - obs_data_set_bool(response_data, "pong", true); - - UNUSED_PARAMETER(priv_data); -} +/* +obs-websocket +Copyright (C) 2020-2021 Kyle Manning + +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 +*/ + +// Similar example code can be found in ../../src/obs-websocket.cpp +// You can test that sample code by specifying -DPLUGIN_TESTS=TRUE + +#include + +#include "../obs-websocket-api.h" + +OBS_DECLARE_MODULE() +OBS_MODULE_USE_DEFAULT_LOCALE(PLUGIN_NAME, "en-US") + +obs_websocket_vendor vendor; + +bool obs_module_load(void) +{ + blog(LOG_INFO, "Example obs-websocket-api plugin loaded!"); + return true; +} + +void example_request_cb(obs_data_t *request_data, obs_data_t *response_data, + void *priv_data); +void obs_module_post_load(void) +{ + vendor = obs_websocket_register_vendor("api_example_plugin"); + if (!vendor) { + blog(LOG_ERROR, + "Vendor registration failed! (obs-websocket should have logged something if installed properly.)"); + return; + } + + if (!obs_websocket_vendor_register_request(vendor, "example_request", + example_request_cb, NULL)) + blog(LOG_ERROR, + "Failed to register `example_request` request with obs-websocket."); + + uint api_version = obs_websocket_get_api_version(); + if (api_version == 0) { + blog(LOG_ERROR, + "Unable to fetch obs-websocket plugin API version."); + return; + } else if (api_version == 1) { + blog(LOG_WARNING, + "Unsupported obs-websocket plugin API version for calling requests."); + return; + } + + struct obs_websocket_request_response *response = + obs_websocket_call_request("GetVersion"); + if (!response) { + blog(LOG_ERROR, + "Failed to call GetVersion due to obs-websocket not being installed."); + return; + } + blog(LOG_INFO, + "[obs_module_post_load] Called GetVersion. Status Code: %u | Comment: %s | Response Data: %s", + response->status_code, response->comment, response->response_data); + obs_websocket_request_response_free(response); +} + +void obs_module_unload(void) +{ + blog(LOG_INFO, "Example obs-websocket-api plugin unloaded!"); +} + +void example_request_cb(obs_data_t *request_data, obs_data_t *response_data, + void *priv_data) +{ + if (obs_data_has_user_value(request_data, "ping")) + obs_data_set_bool(response_data, "pong", true); + + UNUSED_PARAMETER(priv_data); +} diff --git a/lib/obs-websocket-api.h b/lib/obs-websocket-api.h index 8cdfc036..d050f9ac 100644 --- a/lib/obs-websocket-api.h +++ b/lib/obs-websocket-api.h @@ -28,8 +28,9 @@ with this program. If not, see extern "C" { #endif -typedef void* obs_websocket_vendor; -typedef void (*obs_websocket_request_callback_function)(obs_data_t*, obs_data_t*, void*); +typedef void *obs_websocket_vendor; +typedef void (*obs_websocket_request_callback_function)(obs_data_t *, + obs_data_t *, void *); struct obs_websocket_request_response { unsigned int status_code; @@ -55,8 +56,9 @@ static inline proc_handler_t *obs_websocket_get_ph(void) calldata_t cd = {0}; if (!proc_handler_call(global_ph, "obs_websocket_api_get_ph", &cd)) - blog(LOG_DEBUG, "Unable to fetch obs-websocket proc handler object. obs-websocket not installed?"); - proc_handler_t *ret = (proc_handler_t*)calldata_ptr(&cd, "ph"); + blog(LOG_DEBUG, + "Unable to fetch obs-websocket proc handler object. obs-websocket not installed?"); + proc_handler_t *ret = (proc_handler_t *)calldata_ptr(&cd, "ph"); calldata_free(&cd); return ret; @@ -69,7 +71,9 @@ static inline bool obs_websocket_ensure_ph(void) return _ph != NULL; } -static inline bool obs_websocket_vendor_run_simple_proc(obs_websocket_vendor vendor, const char *proc_name, calldata_t *cd) +static inline bool +obs_websocket_vendor_run_simple_proc(obs_websocket_vendor vendor, + const char *proc_name, calldata_t *cd) { if (!obs_websocket_ensure_ph()) return false; @@ -104,7 +108,9 @@ static inline unsigned int obs_websocket_get_api_version(void) } // Calls an obs-websocket request. Free response with `obs_websocket_request_response_free()` -static inline obs_websocket_request_response *obs_websocket_call_request(const char *request_type, obs_data_t *request_data = NULL) +static inline obs_websocket_request_response * +obs_websocket_call_request(const char *request_type, + obs_data_t *request_data = NULL) { if (!obs_websocket_ensure_ph()) return NULL; @@ -120,7 +126,8 @@ static inline obs_websocket_request_response *obs_websocket_call_request(const c proc_handler_call(_ph, "call_request", &cd); - auto ret = (struct obs_websocket_request_response*)calldata_ptr(&cd, "response"); + auto ret = (struct obs_websocket_request_response *)calldata_ptr( + &cd, "response"); calldata_free(&cd); @@ -128,7 +135,8 @@ static inline obs_websocket_request_response *obs_websocket_call_request(const c } // Free a request response object returned by `obs_websocket_call_request()` -static inline void obs_websocket_request_response_free(struct obs_websocket_request_response *response) +static inline void obs_websocket_request_response_free( + struct obs_websocket_request_response *response) { if (!response) return; @@ -144,7 +152,8 @@ static inline void obs_websocket_request_response_free(struct obs_websocket_requ // ALWAYS CALL ONLY VIA `obs_module_post_load()` CALLBACK! // Registers a new "vendor" (Example: obs-ndi) -static inline obs_websocket_vendor obs_websocket_register_vendor(const char *vendor_name) +static inline obs_websocket_vendor +obs_websocket_register_vendor(const char *vendor_name) { if (!obs_websocket_ensure_ph()) return NULL; @@ -161,7 +170,10 @@ static inline obs_websocket_vendor obs_websocket_register_vendor(const char *ven } // Registers a new request for a vendor -static inline bool obs_websocket_vendor_register_request(obs_websocket_vendor vendor, const char *request_type, obs_websocket_request_callback_function request_callback, void* priv_data) +static inline bool obs_websocket_vendor_register_request( + obs_websocket_vendor vendor, const char *request_type, + obs_websocket_request_callback_function request_callback, + void *priv_data) { calldata_t cd = {0}; @@ -172,20 +184,24 @@ static inline bool obs_websocket_vendor_register_request(obs_websocket_vendor ve calldata_set_string(&cd, "type", request_type); calldata_set_ptr(&cd, "callback", &cb); - bool success = obs_websocket_vendor_run_simple_proc(vendor, "vendor_request_register", &cd); + bool success = obs_websocket_vendor_run_simple_proc( + vendor, "vendor_request_register", &cd); calldata_free(&cd); return success; } // Unregisters an existing vendor request -static inline bool obs_websocket_vendor_unregister_request(obs_websocket_vendor vendor, const char *request_type) +static inline bool +obs_websocket_vendor_unregister_request(obs_websocket_vendor vendor, + const char *request_type) { calldata_t cd = {0}; calldata_set_string(&cd, "type", request_type); - bool success = obs_websocket_vendor_run_simple_proc(vendor, "vendor_request_unregister", &cd); + bool success = obs_websocket_vendor_run_simple_proc( + vendor, "vendor_request_unregister", &cd); calldata_free(&cd); return success; @@ -193,14 +209,17 @@ static inline bool obs_websocket_vendor_unregister_request(obs_websocket_vendor // Does not affect event_data refcount. // Emits an event under the vendor's name -static inline bool obs_websocket_vendor_emit_event(obs_websocket_vendor vendor, const char *event_name, obs_data_t *event_data) +static inline bool obs_websocket_vendor_emit_event(obs_websocket_vendor vendor, + const char *event_name, + obs_data_t *event_data) { calldata_t cd = {0}; calldata_set_string(&cd, "type", event_name); - calldata_set_ptr(&cd, "data", (void*)event_data); + calldata_set_ptr(&cd, "data", (void *)event_data); - bool success = obs_websocket_vendor_run_simple_proc(vendor, "vendor_event_emit", &cd); + bool success = obs_websocket_vendor_run_simple_proc( + vendor, "vendor_event_emit", &cd); calldata_free(&cd); return success; diff --git a/src/Config.cpp b/src/Config.cpp index 91ee476f..bdb67470 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -38,37 +38,44 @@ with this program. If not, see #define CMDLINE_WEBSOCKET_PASSWORD "websocket_password" #define CMDLINE_WEBSOCKET_DEBUG "websocket_debug" -Config::Config() : - PortOverridden(false), - PasswordOverridden(false), - FirstLoad(true), - ServerEnabled(true), - ServerPort(4455), - BindLoopback(true), - Ipv4Only(false), - DebugEnabled(false), - AlertsEnabled(false), - AuthRequired(true), - ServerPassword("") +Config::Config() + : PortOverridden(false), + PasswordOverridden(false), + FirstLoad(true), + ServerEnabled(true), + ServerPort(4455), + BindLoopback(true), + Ipv4Only(false), + DebugEnabled(false), + AlertsEnabled(false), + AuthRequired(true), + ServerPassword("") { SetDefaultsToGlobalStore(); } void Config::Load() { - config_t* obsConfig = GetConfigStore(); + config_t *obsConfig = GetConfigStore(); if (!obsConfig) { blog(LOG_ERROR, "[Config::Load] Unable to fetch OBS config!"); return; } - FirstLoad = config_get_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_FIRSTLOAD); - ServerEnabled = config_get_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ENABLED); - AlertsEnabled = config_get_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ALERTS); - ServerPort = config_get_uint(obsConfig, CONFIG_SECTION_NAME, PARAM_PORT); - BindLoopback = config_get_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_BINDLOOPBACK); - AuthRequired = config_get_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_AUTHREQUIRED); - ServerPassword = config_get_string(obsConfig, CONFIG_SECTION_NAME, PARAM_PASSWORD); + FirstLoad = config_get_bool(obsConfig, CONFIG_SECTION_NAME, + PARAM_FIRSTLOAD); + ServerEnabled = + config_get_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ENABLED); + AlertsEnabled = + config_get_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ALERTS); + ServerPort = + config_get_uint(obsConfig, CONFIG_SECTION_NAME, PARAM_PORT); + BindLoopback = config_get_bool(obsConfig, CONFIG_SECTION_NAME, + PARAM_BINDLOOPBACK); + AuthRequired = config_get_bool(obsConfig, CONFIG_SECTION_NAME, + PARAM_AUTHREQUIRED); + ServerPassword = config_get_string(obsConfig, CONFIG_SECTION_NAME, + PARAM_PASSWORD); // Set server password and save it to the config before processing overrides, // so that there is always a true configured password regardless of if @@ -76,38 +83,49 @@ void Config::Load() if (FirstLoad) { FirstLoad = false; if (ServerPassword.isEmpty()) { - blog(LOG_INFO, "[Config::Load] (FirstLoad) Generating new server password."); - ServerPassword = QString::fromStdString(Utils::Crypto::GeneratePassword()); + blog(LOG_INFO, + "[Config::Load] (FirstLoad) Generating new server password."); + ServerPassword = QString::fromStdString( + Utils::Crypto::GeneratePassword()); } else { - blog(LOG_INFO, "[Config::Load] (FirstLoad) Not generating new password since one is already configured."); + blog(LOG_INFO, + "[Config::Load] (FirstLoad) Not generating new password since one is already configured."); } Save(); } // Process `--websocket_port` override - QString portArgument = Utils::Platform::GetCommandLineArgument(CMDLINE_WEBSOCKET_PORT); + QString portArgument = + Utils::Platform::GetCommandLineArgument(CMDLINE_WEBSOCKET_PORT); if (portArgument != "") { bool ok; uint16_t serverPort = portArgument.toUShort(&ok); if (ok) { - blog(LOG_INFO, "[Config::Load] --websocket_port passed. Overriding WebSocket port with: %d", serverPort); + blog(LOG_INFO, + "[Config::Load] --websocket_port passed. Overriding WebSocket port with: %d", + serverPort); PortOverridden = true; ServerPort = serverPort; } else { - blog(LOG_WARNING, "[Config::Load] Not overriding WebSocket port since integer conversion failed."); + blog(LOG_WARNING, + "[Config::Load] Not overriding WebSocket port since integer conversion failed."); } } // Process `--websocket_ipv4_only` override - if (Utils::Platform::GetCommandLineFlagSet(CMDLINE_WEBSOCKET_IPV4_ONLY)) { - blog(LOG_INFO, "[Config::Load] --websocket_ipv4_only passed. Binding only to IPv4 interfaces."); + if (Utils::Platform::GetCommandLineFlagSet( + CMDLINE_WEBSOCKET_IPV4_ONLY)) { + blog(LOG_INFO, + "[Config::Load] --websocket_ipv4_only passed. Binding only to IPv4 interfaces."); Ipv4Only = true; } // Process `--websocket_password` override - QString passwordArgument = Utils::Platform::GetCommandLineArgument(CMDLINE_WEBSOCKET_PASSWORD); + QString passwordArgument = Utils::Platform::GetCommandLineArgument( + CMDLINE_WEBSOCKET_PASSWORD); if (passwordArgument != "") { - blog(LOG_INFO, "[Config::Load] --websocket_password passed. Overriding WebSocket password."); + blog(LOG_INFO, + "[Config::Load] --websocket_password passed. Overriding WebSocket password."); PasswordOverridden = true; AuthRequired = true; ServerPassword = passwordArgument; @@ -116,29 +134,37 @@ void Config::Load() // Process `--websocket_debug` override if (Utils::Platform::GetCommandLineFlagSet(CMDLINE_WEBSOCKET_DEBUG)) { // Debug does not persist on reload, so we let people override it with a flag. - blog(LOG_INFO, "[Config::Load] --websocket_debug passed. Enabling debug logging."); + blog(LOG_INFO, + "[Config::Load] --websocket_debug passed. Enabling debug logging."); DebugEnabled = true; } } void Config::Save() { - config_t* obsConfig = GetConfigStore(); + config_t *obsConfig = GetConfigStore(); if (!obsConfig) { blog(LOG_ERROR, "[Config::Save] Unable to fetch OBS config!"); return; } - config_set_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_FIRSTLOAD, FirstLoad); - config_set_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ENABLED, ServerEnabled); + config_set_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_FIRSTLOAD, + FirstLoad); + config_set_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ENABLED, + ServerEnabled); if (!PortOverridden) { - config_set_uint(obsConfig, CONFIG_SECTION_NAME, PARAM_PORT, ServerPort); + config_set_uint(obsConfig, CONFIG_SECTION_NAME, PARAM_PORT, + ServerPort); } - config_set_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_BINDLOOPBACK, BindLoopback); - config_set_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ALERTS, AlertsEnabled); + config_set_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_BINDLOOPBACK, + BindLoopback); + config_set_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ALERTS, + AlertsEnabled); if (!PasswordOverridden) { - config_set_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_AUTHREQUIRED, AuthRequired); - config_set_string(obsConfig, CONFIG_SECTION_NAME, PARAM_PASSWORD, QT_TO_UTF8(ServerPassword)); + config_set_bool(obsConfig, CONFIG_SECTION_NAME, + PARAM_AUTHREQUIRED, AuthRequired); + config_set_string(obsConfig, CONFIG_SECTION_NAME, + PARAM_PASSWORD, QT_TO_UTF8(ServerPassword)); } config_save(obsConfig); @@ -146,22 +172,30 @@ void Config::Save() void Config::SetDefaultsToGlobalStore() { - config_t* obsConfig = GetConfigStore(); + config_t *obsConfig = GetConfigStore(); if (!obsConfig) { - blog(LOG_ERROR, "[Config::SetDefaultsToGlobalStore] Unable to fetch OBS config!"); + blog(LOG_ERROR, + "[Config::SetDefaultsToGlobalStore] Unable to fetch OBS config!"); return; } - config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_FIRSTLOAD, FirstLoad); - config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ENABLED, ServerEnabled); - config_set_default_uint(obsConfig, CONFIG_SECTION_NAME, PARAM_PORT, ServerPort); - config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_BINDLOOPBACK, BindLoopback); - config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ALERTS, AlertsEnabled); - config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_AUTHREQUIRED, AuthRequired); - config_set_default_string(obsConfig, CONFIG_SECTION_NAME, PARAM_PASSWORD, QT_TO_UTF8(ServerPassword)); + config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_FIRSTLOAD, + FirstLoad); + config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ENABLED, + ServerEnabled); + config_set_default_uint(obsConfig, CONFIG_SECTION_NAME, PARAM_PORT, + ServerPort); + config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, + PARAM_BINDLOOPBACK, BindLoopback); + config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ALERTS, + AlertsEnabled); + config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, + PARAM_AUTHREQUIRED, AuthRequired); + config_set_default_string(obsConfig, CONFIG_SECTION_NAME, + PARAM_PASSWORD, QT_TO_UTF8(ServerPassword)); } -config_t* Config::GetConfigStore() +config_t *Config::GetConfigStore() { return obs_frontend_get_global_config(); } diff --git a/src/Config.h b/src/Config.h index 3b3f4a54..4c337ec9 100644 --- a/src/Config.h +++ b/src/Config.h @@ -30,7 +30,7 @@ struct Config { void Load(); void Save(); void SetDefaultsToGlobalStore(); - config_t* GetConfigStore(); + config_t *GetConfigStore(); std::atomic PortOverridden; std::atomic PasswordOverridden; diff --git a/src/WebSocketApi.cpp b/src/WebSocketApi.cpp index fadbb926..7e6f00f8 100644 --- a/src/WebSocketApi.cpp +++ b/src/WebSocketApi.cpp @@ -3,7 +3,11 @@ #include "obs-websocket.h" #include "utils/Json.h" -#define RETURN_STATUS(status) { calldata_set_bool(cd, "success", status); return; } +#define RETURN_STATUS(status) \ + { \ + calldata_set_bool(cd, "success", status); \ + return; \ + } #define RETURN_SUCCESS() RETURN_STATUS(true); #define RETURN_FAILURE() RETURN_STATUS(false); @@ -11,11 +15,12 @@ WebSocketApi::Vendor *get_vendor(calldata_t *cd) { void *voidVendor; if (!calldata_get_ptr(cd, "vendor", &voidVendor)) { - blog(LOG_WARNING, "[WebSocketApi: get_vendor] Failed due to missing `vendor` pointer."); + blog(LOG_WARNING, + "[WebSocketApi: get_vendor] Failed due to missing `vendor` pointer."); return nullptr; } - return static_cast(voidVendor); + return static_cast(voidVendor); } WebSocketApi::WebSocketApi() @@ -24,17 +29,33 @@ WebSocketApi::WebSocketApi() _procHandler = proc_handler_create(); - proc_handler_add(_procHandler, "bool get_api_version(out int version)", &get_api_version, nullptr); - proc_handler_add(_procHandler, "bool call_request(in string request_type, in string request_data, out ptr response)", &call_request, nullptr); - proc_handler_add(_procHandler, "bool vendor_register(in string name, out ptr vendor)", &vendor_register_cb, this); - proc_handler_add(_procHandler, "bool vendor_request_register(in ptr vendor, in string type, in ptr callback)", &vendor_request_register_cb, this); - proc_handler_add(_procHandler, "bool vendor_request_unregister(in ptr vendor, in string type)", &vendor_request_unregister_cb, this); - proc_handler_add(_procHandler, "bool vendor_event_emit(in ptr vendor, in string type, in ptr data)", &vendor_event_emit_cb, this); + proc_handler_add(_procHandler, "bool get_api_version(out int version)", + &get_api_version, nullptr); + proc_handler_add( + _procHandler, + "bool call_request(in string request_type, in string request_data, out ptr response)", + &call_request, nullptr); + proc_handler_add(_procHandler, + "bool vendor_register(in string name, out ptr vendor)", + &vendor_register_cb, this); + proc_handler_add( + _procHandler, + "bool vendor_request_register(in ptr vendor, in string type, in ptr callback)", + &vendor_request_register_cb, this); + proc_handler_add( + _procHandler, + "bool vendor_request_unregister(in ptr vendor, in string type)", + &vendor_request_unregister_cb, this); + proc_handler_add( + _procHandler, + "bool vendor_event_emit(in ptr vendor, in string type, in ptr data)", + &vendor_event_emit_cb, this); proc_handler_t *ph = obs_get_proc_handler(); assert(ph != NULL); - proc_handler_add(ph, "bool obs_websocket_api_get_ph(out ptr ph)", &get_ph_cb, this); + proc_handler_add(ph, "bool obs_websocket_api_get_ph(out ptr ph)", + &get_ph_cb, this); blog_debug("[WebSocketApi::WebSocketApi] Finished."); } @@ -46,7 +67,8 @@ WebSocketApi::~WebSocketApi() proc_handler_destroy(_procHandler); for (auto vendor : _vendors) { - blog_debug("[WebSocketApi::~WebSocketApi] Deleting vendor: %s", vendor.first.c_str()); + blog_debug("[WebSocketApi::~WebSocketApi] Deleting vendor: %s", + vendor.first.c_str()); delete vendor.second; } @@ -58,7 +80,9 @@ void WebSocketApi::SetEventCallback(EventCallback cb) _eventCallback = cb; } -enum WebSocketApi::RequestReturnCode WebSocketApi::PerformVendorRequest(std::string vendorName, std::string requestType, obs_data_t *requestData, obs_data_t *responseData) +enum WebSocketApi::RequestReturnCode WebSocketApi::PerformVendorRequest( + std::string vendorName, std::string requestType, + obs_data_t *requestData, obs_data_t *responseData) { std::shared_lock l(_mutex); @@ -85,9 +109,9 @@ enum WebSocketApi::RequestReturnCode WebSocketApi::PerformVendorRequest(std::str void WebSocketApi::get_ph_cb(void *priv_data, calldata_t *cd) { - auto c = static_cast(priv_data); + auto c = static_cast(priv_data); - calldata_set_ptr(cd, "ph", (void*)c->_procHandler); + calldata_set_ptr(cd, "ph", (void *)c->_procHandler); RETURN_SUCCESS(); } @@ -107,7 +131,8 @@ void WebSocketApi::call_request(void *, calldata_t *cd) if (!request_type) RETURN_FAILURE(); - auto response = static_cast(bzalloc(sizeof(struct obs_websocket_request_response))); + auto response = static_cast( + bzalloc(sizeof(struct obs_websocket_request_response))); if (!response) RETURN_FAILURE(); @@ -129,18 +154,22 @@ void WebSocketApi::call_request(void *, calldata_t *cd) calldata_set_ptr(cd, "response", response); - blog_debug("[WebSocketApi::call_request] Request %s called, response status code is %u", request_type, response->status_code); + blog_debug( + "[WebSocketApi::call_request] Request %s called, response status code is %u", + request_type, response->status_code); RETURN_SUCCESS(); } void WebSocketApi::vendor_register_cb(void *priv_data, calldata_t *cd) { - auto c = static_cast(priv_data); + auto c = static_cast(priv_data); const char *vendorName; - if (!calldata_get_string(cd, "name", &vendorName) || strlen(vendorName) == 0) { - blog(LOG_WARNING, "[WebSocketApi::vendor_register_cb] Failed due to missing `name` string."); + if (!calldata_get_string(cd, "name", &vendorName) || + strlen(vendorName) == 0) { + blog(LOG_WARNING, + "[WebSocketApi::vendor_register_cb] Failed due to missing `name` string."); RETURN_FAILURE(); } @@ -148,18 +177,22 @@ void WebSocketApi::vendor_register_cb(void *priv_data, calldata_t *cd) std::unique_lock l(c->_mutex); if (c->_vendors.count(vendorName)) { - blog(LOG_WARNING, "[WebSocketApi::vendor_register_cb] Failed because `%s` is already a registered vendor.", vendorName); + blog(LOG_WARNING, + "[WebSocketApi::vendor_register_cb] Failed because `%s` is already a registered vendor.", + vendorName); RETURN_FAILURE(); } - Vendor* v = new Vendor(); + Vendor *v = new Vendor(); v->_name = vendorName; c->_vendors[vendorName] = v; - blog_debug("[WebSocketApi::vendor_register_cb] [vendorName: %s] Registered new vendor.", v->_name.c_str()); + blog_debug( + "[WebSocketApi::vendor_register_cb] [vendorName: %s] Registered new vendor.", + v->_name.c_str()); - calldata_set_ptr(cd, "vendor", static_cast(v)); + calldata_set_ptr(cd, "vendor", static_cast(v)); RETURN_SUCCESS(); } @@ -171,29 +204,38 @@ void WebSocketApi::vendor_request_register_cb(void *, calldata_t *cd) RETURN_FAILURE(); const char *requestType; - if (!calldata_get_string(cd, "type", &requestType) || strlen(requestType) == 0) { - blog(LOG_WARNING, "[WebSocketApi::vendor_request_register_cb] [vendorName: %s] Failed due to missing or empty `type` string.", v->_name.c_str()); + if (!calldata_get_string(cd, "type", &requestType) || + strlen(requestType) == 0) { + blog(LOG_WARNING, + "[WebSocketApi::vendor_request_register_cb] [vendorName: %s] Failed due to missing or empty `type` string.", + v->_name.c_str()); RETURN_FAILURE(); } void *voidCallback; if (!calldata_get_ptr(cd, "callback", &voidCallback) || !voidCallback) { - blog(LOG_WARNING, "[WebSocketApi::vendor_request_register_cb] [vendorName: %s] Failed due to missing `callback` pointer.", v->_name.c_str()); + blog(LOG_WARNING, + "[WebSocketApi::vendor_request_register_cb] [vendorName: %s] Failed due to missing `callback` pointer.", + v->_name.c_str()); RETURN_FAILURE(); } - auto cb = static_cast(voidCallback); + auto cb = static_cast(voidCallback); std::unique_lock l(v->_mutex); if (v->_requests.count(requestType)) { - blog(LOG_WARNING, "[WebSocketApi::vendor_request_register_cb] [vendorName: %s] Failed because `%s` is already a registered request.", v->_name.c_str(), requestType); + blog(LOG_WARNING, + "[WebSocketApi::vendor_request_register_cb] [vendorName: %s] Failed because `%s` is already a registered request.", + v->_name.c_str(), requestType); RETURN_FAILURE(); } v->_requests[requestType] = *cb; - blog_debug("[WebSocketApi::vendor_request_register_cb] [vendorName: %s] Registered new vendor request: %s", v->_name.c_str(), requestType); + blog_debug( + "[WebSocketApi::vendor_request_register_cb] [vendorName: %s] Registered new vendor request: %s", + v->_name.c_str(), requestType); RETURN_SUCCESS(); } @@ -205,46 +247,58 @@ void WebSocketApi::vendor_request_unregister_cb(void *, calldata_t *cd) RETURN_FAILURE(); const char *requestType; - if (!calldata_get_string(cd, "type", &requestType) || strlen(requestType) == 0) { - blog(LOG_WARNING, "[WebSocketApi::vendor_request_unregister_cb] [vendorName: %s] Failed due to missing `type` string.", v->_name.c_str()); + if (!calldata_get_string(cd, "type", &requestType) || + strlen(requestType) == 0) { + blog(LOG_WARNING, + "[WebSocketApi::vendor_request_unregister_cb] [vendorName: %s] Failed due to missing `type` string.", + v->_name.c_str()); RETURN_FAILURE(); } std::unique_lock l(v->_mutex); if (!v->_requests.count(requestType)) { - blog(LOG_WARNING, "[WebSocketApi::vendor_request_register_cb] [vendorName: %s] Failed because `%s` is not a registered request.", v->_name.c_str(), requestType); + blog(LOG_WARNING, + "[WebSocketApi::vendor_request_register_cb] [vendorName: %s] Failed because `%s` is not a registered request.", + v->_name.c_str(), requestType); RETURN_FAILURE(); } v->_requests.erase(requestType); - blog_debug("[WebSocketApi::vendor_request_unregister_cb] [vendorName: %s] Unregistered vendor request: %s", v->_name.c_str(), requestType); + blog_debug( + "[WebSocketApi::vendor_request_unregister_cb] [vendorName: %s] Unregistered vendor request: %s", + v->_name.c_str(), requestType); RETURN_SUCCESS(); } void WebSocketApi::vendor_event_emit_cb(void *priv_data, calldata_t *cd) { - auto c = static_cast(priv_data); + auto c = static_cast(priv_data); Vendor *v = get_vendor(cd); if (!v) RETURN_FAILURE(); const char *eventType; - if (!calldata_get_string(cd, "type", &eventType) || strlen(eventType) == 0) { - blog(LOG_WARNING, "[WebSocketApi::vendor_event_emit_cb] [vendorName: %s] Failed due to missing `type` string.", v->_name.c_str()); + if (!calldata_get_string(cd, "type", &eventType) || + strlen(eventType) == 0) { + blog(LOG_WARNING, + "[WebSocketApi::vendor_event_emit_cb] [vendorName: %s] Failed due to missing `type` string.", + v->_name.c_str()); RETURN_FAILURE(); } void *voidEventData; if (!calldata_get_ptr(cd, "data", &voidEventData)) { - blog(LOG_WARNING, "[WebSocketApi::vendor_event_emit_cb] [vendorName: %s] Failed due to missing `data` pointer.", v->_name.c_str()); + blog(LOG_WARNING, + "[WebSocketApi::vendor_event_emit_cb] [vendorName: %s] Failed due to missing `data` pointer.", + v->_name.c_str()); RETURN_FAILURE(); } - auto eventData = static_cast(voidEventData); + auto eventData = static_cast(voidEventData); if (!c->_eventCallback) RETURN_FAILURE(); diff --git a/src/WebSocketApi.h b/src/WebSocketApi.h index 3d3b92fb..ff09103c 100644 --- a/src/WebSocketApi.h +++ b/src/WebSocketApi.h @@ -10,39 +10,44 @@ #include "../lib/obs-websocket-api.h" class WebSocketApi { - public: - enum RequestReturnCode { - Normal, - NoVendor, - NoVendorRequest, - }; +public: + enum RequestReturnCode { + Normal, + NoVendor, + NoVendorRequest, + }; - typedef std::function EventCallback; + typedef std::function + EventCallback; - struct Vendor { - std::shared_mutex _mutex; - std::string _name; - std::map _requests; - }; - - WebSocketApi(); - ~WebSocketApi(); - - void SetEventCallback(EventCallback cb); - - enum RequestReturnCode PerformVendorRequest(std::string vendorName, std::string requestName, obs_data_t *requestData, obs_data_t *responseData); - - static void get_ph_cb(void *priv_data, calldata_t *cd); - static void get_api_version(void *, calldata_t *cd); - static void call_request(void *, calldata_t *cd); - static void vendor_register_cb(void *priv_data, calldata_t *cd); - static void vendor_request_register_cb(void *priv_data, calldata_t *cd); - static void vendor_request_unregister_cb(void *priv_data, calldata_t *cd); - static void vendor_event_emit_cb(void *priv_data, calldata_t *cd); - - private: + struct Vendor { std::shared_mutex _mutex; - EventCallback _eventCallback; - proc_handler_t *_procHandler; - std::map _vendors; + std::string _name; + std::map _requests; + }; + + WebSocketApi(); + ~WebSocketApi(); + + void SetEventCallback(EventCallback cb); + + enum RequestReturnCode PerformVendorRequest(std::string vendorName, + std::string requestName, + obs_data_t *requestData, + obs_data_t *responseData); + + static void get_ph_cb(void *priv_data, calldata_t *cd); + static void get_api_version(void *, calldata_t *cd); + static void call_request(void *, calldata_t *cd); + static void vendor_register_cb(void *priv_data, calldata_t *cd); + static void vendor_request_register_cb(void *priv_data, calldata_t *cd); + static void vendor_request_unregister_cb(void *priv_data, + calldata_t *cd); + static void vendor_event_emit_cb(void *priv_data, calldata_t *cd); + +private: + std::shared_mutex _mutex; + EventCallback _eventCallback; + proc_handler_t *_procHandler; + std::map _vendors; }; diff --git a/src/eventhandler/EventHandler.cpp b/src/eventhandler/EventHandler.cpp index 4ceeb362..d0dc2422 100644 --- a/src/eventhandler/EventHandler.cpp +++ b/src/eventhandler/EventHandler.cpp @@ -19,25 +19,30 @@ with this program. If not, see #include "EventHandler.h" -EventHandler::EventHandler() : - _obsLoaded(false), - _inputVolumeMetersRef(0), - _inputActiveStateChangedRef(0), - _inputShowStateChangedRef(0), - _sceneItemTransformChangedRef(0) +EventHandler::EventHandler() + : _obsLoaded(false), + _inputVolumeMetersRef(0), + _inputActiveStateChangedRef(0), + _inputShowStateChangedRef(0), + _sceneItemTransformChangedRef(0) { blog_debug("[EventHandler::EventHandler] Setting up..."); obs_frontend_add_event_callback(OnFrontendEvent, this); - signal_handler_t* coreSignalHandler = obs_get_signal_handler(); + signal_handler_t *coreSignalHandler = obs_get_signal_handler(); if (coreSignalHandler) { - signal_handler_connect(coreSignalHandler, "source_create", SourceCreatedMultiHandler, this); - signal_handler_connect(coreSignalHandler, "source_destroy", SourceDestroyedMultiHandler, this); - signal_handler_connect(coreSignalHandler, "source_remove", SourceRemovedMultiHandler, this); - signal_handler_connect(coreSignalHandler, "source_rename", SourceRenamedMultiHandler, this); + signal_handler_connect(coreSignalHandler, "source_create", + SourceCreatedMultiHandler, this); + signal_handler_connect(coreSignalHandler, "source_destroy", + SourceDestroyedMultiHandler, this); + signal_handler_connect(coreSignalHandler, "source_remove", + SourceRemovedMultiHandler, this); + signal_handler_connect(coreSignalHandler, "source_rename", + SourceRenamedMultiHandler, this); } else { - blog(LOG_ERROR, "[EventHandler::EventHandler] Unable to get libobs signal handler!"); + blog(LOG_ERROR, + "[EventHandler::EventHandler] Unable to get libobs signal handler!"); } blog_debug("[EventHandler::EventHandler] Finished."); @@ -49,14 +54,19 @@ EventHandler::~EventHandler() obs_frontend_remove_event_callback(OnFrontendEvent, this); - signal_handler_t* coreSignalHandler = obs_get_signal_handler(); + signal_handler_t *coreSignalHandler = obs_get_signal_handler(); if (coreSignalHandler) { - signal_handler_disconnect(coreSignalHandler, "source_create", SourceCreatedMultiHandler, this); - signal_handler_disconnect(coreSignalHandler, "source_destroy", SourceDestroyedMultiHandler, this); - signal_handler_disconnect(coreSignalHandler, "source_remove", SourceRemovedMultiHandler, this); - signal_handler_disconnect(coreSignalHandler, "source_rename", SourceRenamedMultiHandler, this); + signal_handler_disconnect(coreSignalHandler, "source_create", + SourceCreatedMultiHandler, this); + signal_handler_disconnect(coreSignalHandler, "source_destroy", + SourceDestroyedMultiHandler, this); + signal_handler_disconnect(coreSignalHandler, "source_remove", + SourceRemovedMultiHandler, this); + signal_handler_disconnect(coreSignalHandler, "source_rename", + SourceRenamedMultiHandler, this); } else { - blog(LOG_ERROR, "[EventHandler::~EventHandler] Unable to get libobs signal handler!"); + blog(LOG_ERROR, + "[EventHandler::~EventHandler] Unable to get libobs signal handler!"); } blog_debug("[EventHandler::~EventHandler] Finished."); @@ -78,16 +88,25 @@ void EventHandler::ProcessSubscription(uint64_t eventSubscriptions) if ((eventSubscriptions & EventSubscription::InputVolumeMeters) != 0) { if (_inputVolumeMetersRef.fetch_add(1) == 0) { if (_inputVolumeMetersHandler) - blog(LOG_WARNING, "[EventHandler::ProcessSubscription] Input volume meter handler already exists!"); + blog(LOG_WARNING, + "[EventHandler::ProcessSubscription] Input volume meter handler already exists!"); else - _inputVolumeMetersHandler = std::make_unique(std::bind(&EventHandler::HandleInputVolumeMeters, this, std::placeholders::_1)); + _inputVolumeMetersHandler = std::make_unique< + Utils::Obs::VolumeMeter::Handler>( + std::bind( + &EventHandler:: + HandleInputVolumeMeters, + this, std::placeholders::_1)); } } - if ((eventSubscriptions & EventSubscription::InputActiveStateChanged) != 0) + if ((eventSubscriptions & EventSubscription::InputActiveStateChanged) != + 0) _inputActiveStateChangedRef++; - if ((eventSubscriptions & EventSubscription::InputShowStateChanged) != 0) + if ((eventSubscriptions & EventSubscription::InputShowStateChanged) != + 0) _inputShowStateChangedRef++; - if ((eventSubscriptions & EventSubscription::SceneItemTransformChanged) != 0) + if ((eventSubscriptions & + EventSubscription::SceneItemTransformChanged) != 0) _sceneItemTransformChangedRef++; } @@ -98,16 +117,21 @@ void EventHandler::ProcessUnsubscription(uint64_t eventSubscriptions) if (_inputVolumeMetersRef.fetch_sub(1) == 1) _inputVolumeMetersHandler.reset(); } - if ((eventSubscriptions & EventSubscription::InputActiveStateChanged) != 0) + if ((eventSubscriptions & EventSubscription::InputActiveStateChanged) != + 0) _inputActiveStateChangedRef--; - if ((eventSubscriptions & EventSubscription::InputShowStateChanged) != 0) + if ((eventSubscriptions & EventSubscription::InputShowStateChanged) != + 0) _inputShowStateChangedRef--; - if ((eventSubscriptions & EventSubscription::SceneItemTransformChanged) != 0) + if ((eventSubscriptions & + EventSubscription::SceneItemTransformChanged) != 0) _sceneItemTransformChangedRef--; } // Function required in order to use default arguments -void EventHandler::BroadcastEvent(uint64_t requiredIntent, std::string eventType, json eventData, uint8_t rpcVersion) +void EventHandler::BroadcastEvent(uint64_t requiredIntent, + std::string eventType, json eventData, + uint8_t rpcVersion) { if (!_broadcastCallback) return; @@ -116,7 +140,8 @@ void EventHandler::BroadcastEvent(uint64_t requiredIntent, std::string eventType } // Connect source signals for Inputs, Scenes, and Transitions. Filters are automatically connected. -void EventHandler::ConnectSourceSignals(obs_source_t *source) // Applies to inputs and scenes +void EventHandler::ConnectSourceSignals( + obs_source_t *source) // Applies to inputs and scenes { if (!source || obs_source_removed(source)) return; @@ -124,50 +149,81 @@ void EventHandler::ConnectSourceSignals(obs_source_t *source) // Applies to inpu // Disconnect all existing signals from the source to prevent multiple connections DisconnectSourceSignals(source); - signal_handler_t* sh = obs_source_get_signal_handler(source); + signal_handler_t *sh = obs_source_get_signal_handler(source); obs_source_type sourceType = obs_source_get_type(source); // Inputs if (sourceType == OBS_SOURCE_TYPE_INPUT) { - signal_handler_connect(sh, "activate", HandleInputActiveStateChanged, this); - signal_handler_connect(sh, "deactivate", HandleInputActiveStateChanged, this); - signal_handler_connect(sh, "show", HandleInputShowStateChanged, this); - signal_handler_connect(sh, "hide", HandleInputShowStateChanged, this); - 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, "media_started", HandleMediaInputPlaybackStarted, this); - signal_handler_connect(sh, "media_ended", HandleMediaInputPlaybackEnded, this); - signal_handler_connect(sh, "media_pause", SourceMediaPauseMultiHandler, this); - signal_handler_connect(sh, "media_play", SourceMediaPlayMultiHandler, this); - signal_handler_connect(sh, "media_restart", SourceMediaRestartMultiHandler, this); - signal_handler_connect(sh, "media_stopped", SourceMediaStopMultiHandler, this); - signal_handler_connect(sh, "media_next", SourceMediaNextMultiHandler, this); - signal_handler_connect(sh, "media_previous", SourceMediaPreviousMultiHandler, this); + signal_handler_connect(sh, "activate", + HandleInputActiveStateChanged, this); + signal_handler_connect(sh, "deactivate", + HandleInputActiveStateChanged, this); + signal_handler_connect(sh, "show", HandleInputShowStateChanged, + this); + signal_handler_connect(sh, "hide", HandleInputShowStateChanged, + this); + 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, "media_started", + HandleMediaInputPlaybackStarted, this); + signal_handler_connect(sh, "media_ended", + HandleMediaInputPlaybackEnded, this); + signal_handler_connect(sh, "media_pause", + SourceMediaPauseMultiHandler, this); + signal_handler_connect(sh, "media_play", + SourceMediaPlayMultiHandler, this); + signal_handler_connect(sh, "media_restart", + SourceMediaRestartMultiHandler, this); + signal_handler_connect(sh, "media_stopped", + SourceMediaStopMultiHandler, this); + signal_handler_connect(sh, "media_next", + SourceMediaNextMultiHandler, this); + signal_handler_connect(sh, "media_previous", + SourceMediaPreviousMultiHandler, this); } // Scenes if (sourceType == OBS_SOURCE_TYPE_SCENE) { - signal_handler_connect(sh, "item_add", HandleSceneItemCreated, this); - signal_handler_connect(sh, "item_remove", HandleSceneItemRemoved, this); - signal_handler_connect(sh, "reorder", HandleSceneItemListReindexed, this); - signal_handler_connect(sh, "item_visible", HandleSceneItemEnableStateChanged, this); - signal_handler_connect(sh, "item_locked", HandleSceneItemLockStateChanged, this); - signal_handler_connect(sh, "item_select", HandleSceneItemSelected, this); - signal_handler_connect(sh, "item_transform", HandleSceneItemTransformChanged, this); + signal_handler_connect(sh, "item_add", HandleSceneItemCreated, + this); + signal_handler_connect(sh, "item_remove", + HandleSceneItemRemoved, this); + signal_handler_connect(sh, "reorder", + HandleSceneItemListReindexed, this); + signal_handler_connect(sh, "item_visible", + HandleSceneItemEnableStateChanged, this); + signal_handler_connect(sh, "item_locked", + HandleSceneItemLockStateChanged, this); + signal_handler_connect(sh, "item_select", + HandleSceneItemSelected, this); + signal_handler_connect(sh, "item_transform", + HandleSceneItemTransformChanged, this); } // Scenes and Inputs - if (sourceType == OBS_SOURCE_TYPE_INPUT || sourceType == OBS_SOURCE_TYPE_SCENE) { - signal_handler_connect(sh, "reorder_filters", HandleSourceFilterListReindexed, this); - signal_handler_connect(sh, "filter_add", FilterAddMultiHandler, this); - signal_handler_connect(sh, "filter_remove", FilterRemoveMultiHandler, this); - auto enumFilters = [](obs_source_t *, obs_source_t *filter, void *param){ - auto eventHandler = static_cast(param); + if (sourceType == OBS_SOURCE_TYPE_INPUT || + sourceType == OBS_SOURCE_TYPE_SCENE) { + signal_handler_connect(sh, "reorder_filters", + HandleSourceFilterListReindexed, this); + signal_handler_connect(sh, "filter_add", FilterAddMultiHandler, + this); + signal_handler_connect(sh, "filter_remove", + FilterRemoveMultiHandler, this); + auto enumFilters = [](obs_source_t *, obs_source_t *filter, + void *param) { + auto eventHandler = static_cast(param); eventHandler->ConnectSourceSignals(filter); }; obs_source_enum_filters(source, enumFilters, this); @@ -175,15 +231,21 @@ void EventHandler::ConnectSourceSignals(obs_source_t *source) // Applies to inpu // Transitions if (sourceType == OBS_SOURCE_TYPE_TRANSITION) { - signal_handler_connect(sh, "transition_start", HandleSceneTransitionStarted, this); - signal_handler_connect(sh, "transition_stop", HandleSceneTransitionEnded, this); - signal_handler_connect(sh, "transition_video_stop", HandleSceneTransitionVideoEnded, this); + signal_handler_connect(sh, "transition_start", + HandleSceneTransitionStarted, this); + signal_handler_connect(sh, "transition_stop", + HandleSceneTransitionEnded, this); + signal_handler_connect(sh, "transition_video_stop", + HandleSceneTransitionVideoEnded, this); } // Filters if (sourceType == OBS_SOURCE_TYPE_FILTER) { - signal_handler_connect(sh, "enable", HandleSourceFilterEnableStateChanged, this); - signal_handler_connect(sh, "rename", HandleSourceFilterNameChanged, this); + signal_handler_connect(sh, "enable", + HandleSourceFilterEnableStateChanged, + this); + signal_handler_connect(sh, "rename", + HandleSourceFilterNameChanged, this); } } @@ -193,50 +255,88 @@ void EventHandler::DisconnectSourceSignals(obs_source_t *source) if (!source) return; - signal_handler_t* sh = obs_source_get_signal_handler(source); + signal_handler_t *sh = obs_source_get_signal_handler(source); obs_source_type sourceType = obs_source_get_type(source); // Inputs if (sourceType == OBS_SOURCE_TYPE_INPUT) { - signal_handler_disconnect(sh, "activate", HandleInputActiveStateChanged, this); - signal_handler_disconnect(sh, "deactivate", HandleInputActiveStateChanged, this); - signal_handler_disconnect(sh, "show", HandleInputShowStateChanged, this); - signal_handler_disconnect(sh, "hide", HandleInputShowStateChanged, this); - signal_handler_disconnect(sh, "mute", HandleInputMuteStateChanged, this); - signal_handler_disconnect(sh, "volume", HandleInputVolumeChanged, this); - signal_handler_disconnect(sh, "audio_balance", HandleInputAudioBalanceChanged, this); - signal_handler_disconnect(sh, "audio_sync", HandleInputAudioSyncOffsetChanged, this); - signal_handler_disconnect(sh, "audio_mixers", HandleInputAudioTracksChanged, this); - signal_handler_disconnect(sh, "audio_monitoring", HandleInputAudioMonitorTypeChanged, this); - signal_handler_disconnect(sh, "media_started", HandleMediaInputPlaybackStarted, this); - signal_handler_disconnect(sh, "media_ended", HandleMediaInputPlaybackEnded, this); - signal_handler_disconnect(sh, "media_pause", SourceMediaPauseMultiHandler, this); - signal_handler_disconnect(sh, "media_play", SourceMediaPlayMultiHandler, this); - signal_handler_disconnect(sh, "media_restart", SourceMediaRestartMultiHandler, this); - 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, "activate", + HandleInputActiveStateChanged, this); + signal_handler_disconnect(sh, "deactivate", + HandleInputActiveStateChanged, this); + signal_handler_disconnect(sh, "show", + HandleInputShowStateChanged, this); + signal_handler_disconnect(sh, "hide", + HandleInputShowStateChanged, this); + signal_handler_disconnect(sh, "mute", + HandleInputMuteStateChanged, this); + signal_handler_disconnect(sh, "volume", + HandleInputVolumeChanged, this); + signal_handler_disconnect(sh, "audio_balance", + HandleInputAudioBalanceChanged, this); + signal_handler_disconnect(sh, "audio_sync", + HandleInputAudioSyncOffsetChanged, + this); + signal_handler_disconnect(sh, "audio_mixers", + HandleInputAudioTracksChanged, this); + signal_handler_disconnect(sh, "audio_monitoring", + HandleInputAudioMonitorTypeChanged, + this); + signal_handler_disconnect(sh, "media_started", + HandleMediaInputPlaybackStarted, + this); + signal_handler_disconnect(sh, "media_ended", + HandleMediaInputPlaybackEnded, this); + signal_handler_disconnect(sh, "media_pause", + SourceMediaPauseMultiHandler, this); + signal_handler_disconnect(sh, "media_play", + SourceMediaPlayMultiHandler, this); + signal_handler_disconnect(sh, "media_restart", + SourceMediaRestartMultiHandler, this); + signal_handler_disconnect(sh, "media_stopped", + SourceMediaStopMultiHandler, this); + signal_handler_disconnect(sh, "media_next", + SourceMediaNextMultiHandler, this); + signal_handler_disconnect(sh, "media_previous", + SourceMediaPreviousMultiHandler, + this); } // Scenes if (sourceType == OBS_SOURCE_TYPE_SCENE) { - signal_handler_disconnect(sh, "item_add", HandleSceneItemCreated, this); - signal_handler_disconnect(sh, "item_remove", HandleSceneItemRemoved, this); - signal_handler_disconnect(sh, "reorder", HandleSceneItemListReindexed, this); - signal_handler_disconnect(sh, "item_visible", HandleSceneItemEnableStateChanged, this); - signal_handler_disconnect(sh, "item_locked", HandleSceneItemLockStateChanged, this); - signal_handler_disconnect(sh, "item_select", HandleSceneItemSelected, this); - signal_handler_disconnect(sh, "item_transform", HandleSceneItemTransformChanged, this); + signal_handler_disconnect(sh, "item_add", + HandleSceneItemCreated, this); + signal_handler_disconnect(sh, "item_remove", + HandleSceneItemRemoved, this); + signal_handler_disconnect(sh, "reorder", + HandleSceneItemListReindexed, this); + signal_handler_disconnect(sh, "item_visible", + HandleSceneItemEnableStateChanged, + this); + signal_handler_disconnect(sh, "item_locked", + HandleSceneItemLockStateChanged, + this); + signal_handler_disconnect(sh, "item_select", + HandleSceneItemSelected, this); + signal_handler_disconnect(sh, "item_transform", + HandleSceneItemTransformChanged, + this); } // Inputs and Scenes - if (sourceType == OBS_SOURCE_TYPE_INPUT || sourceType == OBS_SOURCE_TYPE_SCENE) { - signal_handler_disconnect(sh, "reorder_filters", HandleSourceFilterListReindexed, this); - signal_handler_disconnect(sh, "filter_add", FilterAddMultiHandler, this); - signal_handler_disconnect(sh, "filter_remove", FilterRemoveMultiHandler, this); - auto enumFilters = [](obs_source_t *, obs_source_t *filter, void *param){ - auto eventHandler = static_cast(param); + if (sourceType == OBS_SOURCE_TYPE_INPUT || + sourceType == OBS_SOURCE_TYPE_SCENE) { + signal_handler_disconnect(sh, "reorder_filters", + HandleSourceFilterListReindexed, + this); + signal_handler_disconnect(sh, "filter_add", + FilterAddMultiHandler, this); + signal_handler_disconnect(sh, "filter_remove", + FilterRemoveMultiHandler, this); + auto enumFilters = [](obs_source_t *, obs_source_t *filter, + void *param) { + auto eventHandler = static_cast(param); eventHandler->DisconnectSourceSignals(filter); }; obs_source_enum_filters(source, enumFilters, this); @@ -244,250 +344,284 @@ void EventHandler::DisconnectSourceSignals(obs_source_t *source) // Transitions if (sourceType == OBS_SOURCE_TYPE_TRANSITION) { - signal_handler_disconnect(sh, "transition_start", HandleSceneTransitionStarted, this); - signal_handler_disconnect(sh, "transition_stop", HandleSceneTransitionEnded, this); - signal_handler_disconnect(sh, "transition_video_stop", HandleSceneTransitionVideoEnded, this); + signal_handler_disconnect(sh, "transition_start", + HandleSceneTransitionStarted, this); + signal_handler_disconnect(sh, "transition_stop", + HandleSceneTransitionEnded, this); + signal_handler_disconnect(sh, "transition_video_stop", + HandleSceneTransitionVideoEnded, + this); } // Filters if (sourceType == OBS_SOURCE_TYPE_FILTER) { - signal_handler_disconnect(sh, "enable", HandleSourceFilterEnableStateChanged, this); - signal_handler_disconnect(sh, "rename", HandleSourceFilterNameChanged, this); + 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) +void EventHandler::OnFrontendEvent(enum obs_frontend_event event, + void *private_data) { - auto eventHandler = static_cast(private_data); + auto eventHandler = static_cast(private_data); - if (!eventHandler->_obsLoaded.load() && event != OBS_FRONTEND_EVENT_FINISHED_LOADING) + if (!eventHandler->_obsLoaded.load() && + event != OBS_FRONTEND_EVENT_FINISHED_LOADING) return; switch (event) { - // General - case OBS_FRONTEND_EVENT_FINISHED_LOADING: - blog_debug("[EventHandler::OnFrontendEvent] OBS has finished loading. Connecting final handlers and enabling events..."); + // General + case OBS_FRONTEND_EVENT_FINISHED_LOADING: + blog_debug( + "[EventHandler::OnFrontendEvent] OBS has finished loading. Connecting final handlers and enabling events..."); - // Connect source signals and enable events only after OBS has fully loaded (to reduce extra logging). - eventHandler->_obsLoaded.store(true); + // Connect source signals and enable events only after OBS has fully loaded (to reduce extra logging). + eventHandler->_obsLoaded.store(true); - // In the case that plugins become hotloadable, this will have to go back into `EventHandler::EventHandler()` - // Enumerate inputs and connect each one - { - auto enumInputs = [](void *param, obs_source_t *source) { - auto eventHandler = static_cast(param); - eventHandler->ConnectSourceSignals(source); - return true; - }; - obs_enum_sources(enumInputs, private_data); + // In the case that plugins become hotloadable, this will have to go back into `EventHandler::EventHandler()` + // Enumerate inputs and connect each one + { + auto enumInputs = [](void *param, + obs_source_t *source) { + auto eventHandler = + static_cast(param); + eventHandler->ConnectSourceSignals(source); + return true; + }; + obs_enum_sources(enumInputs, private_data); + } + + // Enumerate scenes and connect each one + { + auto enumScenes = [](void *param, + obs_source_t *source) { + auto eventHandler = + static_cast(param); + eventHandler->ConnectSourceSignals(source); + return true; + }; + obs_enum_scenes(enumScenes, private_data); + } + + // Enumerate all scene transitions and connect each one + { + obs_frontend_source_list transitions = {}; + obs_frontend_get_transitions(&transitions); + for (size_t i = 0; i < transitions.sources.num; i++) { + obs_source_t *transition = + transitions.sources.array[i]; + eventHandler->ConnectSourceSignals(transition); } + obs_frontend_source_list_free(&transitions); + } - // Enumerate scenes and connect each one - { - auto enumScenes = [](void *param, obs_source_t *source) { - auto eventHandler = static_cast(param); - eventHandler->ConnectSourceSignals(source); - return true; - }; - obs_enum_scenes(enumScenes, private_data); + blog_debug("[EventHandler::OnFrontendEvent] Finished."); + + if (eventHandler->_obsLoadedCallback) + eventHandler->_obsLoadedCallback(); + + break; + case OBS_FRONTEND_EVENT_EXIT: + eventHandler->HandleExitStarted(); + + blog_debug( + "[EventHandler::OnFrontendEvent] OBS is unloading. Disabling events..."); + // Disconnect source signals and disable events when OBS starts unloading (to reduce extra logging). + eventHandler->_obsLoaded.store(false); + + // In the case that plugins become hotloadable, this will have to go back into `EventHandler::~EventHandler()` + // Enumerate inputs and disconnect each one + { + auto enumInputs = [](void *param, + obs_source_t *source) { + auto eventHandler = + static_cast(param); + eventHandler->DisconnectSourceSignals(source); + return true; + }; + obs_enum_sources(enumInputs, private_data); + } + + // Enumerate scenes and disconnect each one + { + auto enumScenes = [](void *param, + obs_source_t *source) { + auto eventHandler = + static_cast(param); + eventHandler->DisconnectSourceSignals(source); + return true; + }; + obs_enum_scenes(enumScenes, private_data); + } + + // Enumerate all scene transitions and disconnect each one + { + obs_frontend_source_list transitions = {}; + obs_frontend_get_transitions(&transitions); + for (size_t i = 0; i < transitions.sources.num; i++) { + obs_source_t *transition = + transitions.sources.array[i]; + eventHandler->DisconnectSourceSignals( + transition); } + obs_frontend_source_list_free(&transitions); + } - // Enumerate all scene transitions and connect each one - { - obs_frontend_source_list transitions = {}; - obs_frontend_get_transitions(&transitions); - for (size_t i = 0; i < transitions.sources.num; i++) { - obs_source_t* transition = transitions.sources.array[i]; - eventHandler->ConnectSourceSignals(transition); - } - obs_frontend_source_list_free(&transitions); - } + blog_debug("[EventHandler::OnFrontendEvent] Finished."); - blog_debug("[EventHandler::OnFrontendEvent] Finished."); + break; + case OBS_FRONTEND_EVENT_STUDIO_MODE_ENABLED: + eventHandler->HandleStudioModeStateChanged(true); + break; + case OBS_FRONTEND_EVENT_STUDIO_MODE_DISABLED: + eventHandler->HandleStudioModeStateChanged(false); + break; - if (eventHandler->_obsLoadedCallback) - eventHandler->_obsLoadedCallback(); + // Config + case OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGING: { + obs_frontend_source_list transitions = {}; + obs_frontend_get_transitions(&transitions); + for (size_t i = 0; i < transitions.sources.num; i++) { + obs_source_t *transition = transitions.sources.array[i]; + eventHandler->DisconnectSourceSignals(transition); + } + obs_frontend_source_list_free(&transitions); + } + eventHandler->HandleCurrentSceneCollectionChanging(); + break; + case OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGED: { + obs_frontend_source_list transitions = {}; + obs_frontend_get_transitions(&transitions); + for (size_t i = 0; i < transitions.sources.num; i++) { + obs_source_t *transition = transitions.sources.array[i]; + eventHandler->ConnectSourceSignals(transition); + } + obs_frontend_source_list_free(&transitions); + } + eventHandler->HandleCurrentSceneCollectionChanged(); + break; + case OBS_FRONTEND_EVENT_SCENE_COLLECTION_LIST_CHANGED: + eventHandler->HandleSceneCollectionListChanged(); + break; + case OBS_FRONTEND_EVENT_PROFILE_CHANGING: + eventHandler->HandleCurrentProfileChanging(); + break; + case OBS_FRONTEND_EVENT_PROFILE_CHANGED: + eventHandler->HandleCurrentProfileChanged(); + break; + case OBS_FRONTEND_EVENT_PROFILE_LIST_CHANGED: + eventHandler->HandleProfileListChanged(); + break; - break; - case OBS_FRONTEND_EVENT_EXIT: - eventHandler->HandleExitStarted(); + // Scenes + case OBS_FRONTEND_EVENT_SCENE_CHANGED: + eventHandler->HandleCurrentProgramSceneChanged(); + break; + case OBS_FRONTEND_EVENT_PREVIEW_SCENE_CHANGED: + eventHandler->HandleCurrentPreviewSceneChanged(); + break; + case OBS_FRONTEND_EVENT_SCENE_LIST_CHANGED: + eventHandler->HandleSceneListChanged(); + break; - blog_debug("[EventHandler::OnFrontendEvent] OBS is unloading. Disabling events..."); - // Disconnect source signals and disable events when OBS starts unloading (to reduce extra logging). - eventHandler->_obsLoaded.store(false); + // Transitions + case OBS_FRONTEND_EVENT_TRANSITION_CHANGED: + eventHandler->HandleCurrentSceneTransitionChanged(); + break; + case OBS_FRONTEND_EVENT_TRANSITION_LIST_CHANGED: { + obs_frontend_source_list transitions = {}; + obs_frontend_get_transitions(&transitions); + for (size_t i = 0; i < transitions.sources.num; i++) { + obs_source_t *transition = transitions.sources.array[i]; + eventHandler->ConnectSourceSignals(transition); + } + obs_frontend_source_list_free(&transitions); + } break; + case OBS_FRONTEND_EVENT_TRANSITION_DURATION_CHANGED: + eventHandler->HandleCurrentSceneTransitionDurationChanged(); + break; - // In the case that plugins become hotloadable, this will have to go back into `EventHandler::~EventHandler()` - // Enumerate inputs and disconnect each one - { - auto enumInputs = [](void *param, obs_source_t *source) { - auto eventHandler = static_cast(param); - eventHandler->DisconnectSourceSignals(source); - return true; - }; - obs_enum_sources(enumInputs, private_data); - } + // Outputs + case OBS_FRONTEND_EVENT_STREAMING_STARTING: + eventHandler->HandleStreamStateChanged( + OBS_WEBSOCKET_OUTPUT_STARTING); + break; + case OBS_FRONTEND_EVENT_STREAMING_STARTED: + eventHandler->HandleStreamStateChanged( + OBS_WEBSOCKET_OUTPUT_STARTED); + break; + case OBS_FRONTEND_EVENT_STREAMING_STOPPING: + eventHandler->HandleStreamStateChanged( + OBS_WEBSOCKET_OUTPUT_STOPPING); + break; + case OBS_FRONTEND_EVENT_STREAMING_STOPPED: + eventHandler->HandleStreamStateChanged( + OBS_WEBSOCKET_OUTPUT_STOPPED); + break; + case OBS_FRONTEND_EVENT_RECORDING_STARTING: + eventHandler->HandleRecordStateChanged( + OBS_WEBSOCKET_OUTPUT_STARTING); + break; + case OBS_FRONTEND_EVENT_RECORDING_STARTED: + eventHandler->HandleRecordStateChanged( + OBS_WEBSOCKET_OUTPUT_STARTED); + break; + case OBS_FRONTEND_EVENT_RECORDING_STOPPING: + eventHandler->HandleRecordStateChanged( + OBS_WEBSOCKET_OUTPUT_STOPPING); + break; + case OBS_FRONTEND_EVENT_RECORDING_STOPPED: + eventHandler->HandleRecordStateChanged( + OBS_WEBSOCKET_OUTPUT_STOPPED); + break; + case OBS_FRONTEND_EVENT_RECORDING_PAUSED: + eventHandler->HandleRecordStateChanged( + OBS_WEBSOCKET_OUTPUT_PAUSED); + break; + case OBS_FRONTEND_EVENT_RECORDING_UNPAUSED: + eventHandler->HandleRecordStateChanged( + OBS_WEBSOCKET_OUTPUT_RESUMED); + break; + case OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTING: + eventHandler->HandleReplayBufferStateChanged( + OBS_WEBSOCKET_OUTPUT_STARTING); + break; + case OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTED: + eventHandler->HandleReplayBufferStateChanged( + OBS_WEBSOCKET_OUTPUT_STARTED); + break; + case OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPING: + eventHandler->HandleReplayBufferStateChanged( + OBS_WEBSOCKET_OUTPUT_STOPPING); + break; + case OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPED: + eventHandler->HandleReplayBufferStateChanged( + OBS_WEBSOCKET_OUTPUT_STOPPED); + break; + case OBS_FRONTEND_EVENT_VIRTUALCAM_STARTED: + eventHandler->HandleVirtualcamStateChanged( + OBS_WEBSOCKET_OUTPUT_STARTED); + break; + case OBS_FRONTEND_EVENT_VIRTUALCAM_STOPPED: + eventHandler->HandleVirtualcamStateChanged( + OBS_WEBSOCKET_OUTPUT_STOPPED); + break; + case OBS_FRONTEND_EVENT_REPLAY_BUFFER_SAVED: + eventHandler->HandleReplayBufferSaved(); + break; - // Enumerate scenes and disconnect each one - { - auto enumScenes = [](void *param, obs_source_t *source) { - auto eventHandler = static_cast(param); - eventHandler->DisconnectSourceSignals(source); - return true; - }; - obs_enum_scenes(enumScenes, private_data); - } - - // Enumerate all scene transitions and disconnect each one - { - obs_frontend_source_list transitions = {}; - obs_frontend_get_transitions(&transitions); - for (size_t i = 0; i < transitions.sources.num; i++) { - obs_source_t* transition = transitions.sources.array[i]; - eventHandler->DisconnectSourceSignals(transition); - } - obs_frontend_source_list_free(&transitions); - } - - blog_debug("[EventHandler::OnFrontendEvent] Finished."); - - break; - case OBS_FRONTEND_EVENT_STUDIO_MODE_ENABLED: - eventHandler->HandleStudioModeStateChanged(true); - break; - case OBS_FRONTEND_EVENT_STUDIO_MODE_DISABLED: - eventHandler->HandleStudioModeStateChanged(false); - break; - - // Config - case OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGING: - { - obs_frontend_source_list transitions = {}; - obs_frontend_get_transitions(&transitions); - for (size_t i = 0; i < transitions.sources.num; i++) { - obs_source_t* transition = transitions.sources.array[i]; - eventHandler->DisconnectSourceSignals(transition); - } - obs_frontend_source_list_free(&transitions); - } - eventHandler->HandleCurrentSceneCollectionChanging(); - break; - case OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGED: - { - obs_frontend_source_list transitions = {}; - obs_frontend_get_transitions(&transitions); - for (size_t i = 0; i < transitions.sources.num; i++) { - obs_source_t* transition = transitions.sources.array[i]; - eventHandler->ConnectSourceSignals(transition); - } - obs_frontend_source_list_free(&transitions); - } - eventHandler->HandleCurrentSceneCollectionChanged(); - break; - case OBS_FRONTEND_EVENT_SCENE_COLLECTION_LIST_CHANGED: - eventHandler->HandleSceneCollectionListChanged(); - break; - case OBS_FRONTEND_EVENT_PROFILE_CHANGING: - eventHandler->HandleCurrentProfileChanging(); - break; - case OBS_FRONTEND_EVENT_PROFILE_CHANGED: - eventHandler->HandleCurrentProfileChanged(); - break; - case OBS_FRONTEND_EVENT_PROFILE_LIST_CHANGED: - eventHandler->HandleProfileListChanged(); - break; - - // Scenes - case OBS_FRONTEND_EVENT_SCENE_CHANGED: - eventHandler->HandleCurrentProgramSceneChanged(); - break; - case OBS_FRONTEND_EVENT_PREVIEW_SCENE_CHANGED: - eventHandler->HandleCurrentPreviewSceneChanged(); - break; - case OBS_FRONTEND_EVENT_SCENE_LIST_CHANGED: - eventHandler->HandleSceneListChanged(); - break; - - // Transitions - case OBS_FRONTEND_EVENT_TRANSITION_CHANGED: - eventHandler->HandleCurrentSceneTransitionChanged(); - break; - case OBS_FRONTEND_EVENT_TRANSITION_LIST_CHANGED: - { - obs_frontend_source_list transitions = {}; - obs_frontend_get_transitions(&transitions); - for (size_t i = 0; i < transitions.sources.num; i++) { - obs_source_t* transition = transitions.sources.array[i]; - eventHandler->ConnectSourceSignals(transition); - } - obs_frontend_source_list_free(&transitions); - } - break; - case OBS_FRONTEND_EVENT_TRANSITION_DURATION_CHANGED: - eventHandler->HandleCurrentSceneTransitionDurationChanged(); - break; - - // Outputs - case OBS_FRONTEND_EVENT_STREAMING_STARTING: - eventHandler->HandleStreamStateChanged(OBS_WEBSOCKET_OUTPUT_STARTING); - break; - case OBS_FRONTEND_EVENT_STREAMING_STARTED: - eventHandler->HandleStreamStateChanged(OBS_WEBSOCKET_OUTPUT_STARTED); - break; - case OBS_FRONTEND_EVENT_STREAMING_STOPPING: - eventHandler->HandleStreamStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPING); - break; - case OBS_FRONTEND_EVENT_STREAMING_STOPPED: - eventHandler->HandleStreamStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPED); - break; - case OBS_FRONTEND_EVENT_RECORDING_STARTING: - eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_STARTING); - break; - case OBS_FRONTEND_EVENT_RECORDING_STARTED: - eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_STARTED); - break; - case OBS_FRONTEND_EVENT_RECORDING_STOPPING: - eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPING); - break; - case OBS_FRONTEND_EVENT_RECORDING_STOPPED: - eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPED); - break; - case OBS_FRONTEND_EVENT_RECORDING_PAUSED: - eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_PAUSED); - break; - case OBS_FRONTEND_EVENT_RECORDING_UNPAUSED: - eventHandler->HandleRecordStateChanged(OBS_WEBSOCKET_OUTPUT_RESUMED); - break; - case OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTING: - eventHandler->HandleReplayBufferStateChanged(OBS_WEBSOCKET_OUTPUT_STARTING); - break; - case OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTED: - eventHandler->HandleReplayBufferStateChanged(OBS_WEBSOCKET_OUTPUT_STARTED); - break; - case OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPING: - eventHandler->HandleReplayBufferStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPING); - break; - case OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPED: - eventHandler->HandleReplayBufferStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPED); - break; - case OBS_FRONTEND_EVENT_VIRTUALCAM_STARTED: - eventHandler->HandleVirtualcamStateChanged(OBS_WEBSOCKET_OUTPUT_STARTED); - break; - case OBS_FRONTEND_EVENT_VIRTUALCAM_STOPPED: - eventHandler->HandleVirtualcamStateChanged(OBS_WEBSOCKET_OUTPUT_STOPPED); - break; - case OBS_FRONTEND_EVENT_REPLAY_BUFFER_SAVED: - eventHandler->HandleReplayBufferSaved(); - break; - - default: - break; + default: + break; } } // Only called for creation of a public source void EventHandler::SourceCreatedMultiHandler(void *param, calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); // Don't react to signals until OBS has finished loading if (!eventHandler->_obsLoaded.load()) @@ -500,14 +634,14 @@ void EventHandler::SourceCreatedMultiHandler(void *param, calldata_t *data) eventHandler->ConnectSourceSignals(source); switch (obs_source_get_type(source)) { - case OBS_SOURCE_TYPE_INPUT: - eventHandler->HandleInputCreated(source); - break; - case OBS_SOURCE_TYPE_SCENE: - eventHandler->HandleSceneCreated(source); - break; - default: - break; + case OBS_SOURCE_TYPE_INPUT: + eventHandler->HandleInputCreated(source); + break; + case OBS_SOURCE_TYPE_SCENE: + eventHandler->HandleSceneCreated(source); + break; + default: + break; } } @@ -515,7 +649,7 @@ void EventHandler::SourceCreatedMultiHandler(void *param, calldata_t *data) // Used as a fallback if an input/scene is not explicitly removed void EventHandler::SourceDestroyedMultiHandler(void *param, calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); // We can't use any smart types here because releasing the source will cause infinite recursion obs_source_t *source = GetCalldataPointer(data, "source"); @@ -530,18 +664,18 @@ void EventHandler::SourceDestroyedMultiHandler(void *param, calldata_t *data) return; switch (obs_source_get_type(source)) { - case OBS_SOURCE_TYPE_INPUT: - // Only emit removed if the input has not already been removed. This is the case when removing the last scene item of an input. - if (!obs_source_removed(source)) - eventHandler->HandleInputRemoved(source); - break; - case OBS_SOURCE_TYPE_SCENE: - // Only emit removed if the scene has not already been removed. - if (!obs_source_removed(source)) - eventHandler->HandleSceneRemoved(source); - break; - default: - break; + case OBS_SOURCE_TYPE_INPUT: + // Only emit removed if the input has not already been removed. This is the case when removing the last scene item of an input. + if (!obs_source_removed(source)) + eventHandler->HandleInputRemoved(source); + break; + case OBS_SOURCE_TYPE_SCENE: + // Only emit removed if the scene has not already been removed. + if (!obs_source_removed(source)) + eventHandler->HandleSceneRemoved(source); + break; + default: + break; } } @@ -549,7 +683,7 @@ void EventHandler::SourceDestroyedMultiHandler(void *param, calldata_t *data) // For example, if an input is "removed" but there is a dangling ref, you still want to know that it shouldn't exist, but it's not guaranteed to be destroyed. void EventHandler::SourceRemovedMultiHandler(void *param, calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); if (!eventHandler->_obsLoaded.load()) return; @@ -559,20 +693,20 @@ void EventHandler::SourceRemovedMultiHandler(void *param, calldata_t *data) return; switch (obs_source_get_type(source)) { - case OBS_SOURCE_TYPE_INPUT: - eventHandler->HandleInputRemoved(source); - break; - case OBS_SOURCE_TYPE_SCENE: - eventHandler->HandleSceneRemoved(source); - break; - default: - break; + case OBS_SOURCE_TYPE_INPUT: + eventHandler->HandleInputRemoved(source); + break; + case OBS_SOURCE_TYPE_SCENE: + eventHandler->HandleSceneRemoved(source); + break; + default: + break; } } void EventHandler::SourceRenamedMultiHandler(void *param, calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); if (!eventHandler->_obsLoaded.load()) return; @@ -587,15 +721,17 @@ void EventHandler::SourceRenamedMultiHandler(void *param, calldata_t *data) return; switch (obs_source_get_type(source)) { - case OBS_SOURCE_TYPE_INPUT: - eventHandler->HandleInputNameChanged(source, oldSourceName, sourceName); - break; - case OBS_SOURCE_TYPE_TRANSITION: - break; - case OBS_SOURCE_TYPE_SCENE: - eventHandler->HandleSceneNameChanged(source, oldSourceName, sourceName); - break; - default: - break; + case OBS_SOURCE_TYPE_INPUT: + eventHandler->HandleInputNameChanged(source, oldSourceName, + sourceName); + break; + case OBS_SOURCE_TYPE_TRANSITION: + break; + case OBS_SOURCE_TYPE_SCENE: + eventHandler->HandleSceneNameChanged(source, oldSourceName, + sourceName); + break; + default: + break; } } diff --git a/src/eventhandler/EventHandler.h b/src/eventhandler/EventHandler.h index 458470d3..448c12ef 100644 --- a/src/eventhandler/EventHandler.h +++ b/src/eventhandler/EventHandler.h @@ -29,123 +29,181 @@ with this program. If not, see #include "../utils/Obs_VolumeMeter.h" #include "../plugin-macros.generated.h" -class EventHandler -{ - public: - EventHandler(); - ~EventHandler(); +class EventHandler { +public: + EventHandler(); + ~EventHandler(); - typedef std::function BroadcastCallback; - void SetBroadcastCallback(BroadcastCallback cb); - typedef std::function ObsLoadedCallback; - void SetObsLoadedCallback(ObsLoadedCallback cb); + typedef std::function + BroadcastCallback; + void SetBroadcastCallback(BroadcastCallback cb); + typedef std::function ObsLoadedCallback; + void SetObsLoadedCallback(ObsLoadedCallback cb); - void ProcessSubscription(uint64_t eventSubscriptions); - void ProcessUnsubscription(uint64_t eventSubscriptions); + void ProcessSubscription(uint64_t eventSubscriptions); + void ProcessUnsubscription(uint64_t eventSubscriptions); - private: - BroadcastCallback _broadcastCallback; - ObsLoadedCallback _obsLoadedCallback; +private: + BroadcastCallback _broadcastCallback; + ObsLoadedCallback _obsLoadedCallback; - std::atomic _obsLoaded; + std::atomic _obsLoaded; - std::unique_ptr _inputVolumeMetersHandler; - std::atomic _inputVolumeMetersRef; - std::atomic _inputActiveStateChangedRef; - std::atomic _inputShowStateChangedRef; - std::atomic _sceneItemTransformChangedRef; + std::unique_ptr + _inputVolumeMetersHandler; + std::atomic _inputVolumeMetersRef; + std::atomic _inputActiveStateChangedRef; + std::atomic _inputShowStateChangedRef; + std::atomic _sceneItemTransformChangedRef; - void ConnectSourceSignals(obs_source_t *source); - void DisconnectSourceSignals(obs_source_t *source); + void ConnectSourceSignals(obs_source_t *source); + void DisconnectSourceSignals(obs_source_t *source); - void BroadcastEvent(uint64_t requiredIntent, std::string eventType, json eventData = nullptr, uint8_t rpcVersion = 0); + void BroadcastEvent(uint64_t requiredIntent, std::string eventType, + json eventData = nullptr, uint8_t rpcVersion = 0); - // Signal handler: frontend - static void OnFrontendEvent(enum obs_frontend_event event, void *private_data); + // Signal handler: frontend + static void OnFrontendEvent(enum obs_frontend_event event, + void *private_data); - // Signal handler: libobs - static void SourceCreatedMultiHandler(void *param, calldata_t *data); - static void SourceDestroyedMultiHandler(void *param, calldata_t *data); - static void SourceRemovedMultiHandler(void *param, calldata_t *data); + // Signal handler: libobs + static void SourceCreatedMultiHandler(void *param, calldata_t *data); + static void SourceDestroyedMultiHandler(void *param, calldata_t *data); + static void SourceRemovedMultiHandler(void *param, calldata_t *data); - // Signal handler: source - static void SourceRenamedMultiHandler(void *param, calldata_t *data); - static void SourceMediaPauseMultiHandler(void *param, calldata_t *data); - static void SourceMediaPlayMultiHandler(void *param, calldata_t *data); - static void SourceMediaRestartMultiHandler(void *param, calldata_t *data); - static void SourceMediaStopMultiHandler(void *param, calldata_t *data); - static void SourceMediaNextMultiHandler(void *param, calldata_t *data); - static void SourceMediaPreviousMultiHandler(void *param, calldata_t *data); + // Signal handler: source + static void SourceRenamedMultiHandler(void *param, calldata_t *data); + static void SourceMediaPauseMultiHandler(void *param, calldata_t *data); + static void SourceMediaPlayMultiHandler(void *param, calldata_t *data); + static void SourceMediaRestartMultiHandler(void *param, + calldata_t *data); + static void SourceMediaStopMultiHandler(void *param, calldata_t *data); + static void SourceMediaNextMultiHandler(void *param, calldata_t *data); + static void SourceMediaPreviousMultiHandler(void *param, + calldata_t *data); + // General + void HandleExitStarted(); + void HandleStudioModeStateChanged(bool enabled); - // General - void HandleExitStarted(); - void HandleStudioModeStateChanged(bool enabled); + // Config + void HandleCurrentSceneCollectionChanging(); + void HandleCurrentSceneCollectionChanged(); + void HandleSceneCollectionListChanged(); + void HandleCurrentProfileChanging(); + void HandleCurrentProfileChanged(); + void HandleProfileListChanged(); - // Config - void HandleCurrentSceneCollectionChanging(); - void HandleCurrentSceneCollectionChanged(); - void HandleSceneCollectionListChanged(); - void HandleCurrentProfileChanging(); - void HandleCurrentProfileChanged(); - void HandleProfileListChanged(); + // Scenes + void HandleSceneCreated(obs_source_t *source); + void HandleSceneRemoved(obs_source_t *source); + void HandleSceneNameChanged(obs_source_t *source, + std::string oldSceneName, + std::string sceneName); + void HandleCurrentProgramSceneChanged(); + void HandleCurrentPreviewSceneChanged(); + void HandleSceneListChanged(); - // Scenes - void HandleSceneCreated(obs_source_t *source); - void HandleSceneRemoved(obs_source_t *source); - void HandleSceneNameChanged(obs_source_t *source, std::string oldSceneName, std::string sceneName); - void HandleCurrentProgramSceneChanged(); - void HandleCurrentPreviewSceneChanged(); - void HandleSceneListChanged(); + // Inputs + void HandleInputCreated(obs_source_t *source); + void HandleInputRemoved(obs_source_t *source); + void HandleInputNameChanged(obs_source_t *source, + std::string oldInputName, + std::string inputName); + void HandleInputVolumeMeters( + std::vector inputs); // AudioMeter::Handler callback + static void + HandleInputActiveStateChanged(void *param, + calldata_t *data); // Direct callback + static void + HandleInputShowStateChanged(void *param, + calldata_t *data); // Direct callback + static void + HandleInputMuteStateChanged(void *param, + calldata_t *data); // Direct callback + static void + HandleInputVolumeChanged(void *param, + calldata_t *data); // Direct callback + static void + HandleInputAudioBalanceChanged(void *param, + calldata_t *data); // Direct callback + static void + HandleInputAudioSyncOffsetChanged(void *param, + calldata_t *data); // Direct callback + static void + HandleInputAudioTracksChanged(void *param, + calldata_t *data); // Direct callback + static void + HandleInputAudioMonitorTypeChanged(void *param, + calldata_t *data); // Direct callback - // Inputs - void HandleInputCreated(obs_source_t *source); - void HandleInputRemoved(obs_source_t *source); - void HandleInputNameChanged(obs_source_t *source, std::string oldInputName, std::string inputName); - void HandleInputVolumeMeters(std::vector inputs); // AudioMeter::Handler callback - static void HandleInputActiveStateChanged(void *param, calldata_t *data); // Direct callback - static void HandleInputShowStateChanged(void *param, calldata_t *data); // Direct callback - static void HandleInputMuteStateChanged(void *param, calldata_t *data); // Direct callback - static void HandleInputVolumeChanged(void *param, calldata_t *data); // Direct callback - static void HandleInputAudioBalanceChanged(void *param, calldata_t *data); // Direct callback - static void HandleInputAudioSyncOffsetChanged(void *param, calldata_t *data); // Direct callback - static void HandleInputAudioTracksChanged(void *param, calldata_t *data); // Direct callback - static void HandleInputAudioMonitorTypeChanged(void *param, calldata_t *data); // Direct callback + // Transitions + void HandleCurrentSceneTransitionChanged(); + void HandleCurrentSceneTransitionDurationChanged(); + static void + HandleSceneTransitionStarted(void *param, + calldata_t *data); // Direct callback + static void + HandleSceneTransitionEnded(void *param, + calldata_t *data); // Direct callback + static void + HandleSceneTransitionVideoEnded(void *param, + calldata_t *data); // Direct callback - // Transitions - void HandleCurrentSceneTransitionChanged(); - void HandleCurrentSceneTransitionDurationChanged(); - static void HandleSceneTransitionStarted(void *param, calldata_t *data); // Direct callback - static void HandleSceneTransitionEnded(void *param, calldata_t *data); // Direct callback - static void HandleSceneTransitionVideoEnded(void *param, calldata_t *data); // Direct callback + // Filters + static void FilterAddMultiHandler(void *param, + calldata_t *data); // Direct callback + static void + FilterRemoveMultiHandler(void *param, + calldata_t *data); // Direct callback + static void + HandleSourceFilterListReindexed(void *param, + calldata_t *data); // Direct callback + void HandleSourceFilterCreated(obs_source_t *source, + obs_source_t *filter); + void HandleSourceFilterRemoved(obs_source_t *source, + obs_source_t *filter); + static void + HandleSourceFilterNameChanged(void *param, + calldata_t *data); // Direct callback + static void HandleSourceFilterEnableStateChanged( + void *param, calldata_t *data); // Direct callback - // Filters - static void FilterAddMultiHandler(void *param, calldata_t *data); // Direct callback - static void FilterRemoveMultiHandler(void *param, calldata_t *data); // Direct callback - static void HandleSourceFilterListReindexed(void *param, calldata_t *data); // Direct callback - void HandleSourceFilterCreated(obs_source_t *source, obs_source_t *filter); - void HandleSourceFilterRemoved(obs_source_t *source, obs_source_t *filter); - static void HandleSourceFilterNameChanged(void *param, calldata_t *data); // Direct callback - static void HandleSourceFilterEnableStateChanged(void *param, calldata_t *data); // Direct callback + // Outputs + void HandleStreamStateChanged(ObsOutputState state); + void HandleRecordStateChanged(ObsOutputState state); + void HandleReplayBufferStateChanged(ObsOutputState state); + void HandleVirtualcamStateChanged(ObsOutputState state); + void HandleReplayBufferSaved(); - // Outputs - void HandleStreamStateChanged(ObsOutputState state); - void HandleRecordStateChanged(ObsOutputState state); - void HandleReplayBufferStateChanged(ObsOutputState state); - void HandleVirtualcamStateChanged(ObsOutputState state); - void HandleReplayBufferSaved(); + // Scene Items + static void HandleSceneItemCreated(void *param, + calldata_t *data); // Direct callback + static void HandleSceneItemRemoved(void *param, + calldata_t *data); // Direct callback + static void + HandleSceneItemListReindexed(void *param, + calldata_t *data); // Direct callback + static void + HandleSceneItemEnableStateChanged(void *param, + calldata_t *data); // Direct callback + static void + HandleSceneItemLockStateChanged(void *param, + calldata_t *data); // Direct callback + static void + HandleSceneItemSelected(void *param, + calldata_t *data); // Direct callback + static void + HandleSceneItemTransformChanged(void *param, + calldata_t *data); // Direct callback - // Scene Items - static void HandleSceneItemCreated(void *param, calldata_t *data); // Direct callback - static void HandleSceneItemRemoved(void *param, calldata_t *data); // Direct callback - static void HandleSceneItemListReindexed(void *param, calldata_t *data); // Direct callback - static void HandleSceneItemEnableStateChanged(void *param, calldata_t *data); // Direct callback - static void HandleSceneItemLockStateChanged(void *param, calldata_t *data); // Direct callback - static void HandleSceneItemSelected(void *param, calldata_t *data); // Direct callback - static void HandleSceneItemTransformChanged(void *param, calldata_t *data); // Direct callback - - // Media Inputs - 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); + // Media Inputs + 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); }; diff --git a/src/eventhandler/EventHandler_Config.cpp b/src/eventhandler/EventHandler_Config.cpp index d93bc621..3edfdfc6 100644 --- a/src/eventhandler/EventHandler_Config.cpp +++ b/src/eventhandler/EventHandler_Config.cpp @@ -38,8 +38,10 @@ with this program. If not, see void EventHandler::HandleCurrentSceneCollectionChanging() { json eventData; - eventData["sceneCollectionName"] = Utils::Obs::StringHelper::GetCurrentSceneCollection(); - BroadcastEvent(EventSubscription::Config, "CurrentSceneCollectionChanging", eventData); + eventData["sceneCollectionName"] = + Utils::Obs::StringHelper::GetCurrentSceneCollection(); + BroadcastEvent(EventSubscription::Config, + "CurrentSceneCollectionChanging", eventData); } /** @@ -60,8 +62,10 @@ void EventHandler::HandleCurrentSceneCollectionChanging() void EventHandler::HandleCurrentSceneCollectionChanged() { json eventData; - eventData["sceneCollectionName"] = Utils::Obs::StringHelper::GetCurrentSceneCollection(); - BroadcastEvent(EventSubscription::Config, "CurrentSceneCollectionChanged", eventData); + eventData["sceneCollectionName"] = + Utils::Obs::StringHelper::GetCurrentSceneCollection(); + BroadcastEvent(EventSubscription::Config, + "CurrentSceneCollectionChanged", eventData); } /** @@ -80,8 +84,10 @@ void EventHandler::HandleCurrentSceneCollectionChanged() void EventHandler::HandleSceneCollectionListChanged() { json eventData; - eventData["sceneCollections"] = Utils::Obs::ArrayHelper::GetSceneCollectionList(); - BroadcastEvent(EventSubscription::Config, "SceneCollectionListChanged", eventData); + eventData["sceneCollections"] = + Utils::Obs::ArrayHelper::GetSceneCollectionList(); + BroadcastEvent(EventSubscription::Config, "SceneCollectionListChanged", + eventData); } /** @@ -100,8 +106,10 @@ void EventHandler::HandleSceneCollectionListChanged() void EventHandler::HandleCurrentProfileChanging() { json eventData; - eventData["profileName"] = Utils::Obs::StringHelper::GetCurrentProfile(); - BroadcastEvent(EventSubscription::Config, "CurrentProfileChanging", eventData); + eventData["profileName"] = + Utils::Obs::StringHelper::GetCurrentProfile(); + BroadcastEvent(EventSubscription::Config, "CurrentProfileChanging", + eventData); } /** @@ -120,8 +128,10 @@ void EventHandler::HandleCurrentProfileChanging() void EventHandler::HandleCurrentProfileChanged() { json eventData; - eventData["profileName"] = Utils::Obs::StringHelper::GetCurrentProfile(); - BroadcastEvent(EventSubscription::Config, "CurrentProfileChanged", eventData); + eventData["profileName"] = + Utils::Obs::StringHelper::GetCurrentProfile(); + BroadcastEvent(EventSubscription::Config, "CurrentProfileChanged", + eventData); } /** @@ -141,5 +151,6 @@ void EventHandler::HandleProfileListChanged() { json eventData; eventData["profiles"] = Utils::Obs::ArrayHelper::GetProfileList(); - BroadcastEvent(EventSubscription::Config, "ProfileListChanged", eventData); + BroadcastEvent(EventSubscription::Config, "ProfileListChanged", + eventData); } diff --git a/src/eventhandler/EventHandler_Filters.cpp b/src/eventhandler/EventHandler_Filters.cpp index c4f64309..49250ff6 100644 --- a/src/eventhandler/EventHandler_Filters.cpp +++ b/src/eventhandler/EventHandler_Filters.cpp @@ -21,7 +21,7 @@ with this program. If not, see void EventHandler::FilterAddMultiHandler(void *param, calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_source_t *source = GetCalldataPointer(data, "source"); obs_source_t *filter = GetCalldataPointer(data, "filter"); @@ -36,7 +36,7 @@ void EventHandler::FilterAddMultiHandler(void *param, calldata_t *data) void EventHandler::FilterRemoveMultiHandler(void *param, calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_source_t *source = GetCalldataPointer(data, "source"); obs_source_t *filter = GetCalldataPointer(data, "filter"); @@ -63,9 +63,10 @@ void EventHandler::FilterRemoveMultiHandler(void *param, calldata_t *data) * @api events * @category filters */ -void EventHandler::HandleSourceFilterListReindexed(void *param, calldata_t *data) +void EventHandler::HandleSourceFilterListReindexed(void *param, + calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_source_t *source = GetCalldataPointer(data, "source"); if (!source) @@ -73,8 +74,10 @@ void EventHandler::HandleSourceFilterListReindexed(void *param, calldata_t *data json eventData; eventData["sourceName"] = obs_source_get_name(source); - eventData["filters"] = Utils::Obs::ArrayHelper::GetSourceFilterList(source); - eventHandler->BroadcastEvent(EventSubscription::Filters, "SourceFilterListReindexed", eventData); + eventData["filters"] = + Utils::Obs::ArrayHelper::GetSourceFilterList(source); + eventHandler->BroadcastEvent(EventSubscription::Filters, + "SourceFilterListReindexed", eventData); } /** @@ -95,20 +98,26 @@ void EventHandler::HandleSourceFilterListReindexed(void *param, calldata_t *data * @api events * @category filters */ -void EventHandler::HandleSourceFilterCreated(obs_source_t *source, obs_source_t *filter) +void EventHandler::HandleSourceFilterCreated(obs_source_t *source, + obs_source_t *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()); + 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); - BroadcastEvent(EventSubscription::Filters, "SourceFilterCreated", eventData); + eventData["filterIndex"] = + Utils::Obs::NumberHelper::GetSourceFilterIndex(source, filter); + eventData["filterSettings"] = + Utils::Json::ObsDataToJson(filterSettings); + eventData["defaultFilterSettings"] = + Utils::Json::ObsDataToJson(defaultFilterSettings, true); + BroadcastEvent(EventSubscription::Filters, "SourceFilterCreated", + eventData); } /** @@ -125,12 +134,14 @@ void EventHandler::HandleSourceFilterCreated(obs_source_t *source, obs_source_t * @api events * @category filters */ -void EventHandler::HandleSourceFilterRemoved(obs_source_t *source, obs_source_t *filter) +void EventHandler::HandleSourceFilterRemoved(obs_source_t *source, + obs_source_t *filter) { json eventData; eventData["sourceName"] = obs_source_get_name(source); eventData["filterName"] = obs_source_get_name(filter); - BroadcastEvent(EventSubscription::Filters, "SourceFilterRemoved", eventData); + BroadcastEvent(EventSubscription::Filters, "SourceFilterRemoved", + eventData); } /** @@ -150,17 +161,19 @@ void EventHandler::HandleSourceFilterRemoved(obs_source_t *source, obs_source_t */ void EventHandler::HandleSourceFilterNameChanged(void *param, calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_source_t *filter = GetCalldataPointer(data, "source"); if (!filter) return; json eventData; - eventData["sourceName"] = obs_source_get_name(obs_filter_get_parent(filter)); + 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); + eventHandler->BroadcastEvent(EventSubscription::Filters, + "SourceFilterNameChanged", eventData); } /** @@ -178,9 +191,10 @@ void EventHandler::HandleSourceFilterNameChanged(void *param, calldata_t *data) * @api events * @category filters */ -void EventHandler::HandleSourceFilterEnableStateChanged(void *param, calldata_t *data) +void EventHandler::HandleSourceFilterEnableStateChanged(void *param, + calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_source_t *filter = GetCalldataPointer(data, "source"); if (!filter) @@ -197,5 +211,7 @@ void EventHandler::HandleSourceFilterEnableStateChanged(void *param, calldata_t eventData["sourceName"] = obs_source_get_name(source); eventData["filterName"] = obs_source_get_name(filter); eventData["filterEnabled"] = filterEnabled; - eventHandler->BroadcastEvent(EventSubscription::Filters, "SourceFilterEnableStateChanged", eventData); + eventHandler->BroadcastEvent(EventSubscription::Filters, + "SourceFilterEnableStateChanged", + eventData); } diff --git a/src/eventhandler/EventHandler_Inputs.cpp b/src/eventhandler/EventHandler_Inputs.cpp index 45bf9a6a..105d728f 100644 --- a/src/eventhandler/EventHandler_Inputs.cpp +++ b/src/eventhandler/EventHandler_Inputs.cpp @@ -40,14 +40,17 @@ void EventHandler::HandleInputCreated(obs_source_t *source) { std::string inputKind = obs_source_get_id(source); OBSDataAutoRelease inputSettings = obs_source_get_settings(source); - OBSDataAutoRelease defaultInputSettings = obs_get_source_defaults(inputKind.c_str()); + OBSDataAutoRelease defaultInputSettings = + obs_get_source_defaults(inputKind.c_str()); json eventData; eventData["inputName"] = obs_source_get_name(source); eventData["inputKind"] = inputKind; - eventData["unversionedInputKind"] = obs_source_get_unversioned_id(source); + eventData["unversionedInputKind"] = + obs_source_get_unversioned_id(source); eventData["inputSettings"] = Utils::Json::ObsDataToJson(inputSettings); - eventData["defaultInputSettings"] = Utils::Json::ObsDataToJson(defaultInputSettings, true); + eventData["defaultInputSettings"] = + Utils::Json::ObsDataToJson(defaultInputSettings, true); BroadcastEvent(EventSubscription::Inputs, "InputCreated", eventData); } @@ -85,12 +88,15 @@ void EventHandler::HandleInputRemoved(obs_source_t *source) * @api events * @category inputs */ -void EventHandler::HandleInputNameChanged(obs_source_t *, std::string oldInputName, std::string inputName) +void EventHandler::HandleInputNameChanged(obs_source_t *, + std::string oldInputName, + std::string inputName) { json eventData; eventData["oldInputName"] = oldInputName; eventData["inputName"] = inputName; - BroadcastEvent(EventSubscription::Inputs, "InputNameChanged", eventData); + BroadcastEvent(EventSubscription::Inputs, "InputNameChanged", + eventData); } /** @@ -111,7 +117,7 @@ void EventHandler::HandleInputNameChanged(obs_source_t *, std::string oldInputNa */ void EventHandler::HandleInputActiveStateChanged(void *param, calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); if (!eventHandler->_inputActiveStateChangedRef.load()) return; @@ -126,7 +132,8 @@ void EventHandler::HandleInputActiveStateChanged(void *param, calldata_t *data) json eventData; eventData["inputName"] = obs_source_get_name(source); eventData["videoActive"] = obs_source_active(source); - eventHandler->BroadcastEvent(EventSubscription::InputActiveStateChanged, "InputActiveStateChanged", eventData); + eventHandler->BroadcastEvent(EventSubscription::InputActiveStateChanged, + "InputActiveStateChanged", eventData); } /** @@ -147,7 +154,7 @@ void EventHandler::HandleInputActiveStateChanged(void *param, calldata_t *data) */ void EventHandler::HandleInputShowStateChanged(void *param, calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); if (!eventHandler->_inputShowStateChangedRef.load()) return; @@ -162,7 +169,8 @@ void EventHandler::HandleInputShowStateChanged(void *param, calldata_t *data) json eventData; eventData["inputName"] = obs_source_get_name(source); eventData["videoShowing"] = obs_source_showing(source); - eventHandler->BroadcastEvent(EventSubscription::InputShowStateChanged, "InputShowStateChanged", eventData); + eventHandler->BroadcastEvent(EventSubscription::InputShowStateChanged, + "InputShowStateChanged", eventData); } /** @@ -181,7 +189,7 @@ void EventHandler::HandleInputShowStateChanged(void *param, calldata_t *data) */ void EventHandler::HandleInputMuteStateChanged(void *param, calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_source_t *source = GetCalldataPointer(data, "source"); if (!source) @@ -193,7 +201,8 @@ void EventHandler::HandleInputMuteStateChanged(void *param, calldata_t *data) json eventData; eventData["inputName"] = obs_source_get_name(source); eventData["inputMuted"] = obs_source_muted(source); - eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputMuteStateChanged", eventData); + eventHandler->BroadcastEvent(EventSubscription::Inputs, + "InputMuteStateChanged", eventData); } /** @@ -213,7 +222,7 @@ void EventHandler::HandleInputMuteStateChanged(void *param, calldata_t *data) */ void EventHandler::HandleInputVolumeChanged(void *param, calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_source_t *source = GetCalldataPointer(data, "source"); if (!source) @@ -233,7 +242,8 @@ void EventHandler::HandleInputVolumeChanged(void *param, calldata_t *data) eventData["inputName"] = obs_source_get_name(source); eventData["inputVolumeMul"] = inputVolumeMul; eventData["inputVolumeDb"] = inputVolumeDb; - eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputVolumeChanged", eventData); + eventHandler->BroadcastEvent(EventSubscription::Inputs, + "InputVolumeChanged", eventData); } /** @@ -252,7 +262,7 @@ void EventHandler::HandleInputVolumeChanged(void *param, calldata_t *data) */ void EventHandler::HandleInputAudioBalanceChanged(void *param, calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_source_t *source = GetCalldataPointer(data, "source"); if (!source) @@ -266,7 +276,8 @@ void EventHandler::HandleInputAudioBalanceChanged(void *param, calldata_t *data) json eventData; eventData["inputName"] = obs_source_get_name(source); eventData["inputAudioBalance"] = inputAudioBalance; - eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputAudioBalanceChanged", eventData); + eventHandler->BroadcastEvent(EventSubscription::Inputs, + "InputAudioBalanceChanged", eventData); } /** @@ -283,9 +294,10 @@ void EventHandler::HandleInputAudioBalanceChanged(void *param, calldata_t *data) * @api events * @category inputs */ -void EventHandler::HandleInputAudioSyncOffsetChanged(void *param, calldata_t *data) +void EventHandler::HandleInputAudioSyncOffsetChanged(void *param, + calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_source_t *source = GetCalldataPointer(data, "source"); if (!source) @@ -299,7 +311,8 @@ void EventHandler::HandleInputAudioSyncOffsetChanged(void *param, calldata_t *da json eventData; eventData["inputName"] = obs_source_get_name(source); eventData["inputAudioSyncOffset"] = inputAudioSyncOffset / 1000000; - eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputAudioSyncOffsetChanged", eventData); + eventHandler->BroadcastEvent(EventSubscription::Inputs, + "InputAudioSyncOffsetChanged", eventData); } /** @@ -318,7 +331,7 @@ void EventHandler::HandleInputAudioSyncOffsetChanged(void *param, calldata_t *da */ void EventHandler::HandleInputAudioTracksChanged(void *param, calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_source_t *source = GetCalldataPointer(data, "source"); if (!source) @@ -331,13 +344,15 @@ void EventHandler::HandleInputAudioTracksChanged(void *param, calldata_t *data) json inputAudioTracks; for (long long i = 0; i < MAX_AUDIO_MIXES; i++) { - inputAudioTracks[std::to_string(i + 1)] = (bool)((tracks >> i) & 1); + inputAudioTracks[std::to_string(i + 1)] = + (bool)((tracks >> i) & 1); } json eventData; eventData["inputName"] = obs_source_get_name(source); eventData["inputAudioTracks"] = inputAudioTracks; - eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputAudioTracksChanged", eventData); + eventHandler->BroadcastEvent(EventSubscription::Inputs, + "InputAudioTracksChanged", eventData); } /** @@ -360,9 +375,10 @@ void EventHandler::HandleInputAudioTracksChanged(void *param, calldata_t *data) * @api events * @category inputs */ -void EventHandler::HandleInputAudioMonitorTypeChanged(void *param, calldata_t *data) +void EventHandler::HandleInputAudioMonitorTypeChanged(void *param, + calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_source_t *source = GetCalldataPointer(data, "source"); if (!source) @@ -371,14 +387,17 @@ void EventHandler::HandleInputAudioMonitorTypeChanged(void *param, calldata_t *d if (obs_source_get_type(source) != OBS_SOURCE_TYPE_INPUT) return; - enum obs_monitoring_type monitorType = (obs_monitoring_type)calldata_int(data, "type"); + enum obs_monitoring_type monitorType = + (obs_monitoring_type)calldata_int(data, "type"); - std::string monitorTypeString = Utils::Obs::StringHelper::GetInputMonitorType(monitorType); + std::string monitorTypeString = + Utils::Obs::StringHelper::GetInputMonitorType(monitorType); json eventData; eventData["inputName"] = obs_source_get_name(source); eventData["monitorType"] = monitorTypeString; - eventHandler->BroadcastEvent(EventSubscription::Inputs, "InputAudioMonitorTypeChanged", eventData); + eventHandler->BroadcastEvent(EventSubscription::Inputs, + "InputAudioMonitorTypeChanged", eventData); } /** @@ -398,5 +417,6 @@ void EventHandler::HandleInputVolumeMeters(std::vector inputs) { json eventData; eventData["inputs"] = inputs; - BroadcastEvent(EventSubscription::InputVolumeMeters, "InputVolumeMeters", eventData); + BroadcastEvent(EventSubscription::InputVolumeMeters, + "InputVolumeMeters", eventData); } diff --git a/src/eventhandler/EventHandler_MediaInputs.cpp b/src/eventhandler/EventHandler_MediaInputs.cpp index faa000c6..9286f280 100644 --- a/src/eventhandler/EventHandler_MediaInputs.cpp +++ b/src/eventhandler/EventHandler_MediaInputs.cpp @@ -19,11 +19,14 @@ with this program. If not, see #include "EventHandler.h" -#define CASE(x) case x: return #x; +#define CASE(x) \ + case x: \ + return #x; -std::string GetMediaInputActionString(ObsMediaInputAction action) { +std::string GetMediaInputActionString(ObsMediaInputAction action) +{ switch (action) { - default: + default: CASE(OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PAUSE) CASE(OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PLAY) CASE(OBS_WEBSOCKET_MEDIA_INPUT_ACTION_RESTART) @@ -35,7 +38,7 @@ std::string GetMediaInputActionString(ObsMediaInputAction action) { void EventHandler::SourceMediaPauseMultiHandler(void *param, calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_source_t *source = GetCalldataPointer(data, "source"); if (!source) @@ -44,12 +47,13 @@ void EventHandler::SourceMediaPauseMultiHandler(void *param, calldata_t *data) if (obs_source_get_type(source) != OBS_SOURCE_TYPE_INPUT) return; - eventHandler->HandleMediaInputActionTriggered(source, OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PAUSE); + eventHandler->HandleMediaInputActionTriggered( + source, OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PAUSE); } void EventHandler::SourceMediaPlayMultiHandler(void *param, calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_source_t *source = GetCalldataPointer(data, "source"); if (!source) @@ -58,12 +62,13 @@ void EventHandler::SourceMediaPlayMultiHandler(void *param, calldata_t *data) if (obs_source_get_type(source) != OBS_SOURCE_TYPE_INPUT) return; - eventHandler->HandleMediaInputActionTriggered(source, OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PLAY); + eventHandler->HandleMediaInputActionTriggered( + source, OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PLAY); } void EventHandler::SourceMediaRestartMultiHandler(void *param, calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_source_t *source = GetCalldataPointer(data, "source"); if (!source) @@ -72,12 +77,13 @@ void EventHandler::SourceMediaRestartMultiHandler(void *param, calldata_t *data) if (obs_source_get_type(source) != OBS_SOURCE_TYPE_INPUT) return; - eventHandler->HandleMediaInputActionTriggered(source, OBS_WEBSOCKET_MEDIA_INPUT_ACTION_RESTART); + eventHandler->HandleMediaInputActionTriggered( + source, OBS_WEBSOCKET_MEDIA_INPUT_ACTION_RESTART); } void EventHandler::SourceMediaStopMultiHandler(void *param, calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_source_t *source = GetCalldataPointer(data, "source"); if (!source) @@ -86,12 +92,13 @@ void EventHandler::SourceMediaStopMultiHandler(void *param, calldata_t *data) if (obs_source_get_type(source) != OBS_SOURCE_TYPE_INPUT) return; - eventHandler->HandleMediaInputActionTriggered(source, OBS_WEBSOCKET_MEDIA_INPUT_ACTION_STOP); + eventHandler->HandleMediaInputActionTriggered( + source, OBS_WEBSOCKET_MEDIA_INPUT_ACTION_STOP); } void EventHandler::SourceMediaNextMultiHandler(void *param, calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_source_t *source = GetCalldataPointer(data, "source"); if (!source) @@ -100,12 +107,14 @@ void EventHandler::SourceMediaNextMultiHandler(void *param, calldata_t *data) if (obs_source_get_type(source) != OBS_SOURCE_TYPE_INPUT) return; - eventHandler->HandleMediaInputActionTriggered(source, OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NEXT); + eventHandler->HandleMediaInputActionTriggered( + source, OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NEXT); } -void EventHandler::SourceMediaPreviousMultiHandler(void *param, calldata_t *data) +void EventHandler::SourceMediaPreviousMultiHandler(void *param, + calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_source_t *source = GetCalldataPointer(data, "source"); if (!source) @@ -114,7 +123,8 @@ void EventHandler::SourceMediaPreviousMultiHandler(void *param, calldata_t *data if (obs_source_get_type(source) != OBS_SOURCE_TYPE_INPUT) return; - eventHandler->HandleMediaInputActionTriggered(source, OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PREVIOUS); + eventHandler->HandleMediaInputActionTriggered( + source, OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PREVIOUS); } /** @@ -130,9 +140,10 @@ void EventHandler::SourceMediaPreviousMultiHandler(void *param, calldata_t *data * @api events * @category media inputs */ -void EventHandler::HandleMediaInputPlaybackStarted(void *param, calldata_t *data) +void EventHandler::HandleMediaInputPlaybackStarted(void *param, + calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_source_t *source = GetCalldataPointer(data, "source"); if (!source) @@ -143,7 +154,8 @@ void EventHandler::HandleMediaInputPlaybackStarted(void *param, calldata_t *data json eventData; eventData["inputName"] = obs_source_get_name(source); - eventHandler->BroadcastEvent(EventSubscription::MediaInputs, "MediaInputPlaybackStarted", eventData); + eventHandler->BroadcastEvent(EventSubscription::MediaInputs, + "MediaInputPlaybackStarted", eventData); } /** @@ -161,7 +173,7 @@ void EventHandler::HandleMediaInputPlaybackStarted(void *param, calldata_t *data */ void EventHandler::HandleMediaInputPlaybackEnded(void *param, calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_source_t *source = GetCalldataPointer(data, "source"); if (!source) @@ -172,7 +184,8 @@ void EventHandler::HandleMediaInputPlaybackEnded(void *param, calldata_t *data) json eventData; eventData["inputName"] = obs_source_get_name(source); - eventHandler->BroadcastEvent(EventSubscription::MediaInputs, "MediaInputPlaybackEnded", eventData); + eventHandler->BroadcastEvent(EventSubscription::MediaInputs, + "MediaInputPlaybackEnded", eventData); } /** @@ -189,10 +202,12 @@ void EventHandler::HandleMediaInputPlaybackEnded(void *param, calldata_t *data) * @api events * @category media inputs */ -void EventHandler::HandleMediaInputActionTriggered(obs_source_t *source, ObsMediaInputAction action) +void EventHandler::HandleMediaInputActionTriggered(obs_source_t *source, + ObsMediaInputAction action) { json eventData; eventData["inputName"] = obs_source_get_name(source); eventData["mediaAction"] = GetMediaInputActionString(action); - BroadcastEvent(EventSubscription::MediaInputs, "MediaInputActionTriggered", eventData); + BroadcastEvent(EventSubscription::MediaInputs, + "MediaInputActionTriggered", eventData); } \ No newline at end of file diff --git a/src/eventhandler/EventHandler_Outputs.cpp b/src/eventhandler/EventHandler_Outputs.cpp index bf9acfb6..9b630acc 100644 --- a/src/eventhandler/EventHandler_Outputs.cpp +++ b/src/eventhandler/EventHandler_Outputs.cpp @@ -19,18 +19,19 @@ with this program. If not, see #include "EventHandler.h" -static bool GetOutputStateActive(ObsOutputState state) { - switch(state) { - case OBS_WEBSOCKET_OUTPUT_STARTED: - case OBS_WEBSOCKET_OUTPUT_RESUMED: - return true; - case OBS_WEBSOCKET_OUTPUT_STARTING: - case OBS_WEBSOCKET_OUTPUT_STOPPING: - case OBS_WEBSOCKET_OUTPUT_STOPPED: - case OBS_WEBSOCKET_OUTPUT_PAUSED: - return false; - default: - return false; +static bool GetOutputStateActive(ObsOutputState state) +{ + switch (state) { + case OBS_WEBSOCKET_OUTPUT_STARTED: + case OBS_WEBSOCKET_OUTPUT_RESUMED: + return true; + case OBS_WEBSOCKET_OUTPUT_STARTING: + case OBS_WEBSOCKET_OUTPUT_STOPPING: + case OBS_WEBSOCKET_OUTPUT_STOPPED: + case OBS_WEBSOCKET_OUTPUT_PAUSED: + return false; + default: + return false; } } @@ -52,8 +53,10 @@ void EventHandler::HandleStreamStateChanged(ObsOutputState state) { json eventData; eventData["outputActive"] = GetOutputStateActive(state); - eventData["outputState"] = Utils::Obs::StringHelper::GetOutputState(state); - BroadcastEvent(EventSubscription::Outputs, "StreamStateChanged", eventData); + eventData["outputState"] = + Utils::Obs::StringHelper::GetOutputState(state); + BroadcastEvent(EventSubscription::Outputs, "StreamStateChanged", + eventData); } /** @@ -74,8 +77,10 @@ void EventHandler::HandleRecordStateChanged(ObsOutputState state) { json eventData; eventData["outputActive"] = GetOutputStateActive(state); - eventData["outputState"] = Utils::Obs::StringHelper::GetOutputState(state); - BroadcastEvent(EventSubscription::Outputs, "RecordStateChanged", eventData); + eventData["outputState"] = + Utils::Obs::StringHelper::GetOutputState(state); + BroadcastEvent(EventSubscription::Outputs, "RecordStateChanged", + eventData); } /** @@ -96,8 +101,10 @@ void EventHandler::HandleReplayBufferStateChanged(ObsOutputState state) { json eventData; eventData["outputActive"] = GetOutputStateActive(state); - eventData["outputState"] = Utils::Obs::StringHelper::GetOutputState(state); - BroadcastEvent(EventSubscription::Outputs, "ReplayBufferStateChanged", eventData); + eventData["outputState"] = + Utils::Obs::StringHelper::GetOutputState(state); + BroadcastEvent(EventSubscription::Outputs, "ReplayBufferStateChanged", + eventData); } /** @@ -118,8 +125,10 @@ void EventHandler::HandleVirtualcamStateChanged(ObsOutputState state) { json eventData; eventData["outputActive"] = GetOutputStateActive(state); - eventData["outputState"] = Utils::Obs::StringHelper::GetOutputState(state); - BroadcastEvent(EventSubscription::Outputs, "VirtualcamStateChanged", eventData); + eventData["outputState"] = + Utils::Obs::StringHelper::GetOutputState(state); + BroadcastEvent(EventSubscription::Outputs, "VirtualcamStateChanged", + eventData); } /** @@ -138,6 +147,8 @@ void EventHandler::HandleVirtualcamStateChanged(ObsOutputState state) void EventHandler::HandleReplayBufferSaved() { json eventData; - eventData["savedReplayPath"] = Utils::Obs::StringHelper::GetLastReplayBufferFilePath(); - BroadcastEvent(EventSubscription::Outputs, "ReplayBufferSaved", eventData); + eventData["savedReplayPath"] = + Utils::Obs::StringHelper::GetLastReplayBufferFilePath(); + BroadcastEvent(EventSubscription::Outputs, "ReplayBufferSaved", + eventData); } diff --git a/src/eventhandler/EventHandler_SceneItems.cpp b/src/eventhandler/EventHandler_SceneItems.cpp index a161f78e..90a55eea 100644 --- a/src/eventhandler/EventHandler_SceneItems.cpp +++ b/src/eventhandler/EventHandler_SceneItems.cpp @@ -37,22 +37,27 @@ with this program. If not, see */ void EventHandler::HandleSceneItemCreated(void *param, calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_scene_t *scene = GetCalldataPointer(data, "scene"); if (!scene) return; - obs_sceneitem_t *sceneItem = GetCalldataPointer(data, "item"); + obs_sceneitem_t *sceneItem = + GetCalldataPointer(data, "item"); if (!sceneItem) return; json eventData; - eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene)); - eventData["sourceName"] = obs_source_get_name(obs_sceneitem_get_source(sceneItem)); + eventData["sceneName"] = + obs_source_get_name(obs_scene_get_source(scene)); + eventData["sourceName"] = + obs_source_get_name(obs_sceneitem_get_source(sceneItem)); eventData["sceneItemId"] = obs_sceneitem_get_id(sceneItem); - eventData["sceneItemIndex"] = obs_sceneitem_get_order_position(sceneItem); - eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemCreated", eventData); + eventData["sceneItemIndex"] = + obs_sceneitem_get_order_position(sceneItem); + eventHandler->BroadcastEvent(EventSubscription::SceneItems, + "SceneItemCreated", eventData); } /** @@ -74,21 +79,25 @@ void EventHandler::HandleSceneItemCreated(void *param, calldata_t *data) */ void EventHandler::HandleSceneItemRemoved(void *param, calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_scene_t *scene = GetCalldataPointer(data, "scene"); if (!scene) return; - obs_sceneitem_t *sceneItem = GetCalldataPointer(data, "item"); + obs_sceneitem_t *sceneItem = + GetCalldataPointer(data, "item"); if (!sceneItem) return; json eventData; - eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene)); - eventData["sourceName"] = obs_source_get_name(obs_sceneitem_get_source(sceneItem)); + eventData["sceneName"] = + obs_source_get_name(obs_scene_get_source(scene)); + eventData["sourceName"] = + obs_source_get_name(obs_sceneitem_get_source(sceneItem)); eventData["sceneItemId"] = obs_sceneitem_get_id(sceneItem); - eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemRemoved", eventData); + eventHandler->BroadcastEvent(EventSubscription::SceneItems, + "SceneItemRemoved", eventData); } /** @@ -107,16 +116,19 @@ void EventHandler::HandleSceneItemRemoved(void *param, calldata_t *data) */ void EventHandler::HandleSceneItemListReindexed(void *param, calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_scene_t *scene = GetCalldataPointer(data, "scene"); if (!scene) return; json eventData; - eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene)); - eventData["sceneItems"] = Utils::Obs::ArrayHelper::GetSceneItemList(scene, true); - eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemListReindexed", eventData); + eventData["sceneName"] = + obs_source_get_name(obs_scene_get_source(scene)); + eventData["sceneItems"] = + Utils::Obs::ArrayHelper::GetSceneItemList(scene, true); + eventHandler->BroadcastEvent(EventSubscription::SceneItems, + "SceneItemListReindexed", eventData); } /** @@ -134,25 +146,29 @@ void EventHandler::HandleSceneItemListReindexed(void *param, calldata_t *data) * @api events * @category scene items */ -void EventHandler::HandleSceneItemEnableStateChanged(void *param, calldata_t *data) +void EventHandler::HandleSceneItemEnableStateChanged(void *param, + calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_scene_t *scene = GetCalldataPointer(data, "scene"); if (!scene) return; - obs_sceneitem_t *sceneItem = GetCalldataPointer(data, "item"); + obs_sceneitem_t *sceneItem = + GetCalldataPointer(data, "item"); if (!sceneItem) return; bool sceneItemEnabled = calldata_bool(data, "visible"); json eventData; - eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene)); + eventData["sceneName"] = + obs_source_get_name(obs_scene_get_source(scene)); eventData["sceneItemId"] = obs_sceneitem_get_id(sceneItem); eventData["sceneItemEnabled"] = sceneItemEnabled; - eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemEnableStateChanged", eventData); + eventHandler->BroadcastEvent(EventSubscription::SceneItems, + "SceneItemEnableStateChanged", eventData); } /** @@ -170,25 +186,29 @@ void EventHandler::HandleSceneItemEnableStateChanged(void *param, calldata_t *da * @api events * @category scene items */ -void EventHandler::HandleSceneItemLockStateChanged(void *param, calldata_t *data) +void EventHandler::HandleSceneItemLockStateChanged(void *param, + calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_scene_t *scene = GetCalldataPointer(data, "scene"); if (!scene) return; - obs_sceneitem_t *sceneItem = GetCalldataPointer(data, "item"); + obs_sceneitem_t *sceneItem = + GetCalldataPointer(data, "item"); if (!sceneItem) return; bool sceneItemLocked = calldata_bool(data, "locked"); json eventData; - eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene)); + eventData["sceneName"] = + obs_source_get_name(obs_scene_get_source(scene)); eventData["sceneItemId"] = obs_sceneitem_get_id(sceneItem); eventData["sceneItemLocked"] = sceneItemLocked; - eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemLockStateChanged", eventData); + eventHandler->BroadcastEvent(EventSubscription::SceneItems, + "SceneItemLockStateChanged", eventData); } /** @@ -207,20 +227,23 @@ void EventHandler::HandleSceneItemLockStateChanged(void *param, calldata_t *data */ void EventHandler::HandleSceneItemSelected(void *param, calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_scene_t *scene = GetCalldataPointer(data, "scene"); if (!scene) return; - obs_sceneitem_t *sceneItem = GetCalldataPointer(data, "item"); + obs_sceneitem_t *sceneItem = + GetCalldataPointer(data, "item"); if (!sceneItem) return; json eventData; - eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene)); + eventData["sceneName"] = + obs_source_get_name(obs_scene_get_source(scene)); eventData["sceneItemId"] = obs_sceneitem_get_id(sceneItem); - eventHandler->BroadcastEvent(EventSubscription::SceneItems, "SceneItemSelected", eventData); + eventHandler->BroadcastEvent(EventSubscription::SceneItems, + "SceneItemSelected", eventData); } /** @@ -238,9 +261,10 @@ void EventHandler::HandleSceneItemSelected(void *param, calldata_t *data) * @api events * @category scene items */ -void EventHandler::HandleSceneItemTransformChanged(void *param, calldata_t *data) +void EventHandler::HandleSceneItemTransformChanged(void *param, + calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); if (!eventHandler->_sceneItemTransformChangedRef.load()) return; @@ -249,13 +273,18 @@ void EventHandler::HandleSceneItemTransformChanged(void *param, calldata_t *data if (!scene) return; - obs_sceneitem_t *sceneItem = GetCalldataPointer(data, "item"); + obs_sceneitem_t *sceneItem = + GetCalldataPointer(data, "item"); if (!sceneItem) return; json eventData; - eventData["sceneName"] = obs_source_get_name(obs_scene_get_source(scene)); + eventData["sceneName"] = + obs_source_get_name(obs_scene_get_source(scene)); eventData["sceneItemId"] = obs_sceneitem_get_id(sceneItem); - eventData["sceneItemTransform"] = Utils::Obs::ObjectHelper::GetSceneItemTransform(sceneItem); - eventHandler->BroadcastEvent(EventSubscription::SceneItemTransformChanged, "SceneItemTransformChanged", eventData); + eventData["sceneItemTransform"] = + Utils::Obs::ObjectHelper::GetSceneItemTransform(sceneItem); + eventHandler->BroadcastEvent( + EventSubscription::SceneItemTransformChanged, + "SceneItemTransformChanged", eventData); } diff --git a/src/eventhandler/EventHandler_Scenes.cpp b/src/eventhandler/EventHandler_Scenes.cpp index aca61e5a..5af31e06 100644 --- a/src/eventhandler/EventHandler_Scenes.cpp +++ b/src/eventhandler/EventHandler_Scenes.cpp @@ -77,12 +77,15 @@ void EventHandler::HandleSceneRemoved(obs_source_t *source) * @api events * @category scenes */ -void EventHandler::HandleSceneNameChanged(obs_source_t *, std::string oldSceneName, std::string sceneName) +void EventHandler::HandleSceneNameChanged(obs_source_t *, + std::string oldSceneName, + std::string sceneName) { json eventData; eventData["oldSceneName"] = oldSceneName; eventData["sceneName"] = sceneName; - BroadcastEvent(EventSubscription::Scenes, "SceneNameChanged", eventData); + BroadcastEvent(EventSubscription::Scenes, "SceneNameChanged", + eventData); } /** @@ -104,7 +107,8 @@ void EventHandler::HandleCurrentProgramSceneChanged() json eventData; eventData["sceneName"] = obs_source_get_name(currentScene); - BroadcastEvent(EventSubscription::Scenes, "CurrentProgramSceneChanged", eventData); + BroadcastEvent(EventSubscription::Scenes, "CurrentProgramSceneChanged", + eventData); } /** @@ -122,15 +126,17 @@ void EventHandler::HandleCurrentProgramSceneChanged() */ void EventHandler::HandleCurrentPreviewSceneChanged() { - OBSSourceAutoRelease currentPreviewScene = obs_frontend_get_current_preview_scene(); + OBSSourceAutoRelease currentPreviewScene = + obs_frontend_get_current_preview_scene(); - // This event may be called when OBS is not in studio mode, however retreiving the source while not in studio mode will return null. + // This event may be called when OBS is not in studio mode, however retreiving the source while not in studio mode will return null. if (!currentPreviewScene) return; json eventData; eventData["sceneName"] = obs_source_get_name(currentPreviewScene); - BroadcastEvent(EventSubscription::Scenes, "CurrentPreviewSceneChanged", eventData); + BroadcastEvent(EventSubscription::Scenes, "CurrentPreviewSceneChanged", + eventData); } /** @@ -152,5 +158,6 @@ void EventHandler::HandleSceneListChanged() { json eventData; eventData["scenes"] = Utils::Obs::ArrayHelper::GetSceneList(); - BroadcastEvent(EventSubscription::Scenes, "SceneListChanged", eventData); + BroadcastEvent(EventSubscription::Scenes, "SceneListChanged", + eventData); } diff --git a/src/eventhandler/EventHandler_Transitions.cpp b/src/eventhandler/EventHandler_Transitions.cpp index 94bb34d1..24cb7a76 100644 --- a/src/eventhandler/EventHandler_Transitions.cpp +++ b/src/eventhandler/EventHandler_Transitions.cpp @@ -38,7 +38,8 @@ void EventHandler::HandleCurrentSceneTransitionChanged() json eventData; eventData["transitionName"] = obs_source_get_name(transition); - BroadcastEvent(EventSubscription::Transitions, "CurrentSceneTransitionChanged", eventData); + BroadcastEvent(EventSubscription::Transitions, + "CurrentSceneTransitionChanged", eventData); } /** @@ -57,8 +58,10 @@ void EventHandler::HandleCurrentSceneTransitionChanged() void EventHandler::HandleCurrentSceneTransitionDurationChanged() { json eventData; - eventData["transitionDuration"] = obs_frontend_get_transition_duration(); - BroadcastEvent(EventSubscription::Transitions, "CurrentSceneTransitionDurationChanged", eventData); + eventData["transitionDuration"] = + obs_frontend_get_transition_duration(); + BroadcastEvent(EventSubscription::Transitions, + "CurrentSceneTransitionDurationChanged", eventData); } /** @@ -76,7 +79,7 @@ void EventHandler::HandleCurrentSceneTransitionDurationChanged() */ void EventHandler::HandleSceneTransitionStarted(void *param, calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_source_t *source = GetCalldataPointer(data, "source"); if (!source) @@ -84,7 +87,8 @@ void EventHandler::HandleSceneTransitionStarted(void *param, calldata_t *data) json eventData; eventData["transitionName"] = obs_source_get_name(source); - eventHandler->BroadcastEvent(EventSubscription::Transitions, "SceneTransitionStarted", eventData); + eventHandler->BroadcastEvent(EventSubscription::Transitions, + "SceneTransitionStarted", eventData); } /** @@ -104,7 +108,7 @@ void EventHandler::HandleSceneTransitionStarted(void *param, calldata_t *data) */ void EventHandler::HandleSceneTransitionEnded(void *param, calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_source_t *source = GetCalldataPointer(data, "source"); if (!source) @@ -112,7 +116,8 @@ void EventHandler::HandleSceneTransitionEnded(void *param, calldata_t *data) json eventData; eventData["transitionName"] = obs_source_get_name(source); - eventHandler->BroadcastEvent(EventSubscription::Transitions, "SceneTransitionEnded", eventData); + eventHandler->BroadcastEvent(EventSubscription::Transitions, + "SceneTransitionEnded", eventData); } /** @@ -133,9 +138,10 @@ void EventHandler::HandleSceneTransitionEnded(void *param, calldata_t *data) * @api events * @category transitions */ -void EventHandler::HandleSceneTransitionVideoEnded(void *param, calldata_t *data) +void EventHandler::HandleSceneTransitionVideoEnded(void *param, + calldata_t *data) { - auto eventHandler = static_cast(param); + auto eventHandler = static_cast(param); obs_source_t *source = GetCalldataPointer(data, "source"); if (!source) @@ -143,5 +149,6 @@ void EventHandler::HandleSceneTransitionVideoEnded(void *param, calldata_t *data json eventData; eventData["transitionName"] = obs_source_get_name(source); - eventHandler->BroadcastEvent(EventSubscription::Transitions, "SceneTransitionVideoEnded", eventData); + eventHandler->BroadcastEvent(EventSubscription::Transitions, + "SceneTransitionVideoEnded", eventData); } diff --git a/src/eventhandler/EventHandler_Ui.cpp b/src/eventhandler/EventHandler_Ui.cpp index 633baf8a..0248ad5c 100644 --- a/src/eventhandler/EventHandler_Ui.cpp +++ b/src/eventhandler/EventHandler_Ui.cpp @@ -36,5 +36,6 @@ void EventHandler::HandleStudioModeStateChanged(bool enabled) { json eventData; eventData["studioModeEnabled"] = enabled; - BroadcastEvent(EventSubscription::Ui, "StudioModeStateChanged", eventData); + BroadcastEvent(EventSubscription::Ui, "StudioModeStateChanged", + eventData); } diff --git a/src/eventhandler/types/EventSubscription.h b/src/eventhandler/types/EventSubscription.h index 0951745f..f3f61565 100644 --- a/src/eventhandler/types/EventSubscription.h +++ b/src/eventhandler/types/EventSubscription.h @@ -20,8 +20,8 @@ with this program. If not, see #pragma once namespace EventSubscription { - enum EventSubscription { - /** +enum EventSubscription { + /** * Subcription value used to disable all events. * * @enumIdentifier None @@ -31,8 +31,8 @@ namespace EventSubscription { * @initialVersion 5.0.0 * @api enums */ - None = 0, - /** + None = 0, + /** * Subscription value to receive events in the `General` category. * * @enumIdentifier General @@ -42,8 +42,8 @@ namespace EventSubscription { * @initialVersion 5.0.0 * @api enums */ - General = (1 << 0), - /** + General = (1 << 0), + /** * Subscription value to receive events in the `Config` category. * * @enumIdentifier Config @@ -53,8 +53,8 @@ namespace EventSubscription { * @initialVersion 5.0.0 * @api enums */ - Config = (1 << 1), - /** + Config = (1 << 1), + /** * Subscription value to receive events in the `Scenes` category. * * @enumIdentifier Scenes @@ -64,8 +64,8 @@ namespace EventSubscription { * @initialVersion 5.0.0 * @api enums */ - Scenes = (1 << 2), - /** + Scenes = (1 << 2), + /** * Subscription value to receive events in the `Inputs` category. * * @enumIdentifier Inputs @@ -75,8 +75,8 @@ namespace EventSubscription { * @initialVersion 5.0.0 * @api enums */ - Inputs = (1 << 3), - /** + Inputs = (1 << 3), + /** * Subscription value to receive events in the `Transitions` category. * * @enumIdentifier Transitions @@ -86,8 +86,8 @@ namespace EventSubscription { * @initialVersion 5.0.0 * @api enums */ - Transitions = (1 << 4), - /** + Transitions = (1 << 4), + /** * Subscription value to receive events in the `Filters` category. * * @enumIdentifier Filters @@ -97,8 +97,8 @@ namespace EventSubscription { * @initialVersion 5.0.0 * @api enums */ - Filters = (1 << 5), - /** + Filters = (1 << 5), + /** * Subscription value to receive events in the `Outputs` category. * * @enumIdentifier Outputs @@ -108,8 +108,8 @@ namespace EventSubscription { * @initialVersion 5.0.0 * @api enums */ - Outputs = (1 << 6), - /** + Outputs = (1 << 6), + /** * Subscription value to receive events in the `SceneItems` category. * * @enumIdentifier SceneItems @@ -119,8 +119,8 @@ namespace EventSubscription { * @initialVersion 5.0.0 * @api enums */ - SceneItems = (1 << 7), - /** + SceneItems = (1 << 7), + /** * Subscription value to receive events in the `MediaInputs` category. * * @enumIdentifier MediaInputs @@ -130,8 +130,8 @@ namespace EventSubscription { * @initialVersion 5.0.0 * @api enums */ - MediaInputs = (1 << 8), - /** + MediaInputs = (1 << 8), + /** * Subscription value to receive the `VendorEvent` event. * * @enumIdentifier Vendors @@ -141,8 +141,8 @@ namespace EventSubscription { * @initialVersion 5.0.0 * @api enums */ - Vendors = (1 << 9), - /** + Vendors = (1 << 9), + /** * Subscription value to receive events in the `Ui` category. * * @enumIdentifier Ui @@ -152,8 +152,8 @@ namespace EventSubscription { * @initialVersion 5.0.0 * @api enums */ - Ui = (1 << 10), - /** + Ui = (1 << 10), + /** * Helper to receive all non-high-volume events. * * @enumIdentifier All @@ -163,8 +163,9 @@ namespace EventSubscription { * @initialVersion 5.0.0 * @api enums */ - All = (General | Config | Scenes | Inputs | Transitions | Filters | Outputs | SceneItems | MediaInputs | Ui | Vendors), - /** + All = (General | Config | Scenes | Inputs | Transitions | Filters | + Outputs | SceneItems | MediaInputs | Ui | Vendors), + /** * Subscription value to receive the `InputVolumeMeters` high-volume event. * * @enumIdentifier InputVolumeMeters @@ -174,8 +175,8 @@ namespace EventSubscription { * @initialVersion 5.0.0 * @api enums */ - InputVolumeMeters = (1 << 16), - /** + InputVolumeMeters = (1 << 16), + /** * Subscription value to receive the `InputActiveStateChanged` high-volume event. * * @enumIdentifier InputActiveStateChanged @@ -185,8 +186,8 @@ namespace EventSubscription { * @initialVersion 5.0.0 * @api enums */ - InputActiveStateChanged = (1 << 17), - /** + InputActiveStateChanged = (1 << 17), + /** * Subscription value to receive the `InputShowStateChanged` high-volume event. * * @enumIdentifier InputShowStateChanged @@ -196,8 +197,8 @@ namespace EventSubscription { * @initialVersion 5.0.0 * @api enums */ - InputShowStateChanged = (1 << 18), - /** + InputShowStateChanged = (1 << 18), + /** * Subscription value to receive the `SceneItemTransformChanged` high-volume event. * * @enumIdentifier SceneItemTransformChanged @@ -207,6 +208,6 @@ namespace EventSubscription { * @initialVersion 5.0.0 * @api enums */ - SceneItemTransformChanged = (1 << 19), - }; + SceneItemTransformChanged = (1 << 19), +}; } diff --git a/src/forms/ConnectInfo.cpp b/src/forms/ConnectInfo.cpp index 1d2317f2..9a65f0b2 100644 --- a/src/forms/ConnectInfo.cpp +++ b/src/forms/ConnectInfo.cpp @@ -28,18 +28,17 @@ with this program. If not, see #include "../Config.h" #include "../utils/Platform.h" -ConnectInfo::ConnectInfo(QWidget* parent) : - QDialog(parent, Qt::Dialog), - ui(new Ui::ConnectInfo) +ConnectInfo::ConnectInfo(QWidget *parent) + : QDialog(parent, Qt::Dialog), ui(new Ui::ConnectInfo) { ui->setupUi(this); - connect(ui->copyServerIpButton, &QPushButton::clicked, - this, &ConnectInfo::CopyServerIpButtonClicked); - connect(ui->copyServerPortButton, &QPushButton::clicked, - this, &ConnectInfo::CopyServerPortButtonClicked); - connect(ui->copyServerPasswordButton, &QPushButton::clicked, - this, &ConnectInfo::CopyServerPasswordButtonClicked); + connect(ui->copyServerIpButton, &QPushButton::clicked, this, + &ConnectInfo::CopyServerIpButtonClicked); + connect(ui->copyServerPortButton, &QPushButton::clicked, this, + &ConnectInfo::CopyServerPortButtonClicked); + connect(ui->copyServerPasswordButton, &QPushButton::clicked, this, + &ConnectInfo::CopyServerPasswordButtonClicked); } ConnectInfo::~ConnectInfo() @@ -56,11 +55,13 @@ void ConnectInfo::RefreshData() { auto conf = GetConfig(); if (!conf) { - blog(LOG_ERROR, "[ConnectInfo::showEvent] Unable to retreive config!"); + blog(LOG_ERROR, + "[ConnectInfo::showEvent] Unable to retreive config!"); return; } - QString serverIp = QString::fromStdString(Utils::Platform::GetLocalAddress()); + QString serverIp = + QString::fromStdString(Utils::Platform::GetLocalAddress()); ui->serverIpLineEdit->setText(serverIp); QString serverPort = QString::number(conf->ServerPort); @@ -72,15 +73,20 @@ void ConnectInfo::RefreshData() serverPassword = QUrl::toPercentEncoding(conf->ServerPassword); } else { ui->copyServerPasswordButton->setEnabled(false); - serverPassword = obs_module_text("OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText"); + serverPassword = obs_module_text( + "OBSWebSocket.ConnectInfo.ServerPasswordPlaceholderText"); } ui->serverPasswordLineEdit->setText(serverPassword); QString connectString; if (conf->AuthRequired) - connectString = QString("obsws://%1:%2/%3").arg(serverIp).arg(serverPort).arg(serverPassword); + connectString = QString("obsws://%1:%2/%3") + .arg(serverIp) + .arg(serverPort) + .arg(serverPassword); else - connectString = QString("obsws://%1:%2").arg(serverIp).arg(serverPort); + connectString = + QString("obsws://%1:%2").arg(serverIp).arg(serverPort); DrawQr(connectString); } @@ -113,14 +119,15 @@ void ConnectInfo::DrawQr(QString qrText) QPixmap map(230, 230); map.fill(Qt::white); QPainter painter(&map); - - qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText(QT_TO_UTF8(qrText), qrcodegen::QrCode::Ecc::MEDIUM); + + qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText( + QT_TO_UTF8(qrText), qrcodegen::QrCode::Ecc::MEDIUM); const int s = qr.getSize() > 0 ? qr.getSize() : 1; const double w = map.width(); const double h = map.height(); - const double aspect = w/h; + const double aspect = w / h; const double size = ((aspect > 1.0) ? h : w); - const double scale = size / (s+2); + const double scale = size / (s + 2); painter.setPen(Qt::NoPen); painter.setBrush(Qt::black); diff --git a/src/forms/ConnectInfo.h b/src/forms/ConnectInfo.h index 4e0d7a69..b1e13df3 100644 --- a/src/forms/ConnectInfo.h +++ b/src/forms/ConnectInfo.h @@ -25,12 +25,11 @@ with this program. If not, see #include "ui_ConnectInfo.h" -class ConnectInfo : public QDialog -{ +class ConnectInfo : public QDialog { Q_OBJECT public: - explicit ConnectInfo(QWidget* parent = 0); + explicit ConnectInfo(QWidget *parent = 0); ~ConnectInfo(); void showEvent(QShowEvent *event); void RefreshData(); diff --git a/src/forms/SettingsDialog.cpp b/src/forms/SettingsDialog.cpp index bbc9067e..79365db5 100644 --- a/src/forms/SettingsDialog.cpp +++ b/src/forms/SettingsDialog.cpp @@ -32,20 +32,23 @@ with this program. If not, see QString GetToolTipIconHtml() { bool lightTheme = QApplication::palette().text().color().redF() < 0.5; - QString iconFile = lightTheme ? ":toolTip/images/help.svg" : ":toolTip/images/help_light.svg"; - QString iconTemplate = " "; + QString iconFile = lightTheme ? ":toolTip/images/help.svg" + : ":toolTip/images/help_light.svg"; + QString iconTemplate = + " "; return iconTemplate.arg(iconFile); } -SettingsDialog::SettingsDialog(QWidget* parent) : - QDialog(parent, Qt::Dialog), - ui(new Ui::SettingsDialog), - connectInfo(new ConnectInfo), - sessionTableTimer(new QTimer), - passwordManuallyEdited(false) +SettingsDialog::SettingsDialog(QWidget *parent) + : QDialog(parent, Qt::Dialog), + ui(new Ui::SettingsDialog), + connectInfo(new ConnectInfo), + sessionTableTimer(new QTimer), + passwordManuallyEdited(false) { ui->setupUi(this); - ui->websocketSessionTable->horizontalHeader()->resizeSection(3, 100); // Resize Session Table column widths + ui->websocketSessionTable->horizontalHeader()->resizeSection( + 3, 100); // Resize Session Table column widths ui->websocketSessionTable->horizontalHeader()->resizeSection(4, 100); // Remove the ? button on dialogs on Windows @@ -56,18 +59,18 @@ SettingsDialog::SettingsDialog(QWidget* parent) : ui->enableDebugLoggingToolTipLabel->setText(toolTipHtml); ui->allowExternalToolTipLabel->setText(toolTipHtml); - connect(sessionTableTimer, &QTimer::timeout, - this, &SettingsDialog::FillSessionTable); - connect(ui->buttonBox, &QDialogButtonBox::clicked, - this, &SettingsDialog::DialogButtonClicked); + connect(sessionTableTimer, &QTimer::timeout, this, + &SettingsDialog::FillSessionTable); + connect(ui->buttonBox, &QDialogButtonBox::clicked, this, + &SettingsDialog::DialogButtonClicked); connect(ui->enableAuthenticationCheckBox, &QCheckBox::stateChanged, this, &SettingsDialog::EnableAuthenticationCheckBoxChanged); - connect(ui->generatePasswordButton, &QPushButton::clicked, - this, &SettingsDialog::GeneratePasswordButtonClicked); - connect(ui->showConnectInfoButton, &QPushButton::clicked, - this, &SettingsDialog::ShowConnectInfoButtonClicked); - connect(ui->serverPasswordLineEdit, &QLineEdit::textEdited, - this, &SettingsDialog::PasswordEdited); + connect(ui->generatePasswordButton, &QPushButton::clicked, this, + &SettingsDialog::GeneratePasswordButtonClicked); + connect(ui->showConnectInfoButton, &QPushButton::clicked, this, + &SettingsDialog::ShowConnectInfoButtonClicked); + connect(ui->serverPasswordLineEdit, &QLineEdit::textEdited, this, + &SettingsDialog::PasswordEdited); } SettingsDialog::~SettingsDialog() @@ -81,7 +84,8 @@ void SettingsDialog::showEvent(QShowEvent *) { auto conf = GetConfig(); if (!conf) { - blog(LOG_ERROR, "[SettingsDialog::showEvent] Unable to retreive config!"); + blog(LOG_ERROR, + "[SettingsDialog::showEvent] Unable to retreive config!"); return; } @@ -121,7 +125,8 @@ void SettingsDialog::RefreshData() { auto conf = GetConfig(); if (!conf) { - blog(LOG_ERROR, "[SettingsDialog::RefreshData] Unable to retreive config!"); + blog(LOG_ERROR, + "[SettingsDialog::RefreshData] Unable to retreive config!"); return; } @@ -137,7 +142,11 @@ void SettingsDialog::RefreshData() ui->serverPasswordLineEdit->setEnabled(conf->AuthRequired); ui->generatePasswordButton->setEnabled(conf->AuthRequired); - ui->showConnectInfoButton->setToolTip(ui->allowExternalCheckBox->isChecked() ? "" : obs_module_text("OBSWebSocket.Settings.ShowConnectInfoHoverText")); + ui->showConnectInfoButton->setToolTip( + ui->allowExternalCheckBox->isChecked() + ? "" + : obs_module_text( + "OBSWebSocket.Settings.ShowConnectInfoHoverText")); FillSessionTable(); } @@ -155,43 +164,55 @@ void SettingsDialog::SaveFormData() { auto conf = GetConfig(); if (!conf) { - blog(LOG_ERROR, "[SettingsDialog::SaveFormData] Unable to retreive config!"); + blog(LOG_ERROR, + "[SettingsDialog::SaveFormData] Unable to retreive config!"); return; } if (ui->serverPasswordLineEdit->text().length() < 6) { QMessageBox msgBox; - msgBox.setWindowTitle(obs_module_text("OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle")); - msgBox.setText(obs_module_text("OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage")); + msgBox.setWindowTitle(obs_module_text( + "OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle")); + msgBox.setText(obs_module_text( + "OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage")); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.exec(); return; } // Show a confirmation box to the user if they attempt to provide their own password - if (passwordManuallyEdited && (conf->ServerPassword != ui->serverPasswordLineEdit->text())) { + if (passwordManuallyEdited && + (conf->ServerPassword != ui->serverPasswordLineEdit->text())) { QMessageBox msgBox; - msgBox.setWindowTitle(obs_module_text("OBSWebSocket.Settings.Save.UserPasswordWarningTitle")); - msgBox.setText(obs_module_text("OBSWebSocket.Settings.Save.UserPasswordWarningMessage")); - msgBox.setInformativeText(obs_module_text("OBSWebSocket.Settings.Save.UserPasswordWarningInfoText")); + msgBox.setWindowTitle(obs_module_text( + "OBSWebSocket.Settings.Save.UserPasswordWarningTitle")); + msgBox.setText(obs_module_text( + "OBSWebSocket.Settings.Save.UserPasswordWarningMessage")); + msgBox.setInformativeText(obs_module_text( + "OBSWebSocket.Settings.Save.UserPasswordWarningInfoText")); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No); int ret = msgBox.exec(); switch (ret) { - case QMessageBox::Yes: - break; - case QMessageBox::No: - default: - ui->serverPasswordLineEdit->setText(conf->ServerPassword); - return; + case QMessageBox::Yes: + break; + case QMessageBox::No: + default: + ui->serverPasswordLineEdit->setText( + conf->ServerPassword); + return; } } - bool needsRestart = (conf->ServerEnabled != ui->enableWebSocketServerCheckBox->isChecked()) || - (ui->enableAuthenticationCheckBox->isChecked() && conf->ServerPassword != ui->serverPasswordLineEdit->text()) || - (conf->BindLoopback == ui->allowExternalCheckBox->isChecked()) || - (conf->ServerPort != ui->serverPortSpinBox->value()); + bool needsRestart = + (conf->ServerEnabled != + ui->enableWebSocketServerCheckBox->isChecked()) || + (ui->enableAuthenticationCheckBox->isChecked() && + conf->ServerPassword != ui->serverPasswordLineEdit->text()) || + (conf->BindLoopback == + ui->allowExternalCheckBox->isChecked()) || + (conf->ServerPort != ui->serverPortSpinBox->value()); conf->ServerEnabled = ui->enableWebSocketServerCheckBox->isChecked(); conf->AlertsEnabled = ui->enableSystemTrayAlertsCheckBox->isChecked(); @@ -207,7 +228,8 @@ void SettingsDialog::SaveFormData() connectInfo->RefreshData(); if (needsRestart) { - blog(LOG_INFO, "[SettingsDialog::SaveFormData] A setting was changed which requires a server restart."); + blog(LOG_INFO, + "[SettingsDialog::SaveFormData] A setting was changed which requires a server restart."); auto server = GetWebSocketServer(); server->Stop(); if (conf->ServerEnabled) { @@ -220,7 +242,8 @@ void SettingsDialog::FillSessionTable() { auto webSocketServer = GetWebSocketServer(); if (!webSocketServer) { - blog(LOG_ERROR, "[SettingsDialog::FillSessionTable] Unable to fetch websocket server instance!"); + blog(LOG_ERROR, + "[SettingsDialog::FillSessionTable] Unable to fetch websocket server instance!"); return; } @@ -234,19 +257,26 @@ void SettingsDialog::FillSessionTable() QPixmap crossIconPixmap = crossIcon.pixmap(QSize(25, 25)); // Todo: Make a util for translations so that we don't need to import a bunch of obs libraries in order to use them. - QString kickButtonText = obs_module_text("OBSWebSocket.SessionTable.KickButtonText"); + QString kickButtonText = + obs_module_text("OBSWebSocket.SessionTable.KickButtonText"); ui->websocketSessionTable->setRowCount(rowCount); size_t i = 0; for (auto session : webSocketSessions) { - QTableWidgetItem *addressItem = new QTableWidgetItem(QString::fromStdString(session.remoteAddress)); + QTableWidgetItem *addressItem = new QTableWidgetItem( + QString::fromStdString(session.remoteAddress)); ui->websocketSessionTable->setItem(i, 0, addressItem); - uint64_t sessionDuration = QDateTime::currentSecsSinceEpoch() - session.connectedAt; - QTableWidgetItem *durationItem = new QTableWidgetItem(QTime(0, 0, sessionDuration).toString("hh:mm:ss")); + uint64_t sessionDuration = QDateTime::currentSecsSinceEpoch() - + session.connectedAt; + QTableWidgetItem *durationItem = new QTableWidgetItem( + QTime(0, 0, sessionDuration).toString("hh:mm:ss")); ui->websocketSessionTable->setItem(i, 1, durationItem); - QTableWidgetItem *statsItem = new QTableWidgetItem(QString("%1/%2").arg(session.incomingMessages).arg(session.outgoingMessages)); + QTableWidgetItem *statsItem = new QTableWidgetItem( + QString("%1/%2") + .arg(session.incomingMessages) + .arg(session.outgoingMessages)); ui->websocketSessionTable->setItem(i, 2, statsItem); QLabel *identifiedLabel = new QLabel(); @@ -258,14 +288,17 @@ void SettingsDialog::FillSessionTable() } ui->websocketSessionTable->setCellWidget(i, 3, identifiedLabel); - QPushButton *invalidateButton = new QPushButton(kickButtonText, this); + QPushButton *invalidateButton = + new QPushButton(kickButtonText, this); QWidget *invalidateButtonWidget = new QWidget(); - QHBoxLayout *invalidateButtonLayout = new QHBoxLayout(invalidateButtonWidget); + QHBoxLayout *invalidateButtonLayout = + new QHBoxLayout(invalidateButtonWidget); invalidateButtonLayout->addWidget(invalidateButton); invalidateButtonLayout->setAlignment(Qt::AlignCenter); invalidateButtonLayout->setContentsMargins(0, 0, 0, 0); invalidateButtonWidget->setLayout(invalidateButtonLayout); - ui->websocketSessionTable->setCellWidget(i, 4, invalidateButtonWidget); + ui->websocketSessionTable->setCellWidget( + i, 4, invalidateButtonWidget); connect(invalidateButton, &QPushButton::clicked, [=]() { webSocketServer->InvalidateSession(session.hdl); }); @@ -287,7 +320,8 @@ void SettingsDialog::EnableAuthenticationCheckBoxChanged() void SettingsDialog::GeneratePasswordButtonClicked() { - QString newPassword = QString::fromStdString(Utils::Crypto::GeneratePassword()); + QString newPassword = + QString::fromStdString(Utils::Crypto::GeneratePassword()); ui->serverPasswordLineEdit->setText(newPassword); ui->serverPasswordLineEdit->selectAll(); passwordManuallyEdited = false; @@ -297,19 +331,22 @@ void SettingsDialog::ShowConnectInfoButtonClicked() { if (obs_video_active()) { QMessageBox msgBox; - msgBox.setWindowTitle(obs_module_text("OBSWebSocket.Settings.ShowConnectInfoWarningTitle")); - msgBox.setText(obs_module_text("OBSWebSocket.Settings.ShowConnectInfoWarningMessage")); - msgBox.setInformativeText(obs_module_text("OBSWebSocket.Settings.ShowConnectInfoWarningInfoText")); + msgBox.setWindowTitle(obs_module_text( + "OBSWebSocket.Settings.ShowConnectInfoWarningTitle")); + msgBox.setText(obs_module_text( + "OBSWebSocket.Settings.ShowConnectInfoWarningMessage")); + msgBox.setInformativeText(obs_module_text( + "OBSWebSocket.Settings.ShowConnectInfoWarningInfoText")); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No); int ret = msgBox.exec(); switch (ret) { - case QMessageBox::Yes: - break; - case QMessageBox::No: - default: - return; + case QMessageBox::Yes: + break; + case QMessageBox::No: + default: + return; } } diff --git a/src/forms/SettingsDialog.h b/src/forms/SettingsDialog.h index deb008cc..398a801a 100644 --- a/src/forms/SettingsDialog.h +++ b/src/forms/SettingsDialog.h @@ -27,12 +27,11 @@ with this program. If not, see #include "ui_SettingsDialog.h" -class SettingsDialog : public QDialog -{ +class SettingsDialog : public QDialog { Q_OBJECT public: - explicit SettingsDialog(QWidget* parent = 0); + explicit SettingsDialog(QWidget *parent = 0); ~SettingsDialog(); void showEvent(QShowEvent *event); void hideEvent(QHideEvent *event); diff --git a/src/obs-websocket.cpp b/src/obs-websocket.cpp index 3be079da..160bb379 100644 --- a/src/obs-websocket.cpp +++ b/src/obs-websocket.cpp @@ -32,23 +32,35 @@ with this program. If not, see OBS_DECLARE_MODULE() OBS_MODULE_USE_DEFAULT_LOCALE("obs-websocket", "en-US") OBS_MODULE_AUTHOR("OBSProject") -const char *obs_module_name(void) { return "obs-websocket"; } -const char *obs_module_description(void) { return obs_module_text("OBSWebSocket.Plugin.Description"); } +const char *obs_module_name(void) +{ + return "obs-websocket"; +} +const char *obs_module_description(void) +{ + return obs_module_text("OBSWebSocket.Plugin.Description"); +} -os_cpu_usage_info_t* _cpuUsageInfo; +os_cpu_usage_info_t *_cpuUsageInfo; ConfigPtr _config; EventHandlerPtr _eventHandler; WebSocketApiPtr _webSocketApi; WebSocketServerPtr _webSocketServer; SettingsDialog *_settingsDialog = nullptr; -void WebSocketApiEventCallback(std::string vendorName, std::string eventType, obs_data_t *obsEventData); +void WebSocketApiEventCallback(std::string vendorName, std::string eventType, + obs_data_t *obsEventData); bool obs_module_load(void) { - blog(LOG_INFO, "[obs_module_load] you can haz websockets (Version: %s | RPC Version: %d)", OBS_WEBSOCKET_VERSION, OBS_WEBSOCKET_RPC_VERSION); - blog(LOG_INFO, "[obs_module_load] Qt version (compile-time): %s | Qt version (run-time): %s", QT_VERSION_STR, qVersion()); - blog(LOG_INFO, "[obs_module_load] Linked ASIO Version: %d", ASIO_VERSION); + blog(LOG_INFO, + "[obs_module_load] you can haz websockets (Version: %s | RPC Version: %d)", + OBS_WEBSOCKET_VERSION, OBS_WEBSOCKET_RPC_VERSION); + blog(LOG_INFO, + "[obs_module_load] Qt version (compile-time): %s | Qt version (run-time): %s", + QT_VERSION_STR, qVersion()); + blog(LOG_INFO, "[obs_module_load] Linked ASIO Version: %d", + ASIO_VERSION); // Initialize the cpu stats _cpuUsageInfo = os_cpu_usage_info_start(); @@ -69,14 +81,18 @@ bool obs_module_load(void) // Initialize the settings dialog obs_frontend_push_ui_translation(obs_module_get_string); - QMainWindow* mainWindow = static_cast(obs_frontend_get_main_window()); + QMainWindow *mainWindow = + static_cast(obs_frontend_get_main_window()); _settingsDialog = new SettingsDialog(mainWindow); obs_frontend_pop_ui_translation(); // Add the settings dialog to the tools menu - const char* menuActionText = obs_module_text("OBSWebSocket.Settings.DialogTitle"); - QAction* menuAction = (QAction*)obs_frontend_add_tools_menu_qaction(menuActionText); - QObject::connect(menuAction, &QAction::triggered, [] { _settingsDialog->ToggleShowHide(); }); + const char *menuActionText = + obs_module_text("OBSWebSocket.Settings.DialogTitle"); + QAction *menuAction = + (QAction *)obs_frontend_add_tools_menu_qaction(menuActionText); + QObject::connect(menuAction, &QAction::triggered, + [] { _settingsDialog->ToggleShowHide(); }); blog(LOG_INFO, "[obs_module_load] Module loaded."); return true; @@ -88,7 +104,8 @@ void obs_module_unload() // Shutdown the WebSocket server if it is running if (_webSocketServer->IsListening()) { - blog_debug("[obs_module_unload] WebSocket server is running. Stopping..."); + blog_debug( + "[obs_module_unload] WebSocket server is running. Stopping..."); _webSocketServer->Stop(); } @@ -111,7 +128,7 @@ void obs_module_unload() blog(LOG_INFO, "[obs_module_unload] Finished shutting down."); } -os_cpu_usage_info_t* GetCpuUsageInfo() +os_cpu_usage_info_t *GetCpuUsageInfo() { return _cpuUsageInfo; } @@ -159,7 +176,8 @@ bool IsDebugEnabled() * @api events * @category general */ -void WebSocketApiEventCallback(std::string vendorName, std::string eventType, obs_data_t *obsEventData) +void WebSocketApiEventCallback(std::string vendorName, std::string eventType, + obs_data_t *obsEventData) { json eventData = Utils::Json::ObsDataToJson(obsEventData); @@ -168,16 +186,19 @@ void WebSocketApiEventCallback(std::string vendorName, std::string eventType, ob broadcastEventData["eventType"] = eventType; broadcastEventData["eventData"] = eventData; - _webSocketServer->BroadcastEvent(EventSubscription::Vendors, "VendorEvent", broadcastEventData); + _webSocketServer->BroadcastEvent(EventSubscription::Vendors, + "VendorEvent", broadcastEventData); } #ifdef PLUGIN_TESTS -static void test_vendor_request_cb(obs_data_t *requestData, obs_data_t *responseData, void *priv_data) +static void test_vendor_request_cb(obs_data_t *requestData, + obs_data_t *responseData, void *priv_data) { blog(LOG_INFO, "[test_vendor_request_cb] Request called!"); - blog(LOG_INFO, "[test_vendor_request_cb] Request data: %s", obs_data_get_json(requestData)); + blog(LOG_INFO, "[test_vendor_request_cb] Request data: %s", + obs_data_get_json(requestData)); // Set an item to the response data obs_data_set_string(responseData, "test", "pp"); @@ -192,25 +213,34 @@ void obs_module_post_load() // Test plugin API version fetch uint apiVersion = obs_websocket_get_api_version(); - blog(LOG_INFO, "[obs_module_post_load] obs-websocket plugin API version: %u", apiVersion); + blog(LOG_INFO, + "[obs_module_post_load] obs-websocket plugin API version: %u", + apiVersion); // Test calling obs-websocket requests - struct obs_websocket_request_response *response = obs_websocket_call_request("GetVersion"); + struct obs_websocket_request_response *response = + obs_websocket_call_request("GetVersion"); if (response) { - blog(LOG_INFO, "[obs_module_post_load] Called GetVersion. Status Code: %u | Comment: %s | Response Data: %s", response->status_code, response->comment, response->response_data); + blog(LOG_INFO, + "[obs_module_post_load] Called GetVersion. Status Code: %u | Comment: %s | Response Data: %s", + response->status_code, response->comment, + response->response_data); obs_websocket_request_response_free(response); } // Test vendor creation auto vendor = obs_websocket_register_vendor("obs-websocket-test"); if (!vendor) { - blog(LOG_WARNING, "[obs_module_post_load] Failed to create vendor!"); + blog(LOG_WARNING, + "[obs_module_post_load] Failed to create vendor!"); return; } // Test vendor request registration - if (!obs_websocket_vendor_register_request(vendor, "TestRequest", test_vendor_request_cb, vendor)) { - blog(LOG_WARNING, "[obs_module_post_load] Failed to register vendor request!"); + if (!obs_websocket_vendor_register_request( + vendor, "TestRequest", test_vendor_request_cb, vendor)) { + blog(LOG_WARNING, + "[obs_module_post_load] Failed to register vendor request!"); return; } diff --git a/src/obs-websocket.h b/src/obs-websocket.h index bec761be..500d51e4 100644 --- a/src/obs-websocket.h +++ b/src/obs-websocket.h @@ -38,7 +38,7 @@ typedef std::shared_ptr WebSocketApiPtr; class WebSocketServer; typedef std::shared_ptr WebSocketServerPtr; -os_cpu_usage_info_t* GetCpuUsageInfo(); +os_cpu_usage_info_t *GetCpuUsageInfo(); ConfigPtr GetConfig(); diff --git a/src/requesthandler/RequestBatchHandler.cpp b/src/requesthandler/RequestBatchHandler.cpp index 4d3f3383..8e638982 100644 --- a/src/requesthandler/RequestBatchHandler.cpp +++ b/src/requesthandler/RequestBatchHandler.cpp @@ -24,8 +24,7 @@ with this program. If not, see #include "../utils/Compat.h" #include "../obs-websocket.h" -struct SerialFrameBatch -{ +struct SerialFrameBatch { RequestHandler &requestHandler; std::queue requests; std::vector results; @@ -37,43 +36,51 @@ struct SerialFrameBatch std::mutex conditionMutex; std::condition_variable condition; - SerialFrameBatch(RequestHandler &requestHandler, json &variables, bool haltOnFailure) : - requestHandler(requestHandler), - variables(variables), - haltOnFailure(haltOnFailure), - frameCount(0), - sleepUntilFrame(0) - {} + SerialFrameBatch(RequestHandler &requestHandler, json &variables, + bool haltOnFailure) + : requestHandler(requestHandler), + variables(variables), + haltOnFailure(haltOnFailure), + frameCount(0), + sleepUntilFrame(0) + { + } }; -struct ParallelBatchResults -{ +struct ParallelBatchResults { RequestHandler &requestHandler; std::vector results; std::mutex conditionMutex; std::condition_variable condition; - ParallelBatchResults(RequestHandler &requestHandler) : - requestHandler(requestHandler) - {} + ParallelBatchResults(RequestHandler &requestHandler) + : requestHandler(requestHandler) + { + } }; // `{"inputName": "inputNameVariable"}` is essentially `inputName = inputNameVariable` -static void PreProcessVariables(const json &variables, RequestBatchRequest &request) +static void PreProcessVariables(const json &variables, + RequestBatchRequest &request) { - if (variables.empty() || !request.InputVariables.is_object() || request.InputVariables.empty() || !request.RequestData.is_object()) + if (variables.empty() || !request.InputVariables.is_object() || + request.InputVariables.empty() || !request.RequestData.is_object()) return; - for (auto& [key, value] : request.InputVariables.items()) { + for (auto &[key, value] : request.InputVariables.items()) { if (!value.is_string()) { - blog_debug("[WebSocketServer::ProcessRequestBatch] Value of field `%s` in `inputVariables `is not a string. Skipping!", key.c_str()); + blog_debug( + "[WebSocketServer::ProcessRequestBatch] Value of field `%s` in `inputVariables `is not a string. Skipping!", + key.c_str()); continue; } std::string valueString = value; if (!variables.contains(valueString)) { - blog_debug("[WebSocketServer::ProcessRequestBatch] `inputVariables` requested variable `%s`, but it does not exist. Skipping!", valueString.c_str()); + blog_debug( + "[WebSocketServer::ProcessRequestBatch] `inputVariables` requested variable `%s`, but it does not exist. Skipping!", + valueString.c_str()); continue; } @@ -84,20 +91,28 @@ static void PreProcessVariables(const json &variables, RequestBatchRequest &requ } // `{"sceneItemIdVariable": "sceneItemId"}` is essentially `sceneItemIdVariable = sceneItemId` -static void PostProcessVariables(json &variables, const RequestBatchRequest &request, const RequestResult &requestResult) +static void PostProcessVariables(json &variables, + const RequestBatchRequest &request, + const RequestResult &requestResult) { - if (!request.OutputVariables.is_object() || request.OutputVariables.empty() || requestResult.ResponseData.empty()) + if (!request.OutputVariables.is_object() || + request.OutputVariables.empty() || + requestResult.ResponseData.empty()) return; - for (auto& [key, value] : request.OutputVariables.items()) { + for (auto &[key, value] : request.OutputVariables.items()) { if (!value.is_string()) { - blog_debug("[WebSocketServer::ProcessRequestBatch] Value of field `%s` in `outputVariables` is not a string. Skipping!", key.c_str()); + blog_debug( + "[WebSocketServer::ProcessRequestBatch] Value of field `%s` in `outputVariables` is not a string. Skipping!", + key.c_str()); continue; } std::string valueString = value; if (!requestResult.ResponseData.contains(valueString)) { - blog_debug("[WebSocketServer::ProcessRequestBatch] `outputVariables` requested responseData field `%s`, but it does not exist. Skipping!", valueString.c_str()); + blog_debug( + "[WebSocketServer::ProcessRequestBatch] `outputVariables` requested responseData field `%s`, but it does not exist. Skipping!", + valueString.c_str()); continue; } @@ -109,13 +124,14 @@ static void ObsTickCallback(void *param, float) { ScopeProfiler prof{"obs_websocket_request_batch_frame_tick"}; - auto serialFrameBatch = static_cast(param); + auto serialFrameBatch = static_cast(param); // Increment frame count serialFrameBatch->frameCount++; if (serialFrameBatch->sleepUntilFrame) { - if (serialFrameBatch->frameCount < serialFrameBatch->sleepUntilFrame) + if (serialFrameBatch->frameCount < + serialFrameBatch->sleepUntilFrame) // Do not process any requests if in "sleep mode" return; else @@ -126,27 +142,35 @@ static void ObsTickCallback(void *param, float) // Begin recursing any unprocessed requests while (!serialFrameBatch->requests.empty()) { // Fetch first in queue - RequestBatchRequest request = serialFrameBatch->requests.front(); + RequestBatchRequest request = + serialFrameBatch->requests.front(); // Pre-process batch variables PreProcessVariables(serialFrameBatch->variables, request); // Process request and get result - RequestResult requestResult = serialFrameBatch->requestHandler.ProcessRequest(request); + RequestResult requestResult = + serialFrameBatch->requestHandler.ProcessRequest( + request); // Post-process batch variables - PostProcessVariables(serialFrameBatch->variables, request, requestResult); + PostProcessVariables(serialFrameBatch->variables, request, + requestResult); // Add to results vector serialFrameBatch->results.push_back(requestResult); // Remove from front of queue serialFrameBatch->requests.pop(); // If haltOnFailure and the request failed, clear the queue to make the batch return early. - if (serialFrameBatch->haltOnFailure && requestResult.StatusCode != RequestStatus::Success) { - serialFrameBatch->requests = std::queue(); + if (serialFrameBatch->haltOnFailure && + requestResult.StatusCode != RequestStatus::Success) { + serialFrameBatch->requests = + std::queue(); break; } // If the processed request tells us to sleep, do so accordingly if (requestResult.SleepFrames) { - serialFrameBatch->sleepUntilFrame = serialFrameBatch->frameCount + requestResult.SleepFrames; + serialFrameBatch->sleepUntilFrame = + serialFrameBatch->frameCount + + requestResult.SleepFrames; break; } } @@ -156,7 +180,11 @@ static void ObsTickCallback(void *param, float) serialFrameBatch->condition.notify_one(); } -std::vector RequestBatchHandler::ProcessRequestBatch(QThreadPool &threadPool, SessionPtr session, RequestBatchExecutionType::RequestBatchExecutionType executionType, std::vector &requests, json &variables, bool haltOnFailure) +std::vector RequestBatchHandler::ProcessRequestBatch( + QThreadPool &threadPool, SessionPtr session, + RequestBatchExecutionType::RequestBatchExecutionType executionType, + std::vector &requests, json &variables, + bool haltOnFailure) { RequestHandler requestHandler(session); if (executionType == RequestBatchExecutionType::SerialRealtime) { @@ -166,19 +194,22 @@ std::vector RequestBatchHandler::ProcessRequestBatch(QThreadPool for (auto &request : requests) { PreProcessVariables(variables, request); - RequestResult requestResult = requestHandler.ProcessRequest(request); + RequestResult requestResult = + requestHandler.ProcessRequest(request); PostProcessVariables(variables, request, requestResult); ret.push_back(requestResult); - if (haltOnFailure && requestResult.StatusCode != RequestStatus::Success) + if (haltOnFailure && + requestResult.StatusCode != RequestStatus::Success) break; } return ret; } else if (executionType == RequestBatchExecutionType::SerialFrame) { - SerialFrameBatch serialFrameBatch(requestHandler, variables, haltOnFailure); + SerialFrameBatch serialFrameBatch(requestHandler, variables, + haltOnFailure); // Create Request objects in the worker thread (avoid unnecessary processing in graphics thread) for (auto &request : requests) @@ -188,8 +219,11 @@ std::vector RequestBatchHandler::ProcessRequestBatch(QThreadPool obs_add_tick_callback(ObsTickCallback, &serialFrameBatch); // Wait until the graphics thread processes the last request in the queue - std::unique_lock lock(serialFrameBatch.conditionMutex); - serialFrameBatch.condition.wait(lock, [&serialFrameBatch]{return serialFrameBatch.requests.empty();}); + std::unique_lock lock( + serialFrameBatch.conditionMutex); + serialFrameBatch.condition.wait(lock, [&serialFrameBatch] { + return serialFrameBatch.requests.empty(); + }); // Remove the created callback entry since we don't need it anymore obs_remove_tick_callback(ObsTickCallback, &serialFrameBatch); @@ -199,23 +233,33 @@ std::vector RequestBatchHandler::ProcessRequestBatch(QThreadPool ParallelBatchResults parallelResults(requestHandler); // Acquire the lock early to prevent the batch from finishing before we're ready - std::unique_lock lock(parallelResults.conditionMutex); + std::unique_lock lock( + parallelResults.conditionMutex); // Submit each request as a task to the thread pool to be processed ASAP for (auto &request : requests) { - threadPool.start(Utils::Compat::CreateFunctionRunnable([¶llelResults, &request]() { - RequestResult requestResult = parallelResults.requestHandler.ProcessRequest(request); + threadPool.start(Utils::Compat::CreateFunctionRunnable( + [¶llelResults, &request]() { + RequestResult requestResult = + parallelResults.requestHandler + .ProcessRequest( + request); - std::unique_lock lock(parallelResults.conditionMutex); - parallelResults.results.push_back(requestResult); - lock.unlock(); - parallelResults.condition.notify_one(); - })); + std::unique_lock lock( + parallelResults.conditionMutex); + parallelResults.results.push_back( + requestResult); + lock.unlock(); + parallelResults.condition.notify_one(); + })); } // Wait for the last request to finish processing size_t requestCount = requests.size(); - parallelResults.condition.wait(lock, [¶llelResults, requestCount]{return parallelResults.results.size() == requestCount;}); + parallelResults.condition.wait(lock, [¶llelResults, + requestCount] { + return parallelResults.results.size() == requestCount; + }); return parallelResults.results; } diff --git a/src/requesthandler/RequestBatchHandler.h b/src/requesthandler/RequestBatchHandler.h index aa5d0574..6f3c36d6 100644 --- a/src/requesthandler/RequestBatchHandler.h +++ b/src/requesthandler/RequestBatchHandler.h @@ -24,5 +24,9 @@ with this program. If not, see #include "rpc/RequestBatchRequest.h" namespace RequestBatchHandler { - std::vector ProcessRequestBatch(QThreadPool &threadPool, SessionPtr session, RequestBatchExecutionType::RequestBatchExecutionType executionType, std::vector &requests, json &variables, bool haltOnFailure); +std::vector ProcessRequestBatch( + QThreadPool &threadPool, SessionPtr session, + RequestBatchExecutionType::RequestBatchExecutionType executionType, + std::vector &requests, json &variables, + bool haltOnFailure); } diff --git a/src/requesthandler/RequestHandler.cpp b/src/requesthandler/RequestHandler.cpp index 19f9a79a..e8a91ef3 100644 --- a/src/requesthandler/RequestHandler.cpp +++ b/src/requesthandler/RequestHandler.cpp @@ -23,8 +23,7 @@ with this program. If not, see #include "RequestHandler.h" -const std::unordered_map RequestHandler::_handlerMap -{ +const std::unordered_map RequestHandler::_handlerMap{ // General {"GetVersion", &RequestHandler::GetVersion}, {"GetStats", &RequestHandler::GetStats}, @@ -32,14 +31,16 @@ const std::unordered_map RequestHandler::_han {"CallVendorRequest", &RequestHandler::CallVendorRequest}, {"GetHotkeyList", &RequestHandler::GetHotkeyList}, {"TriggerHotkeyByName", &RequestHandler::TriggerHotkeyByName}, - {"TriggerHotkeyByKeySequence", &RequestHandler::TriggerHotkeyByKeySequence}, + {"TriggerHotkeyByKeySequence", + &RequestHandler::TriggerHotkeyByKeySequence}, {"Sleep", &RequestHandler::Sleep}, // Config {"GetPersistentData", &RequestHandler::GetPersistentData}, {"SetPersistentData", &RequestHandler::SetPersistentData}, {"GetSceneCollectionList", &RequestHandler::GetSceneCollectionList}, - {"SetCurrentSceneCollection", &RequestHandler::SetCurrentSceneCollection}, + {"SetCurrentSceneCollection", + &RequestHandler::SetCurrentSceneCollection}, {"CreateSceneCollection", &RequestHandler::CreateSceneCollection}, {"GetProfileList", &RequestHandler::GetProfileList}, {"SetCurrentProfile", &RequestHandler::SetCurrentProfile}, @@ -70,8 +71,10 @@ const std::unordered_map RequestHandler::_han {"CreateScene", &RequestHandler::CreateScene}, {"RemoveScene", &RequestHandler::RemoveScene}, {"SetSceneName", &RequestHandler::SetSceneName}, - {"GetSceneSceneTransitionOverride", &RequestHandler::GetSceneSceneTransitionOverride}, - {"SetSceneSceneTransitionOverride", &RequestHandler::SetSceneSceneTransitionOverride}, + {"GetSceneSceneTransitionOverride", + &RequestHandler::GetSceneSceneTransitionOverride}, + {"SetSceneSceneTransitionOverride", + &RequestHandler::SetSceneSceneTransitionOverride}, // Inputs {"GetInputList", &RequestHandler::GetInputList}, @@ -96,23 +99,32 @@ const std::unordered_map RequestHandler::_han {"SetInputAudioMonitorType", &RequestHandler::SetInputAudioMonitorType}, {"GetInputAudioTracks", &RequestHandler::GetInputAudioTracks}, {"SetInputAudioTracks", &RequestHandler::SetInputAudioTracks}, - {"GetInputPropertiesListPropertyItems", &RequestHandler::GetInputPropertiesListPropertyItems}, - {"PressInputPropertiesButton", &RequestHandler::PressInputPropertiesButton}, + {"GetInputPropertiesListPropertyItems", + &RequestHandler::GetInputPropertiesListPropertyItems}, + {"PressInputPropertiesButton", + &RequestHandler::PressInputPropertiesButton}, // Transitions {"GetTransitionKindList", &RequestHandler::GetTransitionKindList}, {"GetSceneTransitionList", &RequestHandler::GetSceneTransitionList}, - {"GetCurrentSceneTransition", &RequestHandler::GetCurrentSceneTransition}, - {"SetCurrentSceneTransition", &RequestHandler::SetCurrentSceneTransition}, - {"SetCurrentSceneTransitionDuration", &RequestHandler::SetCurrentSceneTransitionDuration}, - {"SetCurrentSceneTransitionSettings", &RequestHandler::SetCurrentSceneTransitionSettings}, - {"GetCurrentSceneTransitionCursor", &RequestHandler::GetCurrentSceneTransitionCursor}, - {"TriggerStudioModeTransition", &RequestHandler::TriggerStudioModeTransition}, + {"GetCurrentSceneTransition", + &RequestHandler::GetCurrentSceneTransition}, + {"SetCurrentSceneTransition", + &RequestHandler::SetCurrentSceneTransition}, + {"SetCurrentSceneTransitionDuration", + &RequestHandler::SetCurrentSceneTransitionDuration}, + {"SetCurrentSceneTransitionSettings", + &RequestHandler::SetCurrentSceneTransitionSettings}, + {"GetCurrentSceneTransitionCursor", + &RequestHandler::GetCurrentSceneTransitionCursor}, + {"TriggerStudioModeTransition", + &RequestHandler::TriggerStudioModeTransition}, {"SetTBarPosition", &RequestHandler::SetTBarPosition}, // Filters {"GetSourceFilterList", &RequestHandler::GetSourceFilterList}, - {"GetSourceFilterDefaultSettings", &RequestHandler::GetSourceFilterDefaultSettings}, + {"GetSourceFilterDefaultSettings", + &RequestHandler::GetSourceFilterDefaultSettings}, {"CreateSourceFilter", &RequestHandler::CreateSourceFilter}, {"RemoveSourceFilter", &RequestHandler::RemoveSourceFilter}, {"SetSourceFilterName", &RequestHandler::SetSourceFilterName}, @@ -138,8 +150,10 @@ const std::unordered_map RequestHandler::_han {"SetSceneItemIndex", &RequestHandler::SetSceneItemIndex}, {"GetSceneItemBlendMode", &RequestHandler::GetSceneItemBlendMode}, {"SetSceneItemBlendMode", &RequestHandler::SetSceneItemBlendMode}, - {"GetSceneItemPrivateSettings", &RequestHandler::GetSceneItemPrivateSettings}, - {"SetSceneItemPrivateSettings", &RequestHandler::SetSceneItemPrivateSettings}, + {"GetSceneItemPrivateSettings", + &RequestHandler::GetSceneItemPrivateSettings}, + {"SetSceneItemPrivateSettings", + &RequestHandler::SetSceneItemPrivateSettings}, // Outputs {"GetVirtualCamStatus", &RequestHandler::GetVirtualCamStatus}, @@ -151,7 +165,8 @@ const std::unordered_map RequestHandler::_han {"StartReplayBuffer", &RequestHandler::StartReplayBuffer}, {"StopReplayBuffer", &RequestHandler::StopReplayBuffer}, {"SaveReplayBuffer", &RequestHandler::SaveReplayBuffer}, - {"GetLastReplayBufferReplay", &RequestHandler::GetLastReplayBufferReplay}, + {"GetLastReplayBufferReplay", + &RequestHandler::GetLastReplayBufferReplay}, // Stream {"GetStreamStatus", &RequestHandler::GetStreamStatus}, @@ -178,34 +193,37 @@ const std::unordered_map RequestHandler::_han // Ui {"GetStudioModeEnabled", &RequestHandler::GetStudioModeEnabled}, {"SetStudioModeEnabled", &RequestHandler::SetStudioModeEnabled}, - {"OpenInputPropertiesDialog", &RequestHandler::OpenInputPropertiesDialog}, + {"OpenInputPropertiesDialog", + &RequestHandler::OpenInputPropertiesDialog}, {"OpenInputFiltersDialog", &RequestHandler::OpenInputFiltersDialog}, {"OpenInputInteractDialog", &RequestHandler::OpenInputInteractDialog}, {"GetMonitorList", &RequestHandler::GetMonitorList}, }; -RequestHandler::RequestHandler(SessionPtr session) : - _session(session) -{ -} +RequestHandler::RequestHandler(SessionPtr session) : _session(session) {} -RequestResult RequestHandler::ProcessRequest(const Request& request) +RequestResult RequestHandler::ProcessRequest(const Request &request) { #ifdef PLUGIN_TESTS ScopeProfiler prof{"obs_websocket_request_processing"}; #endif if (!request.RequestData.is_object() && !request.RequestData.is_null()) - return RequestResult::Error(RequestStatus::InvalidRequestFieldType, "Your request data is not an object."); + return RequestResult::Error( + RequestStatus::InvalidRequestFieldType, + "Your request data is not an object."); if (request.RequestType.empty()) - return RequestResult::Error(RequestStatus::MissingRequestType, "Your request is missing a `requestType`"); + return RequestResult::Error( + RequestStatus::MissingRequestType, + "Your request is missing a `requestType`"); RequestMethodHandler handler; try { handler = _handlerMap.at(request.RequestType); - } catch (const std::out_of_range& oor) { - return RequestResult::Error(RequestStatus::UnknownRequestType, "Your request type is not valid."); + } catch (const std::out_of_range &oor) { + return RequestResult::Error(RequestStatus::UnknownRequestType, + "Your request type is not valid."); } return std::bind(handler, this, std::placeholders::_1)(request); @@ -214,7 +232,7 @@ RequestResult RequestHandler::ProcessRequest(const Request& request) std::vector RequestHandler::GetRequestList() { std::vector ret; - for (auto const& [key, val] : _handlerMap) { + for (auto const &[key, val] : _handlerMap) { ret.push_back(key); } diff --git a/src/requesthandler/RequestHandler.h b/src/requesthandler/RequestHandler.h index dc3b2a02..5f6fc315 100644 --- a/src/requesthandler/RequestHandler.h +++ b/src/requesthandler/RequestHandler.h @@ -33,174 +33,175 @@ with this program. If not, see #include "../plugin-macros.generated.h" class RequestHandler; -typedef RequestResult(RequestHandler::*RequestMethodHandler)(const Request&); +typedef RequestResult (RequestHandler::*RequestMethodHandler)(const Request &); class RequestHandler { - public: - RequestHandler(SessionPtr session = nullptr); +public: + RequestHandler(SessionPtr session = nullptr); - RequestResult ProcessRequest(const Request& request); - std::vector GetRequestList(); + RequestResult ProcessRequest(const Request &request); + std::vector GetRequestList(); - private: - // General - RequestResult GetVersion(const Request&); - RequestResult GetStats(const Request&); - RequestResult BroadcastCustomEvent(const Request&); - RequestResult CallVendorRequest(const Request&); - RequestResult GetHotkeyList(const Request&); - RequestResult TriggerHotkeyByName(const Request&); - RequestResult TriggerHotkeyByKeySequence(const Request&); - RequestResult Sleep(const Request&); +private: + // General + RequestResult GetVersion(const Request &); + RequestResult GetStats(const Request &); + RequestResult BroadcastCustomEvent(const Request &); + RequestResult CallVendorRequest(const Request &); + RequestResult GetHotkeyList(const Request &); + RequestResult TriggerHotkeyByName(const Request &); + RequestResult TriggerHotkeyByKeySequence(const Request &); + RequestResult Sleep(const Request &); - // Config - RequestResult GetPersistentData(const Request&); - RequestResult SetPersistentData(const Request&); - RequestResult GetSceneCollectionList(const Request&); - RequestResult SetCurrentSceneCollection(const Request&); - RequestResult CreateSceneCollection(const Request&); - RequestResult GetProfileList(const Request&); - RequestResult SetCurrentProfile(const Request&); - RequestResult CreateProfile(const Request&); - RequestResult RemoveProfile(const Request&); - RequestResult GetProfileParameter(const Request&); - RequestResult SetProfileParameter(const Request&); - RequestResult GetVideoSettings(const Request&); - RequestResult SetVideoSettings(const Request&); - RequestResult GetStreamServiceSettings(const Request&); - RequestResult SetStreamServiceSettings(const Request&); - RequestResult GetRecordDirectory(const Request&); + // Config + RequestResult GetPersistentData(const Request &); + RequestResult SetPersistentData(const Request &); + RequestResult GetSceneCollectionList(const Request &); + RequestResult SetCurrentSceneCollection(const Request &); + RequestResult CreateSceneCollection(const Request &); + RequestResult GetProfileList(const Request &); + RequestResult SetCurrentProfile(const Request &); + RequestResult CreateProfile(const Request &); + RequestResult RemoveProfile(const Request &); + RequestResult GetProfileParameter(const Request &); + RequestResult SetProfileParameter(const Request &); + RequestResult GetVideoSettings(const Request &); + RequestResult SetVideoSettings(const Request &); + RequestResult GetStreamServiceSettings(const Request &); + RequestResult SetStreamServiceSettings(const Request &); + RequestResult GetRecordDirectory(const Request &); - // Sources - RequestResult GetSourceActive(const Request&); - RequestResult GetSourceScreenshot(const Request&); - RequestResult SaveSourceScreenshot(const Request&); - RequestResult GetSourcePrivateSettings(const Request&); - RequestResult SetSourcePrivateSettings(const Request&); + // Sources + RequestResult GetSourceActive(const Request &); + RequestResult GetSourceScreenshot(const Request &); + RequestResult SaveSourceScreenshot(const Request &); + RequestResult GetSourcePrivateSettings(const Request &); + RequestResult SetSourcePrivateSettings(const Request &); - // Scenes - RequestResult GetSceneList(const Request&); - RequestResult GetGroupList(const Request&); - RequestResult GetCurrentProgramScene(const Request&); - RequestResult SetCurrentProgramScene(const Request&); - RequestResult GetCurrentPreviewScene(const Request&); - RequestResult SetCurrentPreviewScene(const Request&); - RequestResult CreateScene(const Request&); - RequestResult RemoveScene(const Request&); - RequestResult SetSceneName(const Request&); - RequestResult GetSceneSceneTransitionOverride(const Request&); - RequestResult SetSceneSceneTransitionOverride(const Request&); + // Scenes + RequestResult GetSceneList(const Request &); + RequestResult GetGroupList(const Request &); + RequestResult GetCurrentProgramScene(const Request &); + RequestResult SetCurrentProgramScene(const Request &); + RequestResult GetCurrentPreviewScene(const Request &); + RequestResult SetCurrentPreviewScene(const Request &); + RequestResult CreateScene(const Request &); + RequestResult RemoveScene(const Request &); + RequestResult SetSceneName(const Request &); + RequestResult GetSceneSceneTransitionOverride(const Request &); + RequestResult SetSceneSceneTransitionOverride(const Request &); - // Inputs - RequestResult GetInputList(const Request&); - RequestResult GetInputKindList(const Request&); - RequestResult GetSpecialInputs(const Request&); - RequestResult CreateInput(const Request&); - RequestResult RemoveInput(const Request&); - RequestResult SetInputName(const Request&); - RequestResult GetInputDefaultSettings(const Request&); - RequestResult GetInputSettings(const Request&); - RequestResult SetInputSettings(const Request&); - RequestResult GetInputMute(const Request&); - RequestResult SetInputMute(const Request&); - RequestResult ToggleInputMute(const Request&); - RequestResult GetInputVolume(const Request&); - RequestResult SetInputVolume(const Request&); - RequestResult GetInputAudioBalance(const Request&); - RequestResult SetInputAudioBalance(const Request&); - RequestResult GetInputAudioSyncOffset(const Request&); - RequestResult SetInputAudioSyncOffset(const Request&); - RequestResult GetInputAudioMonitorType(const Request&); - RequestResult SetInputAudioMonitorType(const Request&); - RequestResult GetInputAudioTracks(const Request&); - RequestResult SetInputAudioTracks(const Request&); - RequestResult GetInputPropertiesListPropertyItems(const Request&); - RequestResult PressInputPropertiesButton(const Request&); + // Inputs + RequestResult GetInputList(const Request &); + RequestResult GetInputKindList(const Request &); + RequestResult GetSpecialInputs(const Request &); + RequestResult CreateInput(const Request &); + RequestResult RemoveInput(const Request &); + RequestResult SetInputName(const Request &); + RequestResult GetInputDefaultSettings(const Request &); + RequestResult GetInputSettings(const Request &); + RequestResult SetInputSettings(const Request &); + RequestResult GetInputMute(const Request &); + RequestResult SetInputMute(const Request &); + RequestResult ToggleInputMute(const Request &); + RequestResult GetInputVolume(const Request &); + RequestResult SetInputVolume(const Request &); + RequestResult GetInputAudioBalance(const Request &); + RequestResult SetInputAudioBalance(const Request &); + RequestResult GetInputAudioSyncOffset(const Request &); + RequestResult SetInputAudioSyncOffset(const Request &); + RequestResult GetInputAudioMonitorType(const Request &); + RequestResult SetInputAudioMonitorType(const Request &); + RequestResult GetInputAudioTracks(const Request &); + RequestResult SetInputAudioTracks(const Request &); + RequestResult GetInputPropertiesListPropertyItems(const Request &); + RequestResult PressInputPropertiesButton(const Request &); - // Transitions - RequestResult GetTransitionKindList(const Request&); - RequestResult GetSceneTransitionList(const Request&); - RequestResult GetCurrentSceneTransition(const Request&); - RequestResult SetCurrentSceneTransition(const Request&); - RequestResult SetCurrentSceneTransitionDuration(const Request&); - RequestResult SetCurrentSceneTransitionSettings(const Request&); - RequestResult GetCurrentSceneTransitionCursor(const Request&); - RequestResult TriggerStudioModeTransition(const Request&); - RequestResult SetTBarPosition(const Request&); + // Transitions + RequestResult GetTransitionKindList(const Request &); + RequestResult GetSceneTransitionList(const Request &); + RequestResult GetCurrentSceneTransition(const Request &); + RequestResult SetCurrentSceneTransition(const Request &); + RequestResult SetCurrentSceneTransitionDuration(const Request &); + RequestResult SetCurrentSceneTransitionSettings(const Request &); + RequestResult GetCurrentSceneTransitionCursor(const Request &); + RequestResult TriggerStudioModeTransition(const Request &); + RequestResult SetTBarPosition(const Request &); - // Filters - RequestResult GetSourceFilterList(const Request&); - RequestResult GetSourceFilterDefaultSettings(const Request&); - RequestResult CreateSourceFilter(const Request&); - RequestResult RemoveSourceFilter(const Request&); - RequestResult SetSourceFilterName(const Request&); - RequestResult GetSourceFilter(const Request&); - RequestResult SetSourceFilterIndex(const Request&); - RequestResult SetSourceFilterSettings(const Request&); - RequestResult SetSourceFilterEnabled(const Request&); + // Filters + RequestResult GetSourceFilterList(const Request &); + RequestResult GetSourceFilterDefaultSettings(const Request &); + RequestResult CreateSourceFilter(const Request &); + RequestResult RemoveSourceFilter(const Request &); + RequestResult SetSourceFilterName(const Request &); + RequestResult GetSourceFilter(const Request &); + RequestResult SetSourceFilterIndex(const Request &); + RequestResult SetSourceFilterSettings(const Request &); + RequestResult SetSourceFilterEnabled(const Request &); - // Scene Items - RequestResult GetSceneItemList(const Request&); - RequestResult GetGroupSceneItemList(const Request&); - RequestResult GetSceneItemId(const Request&); - RequestResult CreateSceneItem(const Request&); - RequestResult RemoveSceneItem(const Request&); - RequestResult DuplicateSceneItem(const Request&); - RequestResult GetSceneItemTransform(const Request&); - RequestResult SetSceneItemTransform(const Request&); - RequestResult GetSceneItemEnabled(const Request&); - RequestResult SetSceneItemEnabled(const Request&); - RequestResult GetSceneItemLocked(const Request&); - RequestResult SetSceneItemLocked(const Request&); - RequestResult GetSceneItemIndex(const Request&); - RequestResult SetSceneItemIndex(const Request&); - RequestResult GetSceneItemBlendMode(const Request&); - RequestResult SetSceneItemBlendMode(const Request&); - RequestResult GetSceneItemPrivateSettings(const Request&); - RequestResult SetSceneItemPrivateSettings(const Request&); + // Scene Items + RequestResult GetSceneItemList(const Request &); + RequestResult GetGroupSceneItemList(const Request &); + RequestResult GetSceneItemId(const Request &); + RequestResult CreateSceneItem(const Request &); + RequestResult RemoveSceneItem(const Request &); + RequestResult DuplicateSceneItem(const Request &); + RequestResult GetSceneItemTransform(const Request &); + RequestResult SetSceneItemTransform(const Request &); + RequestResult GetSceneItemEnabled(const Request &); + RequestResult SetSceneItemEnabled(const Request &); + RequestResult GetSceneItemLocked(const Request &); + RequestResult SetSceneItemLocked(const Request &); + RequestResult GetSceneItemIndex(const Request &); + RequestResult SetSceneItemIndex(const Request &); + RequestResult GetSceneItemBlendMode(const Request &); + RequestResult SetSceneItemBlendMode(const Request &); + RequestResult GetSceneItemPrivateSettings(const Request &); + RequestResult SetSceneItemPrivateSettings(const Request &); - // Outputs - RequestResult GetVirtualCamStatus(const Request&); - RequestResult ToggleVirtualCam(const Request&); - RequestResult StartVirtualCam(const Request&); - RequestResult StopVirtualCam(const Request&); - RequestResult GetReplayBufferStatus(const Request&); - RequestResult ToggleReplayBuffer(const Request&); - RequestResult StartReplayBuffer(const Request&); - RequestResult StopReplayBuffer(const Request&); - RequestResult SaveReplayBuffer(const Request&); - RequestResult GetLastReplayBufferReplay(const Request&); + // Outputs + RequestResult GetVirtualCamStatus(const Request &); + RequestResult ToggleVirtualCam(const Request &); + RequestResult StartVirtualCam(const Request &); + RequestResult StopVirtualCam(const Request &); + RequestResult GetReplayBufferStatus(const Request &); + RequestResult ToggleReplayBuffer(const Request &); + RequestResult StartReplayBuffer(const Request &); + RequestResult StopReplayBuffer(const Request &); + RequestResult SaveReplayBuffer(const Request &); + RequestResult GetLastReplayBufferReplay(const Request &); - // Stream - RequestResult GetStreamStatus(const Request&); - RequestResult ToggleStream(const Request&); - RequestResult StartStream(const Request&); - RequestResult StopStream(const Request&); - RequestResult SendStreamCaption(const Request&); + // Stream + RequestResult GetStreamStatus(const Request &); + RequestResult ToggleStream(const Request &); + RequestResult StartStream(const Request &); + RequestResult StopStream(const Request &); + RequestResult SendStreamCaption(const Request &); - // Record - RequestResult GetRecordStatus(const Request&); - RequestResult ToggleRecord(const Request&); - RequestResult StartRecord(const Request&); - RequestResult StopRecord(const Request&); - RequestResult ToggleRecordPause(const Request&); - RequestResult PauseRecord(const Request&); - RequestResult ResumeRecord(const Request&); + // Record + RequestResult GetRecordStatus(const Request &); + RequestResult ToggleRecord(const Request &); + RequestResult StartRecord(const Request &); + RequestResult StopRecord(const Request &); + RequestResult ToggleRecordPause(const Request &); + RequestResult PauseRecord(const Request &); + RequestResult ResumeRecord(const Request &); - // Media Inputs - RequestResult GetMediaInputStatus(const Request&); - RequestResult SetMediaInputCursor(const Request&); - RequestResult OffsetMediaInputCursor(const Request&); - RequestResult TriggerMediaInputAction(const Request&); + // Media Inputs + RequestResult GetMediaInputStatus(const Request &); + RequestResult SetMediaInputCursor(const Request &); + RequestResult OffsetMediaInputCursor(const Request &); + RequestResult TriggerMediaInputAction(const Request &); - // Ui - RequestResult GetStudioModeEnabled(const Request&); - RequestResult SetStudioModeEnabled(const Request&); - RequestResult OpenInputPropertiesDialog(const Request&); - RequestResult OpenInputFiltersDialog(const Request&); - RequestResult OpenInputInteractDialog(const Request&); - RequestResult GetMonitorList(const Request&); + // Ui + RequestResult GetStudioModeEnabled(const Request &); + RequestResult SetStudioModeEnabled(const Request &); + RequestResult OpenInputPropertiesDialog(const Request &); + RequestResult OpenInputFiltersDialog(const Request &); + RequestResult OpenInputInteractDialog(const Request &); + RequestResult GetMonitorList(const Request &); - SessionPtr _session; - static const std::unordered_map _handlerMap; + SessionPtr _session; + static const std::unordered_map + _handlerMap; }; diff --git a/src/requesthandler/RequestHandler_Config.cpp b/src/requesthandler/RequestHandler_Config.cpp index ab3612ec..dd3ff44d 100644 --- a/src/requesthandler/RequestHandler_Config.cpp +++ b/src/requesthandler/RequestHandler_Config.cpp @@ -37,27 +37,34 @@ with this program. If not, see * @category config * @api requests */ -RequestResult RequestHandler::GetPersistentData(const Request& request) +RequestResult RequestHandler::GetPersistentData(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - if (!(request.ValidateString("realm", statusCode, comment) && request.ValidateString("slotName", statusCode, comment))) + if (!(request.ValidateString("realm", statusCode, comment) && + request.ValidateString("slotName", statusCode, comment))) return RequestResult::Error(statusCode, comment); std::string realm = request.RequestData["realm"]; std::string slotName = request.RequestData["slotName"]; - std::string persistentDataPath = Utils::Obs::StringHelper::GetCurrentProfilePath(); + std::string persistentDataPath = + Utils::Obs::StringHelper::GetCurrentProfilePath(); if (realm == "OBS_WEBSOCKET_DATA_REALM_GLOBAL") - persistentDataPath += "/../../../obsWebSocketPersistentData.json"; + persistentDataPath += + "/../../../obsWebSocketPersistentData.json"; else if (realm == "OBS_WEBSOCKET_DATA_REALM_PROFILE") persistentDataPath += "/obsWebSocketPersistentData.json"; else - return RequestResult::Error(RequestStatus::ResourceNotFound, "You have specified an invalid persistent data realm."); + return RequestResult::Error( + RequestStatus::ResourceNotFound, + "You have specified an invalid persistent data realm."); json responseData; json persistentData; - if (Utils::Json::GetJsonFileContent(persistentDataPath, persistentData) && persistentData.contains(slotName)) + if (Utils::Json::GetJsonFileContent(persistentDataPath, + persistentData) && + persistentData.contains(slotName)) responseData["slotValue"] = persistentData[slotName]; else responseData["slotValue"] = nullptr; @@ -79,30 +86,39 @@ RequestResult RequestHandler::GetPersistentData(const Request& request) * @category config * @api requests */ -RequestResult RequestHandler::SetPersistentData(const Request& request) +RequestResult RequestHandler::SetPersistentData(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - if (!(request.ValidateString("realm", statusCode, comment) && request.ValidateString("slotName", statusCode, comment) && request.ValidateBasic("slotValue", statusCode, comment))) + if (!(request.ValidateString("realm", statusCode, comment) && + request.ValidateString("slotName", statusCode, comment) && + request.ValidateBasic("slotValue", statusCode, comment))) return RequestResult::Error(statusCode, comment); std::string realm = request.RequestData["realm"]; std::string slotName = request.RequestData["slotName"]; json slotValue = request.RequestData["slotValue"]; - std::string persistentDataPath = Utils::Obs::StringHelper::GetCurrentProfilePath(); + std::string persistentDataPath = + Utils::Obs::StringHelper::GetCurrentProfilePath(); if (realm == "OBS_WEBSOCKET_DATA_REALM_GLOBAL") - persistentDataPath += "/../../../obsWebSocketPersistentData.json"; + persistentDataPath += + "/../../../obsWebSocketPersistentData.json"; else if (realm == "OBS_WEBSOCKET_DATA_REALM_PROFILE") persistentDataPath += "/obsWebSocketPersistentData.json"; else - return RequestResult::Error(RequestStatus::ResourceNotFound, "You have specified an invalid persistent data realm."); + return RequestResult::Error( + RequestStatus::ResourceNotFound, + "You have specified an invalid persistent data realm."); json persistentData = json::object(); Utils::Json::GetJsonFileContent(persistentDataPath, persistentData); persistentData[slotName] = slotValue; - if (!Utils::Json::SetJsonFileContent(persistentDataPath, persistentData)) - return RequestResult::Error(RequestStatus::RequestProcessingFailed, "Unable to write persistent data. No permissions?"); + if (!Utils::Json::SetJsonFileContent(persistentDataPath, + persistentData)) + return RequestResult::Error( + RequestStatus::RequestProcessingFailed, + "Unable to write persistent data. No permissions?"); return RequestResult::Success(); } @@ -120,11 +136,13 @@ RequestResult RequestHandler::SetPersistentData(const Request& request) * @category config * @api requests */ -RequestResult RequestHandler::GetSceneCollectionList(const Request&) +RequestResult RequestHandler::GetSceneCollectionList(const Request &) { json responseData; - responseData["currentSceneCollectionName"] = Utils::Obs::StringHelper::GetCurrentSceneCollection(); - responseData["sceneCollections"] = Utils::Obs::ArrayHelper::GetSceneCollectionList(); + responseData["currentSceneCollectionName"] = + Utils::Obs::StringHelper::GetCurrentSceneCollection(); + responseData["sceneCollections"] = + Utils::Obs::ArrayHelper::GetSceneCollectionList(); return RequestResult::Success(responseData); } @@ -142,25 +160,33 @@ RequestResult RequestHandler::GetSceneCollectionList(const Request&) * @category config * @api requests */ -RequestResult RequestHandler::SetCurrentSceneCollection(const Request& request) +RequestResult RequestHandler::SetCurrentSceneCollection(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; if (!request.ValidateString("sceneCollectionName", statusCode, comment)) return RequestResult::Error(statusCode, comment); - std::string sceneCollectionName = request.RequestData["sceneCollectionName"]; + std::string sceneCollectionName = + request.RequestData["sceneCollectionName"]; - auto sceneCollections = Utils::Obs::ArrayHelper::GetSceneCollectionList(); - if (std::find(sceneCollections.begin(), sceneCollections.end(), sceneCollectionName) == sceneCollections.end()) + auto sceneCollections = + Utils::Obs::ArrayHelper::GetSceneCollectionList(); + if (std::find(sceneCollections.begin(), sceneCollections.end(), + sceneCollectionName) == sceneCollections.end()) return RequestResult::Error(RequestStatus::ResourceNotFound); - std::string currentSceneCollectionName = Utils::Obs::StringHelper::GetCurrentSceneCollection(); + std::string currentSceneCollectionName = + Utils::Obs::StringHelper::GetCurrentSceneCollection(); // Avoid queueing tasks if nothing will change if (currentSceneCollectionName != sceneCollectionName) { - obs_queue_task(OBS_TASK_UI, [](void* param) { - obs_frontend_set_current_scene_collection(static_cast(param)); - }, (void*)sceneCollectionName.c_str(), true); + obs_queue_task( + OBS_TASK_UI, + [](void *param) { + obs_frontend_set_current_scene_collection( + static_cast(param)); + }, + (void *)sceneCollectionName.c_str(), true); } return RequestResult::Success(); @@ -180,24 +206,34 @@ RequestResult RequestHandler::SetCurrentSceneCollection(const Request& request) * @category config * @api requests */ -RequestResult RequestHandler::CreateSceneCollection(const Request& request) +RequestResult RequestHandler::CreateSceneCollection(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; if (!request.ValidateString("sceneCollectionName", statusCode, comment)) return RequestResult::Error(statusCode, comment); - std::string sceneCollectionName = request.RequestData["sceneCollectionName"]; + std::string sceneCollectionName = + request.RequestData["sceneCollectionName"]; - auto sceneCollections = Utils::Obs::ArrayHelper::GetSceneCollectionList(); - if (std::find(sceneCollections.begin(), sceneCollections.end(), sceneCollectionName) != sceneCollections.end()) - return RequestResult::Error(RequestStatus::ResourceAlreadyExists); + auto sceneCollections = + Utils::Obs::ArrayHelper::GetSceneCollectionList(); + if (std::find(sceneCollections.begin(), sceneCollections.end(), + sceneCollectionName) != sceneCollections.end()) + return RequestResult::Error( + RequestStatus::ResourceAlreadyExists); - QMainWindow* mainWindow = static_cast(obs_frontend_get_main_window()); + QMainWindow *mainWindow = + static_cast(obs_frontend_get_main_window()); bool success = false; - QMetaObject::invokeMethod(mainWindow, "AddSceneCollection", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, success), Q_ARG(bool, true), Q_ARG(QString, QString::fromStdString(sceneCollectionName))); + QMetaObject::invokeMethod( + mainWindow, "AddSceneCollection", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(bool, success), Q_ARG(bool, true), + Q_ARG(QString, QString::fromStdString(sceneCollectionName))); if (!success) - return RequestResult::Error(RequestStatus::ResourceCreationFailed, "Failed to create the scene collection."); + return RequestResult::Error( + RequestStatus::ResourceCreationFailed, + "Failed to create the scene collection."); return RequestResult::Success(); } @@ -215,10 +251,11 @@ RequestResult RequestHandler::CreateSceneCollection(const Request& request) * @category config * @api requests */ -RequestResult RequestHandler::GetProfileList(const Request&) +RequestResult RequestHandler::GetProfileList(const Request &) { json responseData; - responseData["currentProfileName"] = Utils::Obs::StringHelper::GetCurrentProfile(); + responseData["currentProfileName"] = + Utils::Obs::StringHelper::GetCurrentProfile(); responseData["profiles"] = Utils::Obs::ArrayHelper::GetProfileList(); return RequestResult::Success(responseData); } @@ -235,7 +272,7 @@ RequestResult RequestHandler::GetProfileList(const Request&) * @category config * @api requests */ -RequestResult RequestHandler::SetCurrentProfile(const Request& request) +RequestResult RequestHandler::SetCurrentProfile(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; @@ -245,15 +282,21 @@ RequestResult RequestHandler::SetCurrentProfile(const Request& request) std::string profileName = request.RequestData["profileName"]; auto profiles = Utils::Obs::ArrayHelper::GetProfileList(); - if (std::find(profiles.begin(), profiles.end(), profileName) == profiles.end()) + if (std::find(profiles.begin(), profiles.end(), profileName) == + profiles.end()) return RequestResult::Error(RequestStatus::ResourceNotFound); - std::string currentProfileName = Utils::Obs::StringHelper::GetCurrentProfile(); + std::string currentProfileName = + Utils::Obs::StringHelper::GetCurrentProfile(); // Avoid queueing tasks if nothing will change if (currentProfileName != profileName) { - obs_queue_task(OBS_TASK_UI, [](void* param) { - obs_frontend_set_current_profile(static_cast(param)); - }, (void*)profileName.c_str(), true); + obs_queue_task( + OBS_TASK_UI, + [](void *param) { + obs_frontend_set_current_profile( + static_cast(param)); + }, + (void *)profileName.c_str(), true); } return RequestResult::Success(); @@ -271,7 +314,7 @@ RequestResult RequestHandler::SetCurrentProfile(const Request& request) * @category config * @api requests */ -RequestResult RequestHandler::CreateProfile(const Request& request) +RequestResult RequestHandler::CreateProfile(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; @@ -281,11 +324,16 @@ RequestResult RequestHandler::CreateProfile(const Request& request) std::string profileName = request.RequestData["profileName"]; auto profiles = Utils::Obs::ArrayHelper::GetProfileList(); - if (std::find(profiles.begin(), profiles.end(), profileName) != profiles.end()) - return RequestResult::Error(RequestStatus::ResourceAlreadyExists); + if (std::find(profiles.begin(), profiles.end(), profileName) != + profiles.end()) + return RequestResult::Error( + RequestStatus::ResourceAlreadyExists); - QMainWindow* mainWindow = static_cast(obs_frontend_get_main_window()); - QMetaObject::invokeMethod(mainWindow, "NewProfile", Qt::BlockingQueuedConnection, Q_ARG(QString, QString::fromStdString(profileName))); + QMainWindow *mainWindow = + static_cast(obs_frontend_get_main_window()); + QMetaObject::invokeMethod( + mainWindow, "NewProfile", Qt::BlockingQueuedConnection, + Q_ARG(QString, QString::fromStdString(profileName))); return RequestResult::Success(); } @@ -302,7 +350,7 @@ RequestResult RequestHandler::CreateProfile(const Request& request) * @category config * @api requests */ -RequestResult RequestHandler::RemoveProfile(const Request& request) +RequestResult RequestHandler::RemoveProfile(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; @@ -312,14 +360,18 @@ RequestResult RequestHandler::RemoveProfile(const Request& request) std::string profileName = request.RequestData["profileName"]; auto profiles = Utils::Obs::ArrayHelper::GetProfileList(); - if (std::find(profiles.begin(), profiles.end(), profileName) == profiles.end()) + if (std::find(profiles.begin(), profiles.end(), profileName) == + profiles.end()) return RequestResult::Error(RequestStatus::ResourceNotFound); if (profiles.size() < 2) return RequestResult::Error(RequestStatus::NotEnoughResources); - QMainWindow* mainWindow = static_cast(obs_frontend_get_main_window()); - QMetaObject::invokeMethod(mainWindow, "DeleteProfile", Qt::BlockingQueuedConnection, Q_ARG(QString, QString::fromStdString(profileName))); + QMainWindow *mainWindow = + static_cast(obs_frontend_get_main_window()); + QMetaObject::invokeMethod( + mainWindow, "DeleteProfile", Qt::BlockingQueuedConnection, + Q_ARG(QString, QString::fromStdString(profileName))); return RequestResult::Success(); } @@ -340,27 +392,40 @@ RequestResult RequestHandler::RemoveProfile(const Request& request) * @category config * @api requests */ -RequestResult RequestHandler::GetProfileParameter(const Request& request) +RequestResult RequestHandler::GetProfileParameter(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - if (!(request.ValidateString("parameterCategory", statusCode, comment) && request.ValidateString("parameterName", statusCode, comment))) + if (!(request.ValidateString("parameterCategory", statusCode, + comment) && + request.ValidateString("parameterName", statusCode, comment))) return RequestResult::Error(statusCode, comment); - std::string parameterCategory = request.RequestData["parameterCategory"]; + std::string parameterCategory = + request.RequestData["parameterCategory"]; std::string parameterName = request.RequestData["parameterName"]; - config_t* profile = obs_frontend_get_profile_config(); + config_t *profile = obs_frontend_get_profile_config(); if (!profile) - blog(LOG_ERROR, "[RequestHandler::GetProfileParameter] Profile is invalid."); + blog(LOG_ERROR, + "[RequestHandler::GetProfileParameter] Profile is invalid."); json responseData; - if (config_has_default_value(profile, parameterCategory.c_str(), parameterName.c_str())) { - responseData["parameterValue"] = config_get_string(profile, parameterCategory.c_str(), parameterName.c_str()); - responseData["defaultParameterValue"] = config_get_default_string(profile, parameterCategory.c_str(), parameterName.c_str()); - } else if (config_has_user_value(profile, parameterCategory.c_str(), parameterName.c_str())) { - responseData["parameterValue"] = config_get_string(profile, parameterCategory.c_str(), parameterName.c_str()); + if (config_has_default_value(profile, parameterCategory.c_str(), + parameterName.c_str())) { + responseData["parameterValue"] = + config_get_string(profile, parameterCategory.c_str(), + parameterName.c_str()); + responseData["defaultParameterValue"] = + config_get_default_string(profile, + parameterCategory.c_str(), + parameterName.c_str()); + } else if (config_has_user_value(profile, parameterCategory.c_str(), + parameterName.c_str())) { + responseData["parameterValue"] = + config_get_string(profile, parameterCategory.c_str(), + parameterName.c_str()); responseData["defaultParameterValue"] = nullptr; } else { responseData["parameterValue"] = nullptr; @@ -384,28 +449,39 @@ RequestResult RequestHandler::GetProfileParameter(const Request& request) * @category config * @api requests */ -RequestResult RequestHandler::SetProfileParameter(const Request& request) +RequestResult RequestHandler::SetProfileParameter(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - if (!(request.ValidateString("parameterCategory", statusCode, comment) && - request.ValidateString("parameterName", statusCode, comment))) + if (!(request.ValidateString("parameterCategory", statusCode, + comment) && + request.ValidateString("parameterName", statusCode, comment))) return RequestResult::Error(statusCode, comment); - std::string parameterCategory = request.RequestData["parameterCategory"]; + std::string parameterCategory = + request.RequestData["parameterCategory"]; std::string parameterName = request.RequestData["parameterName"]; - config_t* profile = obs_frontend_get_profile_config(); + config_t *profile = obs_frontend_get_profile_config(); // Using check helpers here would just make the logic more complicated - if (!request.RequestData.contains("parameterValue") || request.RequestData["parameterValue"].is_null()) { - if (!config_remove_value(profile, parameterCategory.c_str(), parameterName.c_str())) - return RequestResult::Error(RequestStatus::ResourceNotFound, "There are no existing instances of that profile parameter."); + if (!request.RequestData.contains("parameterValue") || + request.RequestData["parameterValue"].is_null()) { + if (!config_remove_value(profile, parameterCategory.c_str(), + parameterName.c_str())) + return RequestResult::Error( + RequestStatus::ResourceNotFound, + "There are no existing instances of that profile parameter."); } else if (request.RequestData["parameterValue"].is_string()) { - std::string parameterValue = request.RequestData["parameterValue"]; - config_set_string(profile, parameterCategory.c_str(), parameterName.c_str(), parameterValue.c_str()); + std::string parameterValue = + request.RequestData["parameterValue"]; + config_set_string(profile, parameterCategory.c_str(), + parameterName.c_str(), + parameterValue.c_str()); } else { - return RequestResult::Error(RequestStatus::InvalidRequestFieldType, "The field `parameterValue` must be a string."); + return RequestResult::Error( + RequestStatus::InvalidRequestFieldType, + "The field `parameterValue` must be a string."); } config_save(profile); @@ -432,11 +508,13 @@ RequestResult RequestHandler::SetProfileParameter(const Request& request) * @category config * @api requests */ -RequestResult RequestHandler::GetVideoSettings(const Request&) +RequestResult RequestHandler::GetVideoSettings(const Request &) { struct obs_video_info ovi; if (!obs_get_video_info(&ovi)) - return RequestResult::Error(RequestStatus::RequestProcessingFailed, "Unable to get internal OBS video info."); + return RequestResult::Error( + RequestStatus::RequestProcessingFailed, + "Unable to get internal OBS video info."); json responseData; responseData["fpsNumerator"] = ovi.fps_num; @@ -468,41 +546,63 @@ RequestResult RequestHandler::GetVideoSettings(const Request&) * @category config * @api requests */ -RequestResult RequestHandler::SetVideoSettings(const Request& request) +RequestResult RequestHandler::SetVideoSettings(const Request &request) { if (obs_video_active()) - return RequestResult::Error(RequestStatus::OutputRunning, "Video settings cannot be changed while an output is active."); + return RequestResult::Error( + RequestStatus::OutputRunning, + "Video settings cannot be changed while an output is active."); RequestStatus::RequestStatus statusCode = RequestStatus::NoError; std::string comment; - bool changeFps = (request.Contains("fpsNumerator") && request.Contains("fpsDenominator")); - if (changeFps && !(request.ValidateOptionalNumber("fpsNumerator", statusCode, comment, 1) && request.ValidateOptionalNumber("fpsDenominator", statusCode, comment, 1))) + bool changeFps = (request.Contains("fpsNumerator") && + request.Contains("fpsDenominator")); + if (changeFps && !(request.ValidateOptionalNumber( + "fpsNumerator", statusCode, comment, 1) && + request.ValidateOptionalNumber( + "fpsDenominator", statusCode, comment, 1))) return RequestResult::Error(statusCode, comment); - bool changeBaseRes = (request.Contains("baseWidth") && request.Contains("baseHeight")); - if (changeBaseRes && !(request.ValidateOptionalNumber("baseWidth", statusCode, comment, 8, 4096) && request.ValidateOptionalNumber("baseHeight", statusCode, comment, 8, 4096))) + bool changeBaseRes = (request.Contains("baseWidth") && + request.Contains("baseHeight")); + if (changeBaseRes && + !(request.ValidateOptionalNumber("baseWidth", statusCode, comment, + 8, 4096) && + request.ValidateOptionalNumber("baseHeight", statusCode, comment, + 8, 4096))) return RequestResult::Error(statusCode, comment); - bool changeOutputRes = (request.Contains("outputWidth") && request.Contains("outputHeight")); - if (changeOutputRes && !(request.ValidateOptionalNumber("outputWidth", statusCode, comment, 8, 4096) && request.ValidateOptionalNumber("outputHeight", statusCode, comment, 8, 4096))) + bool changeOutputRes = (request.Contains("outputWidth") && + request.Contains("outputHeight")); + if (changeOutputRes && + !(request.ValidateOptionalNumber("outputWidth", statusCode, comment, + 8, 4096) && + request.ValidateOptionalNumber("outputHeight", statusCode, + comment, 8, 4096))) return RequestResult::Error(statusCode, comment); config_t *config = obs_frontend_get_profile_config(); if (changeFps) { config_set_uint(config, "Video", "FPSType", 2); - config_set_uint(config, "Video", "FPSNum", request.RequestData["fpsNumerator"]); - config_set_uint(config, "Video", "FPSDen", request.RequestData["fpsDenominator"]); + config_set_uint(config, "Video", "FPSNum", + request.RequestData["fpsNumerator"]); + config_set_uint(config, "Video", "FPSDen", + request.RequestData["fpsDenominator"]); } if (changeBaseRes) { - config_set_uint(config, "Video", "BaseCX", request.RequestData["baseWidth"]); - config_set_uint(config, "Video", "BaseCY", request.RequestData["baseHeight"]); + config_set_uint(config, "Video", "BaseCX", + request.RequestData["baseWidth"]); + config_set_uint(config, "Video", "BaseCY", + request.RequestData["baseHeight"]); } if (changeOutputRes) { - config_set_uint(config, "Video", "OutputCX", request.RequestData["outputWidth"]); - config_set_uint(config, "Video", "OutputCY", request.RequestData["outputHeight"]); + config_set_uint(config, "Video", "OutputCX", + request.RequestData["outputWidth"]); + config_set_uint(config, "Video", "OutputCY", + request.RequestData["outputHeight"]); } if (changeFps || changeBaseRes || changeOutputRes) { @@ -511,7 +611,9 @@ RequestResult RequestHandler::SetVideoSettings(const Request& request) return RequestResult::Success(); } - return RequestResult::Error(RequestStatus::MissingRequestField, "You must specify at least one video-changing pair."); + return RequestResult::Error( + RequestStatus::MissingRequestField, + "You must specify at least one video-changing pair."); } /** @@ -527,14 +629,15 @@ RequestResult RequestHandler::SetVideoSettings(const Request& request) * @category config * @api requests */ -RequestResult RequestHandler::GetStreamServiceSettings(const Request&) +RequestResult RequestHandler::GetStreamServiceSettings(const Request &) { json responseData; OBSService service = obs_frontend_get_streaming_service(); responseData["streamServiceType"] = obs_service_get_type(service); OBSDataAutoRelease serviceSettings = obs_service_get_settings(service); - responseData["streamServiceSettings"] = Utils::Json::ObsDataToJson(serviceSettings, true); + responseData["streamServiceSettings"] = + Utils::Json::ObsDataToJson(serviceSettings, true); return RequestResult::Success(responseData); } @@ -554,38 +657,56 @@ RequestResult RequestHandler::GetStreamServiceSettings(const Request&) * @category config * @api requests */ -RequestResult RequestHandler::SetStreamServiceSettings(const Request& request) +RequestResult RequestHandler::SetStreamServiceSettings(const Request &request) { if (obs_frontend_streaming_active()) - return RequestResult::Error(RequestStatus::OutputRunning, "You cannot change stream service settings while streaming."); + return RequestResult::Error( + RequestStatus::OutputRunning, + "You cannot change stream service settings while streaming."); RequestStatus::RequestStatus statusCode; std::string comment; - if (!(request.ValidateString("streamServiceType", statusCode, comment) && request.ValidateObject("streamServiceSettings", statusCode, comment))) + if (!(request.ValidateString("streamServiceType", statusCode, + comment) && + request.ValidateObject("streamServiceSettings", statusCode, + comment))) return RequestResult::Error(statusCode, comment); OBSService currentStreamService = obs_frontend_get_streaming_service(); - std::string streamServiceType = obs_service_get_type(currentStreamService); - std::string requestedStreamServiceType = request.RequestData["streamServiceType"]; - OBSDataAutoRelease requestedStreamServiceSettings = Utils::Json::JsonToObsData(request.RequestData["streamServiceSettings"]); + std::string streamServiceType = + obs_service_get_type(currentStreamService); + std::string requestedStreamServiceType = + request.RequestData["streamServiceType"]; + OBSDataAutoRelease requestedStreamServiceSettings = + Utils::Json::JsonToObsData( + request.RequestData["streamServiceSettings"]); // Don't create a new service if the current service is the same type. if (streamServiceType == requestedStreamServiceType) { - OBSDataAutoRelease currentStreamServiceSettings = obs_service_get_settings(currentStreamService); + OBSDataAutoRelease currentStreamServiceSettings = + obs_service_get_settings(currentStreamService); // TODO: Add `overlay` field OBSDataAutoRelease newStreamServiceSettings = obs_data_create(); - obs_data_apply(newStreamServiceSettings, currentStreamServiceSettings); - obs_data_apply(newStreamServiceSettings, requestedStreamServiceSettings); + obs_data_apply(newStreamServiceSettings, + currentStreamServiceSettings); + obs_data_apply(newStreamServiceSettings, + requestedStreamServiceSettings); - obs_service_update(currentStreamService, newStreamServiceSettings); + obs_service_update(currentStreamService, + newStreamServiceSettings); } else { // TODO: This leaks memory. I have no idea why. - OBSService newStreamService = obs_service_create(requestedStreamServiceType.c_str(), "obs_websocket_custom_service", requestedStreamServiceSettings, nullptr); + OBSService newStreamService = obs_service_create( + requestedStreamServiceType.c_str(), + "obs_websocket_custom_service", + requestedStreamServiceSettings, nullptr); // TODO: Check service type here, instead of relying on service creation to fail. if (!newStreamService) - return RequestResult::Error(RequestStatus::ResourceCreationFailed, "Failed to create the stream service with the requested streamServiceType. It may be an invalid type."); + return RequestResult::Error( + RequestStatus::ResourceCreationFailed, + "Failed to create the stream service with the requested streamServiceType. It may be an invalid type."); obs_frontend_set_streaming_service(newStreamService); } @@ -607,10 +728,11 @@ RequestResult RequestHandler::SetStreamServiceSettings(const Request& request) * @api requests * @category rconfig */ -RequestResult RequestHandler::GetRecordDirectory(const Request&) +RequestResult RequestHandler::GetRecordDirectory(const Request &) { json responseData; - responseData["recordDirectory"] = Utils::Obs::StringHelper::GetCurrentRecordOutputPath(); + responseData["recordDirectory"] = + Utils::Obs::StringHelper::GetCurrentRecordOutputPath(); return RequestResult::Success(responseData); } diff --git a/src/requesthandler/RequestHandler_Filters.cpp b/src/requesthandler/RequestHandler_Filters.cpp index e69f6df6..1d3db8ce 100644 --- a/src/requesthandler/RequestHandler_Filters.cpp +++ b/src/requesthandler/RequestHandler_Filters.cpp @@ -33,16 +33,18 @@ with this program. If not, see * @api requests * @category filters */ -RequestResult RequestHandler::GetSourceFilterList(const Request& request) +RequestResult RequestHandler::GetSourceFilterList(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease source = request.ValidateSource("sourceName", statusCode, comment); - if(!source) + OBSSourceAutoRelease source = + request.ValidateSource("sourceName", statusCode, comment); + if (!source) return RequestResult::Error(statusCode, comment); json responseData; - responseData["filters"] = Utils::Obs::ArrayHelper::GetSourceFilterList(source); + responseData["filters"] = + Utils::Obs::ArrayHelper::GetSourceFilterList(source); return RequestResult::Success(responseData); } @@ -61,7 +63,8 @@ RequestResult RequestHandler::GetSourceFilterList(const Request& request) * @api requests * @category filters */ -RequestResult RequestHandler::GetSourceFilterDefaultSettings(const Request& request) +RequestResult +RequestHandler::GetSourceFilterDefaultSettings(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; @@ -73,12 +76,14 @@ RequestResult RequestHandler::GetSourceFilterDefaultSettings(const Request& requ if (std::find(kinds.begin(), kinds.end(), filterKind) == kinds.end()) return RequestResult::Error(RequestStatus::InvalidFilterKind); - OBSDataAutoRelease defaultSettings = obs_get_source_defaults(filterKind.c_str()); + 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); + responseData["defaultFilterSettings"] = + Utils::Json::ObsDataToJson(defaultSettings, true); return RequestResult::Success(responseData); } @@ -97,37 +102,51 @@ RequestResult RequestHandler::GetSourceFilterDefaultSettings(const Request& requ * @api requests * @category filters */ -RequestResult RequestHandler::CreateSourceFilter(const Request& request) +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))) + 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()); + 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."); + 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."); + 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)) + if (!request.ValidateOptionalObject("filterSettings", + statusCode, comment, true)) return RequestResult::Error(statusCode, comment); - filterSettings = Utils::Json::JsonToObsData(request.RequestData["filterSettings"]); + filterSettings = Utils::Json::JsonToObsData( + request.RequestData["filterSettings"]); } - OBSSourceAutoRelease filter = Utils::Obs::ActionHelper::CreateSourceFilter(source, filterName, filterKind, filterSettings); + OBSSourceAutoRelease filter = + Utils::Obs::ActionHelper::CreateSourceFilter( + source, filterName, filterKind, filterSettings); - if(!filter) - return RequestResult::Error(RequestStatus::ResourceCreationFailed, "Creation of the filter failed."); + if (!filter) + return RequestResult::Error( + RequestStatus::ResourceCreationFailed, + "Creation of the filter failed."); return RequestResult::Success(); } @@ -145,11 +164,12 @@ RequestResult RequestHandler::CreateSourceFilter(const Request& request) * @api requests * @category filters */ -RequestResult RequestHandler::RemoveSourceFilter(const Request& request) +RequestResult RequestHandler::RemoveSourceFilter(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - FilterPair pair = request.ValidateFilter("sourceName", "filterName", statusCode, comment); + FilterPair pair = request.ValidateFilter("sourceName", "filterName", + statusCode, comment); if (!pair.filter) return RequestResult::Error(statusCode, comment); @@ -172,19 +192,24 @@ RequestResult RequestHandler::RemoveSourceFilter(const Request& request) * @api requests * @category filters */ -RequestResult RequestHandler::SetSourceFilterName(const Request& request) +RequestResult RequestHandler::SetSourceFilterName(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - FilterPair pair = request.ValidateFilter("sourceName", "filterName", statusCode, comment); - if (!pair.filter || !request.ValidateString("newFilterName", statusCode, comment)) + FilterPair pair = request.ValidateFilter("sourceName", "filterName", + statusCode, comment); + if (!pair.filter || + !request.ValidateString("newFilterName", statusCode, comment)) return RequestResult::Error(statusCode, comment); std::string newFilterName = request.RequestData["newFilterName"]; - OBSSourceAutoRelease existingFilter = obs_source_get_filter_by_name(pair.source, newFilterName.c_str()); + OBSSourceAutoRelease existingFilter = obs_source_get_filter_by_name( + pair.source, newFilterName.c_str()); if (existingFilter) - return RequestResult::Error(RequestStatus::ResourceAlreadyExists, "A filter already exists by that new name."); + return RequestResult::Error( + RequestStatus::ResourceAlreadyExists, + "A filter already exists by that new name."); obs_source_set_name(pair.filter, newFilterName.c_str()); @@ -209,21 +234,27 @@ RequestResult RequestHandler::SetSourceFilterName(const Request& request) * @api requests * @category filters */ -RequestResult RequestHandler::GetSourceFilter(const Request& request) +RequestResult RequestHandler::GetSourceFilter(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - FilterPair pair = request.ValidateFilter("sourceName", "filterName", statusCode, comment); + FilterPair pair = request.ValidateFilter("sourceName", "filterName", + statusCode, comment); if (!pair.filter) return RequestResult::Error(statusCode, comment); json responseData; responseData["filterEnabled"] = obs_source_enabled(pair.filter); - responseData["filterIndex"] = Utils::Obs::NumberHelper::GetSourceFilterIndex(pair.source, pair.filter); // Todo: Use `GetSourceFilterlist` to select this filter maybe + responseData["filterIndex"] = + Utils::Obs::NumberHelper::GetSourceFilterIndex( + pair.source, + pair.filter); // Todo: Use `GetSourceFilterlist` to select this filter maybe responseData["filterKind"] = obs_source_get_id(pair.filter); - OBSDataAutoRelease filterSettings = obs_source_get_settings(pair.filter); - responseData["filterSettings"] = Utils::Json::ObsDataToJson(filterSettings); + OBSDataAutoRelease filterSettings = + obs_source_get_settings(pair.filter); + responseData["filterSettings"] = + Utils::Json::ObsDataToJson(filterSettings); return RequestResult::Success(responseData); } @@ -242,17 +273,20 @@ RequestResult RequestHandler::GetSourceFilter(const Request& request) * @api requests * @category filters */ -RequestResult RequestHandler::SetSourceFilterIndex(const Request& request) +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))) + 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); + Utils::Obs::ActionHelper::SetSourceFilterIndex(pair.source, pair.filter, + filterIndex); return RequestResult::Success(); } @@ -272,27 +306,33 @@ RequestResult RequestHandler::SetSourceFilterIndex(const Request& request) * @api requests * @category filters */ -RequestResult RequestHandler::SetSourceFilterSettings(const Request& request) +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))) + 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)) + if (!request.ValidateOptionalBoolean("overlay", statusCode, + comment)) return RequestResult::Error(statusCode, comment); overlay = request.RequestData["overlay"]; } - OBSDataAutoRelease newSettings = Utils::Json::JsonToObsData(request.RequestData["filterSettings"]); + OBSDataAutoRelease newSettings = Utils::Json::JsonToObsData( + request.RequestData["filterSettings"]); if (!newSettings) - return RequestResult::Error(RequestStatus::RequestProcessingFailed, "An internal data conversion operation failed. Please report this!"); + return RequestResult::Error( + RequestStatus::RequestProcessingFailed, + "An internal data conversion operation failed. Please report this!"); if (overlay) obs_source_update(pair.filter, newSettings); @@ -318,12 +358,14 @@ RequestResult RequestHandler::SetSourceFilterSettings(const Request& request) * @api requests * @category filters */ -RequestResult RequestHandler::SetSourceFilterEnabled(const Request& request) +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))) + 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"]; diff --git a/src/requesthandler/RequestHandler_General.cpp b/src/requesthandler/RequestHandler_General.cpp index ca753e5b..3cb73058 100644 --- a/src/requesthandler/RequestHandler_General.cpp +++ b/src/requesthandler/RequestHandler_General.cpp @@ -26,7 +26,6 @@ with this program. If not, see #include "../WebSocketApi.h" #include "../obs-websocket.h" - /** * Gets data about the current plugin and RPC version. * @@ -45,7 +44,7 @@ with this program. If not, see * @category general * @api requests */ -RequestResult RequestHandler::GetVersion(const Request&) +RequestResult RequestHandler::GetVersion(const Request &) { json responseData; responseData["obsVersion"] = Utils::Obs::StringHelper::GetObsVersion(); @@ -53,15 +52,17 @@ RequestResult RequestHandler::GetVersion(const Request&) responseData["rpcVersion"] = OBS_WEBSOCKET_RPC_VERSION; responseData["availableRequests"] = GetRequestList(); - QList imageWriterFormats = QImageWriter::supportedImageFormats(); + QList imageWriterFormats = + QImageWriter::supportedImageFormats(); std::vector supportedImageFormats; - for (const QByteArray& format : imageWriterFormats) { + for (const QByteArray &format : imageWriterFormats) { supportedImageFormats.push_back(format.toStdString()); } responseData["supportedImageFormats"] = supportedImageFormats; responseData["platform"] = QSysInfo::productType().toStdString(); - responseData["platformDescription"] = QSysInfo::prettyProductName().toStdString(); + responseData["platformDescription"] = + QSysInfo::prettyProductName().toStdString(); return RequestResult::Success(responseData); } @@ -88,13 +89,15 @@ RequestResult RequestHandler::GetVersion(const Request&) * @category general * @api requests */ -RequestResult RequestHandler::GetStats(const Request&) +RequestResult RequestHandler::GetStats(const Request &) { json responseData = Utils::Obs::ObjectHelper::GetStats(); if (_session) { - responseData["webSocketSessionIncomingMessages"] = _session->IncomingMessages(); - responseData["webSocketSessionOutgoingMessages"] = _session->OutgoingMessages(); + responseData["webSocketSessionIncomingMessages"] = + _session->IncomingMessages(); + responseData["webSocketSessionOutgoingMessages"] = + _session->OutgoingMessages(); } else { responseData["webSocketSessionIncomingMessages"] = nullptr; responseData["webSocketSessionOutgoingMessages"] = nullptr; @@ -115,7 +118,7 @@ RequestResult RequestHandler::GetStats(const Request&) * @category general * @api requests */ -RequestResult RequestHandler::BroadcastCustomEvent(const Request& request) +RequestResult RequestHandler::BroadcastCustomEvent(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; @@ -124,9 +127,13 @@ RequestResult RequestHandler::BroadcastCustomEvent(const Request& request) auto webSocketServer = GetWebSocketServer(); if (!webSocketServer) - return RequestResult::Error(RequestStatus::RequestProcessingFailed, "Unable to send event due to internal error."); + return RequestResult::Error( + RequestStatus::RequestProcessingFailed, + "Unable to send event due to internal error."); - webSocketServer->BroadcastEvent(EventSubscription::General, "CustomEvent", request.RequestData["eventData"]); + webSocketServer->BroadcastEvent(EventSubscription::General, + "CustomEvent", + request.RequestData["eventData"]); return RequestResult::Success(); } @@ -150,11 +157,12 @@ RequestResult RequestHandler::BroadcastCustomEvent(const Request& request) * @category general * @api requests */ -RequestResult RequestHandler::CallVendorRequest(const Request& request) +RequestResult RequestHandler::CallVendorRequest(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - if (!request.ValidateString("vendorName", statusCode, comment) || !request.ValidateString("requestType", statusCode, comment)) + if (!request.ValidateString("vendorName", statusCode, comment) || + !request.ValidateString("requestType", statusCode, comment)) return RequestResult::Error(statusCode, comment); std::string vendorName = request.RequestData["vendorName"]; @@ -162,31 +170,41 @@ RequestResult RequestHandler::CallVendorRequest(const Request& request) OBSDataAutoRelease requestData = obs_data_create(); if (request.Contains("requestData")) { - if (!request.ValidateOptionalObject("requestData", statusCode, comment)) + if (!request.ValidateOptionalObject("requestData", statusCode, + comment)) return RequestResult::Error(statusCode, comment); - requestData = Utils::Json::JsonToObsData(request.RequestData["requestData"]); + requestData = Utils::Json::JsonToObsData( + request.RequestData["requestData"]); } OBSDataAutoRelease obsResponseData = obs_data_create(); auto webSocketApi = GetWebSocketApi(); if (!webSocketApi) - return RequestResult::Error(RequestStatus::RequestProcessingFailed, "Unable to call request due to internal error."); + return RequestResult::Error( + RequestStatus::RequestProcessingFailed, + "Unable to call request due to internal error."); - auto ret = webSocketApi->PerformVendorRequest(vendorName, requestType, requestData, obsResponseData); + auto ret = webSocketApi->PerformVendorRequest( + vendorName, requestType, requestData, obsResponseData); switch (ret) { - default: - case WebSocketApi::RequestReturnCode::Normal: - break; - case WebSocketApi::RequestReturnCode::NoVendor: - return RequestResult::Error(RequestStatus::ResourceNotFound, "No vendor was found by that name."); - case WebSocketApi::RequestReturnCode::NoVendorRequest: - return RequestResult::Error(RequestStatus::ResourceNotFound, "No request was found by that name."); + default: + case WebSocketApi::RequestReturnCode::Normal: + break; + case WebSocketApi::RequestReturnCode::NoVendor: + return RequestResult::Error( + RequestStatus::ResourceNotFound, + "No vendor was found by that name."); + case WebSocketApi::RequestReturnCode::NoVendorRequest: + return RequestResult::Error( + RequestStatus::ResourceNotFound, + "No request was found by that name."); } json responseData; - responseData["responseData"] = Utils::Json::ObsDataToJson(obsResponseData); + responseData["responseData"] = + Utils::Json::ObsDataToJson(obsResponseData); return RequestResult::Success(responseData); } @@ -203,7 +221,7 @@ RequestResult RequestHandler::CallVendorRequest(const Request& request) * @category general * @api requests */ -RequestResult RequestHandler::GetHotkeyList(const Request&) +RequestResult RequestHandler::GetHotkeyList(const Request &) { json responseData; responseData["hotkeys"] = Utils::Obs::ArrayHelper::GetHotkeyNameList(); @@ -222,16 +240,19 @@ RequestResult RequestHandler::GetHotkeyList(const Request&) * @category general * @api requests */ -RequestResult RequestHandler::TriggerHotkeyByName(const Request& request) +RequestResult RequestHandler::TriggerHotkeyByName(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; if (!request.ValidateString("hotkeyName", statusCode, comment)) return RequestResult::Error(statusCode, comment); - obs_hotkey_t *hotkey = Utils::Obs::SearchHelper::GetHotkeyByName(request.RequestData["hotkeyName"]); + obs_hotkey_t *hotkey = Utils::Obs::SearchHelper::GetHotkeyByName( + request.RequestData["hotkeyName"]); if (!hotkey) - return RequestResult::Error(RequestStatus::ResourceNotFound, "No hotkeys were found by that name."); + return RequestResult::Error( + RequestStatus::ResourceNotFound, + "No hotkeys were found by that name."); obs_hotkey_trigger_routed_callback(obs_hotkey_get_id(hotkey), true); @@ -255,7 +276,7 @@ RequestResult RequestHandler::TriggerHotkeyByName(const Request& request) * @category general * @api requests */ -RequestResult RequestHandler::TriggerHotkeyByKeySequence(const Request& request) +RequestResult RequestHandler::TriggerHotkeyByKeySequence(const Request &request) { obs_key_combination_t combo = {0}; @@ -263,7 +284,8 @@ RequestResult RequestHandler::TriggerHotkeyByKeySequence(const Request& request) std::string comment; if (request.Contains("keyId")) { - if (!request.ValidateOptionalString("keyId", statusCode, comment)) + if (!request.ValidateOptionalString("keyId", statusCode, + comment)) return RequestResult::Error(statusCode, comment); std::string keyId = request.RequestData["keyId"]; @@ -272,24 +294,37 @@ RequestResult RequestHandler::TriggerHotkeyByKeySequence(const Request& request) statusCode = RequestStatus::NoError; if (request.Contains("keyModifiers")) { - if (!request.ValidateOptionalObject("keyModifiers", statusCode, comment, true)) + if (!request.ValidateOptionalObject("keyModifiers", statusCode, + comment, true)) return RequestResult::Error(statusCode, comment); - const json keyModifiersJson = request.RequestData["keyModifiers"]; + const json keyModifiersJson = + request.RequestData["keyModifiers"]; uint32_t keyModifiers = 0; - if (keyModifiersJson.contains("shift") && keyModifiersJson["shift"].is_boolean() && keyModifiersJson["shift"].get()) + if (keyModifiersJson.contains("shift") && + keyModifiersJson["shift"].is_boolean() && + keyModifiersJson["shift"].get()) keyModifiers |= INTERACT_SHIFT_KEY; - if (keyModifiersJson.contains("control") && keyModifiersJson["control"].is_boolean() && keyModifiersJson["control"].get()) + if (keyModifiersJson.contains("control") && + keyModifiersJson["control"].is_boolean() && + keyModifiersJson["control"].get()) keyModifiers |= INTERACT_CONTROL_KEY; - if (keyModifiersJson.contains("alt") && keyModifiersJson["alt"].is_boolean() && keyModifiersJson["alt"].get()) + if (keyModifiersJson.contains("alt") && + keyModifiersJson["alt"].is_boolean() && + keyModifiersJson["alt"].get()) keyModifiers |= INTERACT_ALT_KEY; - if (keyModifiersJson.contains("command") && keyModifiersJson["command"].is_boolean() && keyModifiersJson["command"].get()) + if (keyModifiersJson.contains("command") && + keyModifiersJson["command"].is_boolean() && + keyModifiersJson["command"].get()) keyModifiers |= INTERACT_COMMAND_KEY; combo.modifiers = keyModifiers; } - if (!combo.modifiers && (combo.key == OBS_KEY_NONE || combo.key >= OBS_KEY_LAST_VALUE)) - return RequestResult::Error(RequestStatus::CannotAct, "Your provided request fields cannot be used to trigger a hotkey."); + if (!combo.modifiers && + (combo.key == OBS_KEY_NONE || combo.key >= OBS_KEY_LAST_VALUE)) + return RequestResult::Error( + RequestStatus::CannotAct, + "Your provided request fields cannot be used to trigger a hotkey."); // Apparently things break when you don't start by setting the combo to false obs_hotkey_inject_event(combo, false); @@ -312,24 +347,30 @@ RequestResult RequestHandler::TriggerHotkeyByKeySequence(const Request& request) * @category general * @api requests */ -RequestResult RequestHandler::Sleep(const Request& request) +RequestResult RequestHandler::Sleep(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - if (request.ExecutionType == RequestBatchExecutionType::SerialRealtime) { - if (!request.ValidateNumber("sleepMillis", statusCode, comment, 0, 50000)) + if (request.ExecutionType == + RequestBatchExecutionType::SerialRealtime) { + if (!request.ValidateNumber("sleepMillis", statusCode, comment, + 0, 50000)) return RequestResult::Error(statusCode, comment); int64_t sleepMillis = request.RequestData["sleepMillis"]; - std::this_thread::sleep_for(std::chrono::milliseconds(sleepMillis)); + std::this_thread::sleep_for( + std::chrono::milliseconds(sleepMillis)); return RequestResult::Success(); - } else if (request.ExecutionType == RequestBatchExecutionType::SerialFrame) { - if (!request.ValidateNumber("sleepFrames", statusCode, comment, 0, 10000)) + } else if (request.ExecutionType == + RequestBatchExecutionType::SerialFrame) { + if (!request.ValidateNumber("sleepFrames", statusCode, comment, + 0, 10000)) return RequestResult::Error(statusCode, comment); RequestResult ret = RequestResult::Success(); ret.SleepFrames = request.RequestData["sleepFrames"]; return ret; } else { - return RequestResult::Error(RequestStatus::UnsupportedRequestBatchExecutionType); + return RequestResult::Error( + RequestStatus::UnsupportedRequestBatchExecutionType); } } diff --git a/src/requesthandler/RequestHandler_Inputs.cpp b/src/requesthandler/RequestHandler_Inputs.cpp index fe1611c6..cfbebb65 100644 --- a/src/requesthandler/RequestHandler_Inputs.cpp +++ b/src/requesthandler/RequestHandler_Inputs.cpp @@ -33,21 +33,23 @@ with this program. If not, see * @api requests * @category inputs */ -RequestResult RequestHandler::GetInputList(const Request& request) +RequestResult RequestHandler::GetInputList(const Request &request) { std::string inputKind; if (request.Contains("inputKind")) { RequestStatus::RequestStatus statusCode; std::string comment; - if (!request.ValidateOptionalString("inputKind", statusCode, comment)) + if (!request.ValidateOptionalString("inputKind", statusCode, + comment)) return RequestResult::Error(statusCode, comment); inputKind = request.RequestData["inputKind"]; } json responseData; - responseData["inputs"] = Utils::Obs::ArrayHelper::GetInputList(inputKind); + responseData["inputs"] = + Utils::Obs::ArrayHelper::GetInputList(inputKind); return RequestResult::Success(responseData); } @@ -65,21 +67,23 @@ RequestResult RequestHandler::GetInputList(const Request& request) * @api requests * @category inputs */ -RequestResult RequestHandler::GetInputKindList(const Request& request) +RequestResult RequestHandler::GetInputKindList(const Request &request) { bool unversioned = false; if (request.Contains("unversioned")) { RequestStatus::RequestStatus statusCode; std::string comment; - if (!request.ValidateOptionalBoolean("unversioned", statusCode, comment)) + if (!request.ValidateOptionalBoolean("unversioned", statusCode, + comment)) return RequestResult::Error(statusCode, comment); unversioned = request.RequestData["unversioned"]; } json responseData; - responseData["inputKinds"] = Utils::Obs::ArrayHelper::GetInputKindList(unversioned); + responseData["inputKinds"] = + Utils::Obs::ArrayHelper::GetInputKindList(unversioned); return RequestResult::Success(responseData); } @@ -100,11 +104,12 @@ RequestResult RequestHandler::GetInputKindList(const Request& request) * @api requests * @category inputs */ -RequestResult RequestHandler::GetSpecialInputs(const Request&) +RequestResult RequestHandler::GetSpecialInputs(const Request &) { json responseData; - std::vector channels = {"desktop1", "desktop2", "mic1", "mic2", "mic3", "mic4"}; + std::vector channels = {"desktop1", "desktop2", "mic1", + "mic2", "mic3", "mic4"}; size_t channelId = 1; for (auto &channel : channels) { @@ -138,47 +143,63 @@ RequestResult RequestHandler::GetSpecialInputs(const Request&) * @api requests * @category inputs */ -RequestResult RequestHandler::CreateInput(const Request& request) +RequestResult RequestHandler::CreateInput(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease sceneSource = request.ValidateScene("sceneName", statusCode, comment); - if (!(sceneSource && request.ValidateString("inputName", statusCode, comment) && request.ValidateString("inputKind", statusCode, comment))) + OBSSourceAutoRelease sceneSource = + request.ValidateScene("sceneName", statusCode, comment); + if (!(sceneSource && + request.ValidateString("inputName", statusCode, comment) && + request.ValidateString("inputKind", statusCode, comment))) return RequestResult::Error(statusCode, comment); std::string inputName = request.RequestData["inputName"]; - OBSSourceAutoRelease existingInput = obs_get_source_by_name(inputName.c_str()); + OBSSourceAutoRelease existingInput = + obs_get_source_by_name(inputName.c_str()); if (existingInput) - return RequestResult::Error(RequestStatus::ResourceAlreadyExists, "A source already exists by that input name."); + return RequestResult::Error( + RequestStatus::ResourceAlreadyExists, + "A source already exists by that input name."); 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, "Your specified input kind is not supported by OBS. Check that your specified kind is properly versioned and that any necessary plugins are loaded."); + return RequestResult::Error( + RequestStatus::InvalidInputKind, + "Your specified input kind is not supported by OBS. Check that your specified kind is properly versioned and that any necessary plugins are loaded."); OBSDataAutoRelease inputSettings = nullptr; if (request.Contains("inputSettings")) { - if (!request.ValidateOptionalObject("inputSettings", statusCode, comment, true)) + if (!request.ValidateOptionalObject("inputSettings", statusCode, + comment, true)) return RequestResult::Error(statusCode, comment); - inputSettings = Utils::Json::JsonToObsData(request.RequestData["inputSettings"]); + inputSettings = Utils::Json::JsonToObsData( + request.RequestData["inputSettings"]); } OBSScene scene = obs_scene_from_source(sceneSource); bool sceneItemEnabled = true; if (request.Contains("sceneItemEnabled")) { - if (!request.ValidateOptionalBoolean("sceneItemEnabled", statusCode, comment)) + if (!request.ValidateOptionalBoolean("sceneItemEnabled", + statusCode, comment)) return RequestResult::Error(statusCode, comment); sceneItemEnabled = request.RequestData["sceneItemEnabled"]; } // Create the input and add it as a scene item to the destination scene - OBSSceneItemAutoRelease sceneItem = Utils::Obs::ActionHelper::CreateInput(inputName, inputKind, inputSettings, scene, sceneItemEnabled); + OBSSceneItemAutoRelease sceneItem = + Utils::Obs::ActionHelper::CreateInput(inputName, inputKind, + inputSettings, scene, + sceneItemEnabled); if (!sceneItem) - return RequestResult::Error(RequestStatus::ResourceCreationFailed, "Creation of the input or scene item failed."); + return RequestResult::Error( + RequestStatus::ResourceCreationFailed, + "Creation of the input or scene item failed."); json responseData; responseData["sceneItemId"] = obs_sceneitem_get_id(sceneItem); @@ -199,11 +220,12 @@ RequestResult RequestHandler::CreateInput(const Request& request) * @api requests * @category inputs */ -RequestResult RequestHandler::RemoveInput(const Request& request) +RequestResult RequestHandler::RemoveInput(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); + OBSSourceAutoRelease input = + request.ValidateInput("inputName", statusCode, comment); if (!input) return RequestResult::Error(statusCode, comment); @@ -228,19 +250,24 @@ RequestResult RequestHandler::RemoveInput(const Request& request) * @api requests * @category inputs */ -RequestResult RequestHandler::SetInputName(const Request& request) +RequestResult RequestHandler::SetInputName(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); - if (!(input && request.ValidateString("newInputName", statusCode, comment))) + OBSSourceAutoRelease input = + request.ValidateInput("inputName", statusCode, comment); + if (!(input && + request.ValidateString("newInputName", statusCode, comment))) return RequestResult::Error(statusCode, comment); std::string newInputName = request.RequestData["newInputName"]; - OBSSourceAutoRelease existingSource = obs_get_source_by_name(newInputName.c_str()); + OBSSourceAutoRelease existingSource = + obs_get_source_by_name(newInputName.c_str()); if (existingSource) - return RequestResult::Error(RequestStatus::ResourceAlreadyExists, "A source already exists by that new input name."); + return RequestResult::Error( + RequestStatus::ResourceAlreadyExists, + "A source already exists by that new input name."); obs_source_set_name(input, newInputName.c_str()); @@ -261,7 +288,7 @@ RequestResult RequestHandler::SetInputName(const Request& request) * @api requests * @category inputs */ -RequestResult RequestHandler::GetInputDefaultSettings(const Request& request) +RequestResult RequestHandler::GetInputDefaultSettings(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; @@ -273,12 +300,14 @@ RequestResult RequestHandler::GetInputDefaultSettings(const Request& request) if (std::find(kinds.begin(), kinds.end(), inputKind) == kinds.end()) return RequestResult::Error(RequestStatus::InvalidInputKind); - OBSDataAutoRelease defaultSettings = obs_get_source_defaults(inputKind.c_str()); + OBSDataAutoRelease defaultSettings = + obs_get_source_defaults(inputKind.c_str()); if (!defaultSettings) return RequestResult::Error(RequestStatus::InvalidInputKind); json responseData; - responseData["defaultInputSettings"] = Utils::Json::ObsDataToJson(defaultSettings, true); + responseData["defaultInputSettings"] = + Utils::Json::ObsDataToJson(defaultSettings, true); return RequestResult::Success(responseData); } @@ -299,18 +328,20 @@ RequestResult RequestHandler::GetInputDefaultSettings(const Request& request) * @api requests * @category inputs */ -RequestResult RequestHandler::GetInputSettings(const Request& request) +RequestResult RequestHandler::GetInputSettings(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); + OBSSourceAutoRelease input = + request.ValidateInput("inputName", statusCode, comment); if (!input) return RequestResult::Error(statusCode, comment); OBSDataAutoRelease inputSettings = obs_source_get_settings(input); json responseData; - responseData["inputSettings"] = Utils::Json::ObsDataToJson(inputSettings); + responseData["inputSettings"] = + Utils::Json::ObsDataToJson(inputSettings); responseData["inputKind"] = obs_source_get_id(input); return RequestResult::Success(responseData); } @@ -329,27 +360,33 @@ RequestResult RequestHandler::GetInputSettings(const Request& request) * @api requests * @category inputs */ -RequestResult RequestHandler::SetInputSettings(const Request& request) +RequestResult RequestHandler::SetInputSettings(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); - if (!(input && request.ValidateObject("inputSettings", statusCode, comment, true))) + OBSSourceAutoRelease input = + request.ValidateInput("inputName", statusCode, comment); + if (!(input && request.ValidateObject("inputSettings", statusCode, + comment, true))) return RequestResult::Error(statusCode, comment); bool overlay = true; if (request.Contains("overlay")) { - if (!request.ValidateOptionalBoolean("overlay", statusCode, comment)) + if (!request.ValidateOptionalBoolean("overlay", statusCode, + comment)) return RequestResult::Error(statusCode, comment); overlay = request.RequestData["overlay"]; } // Get the new settings and convert it to obs_data_t* - OBSDataAutoRelease newSettings = Utils::Json::JsonToObsData(request.RequestData["inputSettings"]); + OBSDataAutoRelease newSettings = Utils::Json::JsonToObsData( + request.RequestData["inputSettings"]); if (!newSettings) // This should never happen - return RequestResult::Error(RequestStatus::RequestProcessingFailed, "An internal data conversion operation failed. Please report this!"); + return RequestResult::Error( + RequestStatus::RequestProcessingFailed, + "An internal data conversion operation failed. Please report this!"); if (overlay) // Applies the new settings on top of the existing user settings @@ -378,16 +415,19 @@ RequestResult RequestHandler::SetInputSettings(const Request& request) * @api requests * @category inputs */ -RequestResult RequestHandler::GetInputMute(const Request& request) +RequestResult RequestHandler::GetInputMute(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); + OBSSourceAutoRelease input = + request.ValidateInput("inputName", statusCode, comment); if (!input) return RequestResult::Error(statusCode, comment); if (!(obs_source_get_output_flags(input) & OBS_SOURCE_AUDIO)) - return RequestResult::Error(RequestStatus::InvalidResourceState, "The specified input does not support audio."); + return RequestResult::Error( + RequestStatus::InvalidResourceState, + "The specified input does not support audio."); json responseData; responseData["inputMuted"] = obs_source_muted(input); @@ -407,16 +447,20 @@ RequestResult RequestHandler::GetInputMute(const Request& request) * @api requests * @category inputs */ -RequestResult RequestHandler::SetInputMute(const Request& request) +RequestResult RequestHandler::SetInputMute(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); - if (!(input && request.ValidateBoolean("inputMuted", statusCode, comment))) + OBSSourceAutoRelease input = + request.ValidateInput("inputName", statusCode, comment); + if (!(input && + request.ValidateBoolean("inputMuted", statusCode, comment))) return RequestResult::Error(statusCode, comment); if (!(obs_source_get_output_flags(input) & OBS_SOURCE_AUDIO)) - return RequestResult::Error(RequestStatus::InvalidResourceState, "The specified input does not support audio."); + return RequestResult::Error( + RequestStatus::InvalidResourceState, + "The specified input does not support audio."); obs_source_set_muted(input, request.RequestData["inputMuted"]); @@ -437,16 +481,19 @@ RequestResult RequestHandler::SetInputMute(const Request& request) * @api requests * @category inputs */ -RequestResult RequestHandler::ToggleInputMute(const Request& request) +RequestResult RequestHandler::ToggleInputMute(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); + OBSSourceAutoRelease input = + request.ValidateInput("inputName", statusCode, comment); if (!input) return RequestResult::Error(statusCode, comment); if (!(obs_source_get_output_flags(input) & OBS_SOURCE_AUDIO)) - return RequestResult::Error(RequestStatus::InvalidResourceState, "The specified input does not support audio."); + return RequestResult::Error( + RequestStatus::InvalidResourceState, + "The specified input does not support audio."); bool inputMuted = !obs_source_muted(input); obs_source_set_muted(input, inputMuted); @@ -471,16 +518,19 @@ RequestResult RequestHandler::ToggleInputMute(const Request& request) * @api requests * @category inputs */ -RequestResult RequestHandler::GetInputVolume(const Request& request) +RequestResult RequestHandler::GetInputVolume(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); + OBSSourceAutoRelease input = + request.ValidateInput("inputName", statusCode, comment); if (!input) return RequestResult::Error(statusCode, comment); if (!(obs_source_get_output_flags(input) & OBS_SOURCE_AUDIO)) - return RequestResult::Error(RequestStatus::InvalidResourceState, "The specified input does not support audio."); + return RequestResult::Error( + RequestStatus::InvalidResourceState, + "The specified input does not support audio."); float inputVolumeMul = obs_source_get_volume(input); float inputVolumeDb = obs_mul_to_db(inputVolumeMul); @@ -507,36 +557,46 @@ RequestResult RequestHandler::GetInputVolume(const Request& request) * @api requests * @category inputs */ -RequestResult RequestHandler::SetInputVolume(const Request& request) +RequestResult RequestHandler::SetInputVolume(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); + OBSSourceAutoRelease input = + request.ValidateInput("inputName", statusCode, comment); if (!input) return RequestResult::Error(statusCode, comment); if (!(obs_source_get_output_flags(input) & OBS_SOURCE_AUDIO)) - return RequestResult::Error(RequestStatus::InvalidResourceState, "The specified input does not support audio."); + return RequestResult::Error( + RequestStatus::InvalidResourceState, + "The specified input does not support audio."); bool hasMul = request.Contains("inputVolumeMul"); - if (hasMul && !request.ValidateOptionalNumber("inputVolumeMul", statusCode, comment, 0, 20)) + if (hasMul && !request.ValidateOptionalNumber( + "inputVolumeMul", statusCode, comment, 0, 20)) return RequestResult::Error(statusCode, comment); bool hasDb = request.Contains("inputVolumeDb"); - if (hasDb && !request.ValidateOptionalNumber("inputVolumeDb", statusCode, comment, -100, 26)) + if (hasDb && !request.ValidateOptionalNumber( + "inputVolumeDb", statusCode, comment, -100, 26)) return RequestResult::Error(statusCode, comment); if (hasMul && hasDb) - return RequestResult::Error(RequestStatus::TooManyRequestFields, "You may only specify one volume field."); + return RequestResult::Error( + RequestStatus::TooManyRequestFields, + "You may only specify one volume field."); if (!hasMul && !hasDb) - return RequestResult::Error(RequestStatus::MissingRequestField, "You must specify one volume field."); + return RequestResult::Error( + RequestStatus::MissingRequestField, + "You must specify one volume field."); float inputVolumeMul; if (hasMul) inputVolumeMul = request.RequestData["inputVolumeMul"]; else - inputVolumeMul = obs_db_to_mul(request.RequestData["inputVolumeDb"]); + inputVolumeMul = + obs_db_to_mul(request.RequestData["inputVolumeDb"]); obs_source_set_volume(input, inputVolumeMul); @@ -557,16 +617,19 @@ RequestResult RequestHandler::SetInputVolume(const Request& request) * @api requests * @category inputs */ -RequestResult RequestHandler::GetInputAudioBalance(const Request& request) +RequestResult RequestHandler::GetInputAudioBalance(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); + OBSSourceAutoRelease input = + request.ValidateInput("inputName", statusCode, comment); if (!input) return RequestResult::Error(statusCode, comment); if (!(obs_source_get_output_flags(input) & OBS_SOURCE_AUDIO)) - return RequestResult::Error(RequestStatus::InvalidResourceState, "The specified input does not support audio."); + return RequestResult::Error( + RequestStatus::InvalidResourceState, + "The specified input does not support audio."); json responseData; responseData["inputAudioBalance"] = obs_source_get_balance_value(input); @@ -587,16 +650,20 @@ RequestResult RequestHandler::GetInputAudioBalance(const Request& request) * @api requests * @category inputs */ -RequestResult RequestHandler::SetInputAudioBalance(const Request& request) +RequestResult RequestHandler::SetInputAudioBalance(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); - if (!(input && request.ValidateNumber("inputAudioBalance", statusCode, comment, 0.0, 1.0))) + OBSSourceAutoRelease input = + request.ValidateInput("inputName", statusCode, comment); + if (!(input && request.ValidateNumber("inputAudioBalance", statusCode, + comment, 0.0, 1.0))) return RequestResult::Error(statusCode, comment); if (!(obs_source_get_output_flags(input) & OBS_SOURCE_AUDIO)) - return RequestResult::Error(RequestStatus::InvalidResourceState, "The specified input does not support audio."); + return RequestResult::Error( + RequestStatus::InvalidResourceState, + "The specified input does not support audio."); float inputAudioBalance = request.RequestData["inputAudioBalance"]; obs_source_set_balance_value(input, inputAudioBalance); @@ -620,20 +687,24 @@ RequestResult RequestHandler::SetInputAudioBalance(const Request& request) * @api requests * @category inputs */ -RequestResult RequestHandler::GetInputAudioSyncOffset(const Request& request) +RequestResult RequestHandler::GetInputAudioSyncOffset(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); + OBSSourceAutoRelease input = + request.ValidateInput("inputName", statusCode, comment); if (!input) return RequestResult::Error(statusCode, comment); if (!(obs_source_get_output_flags(input) & OBS_SOURCE_AUDIO)) - return RequestResult::Error(RequestStatus::InvalidResourceState, "The specified input does not support audio."); + return RequestResult::Error( + RequestStatus::InvalidResourceState, + "The specified input does not support audio."); json responseData; // Offset is stored in nanoseconds in OBS. - responseData["inputAudioSyncOffset"] = obs_source_get_sync_offset(input) / 1000000; + responseData["inputAudioSyncOffset"] = + obs_source_get_sync_offset(input) / 1000000; return RequestResult::Success(responseData); } @@ -651,16 +722,21 @@ RequestResult RequestHandler::GetInputAudioSyncOffset(const Request& request) * @api requests * @category inputs */ -RequestResult RequestHandler::SetInputAudioSyncOffset(const Request& request) +RequestResult RequestHandler::SetInputAudioSyncOffset(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); - if (!(input && request.ValidateNumber("inputAudioSyncOffset", statusCode, comment, -950, 20000))) + OBSSourceAutoRelease input = + request.ValidateInput("inputName", statusCode, comment); + if (!(input && + request.ValidateNumber("inputAudioSyncOffset", statusCode, + comment, -950, 20000))) return RequestResult::Error(statusCode, comment); if (!(obs_source_get_output_flags(input) & OBS_SOURCE_AUDIO)) - return RequestResult::Error(RequestStatus::InvalidResourceState, "The specified input does not support audio."); + return RequestResult::Error( + RequestStatus::InvalidResourceState, + "The specified input does not support audio."); int64_t syncOffset = request.RequestData["inputAudioSyncOffset"]; obs_source_set_sync_offset(input, syncOffset * 1000000); @@ -688,19 +764,23 @@ RequestResult RequestHandler::SetInputAudioSyncOffset(const Request& request) * @api requests * @category inputs */ -RequestResult RequestHandler::GetInputAudioMonitorType(const Request& request) +RequestResult RequestHandler::GetInputAudioMonitorType(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); + OBSSourceAutoRelease input = + request.ValidateInput("inputName", statusCode, comment); if (!input) return RequestResult::Error(statusCode, comment); if (!(obs_source_get_output_flags(input) & OBS_SOURCE_AUDIO)) - return RequestResult::Error(RequestStatus::InvalidResourceState, "The specified input does not support audio."); + return RequestResult::Error( + RequestStatus::InvalidResourceState, + "The specified input does not support audio."); json responseData; - responseData["monitorType"] = Utils::Obs::StringHelper::GetInputMonitorType(input); + responseData["monitorType"] = + Utils::Obs::StringHelper::GetInputMonitorType(input); return RequestResult::Success(responseData); } @@ -718,19 +798,25 @@ RequestResult RequestHandler::GetInputAudioMonitorType(const Request& request) * @api requests * @category inputs */ -RequestResult RequestHandler::SetInputAudioMonitorType(const Request& request) +RequestResult RequestHandler::SetInputAudioMonitorType(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); - if (!(input && request.ValidateString("monitorType", statusCode, comment))) + OBSSourceAutoRelease input = + request.ValidateInput("inputName", statusCode, comment); + if (!(input && + request.ValidateString("monitorType", statusCode, comment))) return RequestResult::Error(statusCode, comment); if (!(obs_source_get_output_flags(input) & OBS_SOURCE_AUDIO)) - return RequestResult::Error(RequestStatus::InvalidResourceState, "The specified input does not support audio."); + return RequestResult::Error( + RequestStatus::InvalidResourceState, + "The specified input does not support audio."); if (!obs_audio_monitoring_available()) - return RequestResult::Error(RequestStatus::InvalidResourceState, "Audio monitoring is not available on this platform."); + return RequestResult::Error( + RequestStatus::InvalidResourceState, + "Audio monitoring is not available on this platform."); enum obs_monitoring_type monitorType; std::string monitorTypeString = request.RequestData["monitorType"]; @@ -741,7 +827,10 @@ RequestResult RequestHandler::SetInputAudioMonitorType(const Request& request) else if (monitorTypeString == "OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT") monitorType = OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT; else - return RequestResult::Error(RequestStatus::InvalidRequestField, std::string("Unknown monitor type: ") + monitorTypeString); + return RequestResult::Error( + RequestStatus::InvalidRequestField, + std::string("Unknown monitor type: ") + + monitorTypeString); obs_source_set_monitoring_type(input, monitorType); @@ -762,22 +851,26 @@ RequestResult RequestHandler::SetInputAudioMonitorType(const Request& request) * @api requests * @category inputs */ -RequestResult RequestHandler::GetInputAudioTracks(const Request& request) +RequestResult RequestHandler::GetInputAudioTracks(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); + OBSSourceAutoRelease input = + request.ValidateInput("inputName", statusCode, comment); if (!input) return RequestResult::Error(statusCode, comment); if (!(obs_source_get_output_flags(input) & OBS_SOURCE_AUDIO)) - return RequestResult::Error(RequestStatus::InvalidResourceState, "The specified input does not support audio."); + return RequestResult::Error( + RequestStatus::InvalidResourceState, + "The specified input does not support audio."); long long tracks = obs_source_get_audio_mixers(input); json inputAudioTracks; for (long long i = 0; i < MAX_AUDIO_MIXES; i++) { - inputAudioTracks[std::to_string(i + 1)] = (bool)((tracks >> i) & 1); + inputAudioTracks[std::to_string(i + 1)] = + (bool)((tracks >> i) & 1); } json responseData; @@ -799,16 +892,20 @@ RequestResult RequestHandler::GetInputAudioTracks(const Request& request) * @api requests * @category inputs */ -RequestResult RequestHandler::SetInputAudioTracks(const Request& request) +RequestResult RequestHandler::SetInputAudioTracks(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); - if (!input || !request.ValidateObject("inputAudioTracks", statusCode, comment)) + OBSSourceAutoRelease input = + request.ValidateInput("inputName", statusCode, comment); + if (!input || + !request.ValidateObject("inputAudioTracks", statusCode, comment)) return RequestResult::Error(statusCode, comment); if (!(obs_source_get_output_flags(input) & OBS_SOURCE_AUDIO)) - return RequestResult::Error(RequestStatus::InvalidResourceState, "The specified input does not support audio."); + return RequestResult::Error( + RequestStatus::InvalidResourceState, + "The specified input does not support audio."); json inputAudioTracks = request.RequestData["inputAudioTracks"]; @@ -821,7 +918,9 @@ RequestResult RequestHandler::SetInputAudioTracks(const Request& request) continue; if (!inputAudioTracks[track].is_boolean()) - return RequestResult::Error(RequestStatus::InvalidRequestFieldType, "The value of one of your tracks is not a boolean."); + return RequestResult::Error( + RequestStatus::InvalidRequestFieldType, + "The value of one of your tracks is not a boolean."); bool enabled = inputAudioTracks[track]; @@ -854,25 +953,34 @@ RequestResult RequestHandler::SetInputAudioTracks(const Request& request) * @api requests * @category inputs */ -RequestResult RequestHandler::GetInputPropertiesListPropertyItems(const Request& request) +RequestResult +RequestHandler::GetInputPropertiesListPropertyItems(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); - if (!(input && request.ValidateString("propertyName", statusCode, comment))) + OBSSourceAutoRelease input = + request.ValidateInput("inputName", statusCode, comment); + if (!(input && + request.ValidateString("propertyName", statusCode, comment))) return RequestResult::Error(statusCode, comment); std::string propertyName = request.RequestData["propertyName"]; OBSPropertiesAutoDestroy inputProperties = obs_source_properties(input); - obs_property_t *property = obs_properties_get(inputProperties, propertyName.c_str()); + obs_property_t *property = + obs_properties_get(inputProperties, propertyName.c_str()); if (!property) - return RequestResult::Error(RequestStatus::ResourceNotFound, "Unable to find a property by that name."); + return RequestResult::Error( + RequestStatus::ResourceNotFound, + "Unable to find a property by that name."); if (obs_property_get_type(property) != OBS_PROPERTY_LIST) - return RequestResult::Error(RequestStatus::InvalidResourceType, "The property found is not a list."); + return RequestResult::Error( + RequestStatus::InvalidResourceType, + "The property found is not a list."); json responseData; - responseData["propertyItems"] = Utils::Obs::ArrayHelper::GetListPropertyItems(property); + responseData["propertyItems"] = + Utils::Obs::ArrayHelper::GetListPropertyItems(property); return RequestResult::Success(responseData); } @@ -892,24 +1000,33 @@ RequestResult RequestHandler::GetInputPropertiesListPropertyItems(const Request& * @api requests * @category inputs */ -RequestResult RequestHandler::PressInputPropertiesButton(const Request& request) +RequestResult RequestHandler::PressInputPropertiesButton(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); - if (!(input && request.ValidateString("propertyName", statusCode, comment))) + OBSSourceAutoRelease input = + request.ValidateInput("inputName", statusCode, comment); + if (!(input && + request.ValidateString("propertyName", statusCode, comment))) return RequestResult::Error(statusCode, comment); std::string propertyName = request.RequestData["propertyName"]; OBSPropertiesAutoDestroy inputProperties = obs_source_properties(input); - obs_property_t *property = obs_properties_get(inputProperties, propertyName.c_str()); + obs_property_t *property = + obs_properties_get(inputProperties, propertyName.c_str()); if (!property) - return RequestResult::Error(RequestStatus::ResourceNotFound, "Unable to find a property by that name."); + return RequestResult::Error( + RequestStatus::ResourceNotFound, + "Unable to find a property by that name."); if (obs_property_get_type(property) != OBS_PROPERTY_BUTTON) - return RequestResult::Error(RequestStatus::InvalidResourceType, "The property found is not a button."); + return RequestResult::Error( + RequestStatus::InvalidResourceType, + "The property found is not a button."); if (!obs_property_enabled(property)) - return RequestResult::Error(RequestStatus::InvalidResourceState, "The property item found is not enabled."); + return RequestResult::Error( + RequestStatus::InvalidResourceState, + "The property item found is not enabled."); obs_property_button_clicked(property, input); diff --git a/src/requesthandler/RequestHandler_MediaInputs.cpp b/src/requesthandler/RequestHandler_MediaInputs.cpp index 3cc37502..9f53163b 100644 --- a/src/requesthandler/RequestHandler_MediaInputs.cpp +++ b/src/requesthandler/RequestHandler_MediaInputs.cpp @@ -22,7 +22,8 @@ with this program. If not, see bool IsMediaTimeValid(obs_source_t *input) { auto mediaState = obs_source_media_get_state(input); - return mediaState == OBS_MEDIA_STATE_PLAYING || mediaState == OBS_MEDIA_STATE_PAUSED; + return mediaState == OBS_MEDIA_STATE_PLAYING || + mediaState == OBS_MEDIA_STATE_PAUSED; } /** @@ -52,19 +53,22 @@ bool IsMediaTimeValid(obs_source_t *input) * @api requests * @category media inputs */ -RequestResult RequestHandler::GetMediaInputStatus(const Request& request) +RequestResult RequestHandler::GetMediaInputStatus(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); + OBSSourceAutoRelease input = + request.ValidateInput("inputName", statusCode, comment); if (!input) return RequestResult::Error(statusCode, comment); json responseData; - responseData["mediaState"] = Utils::Obs::StringHelper::GetMediaInputState(input); + responseData["mediaState"] = + Utils::Obs::StringHelper::GetMediaInputState(input); if (IsMediaTimeValid(input)) { - responseData["mediaDuration"] = obs_source_media_get_duration(input); + responseData["mediaDuration"] = + obs_source_media_get_duration(input); responseData["mediaCursor"] = obs_source_media_get_time(input); } else { responseData["mediaDuration"] = nullptr; @@ -89,16 +93,20 @@ RequestResult RequestHandler::GetMediaInputStatus(const Request& request) * @api requests * @category media inputs */ -RequestResult RequestHandler::SetMediaInputCursor(const Request& request) +RequestResult RequestHandler::SetMediaInputCursor(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); - if (!(input && request.ValidateNumber("mediaCursor", statusCode, comment, 0))) + OBSSourceAutoRelease input = + request.ValidateInput("inputName", statusCode, comment); + if (!(input && + request.ValidateNumber("mediaCursor", statusCode, comment, 0))) return RequestResult::Error(statusCode, comment); if (!IsMediaTimeValid(input)) - return RequestResult::Error(RequestStatus::InvalidResourceState, "The media input must be playing or paused in order to set the cursor position."); + return RequestResult::Error( + RequestStatus::InvalidResourceState, + "The media input must be playing or paused in order to set the cursor position."); int64_t mediaCursor = request.RequestData["mediaCursor"]; @@ -123,19 +131,24 @@ RequestResult RequestHandler::SetMediaInputCursor(const Request& request) * @api requests * @category media inputs */ -RequestResult RequestHandler::OffsetMediaInputCursor(const Request& request) +RequestResult RequestHandler::OffsetMediaInputCursor(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); - if (!(input && request.ValidateNumber("mediaCursorOffset", statusCode, comment))) + OBSSourceAutoRelease input = + request.ValidateInput("inputName", statusCode, comment); + if (!(input && + request.ValidateNumber("mediaCursorOffset", statusCode, comment))) return RequestResult::Error(statusCode, comment); if (!IsMediaTimeValid(input)) - return RequestResult::Error(RequestStatus::InvalidResourceState, "The media input must be playing or paused in order to set the cursor position."); + return RequestResult::Error( + RequestStatus::InvalidResourceState, + "The media input must be playing or paused in order to set the cursor position."); int64_t mediaCursorOffset = request.RequestData["mediaCursorOffset"]; - int64_t mediaCursor = obs_source_media_get_time(input) + mediaCursorOffset; + int64_t mediaCursor = + obs_source_media_get_time(input) + mediaCursorOffset; if (mediaCursor < 0) mediaCursor = 0; @@ -158,41 +171,46 @@ RequestResult RequestHandler::OffsetMediaInputCursor(const Request& request) * @api requests * @category media inputs */ -RequestResult RequestHandler::TriggerMediaInputAction(const Request& request) +RequestResult RequestHandler::TriggerMediaInputAction(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); - if (!(input && request.ValidateString("mediaAction", statusCode, comment))) + OBSSourceAutoRelease input = + request.ValidateInput("inputName", statusCode, comment); + if (!(input && + request.ValidateString("mediaAction", statusCode, comment))) return RequestResult::Error(statusCode, comment); std::string mediaActionString = request.RequestData["mediaAction"]; - auto mediaAction = Utils::Obs::EnumHelper::GetMediaInputAction(mediaActionString); + auto mediaAction = + Utils::Obs::EnumHelper::GetMediaInputAction(mediaActionString); switch (mediaAction) { - default: - case OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NONE: - return RequestResult::Error(RequestStatus::InvalidRequestField, "You have specified an invalid media input action."); - case OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PLAY: - // Shoutout to whoever implemented this API call like this - obs_source_media_play_pause(input, false); - break; - case OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PAUSE: - obs_source_media_play_pause(input, true); - break; - case OBS_WEBSOCKET_MEDIA_INPUT_ACTION_STOP: - obs_source_media_stop(input); - break; - case OBS_WEBSOCKET_MEDIA_INPUT_ACTION_RESTART: - // I'm only implementing this because I'm nice. I think its a really dumb action. - obs_source_media_restart(input); - break; - case OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NEXT: - obs_source_media_next(input); - break; - case OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PREVIOUS: - obs_source_media_previous(input); - break; + default: + case OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NONE: + return RequestResult::Error( + RequestStatus::InvalidRequestField, + "You have specified an invalid media input action."); + case OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PLAY: + // Shoutout to whoever implemented this API call like this + obs_source_media_play_pause(input, false); + break; + case OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PAUSE: + obs_source_media_play_pause(input, true); + break; + case OBS_WEBSOCKET_MEDIA_INPUT_ACTION_STOP: + obs_source_media_stop(input); + break; + case OBS_WEBSOCKET_MEDIA_INPUT_ACTION_RESTART: + // I'm only implementing this because I'm nice. I think its a really dumb action. + obs_source_media_restart(input); + break; + case OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NEXT: + obs_source_media_next(input); + break; + case OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PREVIOUS: + obs_source_media_previous(input); + break; } return RequestResult::Success(); diff --git a/src/requesthandler/RequestHandler_Outputs.cpp b/src/requesthandler/RequestHandler_Outputs.cpp index d85f839a..2b75afdd 100644 --- a/src/requesthandler/RequestHandler_Outputs.cpp +++ b/src/requesthandler/RequestHandler_Outputs.cpp @@ -46,10 +46,11 @@ static bool ReplayBufferAvailable() * @category outputs * @api requests */ -RequestResult RequestHandler::GetVirtualCamStatus(const Request&) +RequestResult RequestHandler::GetVirtualCamStatus(const Request &) { if (!VirtualCamAvailable()) - return RequestResult::Error(RequestStatus::InvalidResourceState, "VirtualCam is not available."); + return RequestResult::Error(RequestStatus::InvalidResourceState, + "VirtualCam is not available."); json responseData; responseData["outputActive"] = obs_frontend_virtualcam_active(); @@ -68,10 +69,11 @@ RequestResult RequestHandler::GetVirtualCamStatus(const Request&) * @category outputs * @api requests */ -RequestResult RequestHandler::ToggleVirtualCam(const Request&) +RequestResult RequestHandler::ToggleVirtualCam(const Request &) { if (!VirtualCamAvailable()) - return RequestResult::Error(RequestStatus::InvalidResourceState, "VirtualCam is not available."); + return RequestResult::Error(RequestStatus::InvalidResourceState, + "VirtualCam is not available."); bool outputActive = obs_frontend_virtualcam_active(); @@ -95,10 +97,11 @@ RequestResult RequestHandler::ToggleVirtualCam(const Request&) * @api requests * @category outputs */ -RequestResult RequestHandler::StartVirtualCam(const Request&) +RequestResult RequestHandler::StartVirtualCam(const Request &) { if (!VirtualCamAvailable()) - return RequestResult::Error(RequestStatus::InvalidResourceState, "VirtualCam is not available."); + return RequestResult::Error(RequestStatus::InvalidResourceState, + "VirtualCam is not available."); if (obs_frontend_virtualcam_active()) return RequestResult::Error(RequestStatus::OutputRunning); @@ -118,10 +121,11 @@ RequestResult RequestHandler::StartVirtualCam(const Request&) * @api requests * @category outputs */ -RequestResult RequestHandler::StopVirtualCam(const Request&) +RequestResult RequestHandler::StopVirtualCam(const Request &) { if (!VirtualCamAvailable()) - return RequestResult::Error(RequestStatus::InvalidResourceState, "VirtualCam is not available."); + return RequestResult::Error(RequestStatus::InvalidResourceState, + "VirtualCam is not available."); if (!obs_frontend_virtualcam_active()) return RequestResult::Error(RequestStatus::OutputNotRunning); @@ -143,10 +147,11 @@ RequestResult RequestHandler::StopVirtualCam(const Request&) * @category outputs * @api requests */ -RequestResult RequestHandler::GetReplayBufferStatus(const Request&) +RequestResult RequestHandler::GetReplayBufferStatus(const Request &) { if (!ReplayBufferAvailable()) - return RequestResult::Error(RequestStatus::InvalidResourceState, "Replay buffer is not available."); + return RequestResult::Error(RequestStatus::InvalidResourceState, + "Replay buffer is not available."); json responseData; responseData["outputActive"] = obs_frontend_replay_buffer_active(); @@ -165,10 +170,11 @@ RequestResult RequestHandler::GetReplayBufferStatus(const Request&) * @category outputs * @api requests */ -RequestResult RequestHandler::ToggleReplayBuffer(const Request&) +RequestResult RequestHandler::ToggleReplayBuffer(const Request &) { if (!ReplayBufferAvailable()) - return RequestResult::Error(RequestStatus::InvalidResourceState, "Replay buffer is not available."); + return RequestResult::Error(RequestStatus::InvalidResourceState, + "Replay buffer is not available."); bool outputActive = obs_frontend_replay_buffer_active(); @@ -192,10 +198,11 @@ RequestResult RequestHandler::ToggleReplayBuffer(const Request&) * @api requests * @category outputs */ -RequestResult RequestHandler::StartReplayBuffer(const Request&) +RequestResult RequestHandler::StartReplayBuffer(const Request &) { if (!ReplayBufferAvailable()) - return RequestResult::Error(RequestStatus::InvalidResourceState, "Replay buffer is not available."); + return RequestResult::Error(RequestStatus::InvalidResourceState, + "Replay buffer is not available."); if (obs_frontend_replay_buffer_active()) return RequestResult::Error(RequestStatus::OutputRunning); @@ -215,10 +222,11 @@ RequestResult RequestHandler::StartReplayBuffer(const Request&) * @api requests * @category outputs */ -RequestResult RequestHandler::StopReplayBuffer(const Request&) +RequestResult RequestHandler::StopReplayBuffer(const Request &) { if (!ReplayBufferAvailable()) - return RequestResult::Error(RequestStatus::InvalidResourceState, "Replay buffer is not available."); + return RequestResult::Error(RequestStatus::InvalidResourceState, + "Replay buffer is not available."); if (!obs_frontend_replay_buffer_active()) return RequestResult::Error(RequestStatus::OutputNotRunning); @@ -238,10 +246,11 @@ RequestResult RequestHandler::StopReplayBuffer(const Request&) * @api requests * @category outputs */ -RequestResult RequestHandler::SaveReplayBuffer(const Request&) +RequestResult RequestHandler::SaveReplayBuffer(const Request &) { if (!ReplayBufferAvailable()) - return RequestResult::Error(RequestStatus::InvalidResourceState, "Replay buffer is not available."); + return RequestResult::Error(RequestStatus::InvalidResourceState, + "Replay buffer is not available."); if (!obs_frontend_replay_buffer_active()) return RequestResult::Error(RequestStatus::OutputNotRunning); @@ -263,15 +272,17 @@ RequestResult RequestHandler::SaveReplayBuffer(const Request&) * @api requests * @category outputs */ -RequestResult RequestHandler::GetLastReplayBufferReplay(const Request&) +RequestResult RequestHandler::GetLastReplayBufferReplay(const Request &) { if (!ReplayBufferAvailable()) - return RequestResult::Error(RequestStatus::InvalidResourceState, "Replay buffer is not available."); + return RequestResult::Error(RequestStatus::InvalidResourceState, + "Replay buffer is not available."); if (!obs_frontend_replay_buffer_active()) return RequestResult::Error(RequestStatus::OutputNotRunning); json responseData; - responseData["savedReplayPath"] = Utils::Obs::StringHelper::GetLastReplayBufferFilePath(); + responseData["savedReplayPath"] = + Utils::Obs::StringHelper::GetLastReplayBufferFilePath(); return RequestResult::Success(responseData); } diff --git a/src/requesthandler/RequestHandler_Record.cpp b/src/requesthandler/RequestHandler_Record.cpp index 9eb248ea..7725c19e 100644 --- a/src/requesthandler/RequestHandler_Record.cpp +++ b/src/requesthandler/RequestHandler_Record.cpp @@ -35,18 +35,21 @@ with this program. If not, see * @api requests * @category record */ -RequestResult RequestHandler::GetRecordStatus(const Request&) +RequestResult RequestHandler::GetRecordStatus(const Request &) { OBSOutputAutoRelease recordOutput = obs_frontend_get_recording_output(); - uint64_t outputDuration = Utils::Obs::NumberHelper::GetOutputDuration(recordOutput); + uint64_t outputDuration = + Utils::Obs::NumberHelper::GetOutputDuration(recordOutput); json responseData; responseData["outputActive"] = obs_output_active(recordOutput); responseData["outputPaused"] = obs_output_paused(recordOutput); - responseData["outputTimecode"] = Utils::Obs::StringHelper::DurationToTimecode(outputDuration); + responseData["outputTimecode"] = + Utils::Obs::StringHelper::DurationToTimecode(outputDuration); responseData["outputDuration"] = outputDuration; - responseData["outputBytes"] = (uint64_t)obs_output_get_total_bytes(recordOutput); + responseData["outputBytes"] = + (uint64_t)obs_output_get_total_bytes(recordOutput); return RequestResult::Success(responseData); } @@ -61,7 +64,7 @@ RequestResult RequestHandler::GetRecordStatus(const Request&) * @api requests * @category record */ -RequestResult RequestHandler::ToggleRecord(const Request&) +RequestResult RequestHandler::ToggleRecord(const Request &) { json responseData; if (obs_frontend_recording_active()) { @@ -85,7 +88,7 @@ RequestResult RequestHandler::ToggleRecord(const Request&) * @api requests * @category record */ -RequestResult RequestHandler::StartRecord(const Request&) +RequestResult RequestHandler::StartRecord(const Request &) { if (obs_frontend_recording_active()) return RequestResult::Error(RequestStatus::OutputRunning); @@ -106,7 +109,7 @@ RequestResult RequestHandler::StartRecord(const Request&) * @api requests * @category record */ -RequestResult RequestHandler::StopRecord(const Request&) +RequestResult RequestHandler::StopRecord(const Request &) { if (!obs_frontend_recording_active()) return RequestResult::Error(RequestStatus::OutputNotRunning); @@ -127,7 +130,7 @@ RequestResult RequestHandler::StopRecord(const Request&) * @api requests * @category record */ -RequestResult RequestHandler::ToggleRecordPause(const Request&) +RequestResult RequestHandler::ToggleRecordPause(const Request &) { json responseData; if (obs_frontend_recording_paused()) { @@ -151,7 +154,7 @@ RequestResult RequestHandler::ToggleRecordPause(const Request&) * @api requests * @category record */ -RequestResult RequestHandler::PauseRecord(const Request&) +RequestResult RequestHandler::PauseRecord(const Request &) { if (obs_frontend_recording_paused()) return RequestResult::Error(RequestStatus::OutputPaused); @@ -172,7 +175,7 @@ RequestResult RequestHandler::PauseRecord(const Request&) * @api requests * @category record */ -RequestResult RequestHandler::ResumeRecord(const Request&) +RequestResult RequestHandler::ResumeRecord(const Request &) { if (!obs_frontend_recording_paused()) return RequestResult::Error(RequestStatus::OutputNotPaused); diff --git a/src/requesthandler/RequestHandler_SceneItems.cpp b/src/requesthandler/RequestHandler_SceneItems.cpp index 2b1d5fd9..fb790431 100644 --- a/src/requesthandler/RequestHandler_SceneItems.cpp +++ b/src/requesthandler/RequestHandler_SceneItems.cpp @@ -35,16 +35,18 @@ with this program. If not, see * @api requests * @category scene items */ -RequestResult RequestHandler::GetSceneItemList(const Request& request) +RequestResult RequestHandler::GetSceneItemList(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease scene = request.ValidateScene("sceneName", statusCode, comment); + OBSSourceAutoRelease scene = + request.ValidateScene("sceneName", statusCode, comment); if (!scene) return RequestResult::Error(statusCode, comment); json responseData; - responseData["sceneItems"] = Utils::Obs::ArrayHelper::GetSceneItemList(obs_scene_from_source(scene)); + responseData["sceneItems"] = Utils::Obs::ArrayHelper::GetSceneItemList( + obs_scene_from_source(scene)); return RequestResult::Success(responseData); } @@ -67,16 +69,19 @@ RequestResult RequestHandler::GetSceneItemList(const Request& request) * @api requests * @category scene items */ -RequestResult RequestHandler::GetGroupSceneItemList(const Request& request) +RequestResult RequestHandler::GetGroupSceneItemList(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease scene = request.ValidateScene("sceneName", statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_GROUP_ONLY); + OBSSourceAutoRelease scene = + request.ValidateScene("sceneName", statusCode, comment, + OBS_WEBSOCKET_SCENE_FILTER_GROUP_ONLY); if (!scene) return RequestResult::Error(statusCode, comment); json responseData; - responseData["sceneItems"] = Utils::Obs::ArrayHelper::GetSceneItemList(obs_group_from_source(scene)); + responseData["sceneItems"] = Utils::Obs::ArrayHelper::GetSceneItemList( + obs_group_from_source(scene)); return RequestResult::Success(responseData); } @@ -99,26 +104,34 @@ RequestResult RequestHandler::GetGroupSceneItemList(const Request& request) * @api requests * @category scene items */ -RequestResult RequestHandler::GetSceneItemId(const Request& request) +RequestResult RequestHandler::GetSceneItemId(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSceneAutoRelease scene = request.ValidateScene2("sceneName", statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); - if (!(scene && request.ValidateString("sourceName", statusCode, comment))) + OBSSceneAutoRelease scene = request.ValidateScene2( + "sceneName", statusCode, comment, + OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); + if (!(scene && + request.ValidateString("sourceName", statusCode, comment))) return RequestResult::Error(statusCode, comment); std::string sourceName = request.RequestData["sourceName"]; int offset = 0; if (request.Contains("searchOffset")) { - if (!request.ValidateOptionalNumber("searchOffset", statusCode, comment, -1)) + if (!request.ValidateOptionalNumber("searchOffset", statusCode, + comment, -1)) return RequestResult::Error(statusCode, comment); offset = request.RequestData["searchOffset"]; } - OBSSceneItemAutoRelease item = Utils::Obs::SearchHelper::GetSceneItemByName(scene, sourceName, offset); + OBSSceneItemAutoRelease item = + Utils::Obs::SearchHelper::GetSceneItemByName(scene, sourceName, + offset); if (!item) - return RequestResult::Error(RequestStatus::ResourceNotFound, "No scene items were found in the specified scene by that name or offset."); + return RequestResult::Error( + RequestStatus::ResourceNotFound, + "No scene items were found in the specified scene by that name or offset."); json responseData; responseData["sceneItemId"] = obs_sceneitem_get_id(item); @@ -144,33 +157,43 @@ RequestResult RequestHandler::GetSceneItemId(const Request& request) * @api requests * @category scene items */ -RequestResult RequestHandler::CreateSceneItem(const Request& request) +RequestResult RequestHandler::CreateSceneItem(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease sceneSource = request.ValidateScene("sceneName", statusCode, comment); + OBSSourceAutoRelease sceneSource = + request.ValidateScene("sceneName", statusCode, comment); if (!sceneSource) return RequestResult::Error(statusCode, comment); OBSScene scene = obs_scene_from_source(sceneSource); - OBSSourceAutoRelease source = request.ValidateSource("sourceName", statusCode, comment); + OBSSourceAutoRelease source = + request.ValidateSource("sourceName", statusCode, comment); if (!source) return RequestResult::Error(statusCode, comment); - if (request.RequestData["sceneName"] == request.RequestData["sourceName"]) - return RequestResult::Error(RequestStatus::CannotAct, "You cannot create scene item of a scene within itself."); + if (request.RequestData["sceneName"] == + request.RequestData["sourceName"]) + return RequestResult::Error( + RequestStatus::CannotAct, + "You cannot create scene item of a scene within itself."); bool sceneItemEnabled = true; if (request.Contains("sceneItemEnabled")) { - if (!request.ValidateOptionalBoolean("sceneItemEnabled", statusCode, comment)) + if (!request.ValidateOptionalBoolean("sceneItemEnabled", + statusCode, comment)) return RequestResult::Error(statusCode, comment); sceneItemEnabled = request.RequestData["sceneItemEnabled"]; } - OBSSceneItemAutoRelease sceneItem = Utils::Obs::ActionHelper::CreateSceneItem(source, scene, sceneItemEnabled); + OBSSceneItemAutoRelease sceneItem = + Utils::Obs::ActionHelper::CreateSceneItem(source, scene, + sceneItemEnabled); if (!sceneItem) - return RequestResult::Error(RequestStatus::ResourceCreationFailed, "Failed to create the scene item."); + return RequestResult::Error( + RequestStatus::ResourceCreationFailed, + "Failed to create the scene item."); json responseData; responseData["sceneItemId"] = obs_sceneitem_get_id(sceneItem); @@ -193,11 +216,12 @@ RequestResult RequestHandler::CreateSceneItem(const Request& request) * @api requests * @category scene items */ -RequestResult RequestHandler::RemoveSceneItem(const Request& request) +RequestResult RequestHandler::RemoveSceneItem(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment); + OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem( + "sceneName", "sceneItemId", statusCode, comment); if (!sceneItem) return RequestResult::Error(statusCode, comment); @@ -225,29 +249,37 @@ RequestResult RequestHandler::RemoveSceneItem(const Request& request) * @api requests * @category scene items */ -RequestResult RequestHandler::DuplicateSceneItem(const Request& request) +RequestResult RequestHandler::DuplicateSceneItem(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment); + OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem( + "sceneName", "sceneItemId", statusCode, comment); if (!sceneItem) return RequestResult::Error(statusCode, comment); // Get destination scene obs_scene_t *destinationScene; if (request.Contains("destinationSceneName")) { - destinationScene = request.ValidateScene2("destinationSceneName", statusCode, comment); + destinationScene = request.ValidateScene2( + "destinationSceneName", statusCode, comment); if (!destinationScene) return RequestResult::Error(statusCode, comment); } else { - destinationScene = obs_scene_get_ref(obs_sceneitem_get_scene(sceneItem)); + destinationScene = + obs_scene_get_ref(obs_sceneitem_get_scene(sceneItem)); if (!destinationScene) - return RequestResult::Error(RequestStatus::RequestProcessingFailed, "Internal error: Failed to get ref for scene of scene item."); + return RequestResult::Error( + RequestStatus::RequestProcessingFailed, + "Internal error: Failed to get ref for scene of scene item."); } - if (obs_sceneitem_is_group(sceneItem) && obs_sceneitem_get_scene(sceneItem) == destinationScene) { + if (obs_sceneitem_is_group(sceneItem) && + obs_sceneitem_get_scene(sceneItem) == destinationScene) { obs_scene_release(destinationScene); - return RequestResult::Error(RequestStatus::ResourceCreationFailed, "Scenes may only have one instance of a group."); + return RequestResult::Error( + RequestStatus::ResourceCreationFailed, + "Scenes may only have one instance of a group."); } // Get scene item details @@ -259,10 +291,15 @@ RequestResult RequestHandler::DuplicateSceneItem(const Request& request) obs_sceneitem_get_crop(sceneItem, &sceneItemCrop); // Create the new item - OBSSceneItemAutoRelease newSceneItem = Utils::Obs::ActionHelper::CreateSceneItem(sceneItemSource, destinationScene, sceneItemEnabled, &sceneItemTransform, &sceneItemCrop); + OBSSceneItemAutoRelease newSceneItem = + Utils::Obs::ActionHelper::CreateSceneItem( + sceneItemSource, destinationScene, sceneItemEnabled, + &sceneItemTransform, &sceneItemCrop); obs_scene_release(destinationScene); if (!newSceneItem) - return RequestResult::Error(RequestStatus::ResourceCreationFailed, "Failed to create the scene item."); + return RequestResult::Error( + RequestStatus::ResourceCreationFailed, + "Failed to create the scene item."); json responseData; responseData["sceneItemId"] = obs_sceneitem_get_id(newSceneItem); @@ -287,16 +324,19 @@ RequestResult RequestHandler::DuplicateSceneItem(const Request& request) * @api requests * @category scene items */ -RequestResult RequestHandler::GetSceneItemTransform(const Request& request) +RequestResult RequestHandler::GetSceneItemTransform(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); + OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem( + "sceneName", "sceneItemId", statusCode, comment, + OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); if (!sceneItem) return RequestResult::Error(statusCode, comment); json responseData; - responseData["sceneItemTransform"] = Utils::Obs::ObjectHelper::GetSceneItemTransform(sceneItem); + responseData["sceneItemTransform"] = + Utils::Obs::ObjectHelper::GetSceneItemTransform(sceneItem); return RequestResult::Success(responseData); } @@ -315,12 +355,15 @@ RequestResult RequestHandler::GetSceneItemTransform(const Request& request) * @api requests * @category scene items */ -RequestResult RequestHandler::SetSceneItemTransform(const Request& request) +RequestResult RequestHandler::SetSceneItemTransform(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); - if (!(sceneItem && request.ValidateObject("sceneItemTransform", statusCode, comment))) + OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem( + "sceneName", "sceneItemId", statusCode, comment, + OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); + if (!(sceneItem && request.ValidateObject("sceneItemTransform", + statusCode, comment))) return RequestResult::Error(statusCode, comment); // Create a fake request to use checks on the sub object @@ -338,20 +381,23 @@ RequestResult RequestHandler::SetSceneItemTransform(const Request& request) float sourceHeight = float(obs_source_get_height(source)); if (r.Contains("positionX")) { - if (!r.ValidateOptionalNumber("positionX", statusCode, comment, -90001.0, 90001.0)) + if (!r.ValidateOptionalNumber("positionX", statusCode, comment, + -90001.0, 90001.0)) return RequestResult::Error(statusCode, comment); sceneItemTransform.pos.x = r.RequestData["positionX"]; transformChanged = true; } if (r.Contains("positionY")) { - if (!r.ValidateOptionalNumber("positionY", statusCode, comment, -90001.0, 90001.0)) + if (!r.ValidateOptionalNumber("positionY", statusCode, comment, + -90001.0, 90001.0)) return RequestResult::Error(statusCode, comment); sceneItemTransform.pos.y = r.RequestData["positionY"]; transformChanged = true; } if (r.Contains("rotation")) { - if (!r.ValidateOptionalNumber("rotation", statusCode, comment, -360.0, 360.0)) + if (!r.ValidateOptionalNumber("rotation", statusCode, comment, + -360.0, 360.0)) return RequestResult::Error(statusCode, comment); sceneItemTransform.rot = r.RequestData["rotation"]; transformChanged = true; @@ -363,86 +409,110 @@ RequestResult RequestHandler::SetSceneItemTransform(const Request& request) float scaleX = r.RequestData["scaleX"]; float finalWidth = scaleX * sourceWidth; if (!(finalWidth > -90001.0 && finalWidth < 90001.0)) - return RequestResult::Error(RequestStatus::RequestFieldOutOfRange, "The field scaleX is too small or large for the current source resolution."); + return RequestResult::Error( + RequestStatus::RequestFieldOutOfRange, + "The field scaleX is too small or large for the current source resolution."); sceneItemTransform.scale.x = scaleX; transformChanged = true; } if (r.Contains("scaleY")) { - if (!r.ValidateOptionalNumber("scaleY", statusCode, comment, -90001.0, 90001.0)) + if (!r.ValidateOptionalNumber("scaleY", statusCode, comment, + -90001.0, 90001.0)) return RequestResult::Error(statusCode, comment); float scaleY = r.RequestData["scaleY"]; float finalHeight = scaleY * sourceHeight; if (!(finalHeight > -90001.0 && finalHeight < 90001.0)) - return RequestResult::Error(RequestStatus::RequestFieldOutOfRange, "The field scaleY is too small or large for the current source resolution."); + return RequestResult::Error( + RequestStatus::RequestFieldOutOfRange, + "The field scaleY is too small or large for the current source resolution."); sceneItemTransform.scale.y = scaleY; transformChanged = true; } if (r.Contains("alignment")) { - if (!r.ValidateOptionalNumber("alignment", statusCode, comment, 0, std::numeric_limits::max())) + if (!r.ValidateOptionalNumber( + "alignment", statusCode, comment, 0, + std::numeric_limits::max())) return RequestResult::Error(statusCode, comment); sceneItemTransform.alignment = r.RequestData["alignment"]; transformChanged = true; } if (r.Contains("boundsType")) { - if (!r.ValidateOptionalString("boundsType", statusCode, comment)) + if (!r.ValidateOptionalString("boundsType", statusCode, + comment)) return RequestResult::Error(statusCode, comment); std::string boundsTypeString = r.RequestData["boundsType"]; - enum obs_bounds_type boundsType = Utils::Obs::EnumHelper::GetSceneItemBoundsType(boundsTypeString); - if (boundsType == OBS_BOUNDS_NONE && boundsTypeString != "OBS_BOUNDS_NONE") - return RequestResult::Error(RequestStatus::InvalidRequestField, "The field boundsType has an invalid value."); + enum obs_bounds_type boundsType = + Utils::Obs::EnumHelper::GetSceneItemBoundsType( + boundsTypeString); + if (boundsType == OBS_BOUNDS_NONE && + boundsTypeString != "OBS_BOUNDS_NONE") + return RequestResult::Error( + RequestStatus::InvalidRequestField, + "The field boundsType has an invalid value."); sceneItemTransform.bounds_type = boundsType; transformChanged = true; } if (r.Contains("boundsAlignment")) { - if (!r.ValidateOptionalNumber("boundsAlignment", statusCode, comment, 0, std::numeric_limits::max())) + if (!r.ValidateOptionalNumber( + "boundsAlignment", statusCode, comment, 0, + std::numeric_limits::max())) return RequestResult::Error(statusCode, comment); - sceneItemTransform.bounds_alignment = r.RequestData["boundsAlignment"]; + sceneItemTransform.bounds_alignment = + r.RequestData["boundsAlignment"]; transformChanged = true; } if (r.Contains("boundsWidth")) { - if (!r.ValidateOptionalNumber("boundsWidth", statusCode, comment, 1.0, 90001.0)) + if (!r.ValidateOptionalNumber("boundsWidth", statusCode, + comment, 1.0, 90001.0)) return RequestResult::Error(statusCode, comment); sceneItemTransform.bounds.x = r.RequestData["boundsWidth"]; transformChanged = true; } if (r.Contains("boundsHeight")) { - if (!r.ValidateOptionalNumber("boundsHeight", statusCode, comment, 1.0, 90001.0)) + if (!r.ValidateOptionalNumber("boundsHeight", statusCode, + comment, 1.0, 90001.0)) return RequestResult::Error(statusCode, comment); sceneItemTransform.bounds.y = r.RequestData["boundsHeight"]; transformChanged = true; } if (r.Contains("cropLeft")) { - if (!r.ValidateOptionalNumber("cropLeft", statusCode, comment, 0.0, 100000.0)) + if (!r.ValidateOptionalNumber("cropLeft", statusCode, comment, + 0.0, 100000.0)) return RequestResult::Error(statusCode, comment); sceneItemCrop.left = r.RequestData["cropLeft"]; cropChanged = true; } if (r.Contains("cropRight")) { - if (!r.ValidateOptionalNumber("cropRight", statusCode, comment, 0.0, 100000.0)) + if (!r.ValidateOptionalNumber("cropRight", statusCode, comment, + 0.0, 100000.0)) return RequestResult::Error(statusCode, comment); sceneItemCrop.right = r.RequestData["cropRight"]; cropChanged = true; } if (r.Contains("cropTop")) { - if (!r.ValidateOptionalNumber("cropTop", statusCode, comment, 0.0, 100000.0)) + if (!r.ValidateOptionalNumber("cropTop", statusCode, comment, + 0.0, 100000.0)) return RequestResult::Error(statusCode, comment); sceneItemCrop.top = r.RequestData["cropTop"]; cropChanged = true; } if (r.Contains("cropBottom")) { - if (!r.ValidateOptionalNumber("cropBottom", statusCode, comment, 0.0, 100000.0)) + if (!r.ValidateOptionalNumber("cropBottom", statusCode, comment, + 0.0, 100000.0)) return RequestResult::Error(statusCode, comment); sceneItemCrop.bottom = r.RequestData["cropBottom"]; cropChanged = true; } if (!transformChanged && !cropChanged) - return RequestResult::Error(RequestStatus::CannotAct, "You have not provided any valid transform changes."); + return RequestResult::Error( + RequestStatus::CannotAct, + "You have not provided any valid transform changes."); if (transformChanged) obs_sceneitem_set_info(sceneItem, &sceneItemTransform); @@ -470,11 +540,13 @@ RequestResult RequestHandler::SetSceneItemTransform(const Request& request) * @api requests * @category scene items */ -RequestResult RequestHandler::GetSceneItemEnabled(const Request& request) +RequestResult RequestHandler::GetSceneItemEnabled(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); + OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem( + "sceneName", "sceneItemId", statusCode, comment, + OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); if (!sceneItem) return RequestResult::Error(statusCode, comment); @@ -500,12 +572,15 @@ RequestResult RequestHandler::GetSceneItemEnabled(const Request& request) * @api requests * @category scene items */ -RequestResult RequestHandler::SetSceneItemEnabled(const Request& request) +RequestResult RequestHandler::SetSceneItemEnabled(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); - if (!(sceneItem && request.ValidateBoolean("sceneItemEnabled", statusCode, comment))) + OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem( + "sceneName", "sceneItemId", statusCode, comment, + OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); + if (!(sceneItem && + request.ValidateBoolean("sceneItemEnabled", statusCode, comment))) return RequestResult::Error(statusCode, comment); bool sceneItemEnabled = request.RequestData["sceneItemEnabled"]; @@ -532,11 +607,13 @@ RequestResult RequestHandler::SetSceneItemEnabled(const Request& request) * @api requests * @category scene items */ -RequestResult RequestHandler::GetSceneItemLocked(const Request& request) +RequestResult RequestHandler::GetSceneItemLocked(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); + OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem( + "sceneName", "sceneItemId", statusCode, comment, + OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); if (!sceneItem) return RequestResult::Error(statusCode, comment); @@ -562,12 +639,15 @@ RequestResult RequestHandler::GetSceneItemLocked(const Request& request) * @api requests * @category scene items */ -RequestResult RequestHandler::SetSceneItemLocked(const Request& request) +RequestResult RequestHandler::SetSceneItemLocked(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); - if (!(sceneItem && request.ValidateBoolean("sceneItemLocked", statusCode, comment))) + OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem( + "sceneName", "sceneItemId", statusCode, comment, + OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); + if (!(sceneItem && + request.ValidateBoolean("sceneItemLocked", statusCode, comment))) return RequestResult::Error(statusCode, comment); bool sceneItemLocked = request.RequestData["sceneItemLocked"]; @@ -596,16 +676,19 @@ RequestResult RequestHandler::SetSceneItemLocked(const Request& request) * @api requests * @category scene items */ -RequestResult RequestHandler::GetSceneItemIndex(const Request& request) +RequestResult RequestHandler::GetSceneItemIndex(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); + OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem( + "sceneName", "sceneItemId", statusCode, comment, + OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); if (!sceneItem) return RequestResult::Error(statusCode, comment); json responseData; - responseData["sceneItemIndex"] = obs_sceneitem_get_order_position(sceneItem); + responseData["sceneItemIndex"] = + obs_sceneitem_get_order_position(sceneItem); return RequestResult::Success(responseData); } @@ -626,12 +709,15 @@ RequestResult RequestHandler::GetSceneItemIndex(const Request& request) * @api requests * @category scene items */ -RequestResult RequestHandler::SetSceneItemIndex(const Request& request) +RequestResult RequestHandler::SetSceneItemIndex(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); - if (!(sceneItem && request.ValidateNumber("sceneItemIndex", statusCode, comment, 0, 8192))) + OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem( + "sceneName", "sceneItemId", statusCode, comment, + OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); + if (!(sceneItem && request.ValidateNumber("sceneItemIndex", statusCode, + comment, 0, 8192))) return RequestResult::Error(statusCode, comment); int sceneItemIndex = request.RequestData["sceneItemIndex"]; @@ -668,18 +754,21 @@ RequestResult RequestHandler::SetSceneItemIndex(const Request& request) * @api requests * @category scene items */ -RequestResult RequestHandler::GetSceneItemBlendMode(const Request& request) +RequestResult RequestHandler::GetSceneItemBlendMode(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); + OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem( + "sceneName", "sceneItemId", statusCode, comment, + OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); if (!sceneItem) return RequestResult::Error(statusCode, comment); auto blendMode = obs_sceneitem_get_blending_mode(sceneItem); json responseData; - responseData["sceneItemBlendMode"] = Utils::Obs::StringHelper::GetSceneItemBlendMode(blendMode); + responseData["sceneItemBlendMode"] = + Utils::Obs::StringHelper::GetSceneItemBlendMode(blendMode); return RequestResult::Success(responseData); } @@ -700,19 +789,26 @@ RequestResult RequestHandler::GetSceneItemBlendMode(const Request& request) * @api requests * @category scene items */ -RequestResult RequestHandler::SetSceneItemBlendMode(const Request& request) +RequestResult RequestHandler::SetSceneItemBlendMode(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); - if (!(sceneItem && request.ValidateString("sceneItemBlendMode", statusCode, comment))) + OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem( + "sceneName", "sceneItemId", statusCode, comment, + OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); + if (!(sceneItem && request.ValidateString("sceneItemBlendMode", + statusCode, comment))) return RequestResult::Error(statusCode, comment); std::string blendModeString = request.RequestData["sceneItemBlendMode"]; - auto blendMode = Utils::Obs::EnumHelper::GetSceneItemBlendMode(blendModeString); - if (blendMode == OBS_BLEND_NORMAL && blendModeString != "OBS_BLEND_NORMAL") - return RequestResult::Error(RequestStatus::InvalidRequestField, "The field sceneItemBlendMode has an invalid value."); + auto blendMode = + Utils::Obs::EnumHelper::GetSceneItemBlendMode(blendModeString); + if (blendMode == OBS_BLEND_NORMAL && + blendModeString != "OBS_BLEND_NORMAL") + return RequestResult::Error( + RequestStatus::InvalidRequestField, + "The field sceneItemBlendMode has an invalid value."); obs_sceneitem_set_blending_mode(sceneItem, blendMode); @@ -720,34 +816,45 @@ RequestResult RequestHandler::SetSceneItemBlendMode(const Request& request) } // Intentionally undocumented -RequestResult RequestHandler::GetSceneItemPrivateSettings(const Request& request) +RequestResult +RequestHandler::GetSceneItemPrivateSettings(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); + OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem( + "sceneName", "sceneItemId", statusCode, comment, + OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); if (!sceneItem) return RequestResult::Error(statusCode, comment); - OBSDataAutoRelease privateSettings = obs_sceneitem_get_private_settings(sceneItem); + OBSDataAutoRelease privateSettings = + obs_sceneitem_get_private_settings(sceneItem); json responseData; - responseData["sceneItemSettings"] = Utils::Json::ObsDataToJson(privateSettings); + responseData["sceneItemSettings"] = + Utils::Json::ObsDataToJson(privateSettings); return RequestResult::Success(responseData); } // Intentionally undocumented -RequestResult RequestHandler::SetSceneItemPrivateSettings(const Request& request) +RequestResult +RequestHandler::SetSceneItemPrivateSettings(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem("sceneName", "sceneItemId", statusCode, comment, OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); - if (!sceneItem || !request.ValidateObject("sceneItemSettings", statusCode, comment)) + OBSSceneItemAutoRelease sceneItem = request.ValidateSceneItem( + "sceneName", "sceneItemId", statusCode, comment, + OBS_WEBSOCKET_SCENE_FILTER_SCENE_OR_GROUP); + if (!sceneItem || + !request.ValidateObject("sceneItemSettings", statusCode, comment)) return RequestResult::Error(statusCode, comment); - OBSDataAutoRelease privateSettings = obs_sceneitem_get_private_settings(sceneItem); + OBSDataAutoRelease privateSettings = + obs_sceneitem_get_private_settings(sceneItem); - OBSDataAutoRelease newSettings = Utils::Json::JsonToObsData(request.RequestData["sceneItemSettings"]); + OBSDataAutoRelease newSettings = Utils::Json::JsonToObsData( + request.RequestData["sceneItemSettings"]); // Always overlays to prevent destroying internal source unintentionally obs_data_apply(privateSettings, newSettings); diff --git a/src/requesthandler/RequestHandler_Scenes.cpp b/src/requesthandler/RequestHandler_Scenes.cpp index d4d376fd..02583276 100644 --- a/src/requesthandler/RequestHandler_Scenes.cpp +++ b/src/requesthandler/RequestHandler_Scenes.cpp @@ -33,19 +33,23 @@ with this program. If not, see * @api requests * @category scenes */ -RequestResult RequestHandler::GetSceneList(const Request&) +RequestResult RequestHandler::GetSceneList(const Request &) { json responseData; - OBSSourceAutoRelease currentProgramScene = obs_frontend_get_current_scene(); + OBSSourceAutoRelease currentProgramScene = + obs_frontend_get_current_scene(); if (currentProgramScene) - responseData["currentProgramSceneName"] = obs_source_get_name(currentProgramScene); + responseData["currentProgramSceneName"] = + obs_source_get_name(currentProgramScene); else responseData["currentProgramSceneName"] = nullptr; - OBSSourceAutoRelease currentPreviewScene = obs_frontend_get_current_preview_scene(); + OBSSourceAutoRelease currentPreviewScene = + obs_frontend_get_current_preview_scene(); if (currentPreviewScene) - responseData["currentPreviewSceneName"] = obs_source_get_name(currentPreviewScene); + responseData["currentPreviewSceneName"] = + obs_source_get_name(currentPreviewScene); else responseData["currentPreviewSceneName"] = nullptr; @@ -68,7 +72,7 @@ RequestResult RequestHandler::GetSceneList(const Request&) * @api requests * @category scenes */ -RequestResult RequestHandler::GetGroupList(const Request&) +RequestResult RequestHandler::GetGroupList(const Request &) { json responseData; @@ -89,11 +93,13 @@ RequestResult RequestHandler::GetGroupList(const Request&) * @api requests * @category scenes */ -RequestResult RequestHandler::GetCurrentProgramScene(const Request&) +RequestResult RequestHandler::GetCurrentProgramScene(const Request &) { json responseData; - OBSSourceAutoRelease currentProgramScene = obs_frontend_get_current_scene(); - responseData["currentProgramSceneName"] = obs_source_get_name(currentProgramScene); + OBSSourceAutoRelease currentProgramScene = + obs_frontend_get_current_scene(); + responseData["currentProgramSceneName"] = + obs_source_get_name(currentProgramScene); return RequestResult::Success(responseData); } @@ -110,11 +116,12 @@ RequestResult RequestHandler::GetCurrentProgramScene(const Request&) * @api requests * @category scenes */ -RequestResult RequestHandler::SetCurrentProgramScene(const Request& request) +RequestResult RequestHandler::SetCurrentProgramScene(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease scene = request.ValidateScene("sceneName", statusCode, comment); + OBSSourceAutoRelease scene = + request.ValidateScene("sceneName", statusCode, comment); if (!scene) return RequestResult::Error(statusCode, comment); @@ -137,15 +144,17 @@ RequestResult RequestHandler::SetCurrentProgramScene(const Request& request) * @api requests * @category scenes */ -RequestResult RequestHandler::GetCurrentPreviewScene(const Request&) +RequestResult RequestHandler::GetCurrentPreviewScene(const Request &) { if (!obs_frontend_preview_program_mode_active()) return RequestResult::Error(RequestStatus::StudioModeNotActive); - OBSSourceAutoRelease currentPreviewScene = obs_frontend_get_current_preview_scene(); + OBSSourceAutoRelease currentPreviewScene = + obs_frontend_get_current_preview_scene(); json responseData; - responseData["currentPreviewSceneName"] = obs_source_get_name(currentPreviewScene); + responseData["currentPreviewSceneName"] = + obs_source_get_name(currentPreviewScene); return RequestResult::Success(responseData); } @@ -164,14 +173,15 @@ RequestResult RequestHandler::GetCurrentPreviewScene(const Request&) * @api requests * @category scenes */ -RequestResult RequestHandler::SetCurrentPreviewScene(const Request& request) +RequestResult RequestHandler::SetCurrentPreviewScene(const Request &request) { if (!obs_frontend_preview_program_mode_active()) return RequestResult::Error(RequestStatus::StudioModeNotActive); RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease scene = request.ValidateScene("sceneName", statusCode, comment); + OBSSourceAutoRelease scene = + request.ValidateScene("sceneName", statusCode, comment); if (!scene) return RequestResult::Error(statusCode, comment); @@ -192,7 +202,7 @@ RequestResult RequestHandler::SetCurrentPreviewScene(const Request& request) * @api requests * @category scenes */ -RequestResult RequestHandler::CreateScene(const Request& request) +RequestResult RequestHandler::CreateScene(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; @@ -203,11 +213,15 @@ RequestResult RequestHandler::CreateScene(const Request& request) OBSSourceAutoRelease scene = obs_get_source_by_name(sceneName.c_str()); if (scene) - return RequestResult::Error(RequestStatus::ResourceAlreadyExists, "A source already exists by that scene name."); + return RequestResult::Error( + RequestStatus::ResourceAlreadyExists, + "A source already exists by that scene name."); obs_scene_t *createdScene = obs_scene_create(sceneName.c_str()); if (!createdScene) - return RequestResult::Error(RequestStatus::ResourceCreationFailed, "Failed to create the scene."); + return RequestResult::Error( + RequestStatus::ResourceCreationFailed, + "Failed to create the scene."); obs_scene_release(createdScene); @@ -226,16 +240,19 @@ RequestResult RequestHandler::CreateScene(const Request& request) * @api requests * @category scenes */ -RequestResult RequestHandler::RemoveScene(const Request& request) +RequestResult RequestHandler::RemoveScene(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease scene = request.ValidateScene("sceneName", statusCode, comment); + OBSSourceAutoRelease scene = + request.ValidateScene("sceneName", statusCode, comment); if (!scene) return RequestResult::Error(statusCode, comment); if (Utils::Obs::NumberHelper::GetSceneCount() < 2) - return RequestResult::Error(RequestStatus::NotEnoughResources, "You cannot remove the last scene in the collection."); + return RequestResult::Error( + RequestStatus::NotEnoughResources, + "You cannot remove the last scene in the collection."); obs_source_remove(scene); @@ -255,19 +272,24 @@ RequestResult RequestHandler::RemoveScene(const Request& request) * @api requests * @category scenes */ -RequestResult RequestHandler::SetSceneName(const Request& request) +RequestResult RequestHandler::SetSceneName(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease scene = request.ValidateScene("sceneName", statusCode, comment); - if (!(scene && request.ValidateString("newSceneName", statusCode, comment))) + OBSSourceAutoRelease scene = + request.ValidateScene("sceneName", statusCode, comment); + if (!(scene && + request.ValidateString("newSceneName", statusCode, comment))) return RequestResult::Error(statusCode, comment); std::string newSceneName = request.RequestData["newSceneName"]; - OBSSourceAutoRelease existingSource = obs_get_source_by_name(newSceneName.c_str()); + OBSSourceAutoRelease existingSource = + obs_get_source_by_name(newSceneName.c_str()); if (existingSource) - return RequestResult::Error(RequestStatus::ResourceAlreadyExists, "A source already exists by that new scene name."); + return RequestResult::Error( + RequestStatus::ResourceAlreadyExists, + "A source already exists by that new scene name."); obs_source_set_name(scene, newSceneName.c_str()); @@ -289,25 +311,30 @@ RequestResult RequestHandler::SetSceneName(const Request& request) * @api requests * @category scenes */ -RequestResult RequestHandler::GetSceneSceneTransitionOverride(const Request& request) +RequestResult +RequestHandler::GetSceneSceneTransitionOverride(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease scene = request.ValidateScene("sceneName", statusCode, comment); + OBSSourceAutoRelease scene = + request.ValidateScene("sceneName", statusCode, comment); if (!scene) return RequestResult::Error(statusCode, comment); - OBSDataAutoRelease privateSettings = obs_source_get_private_settings(scene); + OBSDataAutoRelease privateSettings = + obs_source_get_private_settings(scene); json responseData; - const char *transitionName = obs_data_get_string(privateSettings, "transition"); + const char *transitionName = + obs_data_get_string(privateSettings, "transition"); if (transitionName && strlen(transitionName)) responseData["transitionName"] = transitionName; else responseData["transitionName"] = nullptr; if (obs_data_has_user_value(privateSettings, "transition_duration")) - responseData["transitionDuration"] = obs_data_get_int(privateSettings, "transition_duration"); + responseData["transitionDuration"] = obs_data_get_int( + privateSettings, "transition_duration"); else responseData["transitionDuration"] = nullptr; @@ -328,40 +355,55 @@ RequestResult RequestHandler::GetSceneSceneTransitionOverride(const Request& req * @api requests * @category scenes */ -RequestResult RequestHandler::SetSceneSceneTransitionOverride(const Request& request) +RequestResult +RequestHandler::SetSceneSceneTransitionOverride(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease scene = request.ValidateScene("sceneName", statusCode, comment); + OBSSourceAutoRelease scene = + request.ValidateScene("sceneName", statusCode, comment); if (!scene) return RequestResult::Error(statusCode, comment); - OBSDataAutoRelease privateSettings = obs_source_get_private_settings(scene); + OBSDataAutoRelease privateSettings = + obs_source_get_private_settings(scene); bool hasName = request.RequestData.contains("transitionName"); if (hasName && !request.RequestData["transitionName"].is_null()) { - if (!request.ValidateOptionalString("transitionName", statusCode, comment)) + if (!request.ValidateOptionalString("transitionName", + statusCode, comment)) return RequestResult::Error(statusCode, comment); - OBSSourceAutoRelease transition = Utils::Obs::SearchHelper::GetSceneTransitionByName(request.RequestData["transitionName"]); + OBSSourceAutoRelease transition = + Utils::Obs::SearchHelper::GetSceneTransitionByName( + request.RequestData["transitionName"]); if (!transition) - return RequestResult::Error(RequestStatus::ResourceNotFound, "No scene transition was found by that name."); + return RequestResult::Error( + RequestStatus::ResourceNotFound, + "No scene transition was found by that name."); } bool hasDuration = request.RequestData.contains("transitionDuration"); - if (hasDuration && !request.RequestData["transitionDuration"].is_null()) { - if (!request.ValidateOptionalNumber("transitionDuration", statusCode, comment, 50, 20000)) + if (hasDuration && + !request.RequestData["transitionDuration"].is_null()) { + if (!request.ValidateOptionalNumber("transitionDuration", + statusCode, comment, 50, + 20000)) return RequestResult::Error(statusCode, comment); } if (!hasName && !hasDuration) - return RequestResult::Error(RequestStatus::MissingRequestField, "Your request data must include either `transitionName` or `transitionDuration`."); + return RequestResult::Error( + RequestStatus::MissingRequestField, + "Your request data must include either `transitionName` or `transitionDuration`."); if (hasName) { if (request.RequestData["transitionName"].is_null()) { obs_data_erase(privateSettings, "transition"); } else { - std::string transitionName = request.RequestData["transitionName"]; - obs_data_set_string(privateSettings, "transition", transitionName.c_str()); + std::string transitionName = + request.RequestData["transitionName"]; + obs_data_set_string(privateSettings, "transition", + transitionName.c_str()); } } @@ -369,7 +411,9 @@ RequestResult RequestHandler::SetSceneSceneTransitionOverride(const Request& req if (request.RequestData["transitionDuration"].is_null()) { obs_data_erase(privateSettings, "transition_duration"); } else { - obs_data_set_int(privateSettings, "transition_duration", request.RequestData["transitionDuration"]); + obs_data_set_int( + privateSettings, "transition_duration", + request.RequestData["transitionDuration"]); } } diff --git a/src/requesthandler/RequestHandler_Sources.cpp b/src/requesthandler/RequestHandler_Sources.cpp index 584a4143..fb5d81bf 100644 --- a/src/requesthandler/RequestHandler_Sources.cpp +++ b/src/requesthandler/RequestHandler_Sources.cpp @@ -25,12 +25,15 @@ with this program. If not, see #include "RequestHandler.h" -QImage TakeSourceScreenshot(obs_source_t *source, bool &success, uint32_t requestedWidth = 0, uint32_t requestedHeight = 0) +QImage TakeSourceScreenshot(obs_source_t *source, bool &success, + uint32_t requestedWidth = 0, + uint32_t requestedHeight = 0) { // Get info about the requested source const uint32_t sourceWidth = obs_source_get_base_width(source); const uint32_t sourceHeight = obs_source_get_base_height(source); - const double sourceAspectRatio = ((double)sourceWidth / (double)sourceHeight); + const double sourceAspectRatio = + ((double)sourceWidth / (double)sourceHeight); uint32_t imgWidth = sourceWidth; uint32_t imgHeight = sourceHeight; @@ -56,14 +59,15 @@ QImage TakeSourceScreenshot(obs_source_t *source, bool &success, uint32_t reques ret.fill(0); // Video image buffer - uint8_t* videoData = nullptr; + uint8_t *videoData = nullptr; uint32_t videoLinesize = 0; // Enter graphics context obs_enter_graphics(); - gs_texrender_t* texRender = gs_texrender_create(GS_RGBA, GS_ZS_NONE); - gs_stagesurf_t* stageSurface = gs_stagesurface_create(imgWidth, imgHeight, GS_RGBA); + gs_texrender_t *texRender = gs_texrender_create(GS_RGBA, GS_ZS_NONE); + gs_stagesurf_t *stageSurface = + gs_stagesurface_create(imgWidth, imgHeight, GS_RGBA); success = false; gs_texrender_reset(texRender); @@ -72,7 +76,8 @@ QImage TakeSourceScreenshot(obs_source_t *source, bool &success, uint32_t reques vec4_zero(&background); gs_clear(GS_CLEAR_COLOR, &background, 0.0f, 0); - gs_ortho(0.0f, (float)sourceWidth, 0.0f, (float)sourceHeight, -100.0f, 100.0f); + gs_ortho(0.0f, (float)sourceWidth, 0.0f, (float)sourceHeight, + -100.0f, 100.0f); gs_blend_state_push(); gs_blend_function(GS_BLEND_ONE, GS_BLEND_ZERO); @@ -84,11 +89,15 @@ QImage TakeSourceScreenshot(obs_source_t *source, bool &success, uint32_t reques gs_blend_state_pop(); gs_texrender_end(texRender); - gs_stage_texture(stageSurface, gs_texrender_get_texture(texRender)); - if (gs_stagesurface_map(stageSurface, &videoData, &videoLinesize)) { + gs_stage_texture(stageSurface, + gs_texrender_get_texture(texRender)); + if (gs_stagesurface_map(stageSurface, &videoData, + &videoLinesize)) { int lineSize = ret.bytesPerLine(); for (uint y = 0; y < imgHeight; y++) { - memcpy(ret.scanLine(y), videoData + (y * videoLinesize), lineSize); + memcpy(ret.scanLine(y), + videoData + (y * videoLinesize), + lineSize); } gs_stagesurface_unmap(stageSurface); success = true; @@ -126,16 +135,20 @@ bool IsImageFormatValid(std::string format) * @api requests * @category sources */ -RequestResult RequestHandler::GetSourceActive(const Request& request) +RequestResult RequestHandler::GetSourceActive(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease source = request.ValidateSource("sourceName", statusCode, comment); + OBSSourceAutoRelease source = + request.ValidateSource("sourceName", statusCode, comment); if (!source) return RequestResult::Error(statusCode, comment); - if (obs_source_get_type(source) != OBS_SOURCE_TYPE_INPUT && obs_source_get_type(source) != OBS_SOURCE_TYPE_SCENE) - return RequestResult::Error(RequestStatus::InvalidResourceType, "The specified source is not an input or a scene."); + if (obs_source_get_type(source) != OBS_SOURCE_TYPE_INPUT && + obs_source_get_type(source) != OBS_SOURCE_TYPE_SCENE) + return RequestResult::Error( + RequestStatus::InvalidResourceType, + "The specified source is not an input or a scene."); json responseData; responseData["videoActive"] = obs_source_active(source); @@ -166,63 +179,83 @@ RequestResult RequestHandler::GetSourceActive(const Request& request) * @api requests * @category sources */ -RequestResult RequestHandler::GetSourceScreenshot(const Request& request) +RequestResult RequestHandler::GetSourceScreenshot(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease source = request.ValidateSource("sourceName", statusCode, comment); - if (!(source && request.ValidateString("imageFormat", statusCode, comment))) + OBSSourceAutoRelease source = + request.ValidateSource("sourceName", statusCode, comment); + if (!(source && + request.ValidateString("imageFormat", statusCode, comment))) return RequestResult::Error(statusCode, comment); - if (obs_source_get_type(source) != OBS_SOURCE_TYPE_INPUT && obs_source_get_type(source) != OBS_SOURCE_TYPE_SCENE) - return RequestResult::Error(RequestStatus::InvalidResourceType, "The specified source is not an input or a scene."); + if (obs_source_get_type(source) != OBS_SOURCE_TYPE_INPUT && + obs_source_get_type(source) != OBS_SOURCE_TYPE_SCENE) + return RequestResult::Error( + RequestStatus::InvalidResourceType, + "The specified source is not an input or a scene."); std::string imageFormat = request.RequestData["imageFormat"]; if (!IsImageFormatValid(imageFormat)) - return RequestResult::Error(RequestStatus::InvalidRequestField, "Your specified image format is invalid or not supported by this system."); + return RequestResult::Error( + RequestStatus::InvalidRequestField, + "Your specified image format is invalid or not supported by this system."); uint32_t requestedWidth{0}; uint32_t requestedHeight{0}; int compressionQuality{-1}; if (request.Contains("imageWidth")) { - if (!request.ValidateOptionalNumber("imageWidth", statusCode, comment, 8, 4096)) + if (!request.ValidateOptionalNumber("imageWidth", statusCode, + comment, 8, 4096)) return RequestResult::Error(statusCode, comment); requestedWidth = request.RequestData["imageWidth"]; } if (request.Contains("imageHeight")) { - if (!request.ValidateOptionalNumber("imageHeight", statusCode, comment, 8, 4096)) + if (!request.ValidateOptionalNumber("imageHeight", statusCode, + comment, 8, 4096)) return RequestResult::Error(statusCode, comment); requestedHeight = request.RequestData["imageHeight"]; } if (request.Contains("imageCompressionQuality")) { - if (!request.ValidateOptionalNumber("imageCompressionQuality", statusCode, comment, -1, 100)) + if (!request.ValidateOptionalNumber("imageCompressionQuality", + statusCode, comment, -1, + 100)) return RequestResult::Error(statusCode, comment); - compressionQuality = request.RequestData["imageCompressionQuality"]; + compressionQuality = + request.RequestData["imageCompressionQuality"]; } bool success; - QImage renderedImage = TakeSourceScreenshot(source, success, requestedWidth, requestedHeight); + QImage renderedImage = TakeSourceScreenshot( + source, success, requestedWidth, requestedHeight); if (!success) - return RequestResult::Error(RequestStatus::RequestProcessingFailed, "Failed to render screenshot."); + return RequestResult::Error( + RequestStatus::RequestProcessingFailed, + "Failed to render screenshot."); QByteArray encodedImgBytes; QBuffer buffer(&encodedImgBytes); buffer.open(QBuffer::WriteOnly); - if (!renderedImage.save(&buffer, imageFormat.c_str(), compressionQuality)) - return RequestResult::Error(RequestStatus::RequestProcessingFailed, "Failed to encode screenshot."); + if (!renderedImage.save(&buffer, imageFormat.c_str(), + compressionQuality)) + return RequestResult::Error( + RequestStatus::RequestProcessingFailed, + "Failed to encode screenshot."); buffer.close(); - QString encodedPicture = QString("data:image/%1;base64,").arg(imageFormat.c_str()).append(encodedImgBytes.toBase64()); + QString encodedPicture = QString("data:image/%1;base64,") + .arg(imageFormat.c_str()) + .append(encodedImgBytes.toBase64()); json responseData; responseData["imageData"] = encodedPicture.toStdString(); @@ -253,95 +286,123 @@ RequestResult RequestHandler::GetSourceScreenshot(const Request& request) * @api requests * @category sources */ -RequestResult RequestHandler::SaveSourceScreenshot(const Request& request) +RequestResult RequestHandler::SaveSourceScreenshot(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease source = request.ValidateSource("sourceName", statusCode, comment); - if (!(source && request.ValidateString("imageFormat", statusCode, comment) && request.ValidateString("imageFilePath", statusCode, comment))) + OBSSourceAutoRelease source = + request.ValidateSource("sourceName", statusCode, comment); + if (!(source && + request.ValidateString("imageFormat", statusCode, comment) && + request.ValidateString("imageFilePath", statusCode, comment))) return RequestResult::Error(statusCode, comment); - if (obs_source_get_type(source) != OBS_SOURCE_TYPE_INPUT && obs_source_get_type(source) != OBS_SOURCE_TYPE_SCENE) - return RequestResult::Error(RequestStatus::InvalidResourceType, "The specified source is not an input or a scene."); + if (obs_source_get_type(source) != OBS_SOURCE_TYPE_INPUT && + obs_source_get_type(source) != OBS_SOURCE_TYPE_SCENE) + return RequestResult::Error( + RequestStatus::InvalidResourceType, + "The specified source is not an input or a scene."); std::string imageFormat = request.RequestData["imageFormat"]; std::string imageFilePath = request.RequestData["imageFilePath"]; if (!IsImageFormatValid(imageFormat)) - return RequestResult::Error(RequestStatus::InvalidRequestField, "Your specified image format is invalid or not supported by this system."); + return RequestResult::Error( + RequestStatus::InvalidRequestField, + "Your specified image format is invalid or not supported by this system."); QFileInfo filePathInfo(QString::fromStdString(imageFilePath)); if (!filePathInfo.absoluteDir().exists()) - return RequestResult::Error(RequestStatus::ResourceNotFound, "The directory for your file path does not exist."); + return RequestResult::Error( + RequestStatus::ResourceNotFound, + "The directory for your file path does not exist."); uint32_t requestedWidth{0}; uint32_t requestedHeight{0}; int compressionQuality{-1}; if (request.Contains("imageWidth")) { - if (!request.ValidateOptionalNumber("imageWidth", statusCode, comment, 8, 4096)) + if (!request.ValidateOptionalNumber("imageWidth", statusCode, + comment, 8, 4096)) return RequestResult::Error(statusCode, comment); requestedWidth = request.RequestData["imageWidth"]; } if (request.Contains("imageHeight")) { - if (!request.ValidateOptionalNumber("imageHeight", statusCode, comment, 8, 4096)) + if (!request.ValidateOptionalNumber("imageHeight", statusCode, + comment, 8, 4096)) return RequestResult::Error(statusCode, comment); requestedHeight = request.RequestData["imageHeight"]; } if (request.Contains("imageCompressionQuality")) { - if (!request.ValidateOptionalNumber("imageCompressionQuality", statusCode, comment, -1, 100)) + if (!request.ValidateOptionalNumber("imageCompressionQuality", + statusCode, comment, -1, + 100)) return RequestResult::Error(statusCode, comment); - compressionQuality = request.RequestData["imageCompressionQuality"]; + compressionQuality = + request.RequestData["imageCompressionQuality"]; } bool success; - QImage renderedImage = TakeSourceScreenshot(source, success, requestedWidth, requestedHeight); + QImage renderedImage = TakeSourceScreenshot( + source, success, requestedWidth, requestedHeight); if (!success) - return RequestResult::Error(RequestStatus::RequestProcessingFailed, "Failed to render screenshot."); + return RequestResult::Error( + RequestStatus::RequestProcessingFailed, + "Failed to render screenshot."); QString absoluteFilePath = filePathInfo.absoluteFilePath(); - if (!renderedImage.save(absoluteFilePath, imageFormat.c_str(), compressionQuality)) - return RequestResult::Error(RequestStatus::RequestProcessingFailed, "Failed to save screenshot."); + if (!renderedImage.save(absoluteFilePath, imageFormat.c_str(), + compressionQuality)) + return RequestResult::Error( + RequestStatus::RequestProcessingFailed, + "Failed to save screenshot."); return RequestResult::Success(); } // Intentionally undocumented -RequestResult RequestHandler::GetSourcePrivateSettings(const Request& request) +RequestResult RequestHandler::GetSourcePrivateSettings(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease source = request.ValidateSource("sourceName", statusCode, comment); + OBSSourceAutoRelease source = + request.ValidateSource("sourceName", statusCode, comment); if (!source) return RequestResult::Error(statusCode, comment); - OBSDataAutoRelease privateSettings = obs_source_get_private_settings(source); + OBSDataAutoRelease privateSettings = + obs_source_get_private_settings(source); json responseData; - responseData["sourceSettings"] = Utils::Json::ObsDataToJson(privateSettings); + responseData["sourceSettings"] = + Utils::Json::ObsDataToJson(privateSettings); return RequestResult::Success(responseData); } // Intentionally undocumented -RequestResult RequestHandler::SetSourcePrivateSettings(const Request& request) +RequestResult RequestHandler::SetSourcePrivateSettings(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease source = request.ValidateSource("sourceName", statusCode, comment); - if (!source || !request.ValidateObject("sourceSettings", statusCode, comment)) + OBSSourceAutoRelease source = + request.ValidateSource("sourceName", statusCode, comment); + if (!source || + !request.ValidateObject("sourceSettings", statusCode, comment)) return RequestResult::Error(statusCode, comment); - OBSDataAutoRelease privateSettings = obs_source_get_private_settings(source); + OBSDataAutoRelease privateSettings = + obs_source_get_private_settings(source); - OBSDataAutoRelease newSettings = Utils::Json::JsonToObsData(request.RequestData["sourceSettings"]); + OBSDataAutoRelease newSettings = Utils::Json::JsonToObsData( + request.RequestData["sourceSettings"]); // Always overlays to prevent destroying internal source data unintentionally obs_data_apply(privateSettings, newSettings); diff --git a/src/requesthandler/RequestHandler_Stream.cpp b/src/requesthandler/RequestHandler_Stream.cpp index 367ebd48..8285ad5a 100644 --- a/src/requesthandler/RequestHandler_Stream.cpp +++ b/src/requesthandler/RequestHandler_Stream.cpp @@ -37,20 +37,26 @@ with this program. If not, see * @api requests * @category stream */ -RequestResult RequestHandler::GetStreamStatus(const Request&) +RequestResult RequestHandler::GetStreamStatus(const Request &) { OBSOutputAutoRelease streamOutput = obs_frontend_get_streaming_output(); - uint64_t outputDuration = Utils::Obs::NumberHelper::GetOutputDuration(streamOutput); + uint64_t outputDuration = + Utils::Obs::NumberHelper::GetOutputDuration(streamOutput); json responseData; responseData["outputActive"] = obs_output_active(streamOutput); - responseData["outputReconnecting"] = obs_output_reconnecting(streamOutput); - responseData["outputTimecode"] = Utils::Obs::StringHelper::DurationToTimecode(outputDuration); + responseData["outputReconnecting"] = + obs_output_reconnecting(streamOutput); + responseData["outputTimecode"] = + Utils::Obs::StringHelper::DurationToTimecode(outputDuration); responseData["outputDuration"] = outputDuration; - responseData["outputBytes"] = (uint64_t)obs_output_get_total_bytes(streamOutput); - responseData["outputSkippedFrames"] = obs_output_get_frames_dropped(streamOutput); - responseData["outputTotalFrames"] = obs_output_get_total_frames(streamOutput); + responseData["outputBytes"] = + (uint64_t)obs_output_get_total_bytes(streamOutput); + responseData["outputSkippedFrames"] = + obs_output_get_frames_dropped(streamOutput); + responseData["outputTotalFrames"] = + obs_output_get_total_frames(streamOutput); return RequestResult::Success(responseData); } @@ -67,7 +73,7 @@ RequestResult RequestHandler::GetStreamStatus(const Request&) * @api requests * @category stream */ -RequestResult RequestHandler::ToggleStream(const Request&) +RequestResult RequestHandler::ToggleStream(const Request &) { json responseData; if (obs_frontend_streaming_active()) { @@ -91,7 +97,7 @@ RequestResult RequestHandler::ToggleStream(const Request&) * @api requests * @category stream */ -RequestResult RequestHandler::StartStream(const Request&) +RequestResult RequestHandler::StartStream(const Request &) { if (obs_frontend_streaming_active()) return RequestResult::Error(RequestStatus::OutputRunning); @@ -112,7 +118,7 @@ RequestResult RequestHandler::StartStream(const Request&) * @api requests * @category stream */ -RequestResult RequestHandler::StopStream(const Request&) +RequestResult RequestHandler::StopStream(const Request &) { if (!obs_frontend_streaming_active()) return RequestResult::Error(RequestStatus::OutputNotRunning); @@ -135,7 +141,7 @@ RequestResult RequestHandler::StopStream(const Request&) * @category stream * @api requests */ -RequestResult RequestHandler::SendStreamCaption(const Request& request) +RequestResult RequestHandler::SendStreamCaption(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; diff --git a/src/requesthandler/RequestHandler_Transitions.cpp b/src/requesthandler/RequestHandler_Transitions.cpp index a1ebabe8..efcd8daa 100644 --- a/src/requesthandler/RequestHandler_Transitions.cpp +++ b/src/requesthandler/RequestHandler_Transitions.cpp @@ -35,10 +35,11 @@ with this program. If not, see * @api requests * @category transitions */ -RequestResult RequestHandler::GetTransitionKindList(const Request&) +RequestResult RequestHandler::GetTransitionKindList(const Request &) { json responseData; - responseData["transitionKinds"] = Utils::Obs::ArrayHelper::GetTransitionKindList(); + responseData["transitionKinds"] = + Utils::Obs::ArrayHelper::GetTransitionKindList(); return RequestResult::Success(responseData); } @@ -56,20 +57,23 @@ RequestResult RequestHandler::GetTransitionKindList(const Request&) * @api requests * @category transitions */ -RequestResult RequestHandler::GetSceneTransitionList(const Request&) +RequestResult RequestHandler::GetSceneTransitionList(const Request &) { json responseData; OBSSourceAutoRelease transition = obs_frontend_get_current_transition(); if (transition) { - responseData["currentSceneTransitionName"] = obs_source_get_name(transition); - responseData["currentSceneTransitionKind"] = obs_source_get_id(transition); + responseData["currentSceneTransitionName"] = + obs_source_get_name(transition); + responseData["currentSceneTransitionKind"] = + obs_source_get_id(transition); } else { responseData["currentSceneTransitionName"] = nullptr; responseData["currentSceneTransitionKind"] = nullptr; } - responseData["transitions"] = Utils::Obs::ArrayHelper::GetSceneTransitionList(); + responseData["transitions"] = + Utils::Obs::ArrayHelper::GetSceneTransitionList(); return RequestResult::Success(responseData); } @@ -91,11 +95,13 @@ RequestResult RequestHandler::GetSceneTransitionList(const Request&) * @api requests * @category transitions */ -RequestResult RequestHandler::GetCurrentSceneTransition(const Request&) +RequestResult RequestHandler::GetCurrentSceneTransition(const Request &) { OBSSourceAutoRelease transition = obs_frontend_get_current_transition(); if (!transition) - return RequestResult::Error(RequestStatus::InvalidResourceState, "OBS does not currently have a scene transition set."); // This should not happen! + return RequestResult::Error( + RequestStatus::InvalidResourceState, + "OBS does not currently have a scene transition set."); // This should not happen! json responseData; responseData["transitionName"] = obs_source_get_name(transition); @@ -106,13 +112,16 @@ RequestResult RequestHandler::GetCurrentSceneTransition(const Request&) responseData["transitionDuration"] = nullptr; } else { responseData["transitionFixed"] = false; - responseData["transitionDuration"] = obs_frontend_get_transition_duration(); + responseData["transitionDuration"] = + obs_frontend_get_transition_duration(); } if (obs_source_configurable(transition)) { responseData["transitionConfigurable"] = true; - OBSDataAutoRelease transitionSettings = obs_source_get_settings(transition); - responseData["transitionSettings"] = Utils::Json::ObsDataToJson(transitionSettings); + OBSDataAutoRelease transitionSettings = + obs_source_get_settings(transition); + responseData["transitionSettings"] = + Utils::Json::ObsDataToJson(transitionSettings); } else { responseData["transitionConfigurable"] = false; responseData["transitionSettings"] = nullptr; @@ -135,7 +144,7 @@ RequestResult RequestHandler::GetCurrentSceneTransition(const Request&) * @api requests * @category transitions */ -RequestResult RequestHandler::SetCurrentSceneTransition(const Request& request) +RequestResult RequestHandler::SetCurrentSceneTransition(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; @@ -144,9 +153,13 @@ RequestResult RequestHandler::SetCurrentSceneTransition(const Request& request) std::string transitionName = request.RequestData["transitionName"]; - OBSSourceAutoRelease transition = Utils::Obs::SearchHelper::GetSceneTransitionByName(transitionName); + OBSSourceAutoRelease transition = + Utils::Obs::SearchHelper::GetSceneTransitionByName( + transitionName); if (!transition) - return RequestResult::Error(RequestStatus::ResourceNotFound, "No scene transition was found by that name."); + return RequestResult::Error( + RequestStatus::ResourceNotFound, + "No scene transition was found by that name."); obs_frontend_set_current_transition(transition); @@ -165,11 +178,13 @@ RequestResult RequestHandler::SetCurrentSceneTransition(const Request& request) * @api requests * @category transitions */ -RequestResult RequestHandler::SetCurrentSceneTransitionDuration(const Request& request) +RequestResult +RequestHandler::SetCurrentSceneTransitionDuration(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - if (!request.ValidateNumber("transitionDuration", statusCode, comment, 50, 20000)) + if (!request.ValidateNumber("transitionDuration", statusCode, comment, + 50, 20000)) return RequestResult::Error(statusCode, comment); int transitionDuration = request.RequestData["transitionDuration"]; @@ -192,31 +207,41 @@ RequestResult RequestHandler::SetCurrentSceneTransitionDuration(const Request& r * @api requests * @category transitions */ -RequestResult RequestHandler::SetCurrentSceneTransitionSettings(const Request& request) +RequestResult +RequestHandler::SetCurrentSceneTransitionSettings(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - if (!request.ValidateObject("transitionSettings", statusCode, comment, true)) + if (!request.ValidateObject("transitionSettings", statusCode, comment, + true)) return RequestResult::Error(statusCode, comment); OBSSourceAutoRelease transition = obs_frontend_get_current_transition(); if (!transition) - return RequestResult::Error(RequestStatus::InvalidResourceState, "OBS does not currently have a scene transition set."); // This should not happen! + return RequestResult::Error( + RequestStatus::InvalidResourceState, + "OBS does not currently have a scene transition set."); // This should not happen! if (!obs_source_configurable(transition)) - return RequestResult::Error(RequestStatus::ResourceNotConfigurable, "The current transition does not support custom settings."); + return RequestResult::Error( + RequestStatus::ResourceNotConfigurable, + "The current transition does not support custom settings."); bool overlay = true; if (request.Contains("overlay")) { - if (!request.ValidateOptionalBoolean("overlay", statusCode, comment)) + if (!request.ValidateOptionalBoolean("overlay", statusCode, + comment)) return RequestResult::Error(statusCode, comment); overlay = request.RequestData["overlay"]; } - OBSDataAutoRelease newSettings = Utils::Json::JsonToObsData(request.RequestData["transitionSettings"]); + OBSDataAutoRelease newSettings = Utils::Json::JsonToObsData( + request.RequestData["transitionSettings"]); if (!newSettings) - return RequestResult::Error(RequestStatus::RequestProcessingFailed, "An internal data conversion operation failed. Please report this!"); + return RequestResult::Error( + RequestStatus::RequestProcessingFailed, + "An internal data conversion operation failed. Please report this!"); if (overlay) obs_source_update(transition, newSettings); @@ -242,11 +267,13 @@ RequestResult RequestHandler::SetCurrentSceneTransitionSettings(const Request& r * @api requests * @category transitions */ -RequestResult RequestHandler::GetCurrentSceneTransitionCursor(const Request&) +RequestResult RequestHandler::GetCurrentSceneTransitionCursor(const Request &) { OBSSourceAutoRelease transition = obs_frontend_get_current_transition(); if (!transition) - return RequestResult::Error(RequestStatus::InvalidResourceState, "OBS does not currently have a scene transition set."); // This should not happen! + return RequestResult::Error( + RequestStatus::InvalidResourceState, + "OBS does not currently have a scene transition set."); // This should not happen! json responseData; responseData["transitionCursor"] = obs_transition_get_time(transition); @@ -264,12 +291,13 @@ RequestResult RequestHandler::GetCurrentSceneTransitionCursor(const Request&) * @api requests * @category transitions */ -RequestResult RequestHandler::TriggerStudioModeTransition(const Request&) +RequestResult RequestHandler::TriggerStudioModeTransition(const Request &) { if (!obs_frontend_preview_program_mode_active()) return RequestResult::Error(RequestStatus::StudioModeNotActive); - OBSSourceAutoRelease previewScene = obs_frontend_get_current_preview_scene(); + OBSSourceAutoRelease previewScene = + obs_frontend_get_current_preview_scene(); obs_frontend_set_current_scene(previewScene); @@ -291,7 +319,7 @@ RequestResult RequestHandler::TriggerStudioModeTransition(const Request&) * @api requests * @category transitions */ -RequestResult RequestHandler::SetTBarPosition(const Request& request) +RequestResult RequestHandler::SetTBarPosition(const Request &request) { if (!obs_frontend_preview_program_mode_active()) return RequestResult::Error(RequestStatus::StudioModeNotActive); @@ -303,13 +331,16 @@ RequestResult RequestHandler::SetTBarPosition(const Request& request) bool release = true; if (request.Contains("release")) { - if (!request.ValidateOptionalBoolean("release", statusCode, comment)) + if (!request.ValidateOptionalBoolean("release", statusCode, + comment)) return RequestResult::Error(statusCode, comment); } OBSSourceAutoRelease transition = obs_frontend_get_current_transition(); if (!transition) - return RequestResult::Error(RequestStatus::InvalidResourceState, "OBS does not currently have a scene transition set."); // This should not happen! + return RequestResult::Error( + RequestStatus::InvalidResourceState, + "OBS does not currently have a scene transition set."); // This should not happen! float position = request.RequestData["position"]; diff --git a/src/requesthandler/RequestHandler_Ui.cpp b/src/requesthandler/RequestHandler_Ui.cpp index 7aa2e277..3686c7aa 100644 --- a/src/requesthandler/RequestHandler_Ui.cpp +++ b/src/requesthandler/RequestHandler_Ui.cpp @@ -36,10 +36,11 @@ with this program. If not, see * @category ui * @api requests */ -RequestResult RequestHandler::GetStudioModeEnabled(const Request&) +RequestResult RequestHandler::GetStudioModeEnabled(const Request &) { json responseData; - responseData["studioModeEnabled"] = obs_frontend_preview_program_mode_active(); + responseData["studioModeEnabled"] = + obs_frontend_preview_program_mode_active(); return RequestResult::Success(responseData); } @@ -55,7 +56,7 @@ RequestResult RequestHandler::GetStudioModeEnabled(const Request&) * @category ui * @api requests */ -RequestResult RequestHandler::SetStudioModeEnabled(const Request& request) +RequestResult RequestHandler::SetStudioModeEnabled(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; @@ -63,14 +64,20 @@ RequestResult RequestHandler::SetStudioModeEnabled(const Request& request) return RequestResult::Error(statusCode, comment); // Avoid queueing tasks if nothing will change - if (obs_frontend_preview_program_mode_active() != request.RequestData["studioModeEnabled"]) { + if (obs_frontend_preview_program_mode_active() != + request.RequestData["studioModeEnabled"]) { // (Bad) Create a boolean then pass it as a reference to the task. Requires `wait` in obs_queue_task() to be true, else undefined behavior - bool studioModeEnabled = request.RequestData["studioModeEnabled"]; + bool studioModeEnabled = + request.RequestData["studioModeEnabled"]; // Queue the task inside of the UI thread to prevent race conditions - obs_queue_task(OBS_TASK_UI, [](void* param) { - auto studioModeEnabled = (bool*)param; - obs_frontend_set_preview_program_mode(*studioModeEnabled); - }, &studioModeEnabled, true); + obs_queue_task( + OBS_TASK_UI, + [](void *param) { + auto studioModeEnabled = (bool *)param; + obs_frontend_set_preview_program_mode( + *studioModeEnabled); + }, + &studioModeEnabled, true); } return RequestResult::Success(); @@ -88,11 +95,12 @@ RequestResult RequestHandler::SetStudioModeEnabled(const Request& request) * @category ui * @api requests */ -RequestResult RequestHandler::OpenInputPropertiesDialog(const Request& request) +RequestResult RequestHandler::OpenInputPropertiesDialog(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); + OBSSourceAutoRelease input = + request.ValidateInput("inputName", statusCode, comment); if (!input) return RequestResult::Error(statusCode, comment); @@ -113,11 +121,12 @@ RequestResult RequestHandler::OpenInputPropertiesDialog(const Request& request) * @category ui * @api requests */ -RequestResult RequestHandler::OpenInputFiltersDialog(const Request& request) +RequestResult RequestHandler::OpenInputFiltersDialog(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); + OBSSourceAutoRelease input = + request.ValidateInput("inputName", statusCode, comment); if (!input) return RequestResult::Error(statusCode, comment); @@ -138,16 +147,19 @@ RequestResult RequestHandler::OpenInputFiltersDialog(const Request& request) * @category ui * @api requests */ -RequestResult RequestHandler::OpenInputInteractDialog(const Request& request) +RequestResult RequestHandler::OpenInputInteractDialog(const Request &request) { RequestStatus::RequestStatus statusCode; std::string comment; - OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); + OBSSourceAutoRelease input = + request.ValidateInput("inputName", statusCode, comment); if (!input) return RequestResult::Error(statusCode, comment); if (!(obs_source_get_output_flags(input) & OBS_SOURCE_INTERACTION)) - return RequestResult::Error(RequestStatus::InvalidResourceState, "The specified input does not support interaction."); + return RequestResult::Error( + RequestStatus::InvalidResourceState, + "The specified input does not support interaction."); obs_frontend_open_source_interaction(input); @@ -166,15 +178,15 @@ RequestResult RequestHandler::OpenInputInteractDialog(const Request& request) * @category ui * @api requests */ -RequestResult RequestHandler::GetMonitorList(const Request&) +RequestResult RequestHandler::GetMonitorList(const Request &) { json responseData; std::vector monitorsData; QList screensList = QGuiApplication::screens(); - for (int screenIndex = 0; screenIndex < screensList.size(); screenIndex++) - { + for (int screenIndex = 0; screenIndex < screensList.size(); + screenIndex++) { json screenData; - QScreen const* screen = screensList[screenIndex]; + QScreen const *screen = screensList[screenIndex]; std::stringstream nameAndIndex; nameAndIndex << screen->name().toStdString(); nameAndIndex << '(' << screenIndex << ')'; diff --git a/src/requesthandler/rpc/Request.cpp b/src/requesthandler/rpc/Request.cpp index 3458347b..33809f0b 100644 --- a/src/requesthandler/rpc/Request.cpp +++ b/src/requesthandler/rpc/Request.cpp @@ -29,88 +29,115 @@ json GetDefaultJsonObject(const json &requestData) return requestData; } -Request::Request(const std::string &requestType, const json &requestData, const RequestBatchExecutionType::RequestBatchExecutionType executionType) : - RequestType(requestType), - HasRequestData(requestData.is_object()), - RequestData(GetDefaultJsonObject(requestData)), - ExecutionType(executionType) +Request::Request(const std::string &requestType, const json &requestData, + const RequestBatchExecutionType::RequestBatchExecutionType + executionType) + : RequestType(requestType), + HasRequestData(requestData.is_object()), + RequestData(GetDefaultJsonObject(requestData)), + ExecutionType(executionType) { } bool Request::Contains(const std::string &keyName) const { - return (RequestData.contains(keyName) && !RequestData[keyName].is_null()); + return (RequestData.contains(keyName) && + !RequestData[keyName].is_null()); } -bool Request::ValidateBasic(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const +bool Request::ValidateBasic(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment) const { if (!HasRequestData) { statusCode = RequestStatus::MissingRequestData; - comment = "Your request data is missing or invalid (non-object)"; + comment = + "Your request data is missing or invalid (non-object)"; return false; } if (!RequestData.contains(keyName) || RequestData[keyName].is_null()) { statusCode = RequestStatus::MissingRequestField; - comment = std::string("Your request is missing the `") + keyName + "` field."; + comment = std::string("Your request is missing the `") + + keyName + "` field."; return false; } return true; } -bool Request::ValidateOptionalNumber(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const double minValue, const double maxValue) const +bool Request::ValidateOptionalNumber(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment, + const double minValue, + const double maxValue) const { if (!RequestData[keyName].is_number()) { statusCode = RequestStatus::InvalidRequestFieldType; - comment = std::string("The field value of `") + keyName + "` must be a number."; + comment = std::string("The field value of `") + keyName + + "` must be a number."; return false; } double value = RequestData[keyName]; if (value < minValue) { statusCode = RequestStatus::RequestFieldOutOfRange; - comment = std::string("The field value of `") + keyName + "` is below the minimum of `" + std::to_string(minValue) + "`"; + comment = std::string("The field value of `") + keyName + + "` is below the minimum of `" + + std::to_string(minValue) + "`"; return false; } if (value > maxValue) { statusCode = RequestStatus::RequestFieldOutOfRange; - comment = std::string("The field value of `") + keyName + "` is above the maximum of `" + std::to_string(maxValue) + "`"; + comment = std::string("The field value of `") + keyName + + "` is above the maximum of `" + + std::to_string(maxValue) + "`"; return false; } return true; } -bool Request::ValidateNumber(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const double minValue, const double maxValue) const +bool Request::ValidateNumber(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment, const double minValue, + const double maxValue) const { if (!ValidateBasic(keyName, statusCode, comment)) return false; - if (!ValidateOptionalNumber(keyName, statusCode, comment, minValue, maxValue)) + if (!ValidateOptionalNumber(keyName, statusCode, comment, minValue, + maxValue)) return false; return true; } -bool Request::ValidateOptionalString(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty) const +bool Request::ValidateOptionalString(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment, + const bool allowEmpty) const { if (!RequestData[keyName].is_string()) { statusCode = RequestStatus::InvalidRequestFieldType; - comment = std::string("The field value of `") + keyName + "` must be a string."; + comment = std::string("The field value of `") + keyName + + "` must be a string."; return false; } if (RequestData[keyName].get().empty() && !allowEmpty) { statusCode = RequestStatus::RequestFieldEmpty; - comment = std::string("The field value of `") + keyName + "` must not be empty."; + comment = std::string("The field value of `") + keyName + + "` must not be empty."; return false; } return true; } -bool Request::ValidateString(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty) const +bool Request::ValidateString(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment, const bool allowEmpty) const { if (!ValidateBasic(keyName, statusCode, comment)) return false; @@ -121,18 +148,23 @@ bool Request::ValidateString(const std::string &keyName, RequestStatus::RequestS return true; } -bool Request::ValidateOptionalBoolean(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const +bool Request::ValidateOptionalBoolean(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment) const { if (!RequestData[keyName].is_boolean()) { statusCode = RequestStatus::InvalidRequestFieldType; - comment = std::string("The field value of `") + keyName + "` must be boolean."; + comment = std::string("The field value of `") + keyName + + "` must be boolean."; return false; } return true; } -bool Request::ValidateBoolean(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const +bool Request::ValidateBoolean(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment) const { if (!ValidateBasic(keyName, statusCode, comment)) return false; @@ -143,24 +175,31 @@ bool Request::ValidateBoolean(const std::string &keyName, RequestStatus::Request return true; } -bool Request::ValidateOptionalObject(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty) const +bool Request::ValidateOptionalObject(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment, + const bool allowEmpty) const { if (!RequestData[keyName].is_object()) { statusCode = RequestStatus::InvalidRequestFieldType; - comment = std::string("The field value of `") + keyName + "` must be an object."; + comment = std::string("The field value of `") + keyName + + "` must be an object."; return false; } if (RequestData[keyName].empty() && !allowEmpty) { statusCode = RequestStatus::RequestFieldEmpty; - comment = std::string("The field value of `") + keyName + "` must not be empty."; + comment = std::string("The field value of `") + keyName + + "` must not be empty."; return false; } return true; } -bool Request::ValidateObject(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty) const +bool Request::ValidateObject(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment, const bool allowEmpty) const { if (!ValidateBasic(keyName, statusCode, comment)) return false; @@ -171,24 +210,31 @@ bool Request::ValidateObject(const std::string &keyName, RequestStatus::RequestS return true; } -bool Request::ValidateOptionalArray(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty) const +bool Request::ValidateOptionalArray(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment, + const bool allowEmpty) const { if (!RequestData[keyName].is_array()) { statusCode = RequestStatus::InvalidRequestFieldType; - comment = std::string("The field value of `") + keyName + "` must be an array."; + comment = std::string("The field value of `") + keyName + + "` must be an array."; return false; } if (RequestData[keyName].empty() && !allowEmpty) { statusCode = RequestStatus::RequestFieldEmpty; - comment = std::string("The field value of `") + keyName + "` must not be empty."; + comment = std::string("The field value of `") + keyName + + "` must not be empty."; return false; } return true; } -bool Request::ValidateArray(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty) const +bool Request::ValidateArray(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment, const bool allowEmpty) const { if (!ValidateBasic(keyName, statusCode, comment)) return false; @@ -199,7 +245,9 @@ bool Request::ValidateArray(const std::string &keyName, RequestStatus::RequestSt return true; } -obs_source_t *Request::ValidateSource(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const +obs_source_t *Request::ValidateSource(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment) const { if (!ValidateString(keyName, statusCode, comment)) return nullptr; @@ -209,14 +257,18 @@ obs_source_t *Request::ValidateSource(const std::string &keyName, RequestStatus: obs_source_t *ret = obs_get_source_by_name(sourceName.c_str()); if (!ret) { statusCode = RequestStatus::ResourceNotFound; - comment = std::string("No source was found by the name of `") + sourceName + "`."; + comment = std::string("No source was found by the name of `") + + sourceName + "`."; return nullptr; } return ret; } -obs_source_t *Request::ValidateScene(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const ObsWebSocketSceneFilter filter) const +obs_source_t *Request::ValidateScene(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment, + const ObsWebSocketSceneFilter filter) const { obs_source_t *ret = ValidateSource(keyName, statusCode, comment); if (!ret) @@ -235,7 +287,8 @@ obs_source_t *Request::ValidateScene(const std::string &keyName, RequestStatus:: statusCode = RequestStatus::InvalidResourceType; comment = "The specified source is not a scene. (Is group)"; return nullptr; - } else if (filter == OBS_WEBSOCKET_SCENE_FILTER_GROUP_ONLY && !isGroup) { + } else if (filter == OBS_WEBSOCKET_SCENE_FILTER_GROUP_ONLY && + !isGroup) { obs_source_release(ret); statusCode = RequestStatus::InvalidResourceType; comment = "The specified source is not a group. (Is scene)"; @@ -245,9 +298,13 @@ obs_source_t *Request::ValidateScene(const std::string &keyName, RequestStatus:: return ret; } -obs_scene_t *Request::ValidateScene2(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const ObsWebSocketSceneFilter filter) const +obs_scene_t *Request::ValidateScene2(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment, + const ObsWebSocketSceneFilter filter) const { - OBSSourceAutoRelease sceneSource = ValidateSource(keyName, statusCode, comment); + OBSSourceAutoRelease sceneSource = + ValidateSource(keyName, statusCode, comment); if (!sceneSource) return nullptr; @@ -261,21 +318,25 @@ obs_scene_t *Request::ValidateScene2(const std::string &keyName, RequestStatus:: if (isGroup) { if (filter == OBS_WEBSOCKET_SCENE_FILTER_SCENE_ONLY) { statusCode = RequestStatus::InvalidResourceType; - comment = "The specified source is not a scene. (Is group)"; + comment = + "The specified source is not a scene. (Is group)"; return nullptr; } return obs_scene_get_ref(obs_group_from_source(sceneSource)); } else { if (filter == OBS_WEBSOCKET_SCENE_FILTER_GROUP_ONLY) { statusCode = RequestStatus::InvalidResourceType; - comment = "The specified source is not a group. (Is scene)"; + comment = + "The specified source is not a group. (Is scene)"; return nullptr; } return obs_scene_get_ref(obs_scene_from_source(sceneSource)); } } -obs_source_t *Request::ValidateInput(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const +obs_source_t *Request::ValidateInput(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment) const { obs_source_t *ret = ValidateSource(keyName, statusCode, comment); if (!ret) @@ -291,9 +352,13 @@ obs_source_t *Request::ValidateInput(const std::string &keyName, RequestStatus:: return ret; } -FilterPair Request::ValidateFilter(const std::string &sourceKeyName, const std::string &filterKeyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const +FilterPair Request::ValidateFilter(const std::string &sourceKeyName, + const std::string &filterKeyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment) const { - obs_source_t *source = ValidateSource(sourceKeyName, statusCode, comment); + obs_source_t *source = + ValidateSource(sourceKeyName, statusCode, comment); if (!source) return FilterPair{source, nullptr}; @@ -302,19 +367,26 @@ FilterPair Request::ValidateFilter(const std::string &sourceKeyName, const std:: std::string filterName = RequestData[filterKeyName]; - obs_source_t *filter = obs_source_get_filter_by_name(source, filterName.c_str()); + obs_source_t *filter = + obs_source_get_filter_by_name(source, filterName.c_str()); if (!filter) { statusCode = RequestStatus::ResourceNotFound; - comment = std::string("No filter was found in the source `") + RequestData[sourceKeyName].get() + "` with the name `" + filterName + "`."; + comment = std::string("No filter was found in the source `") + + RequestData[sourceKeyName].get() + + "` with the name `" + filterName + "`."; return FilterPair{source, nullptr}; } return FilterPair{source, filter}; } -obs_sceneitem_t *Request::ValidateSceneItem(const std::string &sceneKeyName, const std::string &sceneItemIdKeyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const ObsWebSocketSceneFilter filter) const +obs_sceneitem_t *Request::ValidateSceneItem( + const std::string &sceneKeyName, const std::string &sceneItemIdKeyName, + RequestStatus::RequestStatus &statusCode, std::string &comment, + const ObsWebSocketSceneFilter filter) const { - OBSSceneAutoRelease scene = ValidateScene2(sceneKeyName, statusCode, comment, filter); + OBSSceneAutoRelease scene = + ValidateScene2(sceneKeyName, statusCode, comment, filter); if (!scene) return nullptr; @@ -323,10 +395,14 @@ obs_sceneitem_t *Request::ValidateSceneItem(const std::string &sceneKeyName, con int64_t sceneItemId = RequestData[sceneItemIdKeyName]; - OBSSceneItem sceneItem = obs_scene_find_sceneitem_by_id(scene, sceneItemId); + OBSSceneItem sceneItem = + obs_scene_find_sceneitem_by_id(scene, sceneItemId); if (!sceneItem) { statusCode = RequestStatus::ResourceNotFound; - comment = std::string("No scene items were found in scene `") + RequestData[sceneKeyName].get() + "` with the ID `" + std::to_string(sceneItemId) + "`."; + comment = std::string("No scene items were found in scene `") + + RequestData[sceneKeyName].get() + + "` with the ID `" + std::to_string(sceneItemId) + + "`."; return nullptr; } diff --git a/src/requesthandler/rpc/Request.h b/src/requesthandler/rpc/Request.h index 0f44308b..5810d4eb 100644 --- a/src/requesthandler/rpc/Request.h +++ b/src/requesthandler/rpc/Request.h @@ -35,32 +35,89 @@ struct FilterPair { OBSSourceAutoRelease filter; }; -struct Request -{ - Request(const std::string &requestType, const json &requestData = nullptr, const RequestBatchExecutionType::RequestBatchExecutionType executionType = RequestBatchExecutionType::None); +struct Request { + Request(const std::string &requestType, + const json &requestData = nullptr, + const RequestBatchExecutionType::RequestBatchExecutionType + executionType = RequestBatchExecutionType::None); // Contains the key and is not null bool Contains(const std::string &keyName) const; - bool ValidateBasic(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const; - bool ValidateOptionalNumber(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const double minValue = -INFINITY, const double maxValue = INFINITY) const; - bool ValidateNumber(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const double minValue = -INFINITY, const double maxValue = INFINITY) const; - bool ValidateOptionalString(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty = false) const; - bool ValidateString(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty = false) const; - bool ValidateOptionalBoolean(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const; - bool ValidateBoolean(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const; - bool ValidateOptionalObject(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty = false) const; - bool ValidateObject(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty = false) const; - bool ValidateOptionalArray(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty = false) const; - bool ValidateArray(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty = false) const; + bool ValidateBasic(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment) const; + bool ValidateOptionalNumber(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment, + const double minValue = -INFINITY, + const double maxValue = INFINITY) const; + bool ValidateNumber(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment, + const double minValue = -INFINITY, + const double maxValue = INFINITY) const; + bool ValidateOptionalString(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment, + const bool allowEmpty = false) const; + bool ValidateString(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment, + const bool allowEmpty = false) const; + bool ValidateOptionalBoolean(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment) const; + bool ValidateBoolean(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment) const; + bool ValidateOptionalObject(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment, + const bool allowEmpty = false) const; + bool ValidateObject(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment, + const bool allowEmpty = false) const; + bool ValidateOptionalArray(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment, + const bool allowEmpty = false) const; + bool ValidateArray(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment, + const bool allowEmpty = false) const; // All return values have incremented refcounts - obs_source_t *ValidateSource(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const; - obs_source_t *ValidateScene(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const ObsWebSocketSceneFilter filter = OBS_WEBSOCKET_SCENE_FILTER_SCENE_ONLY) const; - obs_scene_t *ValidateScene2(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const ObsWebSocketSceneFilter filter = OBS_WEBSOCKET_SCENE_FILTER_SCENE_ONLY) const; - obs_source_t *ValidateInput(const std::string &keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const; - FilterPair ValidateFilter(const std::string &sourceKeyName, const std::string &filterKeyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const; - obs_sceneitem_t *ValidateSceneItem(const std::string &sceneKeyName, const std::string &sceneItemIdKeyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const ObsWebSocketSceneFilter filter = OBS_WEBSOCKET_SCENE_FILTER_SCENE_ONLY) const; + obs_source_t *ValidateSource(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment) const; + obs_source_t * + ValidateScene(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment, + const ObsWebSocketSceneFilter filter = + OBS_WEBSOCKET_SCENE_FILTER_SCENE_ONLY) const; + obs_scene_t * + ValidateScene2(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment, + const ObsWebSocketSceneFilter filter = + OBS_WEBSOCKET_SCENE_FILTER_SCENE_ONLY) const; + obs_source_t *ValidateInput(const std::string &keyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment) const; + FilterPair ValidateFilter(const std::string &sourceKeyName, + const std::string &filterKeyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment) const; + obs_sceneitem_t * + ValidateSceneItem(const std::string &sceneKeyName, + const std::string &sceneItemIdKeyName, + RequestStatus::RequestStatus &statusCode, + std::string &comment, + const ObsWebSocketSceneFilter filter = + OBS_WEBSOCKET_SCENE_FILTER_SCENE_ONLY) const; std::string RequestType; bool HasRequestData; diff --git a/src/requesthandler/rpc/RequestBatchRequest.cpp b/src/requesthandler/rpc/RequestBatchRequest.cpp index 6ea83eb6..57a53bb9 100644 --- a/src/requesthandler/rpc/RequestBatchRequest.cpp +++ b/src/requesthandler/rpc/RequestBatchRequest.cpp @@ -18,9 +18,12 @@ with this program. If not, see #include "RequestBatchRequest.h" -RequestBatchRequest::RequestBatchRequest(const std::string &requestType, const json &requestData, RequestBatchExecutionType::RequestBatchExecutionType executionType, const json &inputVariables, const json &outputVariables) : - Request(requestType, requestData, executionType), - InputVariables(inputVariables), - OutputVariables(outputVariables) +RequestBatchRequest::RequestBatchRequest( + const std::string &requestType, const json &requestData, + RequestBatchExecutionType::RequestBatchExecutionType executionType, + const json &inputVariables, const json &outputVariables) + : Request(requestType, requestData, executionType), + InputVariables(inputVariables), + OutputVariables(outputVariables) { } diff --git a/src/requesthandler/rpc/RequestBatchRequest.h b/src/requesthandler/rpc/RequestBatchRequest.h index bbe5e6e0..0efc052d 100644 --- a/src/requesthandler/rpc/RequestBatchRequest.h +++ b/src/requesthandler/rpc/RequestBatchRequest.h @@ -21,7 +21,12 @@ with this program. If not, see #include "Request.h" struct RequestBatchRequest : Request { - RequestBatchRequest(const std::string &requestType, const json &requestData, RequestBatchExecutionType::RequestBatchExecutionType executionType, const json &inputVariables = nullptr, const json &outputVariables = nullptr); + RequestBatchRequest(const std::string &requestType, + const json &requestData, + RequestBatchExecutionType::RequestBatchExecutionType + executionType, + const json &inputVariables = nullptr, + const json &outputVariables = nullptr); json InputVariables; json OutputVariables; diff --git a/src/requesthandler/rpc/RequestResult.cpp b/src/requesthandler/rpc/RequestResult.cpp index 222f8259..d6000825 100644 --- a/src/requesthandler/rpc/RequestResult.cpp +++ b/src/requesthandler/rpc/RequestResult.cpp @@ -19,11 +19,12 @@ with this program. If not, see #include "RequestResult.h" -RequestResult::RequestResult(RequestStatus::RequestStatus statusCode, json responseData, std::string comment) : - StatusCode(statusCode), - ResponseData(responseData), - Comment(comment), - SleepFrames(0) +RequestResult::RequestResult(RequestStatus::RequestStatus statusCode, + json responseData, std::string comment) + : StatusCode(statusCode), + ResponseData(responseData), + Comment(comment), + SleepFrames(0) { } @@ -32,7 +33,8 @@ RequestResult RequestResult::Success(json responseData) return RequestResult(RequestStatus::Success, responseData, ""); } -RequestResult RequestResult::Error(RequestStatus::RequestStatus statusCode, std::string comment) +RequestResult RequestResult::Error(RequestStatus::RequestStatus statusCode, + std::string comment) { return RequestResult(statusCode, nullptr, comment); } diff --git a/src/requesthandler/rpc/RequestResult.h b/src/requesthandler/rpc/RequestResult.h index 6ec410c0..3cefe652 100644 --- a/src/requesthandler/rpc/RequestResult.h +++ b/src/requesthandler/rpc/RequestResult.h @@ -22,11 +22,13 @@ with this program. If not, see #include "../types/RequestStatus.h" #include "../../utils/Json.h" -struct RequestResult -{ - RequestResult(RequestStatus::RequestStatus statusCode = RequestStatus::Success, json responseData = nullptr, std::string comment = ""); +struct RequestResult { + RequestResult(RequestStatus::RequestStatus statusCode = + RequestStatus::Success, + json responseData = nullptr, std::string comment = ""); static RequestResult Success(json responseData = nullptr); - static RequestResult Error(RequestStatus::RequestStatus statusCode, std::string comment = ""); + static RequestResult Error(RequestStatus::RequestStatus statusCode, + std::string comment = ""); RequestStatus::RequestStatus StatusCode; json ResponseData; std::string Comment; diff --git a/src/requesthandler/types/RequestBatchExecutionType.h b/src/requesthandler/types/RequestBatchExecutionType.h index df158ffe..a1871f53 100644 --- a/src/requesthandler/types/RequestBatchExecutionType.h +++ b/src/requesthandler/types/RequestBatchExecutionType.h @@ -22,8 +22,8 @@ with this program. If not, see #include namespace RequestBatchExecutionType { - enum RequestBatchExecutionType: int8_t { - /** +enum RequestBatchExecutionType : int8_t { + /** * Not a request batch. * * @enumIdentifier None @@ -33,8 +33,8 @@ namespace RequestBatchExecutionType { * @initialVersion 5.0.0 * @api enums */ - None = -1, - /** + None = -1, + /** * A request batch which processes all requests serially, as fast as possible. * * Note: To introduce artificial delay, use the `Sleep` request and the `sleepMillis` request field. @@ -46,8 +46,8 @@ namespace RequestBatchExecutionType { * @initialVersion 5.0.0 * @api enums */ - SerialRealtime = 0, - /** + SerialRealtime = 0, + /** * A request batch type which processes all requests serially, in sync with the graphics thread. Designed to * provide high accuracy for animations. * @@ -60,8 +60,8 @@ namespace RequestBatchExecutionType { * @initialVersion 5.0.0 * @api enums */ - SerialFrame = 1, - /** + SerialFrame = 1, + /** * A request batch type which processes all requests using all available threads in the thread pool. * * Note: This is mainly experimental, and only really shows its colors during requests which require lots of @@ -74,11 +74,11 @@ namespace RequestBatchExecutionType { * @initialVersion 5.0.0 * @api enums */ - Parallel = 2, - }; + Parallel = 2, +}; - inline bool IsValid(int8_t executionType) - { - return executionType >= None && executionType <= Parallel; - } +inline bool IsValid(int8_t executionType) +{ + return executionType >= None && executionType <= Parallel; +} } diff --git a/src/requesthandler/types/RequestStatus.h b/src/requesthandler/types/RequestStatus.h index 45d7e04e..e6616e5b 100644 --- a/src/requesthandler/types/RequestStatus.h +++ b/src/requesthandler/types/RequestStatus.h @@ -20,8 +20,8 @@ with this program. If not, see #pragma once namespace RequestStatus { - enum RequestStatus { - /** +enum RequestStatus { + /** * Unknown status, should never be used. * * @enumIdentifier Unknown @@ -31,9 +31,9 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - Unknown = 0, + Unknown = 0, - /** + /** * For internal use to signify a successful field check. * * @enumIdentifier NoError @@ -43,9 +43,9 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - NoError = 10, + NoError = 10, - /** + /** * The request has succeeded. * * @enumIdentifier Success @@ -55,9 +55,9 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - Success = 100, + Success = 100, - /** + /** * The `requestType` field is missing from the request data. * * @enumIdentifier MissingRequestType @@ -67,8 +67,8 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - MissingRequestType = 203, - /** + MissingRequestType = 203, + /** * The request type is invalid or does not exist. * * @enumIdentifier UnknownRequestType @@ -78,8 +78,8 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - UnknownRequestType = 204, - /** + UnknownRequestType = 204, + /** * Generic error code. * * Note: A comment is required to be provided by obs-websocket. @@ -91,8 +91,8 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - GenericError = 205, - /** + GenericError = 205, + /** * The request batch execution type is not supported. * * @enumIdentifier UnsupportedRequestBatchExecutionType @@ -102,9 +102,9 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - UnsupportedRequestBatchExecutionType = 206, + UnsupportedRequestBatchExecutionType = 206, - /** + /** * A required request field is missing. * * @enumIdentifier MissingRequestField @@ -114,8 +114,8 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - MissingRequestField = 300, - /** + MissingRequestField = 300, + /** * The request does not have a valid requestData object. * * @enumIdentifier MissingRequestData @@ -125,9 +125,9 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - MissingRequestData = 301, + MissingRequestData = 301, - /** + /** * Generic invalid request field message. * * Note: A comment is required to be provided by obs-websocket. @@ -139,8 +139,8 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - InvalidRequestField = 400, - /** + InvalidRequestField = 400, + /** * A request field has the wrong data type. * * @enumIdentifier InvalidRequestFieldType @@ -150,8 +150,8 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - InvalidRequestFieldType = 401, - /** + InvalidRequestFieldType = 401, + /** * A request field (number) is outside of the allowed range. * * @enumIdentifier RequestFieldOutOfRange @@ -161,8 +161,8 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - RequestFieldOutOfRange = 402, - /** + RequestFieldOutOfRange = 402, + /** * A request field (string or array) is empty and cannot be. * * @enumIdentifier RequestFieldEmpty @@ -172,8 +172,8 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - RequestFieldEmpty = 403, - /** + RequestFieldEmpty = 403, + /** * There are too many request fields (eg. a request takes two optionals, where only one is allowed at a time). * * @enumIdentifier TooManyRequestFields @@ -183,9 +183,9 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - TooManyRequestFields = 404, + TooManyRequestFields = 404, - /** + /** * An output is running and cannot be in order to perform the request. * * @enumIdentifier OutputRunning @@ -195,8 +195,8 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - OutputRunning = 500, - /** + OutputRunning = 500, + /** * An output is not running and should be. * * @enumIdentifier OutputNotRunning @@ -206,8 +206,8 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - OutputNotRunning = 501, - /** + OutputNotRunning = 501, + /** * An output is paused and should not be. * * @enumIdentifier OutputPaused @@ -217,8 +217,8 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - OutputPaused = 502, - /** + OutputPaused = 502, + /** * An output is not paused and should be. * * @enumIdentifier OutputNotPaused @@ -228,8 +228,8 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - OutputNotPaused = 503, - /** + OutputNotPaused = 503, + /** * An output is disabled and should not be. * * @enumIdentifier OutputDisabled @@ -239,8 +239,8 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - OutputDisabled = 504, - /** + OutputDisabled = 504, + /** * Studio mode is active and cannot be. * * @enumIdentifier StudioModeActive @@ -250,8 +250,8 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - StudioModeActive = 505, - /** + StudioModeActive = 505, + /** * Studio mode is not active and should be. * * @enumIdentifier StudioModeNotActive @@ -261,10 +261,9 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - StudioModeNotActive = 506, - + StudioModeNotActive = 506, - /** + /** * The resource was not found. * * Note: Resources are any kind of object in obs-websocket, like inputs, profiles, outputs, etc. @@ -276,8 +275,8 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - ResourceNotFound = 600, - /** + ResourceNotFound = 600, + /** * The resource already exists. * * @enumIdentifier ResourceAlreadyExists @@ -287,8 +286,8 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - ResourceAlreadyExists = 601, - /** + ResourceAlreadyExists = 601, + /** * The type of resource found is invalid. * * @enumIdentifier InvalidResourceType @@ -298,8 +297,8 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - InvalidResourceType = 602, - /** + InvalidResourceType = 602, + /** * There are not enough instances of the resource in order to perform the request. * * @enumIdentifier NotEnoughResources @@ -309,8 +308,8 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - NotEnoughResources = 603, - /** + NotEnoughResources = 603, + /** * The state of the resource is invalid. For example, if the resource is blocked from being accessed. * * @enumIdentifier InvalidResourceState @@ -320,8 +319,8 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - InvalidResourceState = 604, - /** + InvalidResourceState = 604, + /** * The specified input (obs_source_t-OBS_SOURCE_TYPE_INPUT) had the wrong kind. * * @enumIdentifier InvalidInputKind @@ -331,8 +330,8 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - InvalidInputKind = 605, - /** + InvalidInputKind = 605, + /** * The resource does not support being configured. * * This is particularly relevant to transitions, where they do not always have changeable settings. @@ -344,8 +343,8 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - ResourceNotConfigurable = 606, - /** + ResourceNotConfigurable = 606, + /** * The specified filter (obs_source_t-OBS_SOURCE_TYPE_FILTER) had the wrong kind. * * @enumIdentifier InvalidFilterKind @@ -355,9 +354,9 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - InvalidFilterKind = 607, + InvalidFilterKind = 607, - /** + /** * Creating the resource failed. * * @enumIdentifier ResourceCreationFailed @@ -367,8 +366,8 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - ResourceCreationFailed = 700, - /** + ResourceCreationFailed = 700, + /** * Performing an action on the resource failed. * * @enumIdentifier ResourceActionFailed @@ -378,8 +377,8 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - ResourceActionFailed = 701, - /** + ResourceActionFailed = 701, + /** * Processing the request failed unexpectedly. * * Note: A comment is required to be provided by obs-websocket. @@ -391,8 +390,8 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - RequestProcessingFailed = 702, - /** + RequestProcessingFailed = 702, + /** * The combination of request fields cannot be used to perform an action. * * @enumIdentifier CannotAct @@ -402,6 +401,6 @@ namespace RequestStatus { * @initialVersion 5.0.0 * @api enums */ - CannotAct = 703, - }; + CannotAct = 703, +}; } diff --git a/src/utils/Compat.cpp b/src/utils/Compat.cpp index c35ae1dd..9eb784f4 100644 --- a/src/utils/Compat.cpp +++ b/src/utils/Compat.cpp @@ -19,8 +19,9 @@ with this program. If not, see #include "Compat.h" -Utils::Compat::StdFunctionRunnable::StdFunctionRunnable(std::function func) : - cb(std::move(func)) +Utils::Compat::StdFunctionRunnable::StdFunctionRunnable( + std::function func) + : cb(std::move(func)) { } diff --git a/src/utils/Compat.h b/src/utils/Compat.h index 67c0dc85..201c1574 100644 --- a/src/utils/Compat.h +++ b/src/utils/Compat.h @@ -23,15 +23,16 @@ with this program. If not, see #include namespace Utils { - namespace Compat { - // Reimplement QRunnable for std::function. Retrocompatability for Qt < 5.15 - class StdFunctionRunnable : public QRunnable { - std::function cb; - public: - StdFunctionRunnable(std::function func); - void run() override; - }; +namespace Compat { +// Reimplement QRunnable for std::function. Retrocompatability for Qt < 5.15 +class StdFunctionRunnable : public QRunnable { + std::function cb; - QRunnable *CreateFunctionRunnable(std::function func); - } +public: + StdFunctionRunnable(std::function func); + void run() override; +}; + +QRunnable *CreateFunctionRunnable(std::function func); +} } diff --git a/src/utils/Crypto.cpp b/src/utils/Crypto.cpp index d642f40e..8b89331c 100644 --- a/src/utils/Crypto.cpp +++ b/src/utils/Crypto.cpp @@ -24,7 +24,8 @@ with this program. If not, see #include "Crypto.h" #include "../plugin-macros.generated.h" -static const char allowedChars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; +static const char allowedChars[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; static const int allowedCharsCount = static_cast(sizeof(allowedChars) - 1); std::string Utils::Crypto::GenerateSalt() @@ -42,10 +43,12 @@ std::string Utils::Crypto::GenerateSalt() return randomChars.toBase64().toStdString(); } -std::string Utils::Crypto::GenerateSecret(std::string password, std::string salt) +std::string Utils::Crypto::GenerateSecret(std::string password, + std::string salt) { // Create challenge hash - auto challengeHash = QCryptographicHash(QCryptographicHash::Algorithm::Sha256); + auto challengeHash = + QCryptographicHash(QCryptographicHash::Algorithm::Sha256); // Add password bytes to hash challengeHash.addData(QByteArray::fromStdString(password)); // Add salt bytes to hash @@ -55,7 +58,9 @@ std::string Utils::Crypto::GenerateSecret(std::string password, std::string salt return challengeHash.result().toBase64().toStdString(); } -bool Utils::Crypto::CheckAuthenticationString(std::string secret, std::string challenge, std::string authenticationString) +bool Utils::Crypto::CheckAuthenticationString(std::string secret, + std::string challenge, + std::string authenticationString) { // Concatenate auth secret with the challenge sent to the user QString secretAndChallenge = ""; @@ -63,13 +68,13 @@ bool Utils::Crypto::CheckAuthenticationString(std::string secret, std::string ch secretAndChallenge += QString::fromStdString(challenge); // Generate a SHA256 hash of secretAndChallenge - auto hash = QCryptographicHash::hash( - secretAndChallenge.toUtf8(), - QCryptographicHash::Algorithm::Sha256 - ); + auto hash = + QCryptographicHash::hash(secretAndChallenge.toUtf8(), + QCryptographicHash::Algorithm::Sha256); // Encode the SHA256 hash to Base64 - std::string expectedAuthenticationString = hash.toBase64().toStdString(); + std::string expectedAuthenticationString = + hash.toBase64().toStdString(); return (authenticationString == expectedAuthenticationString); } diff --git a/src/utils/Crypto.h b/src/utils/Crypto.h index a86319bb..0e2b56e9 100644 --- a/src/utils/Crypto.h +++ b/src/utils/Crypto.h @@ -23,10 +23,11 @@ with this program. If not, see #include namespace Utils { - namespace Crypto { - std::string GenerateSalt(); - std::string GenerateSecret(std::string password, std::string salt); - bool CheckAuthenticationString(std::string secret, std::string challenge, std::string authenticationString); - std::string GeneratePassword(size_t length = 16); - } +namespace Crypto { +std::string GenerateSalt(); +std::string GenerateSecret(std::string password, std::string salt); +bool CheckAuthenticationString(std::string secret, std::string challenge, + std::string authenticationString); +std::string GeneratePassword(size_t length = 16); +} } diff --git a/src/utils/Json.cpp b/src/utils/Json.cpp index 114f3afe..34bbb7c4 100644 --- a/src/utils/Json.cpp +++ b/src/utils/Json.cpp @@ -45,7 +45,7 @@ void obs_data_set_json_array(obs_data_t *d, const char *key, json j) { obs_data_array_t *array = obs_data_array_create(); - for (auto& [key, value] : j.items()) { + for (auto &[key, value] : j.items()) { if (!value.is_object()) continue; @@ -61,17 +61,19 @@ void obs_data_set_json_array(obs_data_t *d, const char *key, json j) void obs_data_set_json_object_item(obs_data_t *d, json j) { - for (auto& [key, value] : j.items()) { + for (auto &[key, value] : j.items()) { if (value.is_object()) { obs_data_set_json_object(d, key.c_str(), value); } else if (value.is_array()) { obs_data_set_json_array(d, key.c_str(), value); } else if (value.is_string()) { - obs_data_set_string(d, key.c_str(), value.get().c_str()); + obs_data_set_string(d, key.c_str(), + value.get().c_str()); } else if (value.is_number_integer()) { obs_data_set_int(d, key.c_str(), value.get()); } else if (value.is_number_float()) { - obs_data_set_double(d, key.c_str(), value.get()); + obs_data_set_double(d, key.c_str(), + value.get()); } else if (value.is_boolean()) { obs_data_set_bool(d, key.c_str(), value.get()); } @@ -114,13 +116,15 @@ void set_json_bool(json *j, const char *name, obs_data_item_t *item) bool val = obs_data_item_get_bool(item); j->emplace(name, val); } -void set_json_object(json *j, const char *name, obs_data_item_t *item, bool includeDefault) +void set_json_object(json *j, const char *name, obs_data_item_t *item, + bool includeDefault) { obs_data_t *obj = obs_data_item_get_obj(item); j->emplace(name, Utils::Json::ObsDataToJson(obj, includeDefault)); obs_data_release(obj); } -void set_json_array(json *j, const char *name, obs_data_item_t *item, bool includeDefault) +void set_json_array(json *j, const char *name, obs_data_item_t *item, + bool includeDefault) { json jArray = json::array(); obs_data_array_t *array = obs_data_item_get_array(item); @@ -128,7 +132,8 @@ void set_json_array(json *j, const char *name, obs_data_item_t *item, bool inclu for (size_t idx = 0; idx < count; idx++) { obs_data_t *subItem = obs_data_array_item(array, idx); - json jItem = Utils::Json::ObsDataToJson(subItem, includeDefault); + json jItem = + Utils::Json::ObsDataToJson(subItem, includeDefault); obs_data_release(subItem); jArray.push_back(jItem); } @@ -153,23 +158,22 @@ json Utils::Json::ObsDataToJson(obs_data_t *d, bool includeDefault) continue; switch (type) { - case OBS_DATA_STRING: - set_json_string(&j, name, item); - break; - case OBS_DATA_NUMBER: - set_json_number(&j, name, item); - break; - case OBS_DATA_BOOLEAN: - set_json_bool(&j, name, item); - break; - case OBS_DATA_OBJECT: - set_json_object(&j, name, item, includeDefault); - break; - case OBS_DATA_ARRAY: - set_json_array(&j, name, item, includeDefault); - break; - default: - ; + case OBS_DATA_STRING: + set_json_string(&j, name, item); + break; + case OBS_DATA_NUMBER: + set_json_number(&j, name, item); + break; + case OBS_DATA_BOOLEAN: + set_json_bool(&j, name, item); + break; + case OBS_DATA_OBJECT: + set_json_object(&j, name, item, includeDefault); + break; + case OBS_DATA_ARRAY: + set_json_array(&j, name, item, includeDefault); + break; + default:; } } @@ -184,15 +188,19 @@ bool Utils::Json::GetJsonFileContent(std::string fileName, json &content) try { content = json::parse(textContent); - } catch (json::parse_error& e) { - blog(LOG_WARNING, "Failed to decode content of JSON file `%s`. Error: %s", fileName.c_str(), e.what()); + } catch (json::parse_error &e) { + blog(LOG_WARNING, + "Failed to decode content of JSON file `%s`. Error: %s", + fileName.c_str(), e.what()); return false; } return true; } -bool Utils::Json::SetJsonFileContent(std::string fileName, const json &content, bool createNew) +bool Utils::Json::SetJsonFileContent(std::string fileName, const json &content, + bool createNew) { std::string textContent = content.dump(2); - return Utils::Platform::SetTextFileContent(fileName, textContent, createNew); + return Utils::Platform::SetTextFileContent(fileName, textContent, + createNew); } diff --git a/src/utils/Json.h b/src/utils/Json.h index f2b88f2b..66998352 100644 --- a/src/utils/Json.h +++ b/src/utils/Json.h @@ -26,12 +26,16 @@ with this program. If not, see using json = nlohmann::json; namespace Utils { - namespace Json { - bool JsonArrayIsValidObsArray(const json &j); - obs_data_t *JsonToObsData(json j); - json ObsDataToJson(obs_data_t *d, bool includeDefault = false); - bool GetJsonFileContent(std::string fileName, json &content); - bool SetJsonFileContent(std::string fileName, const json &content, bool createNew = true); - static inline bool Contains(const json &j, std::string key) { return j.contains(key) && !j[key].is_null(); } - } +namespace Json { +bool JsonArrayIsValidObsArray(const json &j); +obs_data_t *JsonToObsData(json j); +json ObsDataToJson(obs_data_t *d, bool includeDefault = false); +bool GetJsonFileContent(std::string fileName, json &content); +bool SetJsonFileContent(std::string fileName, const json &content, + bool createNew = true); +static inline bool Contains(const json &j, std::string key) +{ + return j.contains(key) && !j[key].is_null(); +} +} } diff --git a/src/utils/Obs.h b/src/utils/Obs.h index 82ffa3a9..f849cc83 100644 --- a/src/utils/Obs.h +++ b/src/utils/Obs.h @@ -26,43 +26,65 @@ with this program. If not, see #include "Json.h" // Autorelease object definitions -inline void ___properties_dummy_addref(obs_properties_t*){} -using OBSPropertiesAutoDestroy = OBSRef; +inline void ___properties_dummy_addref(obs_properties_t *) {} +using OBSPropertiesAutoDestroy = + OBSRef; #if !defined(OBS_AUTORELEASE) -inline void ___source_dummy_addref(obs_source_t*){} -inline void ___scene_dummy_addref(obs_scene_t*){} -inline void ___sceneitem_dummy_addref(obs_sceneitem_t*){} -inline void ___data_dummy_addref(obs_data_t*){} -inline void ___data_array_dummy_addref(obs_data_array_t*){} -inline void ___output_dummy_addref(obs_output_t*){} -inline void ___encoder_dummy_addref(obs_encoder_t *){} -inline void ___service_dummy_addref(obs_service_t *){} +inline void ___source_dummy_addref(obs_source_t *) {} +inline void ___scene_dummy_addref(obs_scene_t *) {} +inline void ___sceneitem_dummy_addref(obs_sceneitem_t *) {} +inline void ___data_dummy_addref(obs_data_t *) {} +inline void ___data_array_dummy_addref(obs_data_array_t *) {} +inline void ___output_dummy_addref(obs_output_t *) {} +inline void ___encoder_dummy_addref(obs_encoder_t *) {} +inline void ___service_dummy_addref(obs_service_t *) {} -inline void ___weak_source_dummy_addref(obs_weak_source_t*){} -inline void ___weak_output_dummy_addref(obs_weak_output_t *){} -inline void ___weak_encoder_dummy_addref(obs_weak_encoder_t *){} -inline void ___weak_service_dummy_addref(obs_weak_service_t *){} +inline void ___weak_source_dummy_addref(obs_weak_source_t *) {} +inline void ___weak_output_dummy_addref(obs_weak_output_t *) {} +inline void ___weak_encoder_dummy_addref(obs_weak_encoder_t *) {} +inline void ___weak_service_dummy_addref(obs_weak_service_t *) {} -using OBSSourceAutoRelease = OBSRef; -using OBSSceneAutoRelease = OBSRef; -using OBSSceneItemAutoRelease = OBSRef; -using OBSDataAutoRelease = OBSRef; -using OBSDataArrayAutoRelease = OBSRef; -using OBSOutputAutoRelease = OBSRef; -using OBSEncoderAutoRelease = OBSRef; -using OBSServiceAutoRelease = OBSRef; +using OBSSourceAutoRelease = + OBSRef; +using OBSSceneAutoRelease = + OBSRef; +using OBSSceneItemAutoRelease = + OBSRef; +using OBSDataAutoRelease = + OBSRef; +using OBSDataArrayAutoRelease = + OBSRef; +using OBSOutputAutoRelease = + OBSRef; +using OBSEncoderAutoRelease = + OBSRef; +using OBSServiceAutoRelease = + OBSRef; -using OBSWeakSourceAutoRelease = OBSRef; -using OBSWeakOutputAutoRelease = OBSRef; -using OBSWeakEncoderAutoRelease = OBSRef; -using OBSWeakServiceAutoRelease = OBSRef; +using OBSWeakSourceAutoRelease = + OBSRef; +using OBSWeakOutputAutoRelease = + OBSRef; +using OBSWeakEncoderAutoRelease = + OBSRef; +using OBSWeakServiceAutoRelease = + OBSRef; #endif -template T* GetCalldataPointer(const calldata_t *data, const char* name) { +template +T *GetCalldataPointer(const calldata_t *data, const char *name) +{ void *ptr = nullptr; calldata_get_ptr(data, name, &ptr); - return static_cast(ptr); + return static_cast(ptr); } enum ObsOutputState { @@ -150,69 +172,86 @@ enum ObsMediaInputAction { }; namespace Utils { - namespace Obs { - namespace StringHelper { - std::string GetObsVersion(); - std::string GetCurrentSceneCollection(); - std::string GetCurrentProfile(); - std::string GetCurrentProfilePath(); - std::string GetCurrentRecordOutputPath(); - std::string GetSourceType(obs_source_t *source); - std::string GetInputMonitorType(enum obs_monitoring_type monitorType); - std::string GetInputMonitorType(obs_source_t *input); - std::string GetMediaInputState(obs_source_t *input); - std::string GetLastReplayBufferFilePath(); - std::string GetSceneItemBoundsType(enum obs_bounds_type type); - std::string GetSceneItemBlendMode(enum obs_blending_type mode); - std::string DurationToTimecode(uint64_t); - std::string GetOutputState(ObsOutputState state); - } - - namespace EnumHelper { - enum obs_bounds_type GetSceneItemBoundsType(std::string boundsType); - enum ObsMediaInputAction GetMediaInputAction(std::string mediaAction); - enum obs_blending_type GetSceneItemBlendMode(std::string mode); - } - - namespace NumberHelper { - uint64_t GetOutputDuration(obs_output_t *output); - size_t GetSceneCount(); - size_t GetSourceFilterIndex(obs_source_t *source, obs_source_t *filter); - } - - namespace ArrayHelper { - std::vector GetSceneCollectionList(); - std::vector GetProfileList(); - std::vector GetHotkeyList(); - std::vector GetHotkeyNameList(); - std::vector GetSceneList(); - std::vector GetGroupList(); - std::vector GetSceneItemList(obs_scene_t *scene, bool basic = false); - std::vector GetInputList(std::string inputKind = ""); - std::vector GetInputKindList(bool unversioned = false, bool includeDisabled = false); - std::vector GetListPropertyItems(obs_property_t *property); - std::vector GetTransitionKindList(); - std::vector GetSceneTransitionList(); - std::vector GetSourceFilterList(obs_source_t *source); - std::vector GetFilterKindList(); - } - - namespace ObjectHelper { - json GetStats(); - json GetSceneItemTransform(obs_sceneitem_t *item); - } - - namespace SearchHelper { - obs_hotkey_t *GetHotkeyByName(std::string name); - obs_source_t *GetSceneTransitionByName(std::string name); // Increments source ref. Use OBSSourceAutoRelease - obs_sceneitem_t *GetSceneItemByName(obs_scene_t *scene, std::string name, int offset = 0); // Increments ref. Use OBSSceneItemAutoRelease - } - - 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); - } - } +namespace Obs { +namespace StringHelper { +std::string GetObsVersion(); +std::string GetCurrentSceneCollection(); +std::string GetCurrentProfile(); +std::string GetCurrentProfilePath(); +std::string GetCurrentRecordOutputPath(); +std::string GetSourceType(obs_source_t *source); +std::string GetInputMonitorType(enum obs_monitoring_type monitorType); +std::string GetInputMonitorType(obs_source_t *input); +std::string GetMediaInputState(obs_source_t *input); +std::string GetLastReplayBufferFilePath(); +std::string GetSceneItemBoundsType(enum obs_bounds_type type); +std::string GetSceneItemBlendMode(enum obs_blending_type mode); +std::string DurationToTimecode(uint64_t); +std::string GetOutputState(ObsOutputState state); +} + +namespace EnumHelper { +enum obs_bounds_type GetSceneItemBoundsType(std::string boundsType); +enum ObsMediaInputAction GetMediaInputAction(std::string mediaAction); +enum obs_blending_type GetSceneItemBlendMode(std::string mode); +} + +namespace NumberHelper { +uint64_t GetOutputDuration(obs_output_t *output); +size_t GetSceneCount(); +size_t GetSourceFilterIndex(obs_source_t *source, obs_source_t *filter); +} + +namespace ArrayHelper { +std::vector GetSceneCollectionList(); +std::vector GetProfileList(); +std::vector GetHotkeyList(); +std::vector GetHotkeyNameList(); +std::vector GetSceneList(); +std::vector GetGroupList(); +std::vector GetSceneItemList(obs_scene_t *scene, bool basic = false); +std::vector GetInputList(std::string inputKind = ""); +std::vector GetInputKindList(bool unversioned = false, + bool includeDisabled = false); +std::vector GetListPropertyItems(obs_property_t *property); +std::vector GetTransitionKindList(); +std::vector GetSceneTransitionList(); +std::vector GetSourceFilterList(obs_source_t *source); +std::vector GetFilterKindList(); +} + +namespace ObjectHelper { +json GetStats(); +json GetSceneItemTransform(obs_sceneitem_t *item); +} + +namespace SearchHelper { +obs_hotkey_t *GetHotkeyByName(std::string name); +obs_source_t *GetSceneTransitionByName( + std::string name); // Increments source ref. Use OBSSourceAutoRelease +obs_sceneitem_t *GetSceneItemByName( + obs_scene_t *scene, std::string name, + int offset = 0); // Increments ref. Use OBSSceneItemAutoRelease +} + +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); +} +} } diff --git a/src/utils/Obs_ActionHelper.cpp b/src/utils/Obs_ActionHelper.cpp index 8e981125..bd0d1444 100644 --- a/src/utils/Obs_ActionHelper.cpp +++ b/src/utils/Obs_ActionHelper.cpp @@ -20,20 +20,21 @@ with this program. If not, see #include "../plugin-macros.generated.h" struct CreateSceneItemData { - obs_source_t *source; // In - bool sceneItemEnabled; // In + obs_source_t *source; // In + bool sceneItemEnabled; // In obs_transform_info *sceneItemTransform = nullptr; // In - obs_sceneitem_crop *sceneItemCrop = nullptr; // In - OBSSceneItem sceneItem; // Out + obs_sceneitem_crop *sceneItemCrop = nullptr; // In + OBSSceneItem sceneItem; // Out }; void CreateSceneItemHelper(void *_data, obs_scene_t *scene) { - auto *data = static_cast(_data); + auto *data = static_cast(_data); data->sceneItem = obs_scene_add(scene, data->source); if (data->sceneItemTransform) - obs_sceneitem_set_info(data->sceneItem, data->sceneItemTransform); + obs_sceneitem_set_info(data->sceneItem, + data->sceneItemTransform); if (data->sceneItemCrop) obs_sceneitem_set_crop(data->sceneItem, data->sceneItemCrop); @@ -41,7 +42,10 @@ void CreateSceneItemHelper(void *_data, obs_scene_t *scene) obs_sceneitem_set_visible(data->sceneItem, data->sceneItemEnabled); } -obs_sceneitem_t *Utils::Obs::ActionHelper::CreateSceneItem(obs_source_t *source, obs_scene_t *scene, bool sceneItemEnabled, obs_transform_info *sceneItemTransform, obs_sceneitem_crop *sceneItemCrop) +obs_sceneitem_t *Utils::Obs::ActionHelper::CreateSceneItem( + obs_source_t *source, obs_scene_t *scene, bool sceneItemEnabled, + obs_transform_info *sceneItemTransform, + obs_sceneitem_crop *sceneItemCrop) { // Sanity check for valid scene if (!(source && scene)) @@ -64,10 +68,13 @@ obs_sceneitem_t *Utils::Obs::ActionHelper::CreateSceneItem(obs_source_t *source, return data.sceneItem; } -obs_sceneitem_t *Utils::Obs::ActionHelper::CreateInput(std::string inputName, std::string inputKind, obs_data_t *inputSettings, obs_scene_t *scene, bool sceneItemEnabled) +obs_sceneitem_t *Utils::Obs::ActionHelper::CreateInput( + std::string inputName, std::string inputKind, obs_data_t *inputSettings, + obs_scene_t *scene, bool sceneItemEnabled) { // Create the input - OBSSourceAutoRelease input = obs_source_create(inputKind.c_str(), inputName.c_str(), inputSettings, nullptr); + OBSSourceAutoRelease input = obs_source_create( + inputKind.c_str(), inputName.c_str(), inputSettings, nullptr); // Check that everything was created properly if (!input) @@ -76,7 +83,8 @@ obs_sceneitem_t *Utils::Obs::ActionHelper::CreateInput(std::string inputName, st // Apparently not all default input properties actually get applied on creation (smh) uint32_t flags = obs_source_get_output_flags(input); if ((flags & OBS_SOURCE_MONITOR_BY_DEFAULT) != 0) - obs_source_set_monitoring_type(input, OBS_MONITORING_TYPE_MONITOR_ONLY); + obs_source_set_monitoring_type( + input, OBS_MONITORING_TYPE_MONITOR_ONLY); // Create a scene item for the input obs_sceneitem_t *ret = CreateSceneItem(input, scene, sceneItemEnabled); @@ -88,9 +96,12 @@ 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 *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); + obs_source_t *filter = obs_source_create_private( + filterKind.c_str(), filterName.c_str(), filterSettings); if (!filter) return nullptr; @@ -100,12 +111,16 @@ obs_source_t *Utils::Obs::ActionHelper::CreateSourceFilter(obs_source_t *source, return filter; } -void Utils::Obs::ActionHelper::SetSourceFilterIndex(obs_source_t *source, obs_source_t *filter, size_t index) +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; + 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) { + while (currentIndex != index) { obs_source_filter_set_order(source, filter, direction); if (direction == OBS_ORDER_MOVE_DOWN) diff --git a/src/utils/Obs_ArrayHelper.cpp b/src/utils/Obs_ArrayHelper.cpp index 3b99f2ce..eb70aac7 100644 --- a/src/utils/Obs_ArrayHelper.cpp +++ b/src/utils/Obs_ArrayHelper.cpp @@ -29,7 +29,7 @@ static std::vector ConvertStringArray(char **array) return ret; size_t index = 0; - char* value = nullptr; + char *value = nullptr; do { value = array[index]; if (value) @@ -42,7 +42,7 @@ static std::vector ConvertStringArray(char **array) std::vector Utils::Obs::ArrayHelper::GetSceneCollectionList() { - char** sceneCollections = obs_frontend_get_scene_collections(); + char **sceneCollections = obs_frontend_get_scene_collections(); auto ret = ConvertStringArray(sceneCollections); bfree(sceneCollections); return ret; @@ -50,7 +50,7 @@ std::vector Utils::Obs::ArrayHelper::GetSceneCollectionList() std::vector Utils::Obs::ArrayHelper::GetProfileList() { - char** profiles = obs_frontend_get_profiles(); + char **profiles = obs_frontend_get_profiles(); auto ret = ConvertStringArray(profiles); bfree(profiles); return ret; @@ -60,13 +60,16 @@ std::vector Utils::Obs::ArrayHelper::GetHotkeyList() { std::vector ret; - obs_enum_hotkeys([](void* data, obs_hotkey_id, obs_hotkey_t* hotkey) { - auto ret = static_cast *>(data); + obs_enum_hotkeys( + [](void *data, obs_hotkey_id, obs_hotkey_t *hotkey) { + auto ret = static_cast *>( + data); - ret->push_back(hotkey); + ret->push_back(hotkey); - return true; - }, &ret); + return true; + }, + &ret); return ret; } @@ -112,7 +115,7 @@ std::vector Utils::Obs::ArrayHelper::GetGroupList() std::vector ret; auto cb = [](void *priv_data, obs_source_t *scene) { - auto ret = static_cast*>(priv_data); + auto ret = static_cast *>(priv_data); if (!obs_source_is_group(scene)) return true; @@ -127,36 +130,48 @@ std::vector Utils::Obs::ArrayHelper::GetGroupList() return ret; } -std::vector Utils::Obs::ArrayHelper::GetSceneItemList(obs_scene_t *scene, bool basic) +std::vector Utils::Obs::ArrayHelper::GetSceneItemList(obs_scene_t *scene, + bool basic) { std::pair, bool> enumData; enumData.second = basic; - obs_scene_enum_items(scene, [](obs_scene_t*, obs_sceneitem_t* sceneItem, void* param) { - auto enumData = static_cast, bool>*>(param); + obs_scene_enum_items( + scene, + [](obs_scene_t *, obs_sceneitem_t *sceneItem, void *param) { + auto enumData = static_cast< + std::pair, bool> *>(param); - json item; - item["sceneItemId"] = obs_sceneitem_get_id(sceneItem); - // Should be slightly faster than calling obs_sceneitem_get_order_position() - item["sceneItemIndex"] = enumData->first.size(); - if (!enumData->second) { - OBSSource itemSource = obs_sceneitem_get_source(sceneItem); - item["sourceName"] = obs_source_get_name(itemSource); - item["sourceType"] = StringHelper::GetSourceType(itemSource); - if (obs_source_get_type(itemSource) == OBS_SOURCE_TYPE_INPUT) - item["inputKind"] = obs_source_get_id(itemSource); - else - item["inputKind"] = nullptr; - if (obs_source_get_type(itemSource) == OBS_SOURCE_TYPE_SCENE) - item["isGroup"] = obs_source_is_group(itemSource); - else - item["isGroup"] = nullptr; - } + json item; + item["sceneItemId"] = obs_sceneitem_get_id(sceneItem); + // Should be slightly faster than calling obs_sceneitem_get_order_position() + item["sceneItemIndex"] = enumData->first.size(); + if (!enumData->second) { + OBSSource itemSource = + obs_sceneitem_get_source(sceneItem); + item["sourceName"] = + obs_source_get_name(itemSource); + item["sourceType"] = + StringHelper::GetSourceType(itemSource); + if (obs_source_get_type(itemSource) == + OBS_SOURCE_TYPE_INPUT) + item["inputKind"] = + obs_source_get_id(itemSource); + else + item["inputKind"] = nullptr; + if (obs_source_get_type(itemSource) == + OBS_SOURCE_TYPE_SCENE) + item["isGroup"] = + obs_source_is_group(itemSource); + else + item["isGroup"] = nullptr; + } - enumData->first.push_back(item); + enumData->first.push_back(item); - return true; - }, &enumData); + return true; + }, + &enumData); return enumData.first; } @@ -176,17 +191,19 @@ std::vector Utils::Obs::ArrayHelper::GetInputList(std::string inputKind) if (obs_source_get_type(input) != OBS_SOURCE_TYPE_INPUT) return true; - auto inputInfo = static_cast(param); + auto inputInfo = static_cast(param); std::string inputKind = obs_source_get_id(input); - if (!inputInfo->inputKind.empty() && inputInfo->inputKind != inputKind) + if (!inputInfo->inputKind.empty() && + inputInfo->inputKind != inputKind) return true; json inputJson; inputJson["inputName"] = obs_source_get_name(input); inputJson["inputKind"] = inputKind; - inputJson["unversionedInputKind"] = obs_source_get_unversioned_id(input); + inputJson["unversionedInputKind"] = + obs_source_get_unversioned_id(input); inputInfo->inputs.push_back(inputJson); return true; @@ -197,7 +214,9 @@ std::vector Utils::Obs::ArrayHelper::GetInputList(std::string inputKind) return inputInfo.inputs; } -std::vector Utils::Obs::ArrayHelper::GetInputKindList(bool unversioned, bool includeDisabled) +std::vector +Utils::Obs::ArrayHelper::GetInputKindList(bool unversioned, + bool includeDisabled) { std::vector ret; @@ -219,7 +238,8 @@ std::vector Utils::Obs::ArrayHelper::GetInputKindList(bool unversio return ret; } -std::vector Utils::Obs::ArrayHelper::GetListPropertyItems(obs_property_t *property) +std::vector +Utils::Obs::ArrayHelper::GetListPropertyItems(obs_property_t *property) { std::vector ret; @@ -231,13 +251,17 @@ std::vector Utils::Obs::ArrayHelper::GetListPropertyItems(obs_property_t * for (size_t i = 0; i < itemCount; i++) { json itemData; itemData["itemName"] = obs_property_list_item_name(property, i); - itemData["itemEnabled"] = !obs_property_list_item_disabled(property, i); + itemData["itemEnabled"] = + !obs_property_list_item_disabled(property, i); if (itemFormat == OBS_COMBO_FORMAT_INT) { - itemData["itemValue"] = obs_property_list_item_int(property, i); + itemData["itemValue"] = + obs_property_list_item_int(property, i); } else if (itemFormat == OBS_COMBO_FORMAT_FLOAT) { - itemData["itemValue"] = obs_property_list_item_float(property, i); + itemData["itemValue"] = + obs_property_list_item_float(property, i); } else if (itemFormat == OBS_COMBO_FORMAT_STRING) { - itemData["itemValue"] = obs_property_list_item_string(property, i); + itemData["itemValue"] = + obs_property_list_item_string(property, i); } else { itemData["itemValue"] = nullptr; } @@ -269,10 +293,14 @@ std::vector Utils::Obs::ArrayHelper::GetSceneTransitionList() for (size_t i = 0; i < transitionList.sources.num; i++) { obs_source_t *transition = transitionList.sources.array[i]; json transitionJson; - transitionJson["transitionName"] = obs_source_get_name(transition); - transitionJson["transitionKind"] = obs_source_get_id(transition); - transitionJson["transitionFixed"] = obs_transition_fixed(transition); - transitionJson["transitionConfigurable"] = obs_source_configurable(transition); + transitionJson["transitionName"] = + obs_source_get_name(transition); + transitionJson["transitionKind"] = + obs_source_get_id(transition); + transitionJson["transitionFixed"] = + obs_transition_fixed(transition); + transitionJson["transitionConfigurable"] = + obs_source_configurable(transition); ret.push_back(transitionJson); } @@ -287,18 +315,20 @@ std::vector Utils::Obs::ArrayHelper::GetFilterKindList() size_t idx = 0; const char *kind; - while(obs_enum_filter_types(idx++, &kind)) + while (obs_enum_filter_types(idx++, &kind)) ret.push_back(kind); return ret; } -std::vector Utils::Obs::ArrayHelper::GetSourceFilterList(obs_source_t *source) +std::vector +Utils::Obs::ArrayHelper::GetSourceFilterList(obs_source_t *source) { std::vector filters; - auto enumFilters = [](obs_source_t *, obs_source_t *filter, void *param) { - auto filters = reinterpret_cast*>(param); + auto enumFilters = [](obs_source_t *, obs_source_t *filter, + void *param) { + auto filters = reinterpret_cast *>(param); json filterJson; filterJson["filterEnabled"] = obs_source_enabled(filter); @@ -306,8 +336,10 @@ std::vector Utils::Obs::ArrayHelper::GetSourceFilterList(obs_source_t *sou 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); + OBSDataAutoRelease filterSettings = + obs_source_get_settings(filter); + filterJson["filterSettings"] = + Utils::Json::ObsDataToJson(filterSettings); filters->push_back(filterJson); }; diff --git a/src/utils/Obs_EnumHelper.cpp b/src/utils/Obs_EnumHelper.cpp index 887c33d1..b36e0eaa 100644 --- a/src/utils/Obs_EnumHelper.cpp +++ b/src/utils/Obs_EnumHelper.cpp @@ -19,9 +19,12 @@ with this program. If not, see #include "Obs.h" #include "../plugin-macros.generated.h" -#define RET_COMPARE(str, x) if (str == #x) return x; +#define RET_COMPARE(str, x) \ + if (str == #x) \ + return x; -enum obs_bounds_type Utils::Obs::EnumHelper::GetSceneItemBoundsType(std::string boundsType) +enum obs_bounds_type +Utils::Obs::EnumHelper::GetSceneItemBoundsType(std::string boundsType) { RET_COMPARE(boundsType, OBS_BOUNDS_NONE) RET_COMPARE(boundsType, OBS_BOUNDS_STRETCH) @@ -34,7 +37,8 @@ enum obs_bounds_type Utils::Obs::EnumHelper::GetSceneItemBoundsType(std::string return OBS_BOUNDS_NONE; } -enum ObsMediaInputAction Utils::Obs::EnumHelper::GetMediaInputAction(std::string mediaAction) +enum ObsMediaInputAction +Utils::Obs::EnumHelper::GetMediaInputAction(std::string mediaAction) { RET_COMPARE(mediaAction, OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PLAY) RET_COMPARE(mediaAction, OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PAUSE) @@ -46,7 +50,8 @@ enum ObsMediaInputAction Utils::Obs::EnumHelper::GetMediaInputAction(std::string return OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NONE; } -enum obs_blending_type Utils::Obs::EnumHelper::GetSceneItemBlendMode(std::string mode) +enum obs_blending_type +Utils::Obs::EnumHelper::GetSceneItemBlendMode(std::string mode) { RET_COMPARE(mode, OBS_BLEND_NORMAL) RET_COMPARE(mode, OBS_BLEND_ADDITIVE) diff --git a/src/utils/Obs_NumberHelper.cpp b/src/utils/Obs_NumberHelper.cpp index a510c783..4198c5a6 100644 --- a/src/utils/Obs_NumberHelper.cpp +++ b/src/utils/Obs_NumberHelper.cpp @@ -28,7 +28,7 @@ uint64_t Utils::Obs::NumberHelper::GetOutputDuration(obs_output_t *output) if (!output || !obs_output_active(output)) return 0; - video_t* video = obs_output_video(output); + video_t *video = obs_output_video(output); uint64_t frameTimeNs = video_output_get_frame_time(video); int totalFrames = obs_output_get_total_frames(output); @@ -39,7 +39,7 @@ size_t Utils::Obs::NumberHelper::GetSceneCount() { size_t ret; auto sceneEnumProc = [](void *param, obs_source_t *scene) { - auto ret = static_cast(param); + auto ret = static_cast(param); if (obs_source_is_group(scene)) return true; @@ -53,7 +53,8 @@ size_t Utils::Obs::NumberHelper::GetSceneCount() return ret; } -size_t Utils::Obs::NumberHelper::GetSourceFilterIndex(obs_source_t *source, obs_source_t *filter) +size_t Utils::Obs::NumberHelper::GetSourceFilterIndex(obs_source_t *source, + obs_source_t *filter) { struct FilterSearch { obs_source_t *filter; @@ -61,8 +62,9 @@ size_t Utils::Obs::NumberHelper::GetSourceFilterIndex(obs_source_t *source, obs_ size_t index; }; - auto search = [](obs_source_t *, obs_source_t *filter, void *priv_data) { - auto filterSearch = static_cast(priv_data); + auto search = [](obs_source_t *, obs_source_t *filter, + void *priv_data) { + auto filterSearch = static_cast(priv_data); if (filter == filterSearch->filter) filterSearch->found = true; diff --git a/src/utils/Obs_ObjectHelper.cpp b/src/utils/Obs_ObjectHelper.cpp index 14714976..ddf99001 100644 --- a/src/utils/Obs_ObjectHelper.cpp +++ b/src/utils/Obs_ObjectHelper.cpp @@ -27,15 +27,20 @@ json Utils::Obs::ObjectHelper::GetStats() { json ret; - std::string outputPath = Utils::Obs::StringHelper::GetCurrentRecordOutputPath(); + std::string outputPath = + Utils::Obs::StringHelper::GetCurrentRecordOutputPath(); - video_t* video = obs_get_video(); + video_t *video = obs_get_video(); ret["cpuUsage"] = os_cpu_usage_info_query(GetCpuUsageInfo()); - ret["memoryUsage"] = (double)os_get_proc_resident_size() / (1024.0 * 1024.0); - ret["availableDiskSpace"] = (double)os_get_free_disk_space(outputPath.c_str()) / (1024.0 * 1024.0); + ret["memoryUsage"] = + (double)os_get_proc_resident_size() / (1024.0 * 1024.0); + ret["availableDiskSpace"] = + (double)os_get_free_disk_space(outputPath.c_str()) / + (1024.0 * 1024.0); ret["activeFps"] = obs_get_active_fps(); - ret["averageFrameRenderTime"] = (double)obs_get_average_frame_time_ns() / 1000000.0; + ret["averageFrameRenderTime"] = + (double)obs_get_average_frame_time_ns() / 1000000.0; ret["renderSkippedFrames"] = obs_get_lagged_frames(); ret["renderTotalFrames"] = obs_get_total_frames(); ret["outputSkippedFrames"] = video_output_get_skipped_frames(video); @@ -73,7 +78,8 @@ json Utils::Obs::ObjectHelper::GetSceneItemTransform(obs_sceneitem_t *item) ret["alignment"] = osi.alignment; - ret["boundsType"] = StringHelper::GetSceneItemBoundsType(osi.bounds_type); + ret["boundsType"] = + StringHelper::GetSceneItemBoundsType(osi.bounds_type); ret["boundsAlignment"] = osi.bounds_alignment; ret["boundsWidth"] = osi.bounds.x; ret["boundsHeight"] = osi.bounds.y; diff --git a/src/utils/Obs_SearchHelper.cpp b/src/utils/Obs_SearchHelper.cpp index f16501d6..a6808505 100644 --- a/src/utils/Obs_SearchHelper.cpp +++ b/src/utils/Obs_SearchHelper.cpp @@ -35,7 +35,8 @@ obs_hotkey_t *Utils::Obs::SearchHelper::GetHotkeyByName(std::string name) } // Increments source ref. Use OBSSourceAutoRelease -obs_source_t *Utils::Obs::SearchHelper::GetSceneTransitionByName(std::string name) +obs_source_t * +Utils::Obs::SearchHelper::GetSceneTransitionByName(std::string name) { obs_frontend_source_list transitionList = {}; obs_frontend_get_transitions(&transitionList); @@ -61,7 +62,9 @@ struct SceneItemSearchData { }; // Increments item ref. Use OBSSceneItemAutoRelease -obs_sceneitem_t *Utils::Obs::SearchHelper::GetSceneItemByName(obs_scene_t *scene, std::string name, int offset) +obs_sceneitem_t * +Utils::Obs::SearchHelper::GetSceneItemByName(obs_scene_t *scene, + std::string name, int offset) { if (name.empty()) return nullptr; @@ -70,26 +73,34 @@ obs_sceneitem_t *Utils::Obs::SearchHelper::GetSceneItemByName(obs_scene_t *scene enumData.name = name; enumData.offset = offset; - obs_scene_enum_items(scene, [](obs_scene_t*, obs_sceneitem_t* sceneItem, void* param) { - auto enumData = static_cast(param); + obs_scene_enum_items( + scene, + [](obs_scene_t *, obs_sceneitem_t *sceneItem, void *param) { + auto enumData = + static_cast(param); - OBSSource itemSource = obs_sceneitem_get_source(sceneItem); - std::string sourceName = obs_source_get_name(itemSource); - if (sourceName == enumData->name) { - if (enumData->offset > 0) { - enumData->offset--; - } else { - if (enumData->ret) // Release existing selection in the case of last match selection - obs_sceneitem_release(enumData->ret); - obs_sceneitem_addref(sceneItem); - enumData->ret = sceneItem; - if (enumData->offset == 0) // Only break if in normal selection mode (not offset == -1) - return false; + OBSSource itemSource = + obs_sceneitem_get_source(sceneItem); + std::string sourceName = + obs_source_get_name(itemSource); + if (sourceName == enumData->name) { + if (enumData->offset > 0) { + enumData->offset--; + } else { + if (enumData->ret) // Release existing selection in the case of last match selection + obs_sceneitem_release( + enumData->ret); + obs_sceneitem_addref(sceneItem); + enumData->ret = sceneItem; + if (enumData->offset == + 0) // Only break if in normal selection mode (not offset == -1) + return false; + } } - } - return true; - }, &enumData); + return true; + }, + &enumData); return enumData.ret; } diff --git a/src/utils/Obs_StringHelper.cpp b/src/utils/Obs_StringHelper.cpp index c5e1bc07..a0e8ca65 100644 --- a/src/utils/Obs_StringHelper.cpp +++ b/src/utils/Obs_StringHelper.cpp @@ -23,7 +23,9 @@ with this program. If not, see #include "Obs.h" #include "../plugin-macros.generated.h" -#define CASE(x) case x: return #x; +#define CASE(x) \ + case x: \ + return #x; std::string Utils::Obs::StringHelper::GetObsVersion() { @@ -75,7 +77,7 @@ std::string Utils::Obs::StringHelper::GetSourceType(obs_source_t *source) obs_source_type sourceType = obs_source_get_type(source); switch (sourceType) { - default: + default: CASE(OBS_SOURCE_TYPE_INPUT) CASE(OBS_SOURCE_TYPE_FILTER) CASE(OBS_SOURCE_TYPE_TRANSITION) @@ -83,10 +85,11 @@ std::string Utils::Obs::StringHelper::GetSourceType(obs_source_t *source) } } -std::string Utils::Obs::StringHelper::GetInputMonitorType(enum obs_monitoring_type monitorType) +std::string Utils::Obs::StringHelper::GetInputMonitorType( + enum obs_monitoring_type monitorType) { switch (monitorType) { - default: + default: CASE(OBS_MONITORING_TYPE_NONE) CASE(OBS_MONITORING_TYPE_MONITOR_ONLY) CASE(OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT) @@ -105,7 +108,7 @@ std::string Utils::Obs::StringHelper::GetMediaInputState(obs_source_t *input) obs_media_state mediaState = obs_source_media_get_state(input); switch (mediaState) { - default: + default: CASE(OBS_MEDIA_STATE_NONE) CASE(OBS_MEDIA_STATE_PLAYING) CASE(OBS_MEDIA_STATE_OPENING) @@ -135,10 +138,11 @@ std::string Utils::Obs::StringHelper::GetLastReplayBufferFilePath() return savedReplayPath; } -std::string Utils::Obs::StringHelper::GetSceneItemBoundsType(enum obs_bounds_type type) +std::string +Utils::Obs::StringHelper::GetSceneItemBoundsType(enum obs_bounds_type type) { switch (type) { - default: + default: CASE(OBS_BOUNDS_NONE) CASE(OBS_BOUNDS_STRETCH) CASE(OBS_BOUNDS_SCALE_INNER) @@ -149,10 +153,11 @@ std::string Utils::Obs::StringHelper::GetSceneItemBoundsType(enum obs_bounds_typ } } -std::string Utils::Obs::StringHelper::GetSceneItemBlendMode(enum obs_blending_type mode) +std::string +Utils::Obs::StringHelper::GetSceneItemBlendMode(enum obs_blending_type mode) { switch (mode) { - default: + default: CASE(OBS_BLEND_NORMAL) CASE(OBS_BLEND_ADDITIVE) CASE(OBS_BLEND_SUBTRACT) @@ -173,14 +178,17 @@ std::string Utils::Obs::StringHelper::DurationToTimecode(uint64_t ms) uint64_t secsPart = secs % 60ULL; uint64_t msPart = ms % 1000ULL; - QString formatted = QString::asprintf("%02" PRIu64 ":%02" PRIu64 ":%02" PRIu64 ".%03" PRIu64, hoursPart, minutesPart, secsPart, msPart); + QString formatted = QString::asprintf("%02" PRIu64 ":%02" PRIu64 + ":%02" PRIu64 ".%03" PRIu64, + hoursPart, minutesPart, secsPart, + msPart); return formatted.toStdString(); } std::string Utils::Obs::StringHelper::GetOutputState(ObsOutputState state) { switch (state) { - default: + default: CASE(OBS_WEBSOCKET_OUTPUT_UNKNOWN) CASE(OBS_WEBSOCKET_OUTPUT_STARTING) CASE(OBS_WEBSOCKET_OUTPUT_STARTED) diff --git a/src/utils/Obs_VolumeMeter.cpp b/src/utils/Obs_VolumeMeter.cpp index 9fa75eec..7f927225 100644 --- a/src/utils/Obs_VolumeMeter.cpp +++ b/src/utils/Obs_VolumeMeter.cpp @@ -26,35 +26,43 @@ with this program. If not, see #include "Obs_VolumeMeter_Helpers.h" #include "../obs-websocket.h" -Utils::Obs::VolumeMeter::Meter::Meter(obs_source_t *input) : - PeakMeterType(SAMPLE_PEAK_METER), - _input(obs_source_get_weak_source(input)), - _channels(0), - _lastUpdate(0), - _volume(obs_source_get_volume(input)) +Utils::Obs::VolumeMeter::Meter::Meter(obs_source_t *input) + : PeakMeterType(SAMPLE_PEAK_METER), + _input(obs_source_get_weak_source(input)), + _channels(0), + _lastUpdate(0), + _volume(obs_source_get_volume(input)) { signal_handler_t *sh = obs_source_get_signal_handler(input); signal_handler_connect(sh, "volume", Meter::InputVolumeCallback, this); - obs_source_add_audio_capture_callback(input, Meter::InputAudioCaptureCallback, this); + obs_source_add_audio_capture_callback( + input, Meter::InputAudioCaptureCallback, this); - blog_debug("[Utils::Obs::VolumeMeter::Meter::Meter] Meter created for input: %s", obs_source_get_name(input)); + blog_debug( + "[Utils::Obs::VolumeMeter::Meter::Meter] Meter created for input: %s", + obs_source_get_name(input)); } Utils::Obs::VolumeMeter::Meter::~Meter() { OBSSourceAutoRelease input = obs_weak_source_get_source(_input); if (!input) { - blog(LOG_WARNING, "[Utils::Obs::VolumeMeter::Meter::~Meter] Failed to get strong reference to input. Has it been destroyed?"); + blog(LOG_WARNING, + "[Utils::Obs::VolumeMeter::Meter::~Meter] Failed to get strong reference to input. Has it been destroyed?"); return; } signal_handler_t *sh = obs_source_get_signal_handler(input); - signal_handler_disconnect(sh, "volume", Meter::InputVolumeCallback, this); + signal_handler_disconnect(sh, "volume", Meter::InputVolumeCallback, + this); - obs_source_remove_audio_capture_callback(input, Meter::InputAudioCaptureCallback, this); + obs_source_remove_audio_capture_callback( + input, Meter::InputAudioCaptureCallback, this); - blog_debug("[Utils::Obs::VolumeMeter::Meter::~Meter] Meter destroyed for input: %s", obs_source_get_name(input)); + blog_debug( + "[Utils::Obs::VolumeMeter::Meter::~Meter] Meter destroyed for input: %s", + obs_source_get_name(input)); } bool Utils::Obs::VolumeMeter::Meter::InputValid() @@ -68,7 +76,8 @@ json Utils::Obs::VolumeMeter::Meter::GetMeterData() OBSSourceAutoRelease input = obs_weak_source_get_source(_input); if (!input) { - blog(LOG_WARNING, "[Utils::Obs::VolumeMeter::Meter::GetMeterData] Failed to get strong reference to input. Has it been destroyed?"); + blog(LOG_WARNING, + "[Utils::Obs::VolumeMeter::Meter::GetMeterData] Failed to get strong reference to input. Has it been destroyed?"); return ret; } @@ -77,7 +86,8 @@ json Utils::Obs::VolumeMeter::Meter::GetMeterData() std::unique_lock l(_mutex); - if (_lastUpdate != 0 && (os_gettime_ns() - _lastUpdate) * 0.000000001 > 0.3) + if (_lastUpdate != 0 && + (os_gettime_ns() - _lastUpdate) * 0.000000001 > 0.3) ResetAudioLevels(); for (int channel = 0; channel < _channels; channel++) { @@ -100,14 +110,16 @@ json Utils::Obs::VolumeMeter::Meter::GetMeterData() void Utils::Obs::VolumeMeter::Meter::ResetAudioLevels() { _lastUpdate = 0; - for (int channelNumber = 0; channelNumber < MAX_AUDIO_CHANNELS; channelNumber++) { + for (int channelNumber = 0; channelNumber < MAX_AUDIO_CHANNELS; + channelNumber++) { _magnitude[channelNumber] = 0; _peak[channelNumber] = 0; } } // MUST HOLD LOCK -void Utils::Obs::VolumeMeter::Meter::ProcessAudioChannels(const struct audio_data *data) +void Utils::Obs::VolumeMeter::Meter::ProcessAudioChannels( + const struct audio_data *data) { int channels = 0; for (int i = 0; i < MAX_AV_PLANES; i++) { @@ -129,7 +141,7 @@ void Utils::Obs::VolumeMeter::Meter::ProcessPeak(const struct audio_data *data) int channelNumber = 0; for (int planeNumber = 0; channelNumber < _channels; planeNumber++) { - float *samples = (float*)data->data[planeNumber]; + float *samples = (float *)data->data[planeNumber]; if (!samples) continue; @@ -139,45 +151,64 @@ void Utils::Obs::VolumeMeter::Meter::ProcessPeak(const struct audio_data *data) continue; } - __m128 previousSamples = _mm_loadu_ps(_previousSamples[channelNumber]); + __m128 previousSamples = + _mm_loadu_ps(_previousSamples[channelNumber]); float peak; switch (PeakMeterType) { - default: - case SAMPLE_PEAK_METER: - peak = GetSamplePeak(previousSamples, samples, sampleCount); - break; - case TRUE_PEAK_METER: - peak = GetTruePeak(previousSamples, samples, sampleCount); - break; + default: + case SAMPLE_PEAK_METER: + peak = GetSamplePeak(previousSamples, samples, + sampleCount); + break; + case TRUE_PEAK_METER: + peak = GetTruePeak(previousSamples, samples, + sampleCount); + break; } switch (sampleCount) { - case 0: - break; - case 1: - _previousSamples[channelNumber][0] = _previousSamples[channelNumber][1]; - _previousSamples[channelNumber][1] = _previousSamples[channelNumber][2]; - _previousSamples[channelNumber][2] = _previousSamples[channelNumber][3]; - _previousSamples[channelNumber][3] = samples[sampleCount - 1]; - break; - case 2: - _previousSamples[channelNumber][0] = _previousSamples[channelNumber][2]; - _previousSamples[channelNumber][1] = _previousSamples[channelNumber][3]; - _previousSamples[channelNumber][2] = samples[sampleCount - 2]; - _previousSamples[channelNumber][3] = samples[sampleCount - 1]; - break; - case 3: - _previousSamples[channelNumber][0] = _previousSamples[channelNumber][3]; - _previousSamples[channelNumber][1] = samples[sampleCount - 3]; - _previousSamples[channelNumber][2] = samples[sampleCount - 2]; - _previousSamples[channelNumber][3] = samples[sampleCount - 1]; - break; - default: - _previousSamples[channelNumber][0] = samples[sampleCount - 4]; - _previousSamples[channelNumber][1] = samples[sampleCount - 3]; - _previousSamples[channelNumber][2] = samples[sampleCount - 2]; - _previousSamples[channelNumber][3] = samples[sampleCount - 1]; + case 0: + break; + case 1: + _previousSamples[channelNumber][0] = + _previousSamples[channelNumber][1]; + _previousSamples[channelNumber][1] = + _previousSamples[channelNumber][2]; + _previousSamples[channelNumber][2] = + _previousSamples[channelNumber][3]; + _previousSamples[channelNumber][3] = + samples[sampleCount - 1]; + break; + case 2: + _previousSamples[channelNumber][0] = + _previousSamples[channelNumber][2]; + _previousSamples[channelNumber][1] = + _previousSamples[channelNumber][3]; + _previousSamples[channelNumber][2] = + samples[sampleCount - 2]; + _previousSamples[channelNumber][3] = + samples[sampleCount - 1]; + break; + case 3: + _previousSamples[channelNumber][0] = + _previousSamples[channelNumber][3]; + _previousSamples[channelNumber][1] = + samples[sampleCount - 3]; + _previousSamples[channelNumber][2] = + samples[sampleCount - 2]; + _previousSamples[channelNumber][3] = + samples[sampleCount - 1]; + break; + default: + _previousSamples[channelNumber][0] = + samples[sampleCount - 4]; + _previousSamples[channelNumber][1] = + samples[sampleCount - 3]; + _previousSamples[channelNumber][2] = + samples[sampleCount - 2]; + _previousSamples[channelNumber][3] = + samples[sampleCount - 1]; } _peak[channelNumber] = peak; @@ -190,13 +221,14 @@ void Utils::Obs::VolumeMeter::Meter::ProcessPeak(const struct audio_data *data) } // MUST HOLD LOCK -void Utils::Obs::VolumeMeter::Meter::ProcessMagnitude(const struct audio_data *data) +void Utils::Obs::VolumeMeter::Meter::ProcessMagnitude( + const struct audio_data *data) { size_t sampleCount = data->frames; int channelNumber = 0; for (int planeNumber = 0; channelNumber < _channels; planeNumber++) { - float *samples = (float*)data->data[planeNumber]; + float *samples = (float *)data->data[planeNumber]; if (!samples) continue; @@ -212,9 +244,11 @@ void Utils::Obs::VolumeMeter::Meter::ProcessMagnitude(const struct audio_data *d } } -void Utils::Obs::VolumeMeter::Meter::InputAudioCaptureCallback(void *priv_data, obs_source_t *, const struct audio_data *data, bool muted) +void Utils::Obs::VolumeMeter::Meter::InputAudioCaptureCallback( + void *priv_data, obs_source_t *, const struct audio_data *data, + bool muted) { - auto c = static_cast(priv_data); + auto c = static_cast(priv_data); std::unique_lock l(c->_mutex); @@ -226,24 +260,24 @@ void Utils::Obs::VolumeMeter::Meter::InputAudioCaptureCallback(void *priv_data, c->_lastUpdate = os_gettime_ns(); } -void Utils::Obs::VolumeMeter::Meter::InputVolumeCallback(void *priv_data, calldata_t *cd) +void Utils::Obs::VolumeMeter::Meter::InputVolumeCallback(void *priv_data, + calldata_t *cd) { - auto c = static_cast(priv_data); + auto c = static_cast(priv_data); c->_volume = (float)calldata_float(cd, "volume"); } -Utils::Obs::VolumeMeter::Handler::Handler(UpdateCallback cb, uint64_t updatePeriod) : - _updateCallback(cb), - _updatePeriod(updatePeriod), - _running(false) +Utils::Obs::VolumeMeter::Handler::Handler(UpdateCallback cb, + uint64_t updatePeriod) + : _updateCallback(cb), _updatePeriod(updatePeriod), _running(false) { signal_handler_t *sh = obs_get_signal_handler(); if (!sh) return; auto enumProc = [](void *priv_data, obs_source_t *input) { - auto c = static_cast(priv_data); + auto c = static_cast(priv_data); if (!obs_source_active(input)) return true; @@ -258,13 +292,16 @@ Utils::Obs::VolumeMeter::Handler::Handler(UpdateCallback cb, uint64_t updatePeri }; obs_enum_sources(enumProc, this); - signal_handler_connect(sh, "source_activate", Handler::InputActivateCallback, this); - signal_handler_connect(sh, "source_deactivate", Handler::InputDeactivateCallback, this); + signal_handler_connect(sh, "source_activate", + Handler::InputActivateCallback, this); + signal_handler_connect(sh, "source_deactivate", + Handler::InputDeactivateCallback, this); _running = true; _updateThread = std::thread(&Handler::UpdateThread, this); - blog_debug("[Utils::Obs::VolumeMeter::Handler::Handler] Handler created."); + blog_debug( + "[Utils::Obs::VolumeMeter::Handler::Handler] Handler created."); } Utils::Obs::VolumeMeter::Handler::~Handler() @@ -273,8 +310,10 @@ Utils::Obs::VolumeMeter::Handler::~Handler() if (!sh) return; - signal_handler_disconnect(sh, "source_activate", Handler::InputActivateCallback, this); - signal_handler_disconnect(sh, "source_deactivate", Handler::InputDeactivateCallback, this); + signal_handler_disconnect(sh, "source_activate", + Handler::InputActivateCallback, this); + signal_handler_disconnect(sh, "source_deactivate", + Handler::InputDeactivateCallback, this); if (_running) { _running = false; @@ -284,16 +323,20 @@ Utils::Obs::VolumeMeter::Handler::~Handler() if (_updateThread.joinable()) _updateThread.join(); - blog_debug("[Utils::Obs::VolumeMeter::Handler::~Handler] Handler destroyed."); + blog_debug( + "[Utils::Obs::VolumeMeter::Handler::~Handler] Handler destroyed."); } void Utils::Obs::VolumeMeter::Handler::UpdateThread() { - blog_debug("[Utils::Obs::VolumeMeter::Handler::UpdateThread] Thread started."); + blog_debug( + "[Utils::Obs::VolumeMeter::Handler::UpdateThread] Thread started."); while (_running) { { std::unique_lock l(_mutex); - if (_cond.wait_for(l, std::chrono::milliseconds(_updatePeriod), [this]{ return !_running; })) + if (_cond.wait_for( + l, std::chrono::milliseconds(_updatePeriod), + [this] { return !_running; })) break; } @@ -308,12 +351,14 @@ void Utils::Obs::VolumeMeter::Handler::UpdateThread() if (_updateCallback) _updateCallback(inputs); } - blog_debug("[Utils::Obs::VolumeMeter::Handler::UpdateThread] Thread stopped."); + blog_debug( + "[Utils::Obs::VolumeMeter::Handler::UpdateThread] Thread stopped."); } -void Utils::Obs::VolumeMeter::Handler::InputActivateCallback(void *priv_data, calldata_t *cd) +void Utils::Obs::VolumeMeter::Handler::InputActivateCallback(void *priv_data, + calldata_t *cd) { - auto c = static_cast(priv_data); + auto c = static_cast(priv_data); obs_source_t *input = GetCalldataPointer(cd, "source"); if (!input) @@ -330,9 +375,10 @@ void Utils::Obs::VolumeMeter::Handler::InputActivateCallback(void *priv_data, ca c->_meters.emplace_back(std::move(new Meter(input))); } -void Utils::Obs::VolumeMeter::Handler::InputDeactivateCallback(void *priv_data, calldata_t *cd) +void Utils::Obs::VolumeMeter::Handler::InputDeactivateCallback(void *priv_data, + calldata_t *cd) { - auto c = static_cast(priv_data); + auto c = static_cast(priv_data); obs_source_t *input = GetCalldataPointer(cd, "source"); if (!input) @@ -345,7 +391,8 @@ void Utils::Obs::VolumeMeter::Handler::InputDeactivateCallback(void *priv_data, std::unique_lock l(c->_meterMutex); std::vector::iterator iter; for (iter = c->_meters.begin(); iter != c->_meters.end();) { - if (obs_weak_source_references_source(iter->get()->GetWeakInput(), input)) + if (obs_weak_source_references_source( + iter->get()->GetWeakInput(), input)) iter = c->_meters.erase(iter); else ++iter; diff --git a/src/utils/Obs_VolumeMeter.h b/src/utils/Obs_VolumeMeter.h index e2b20a6e..9ab1670c 100644 --- a/src/utils/Obs_VolumeMeter.h +++ b/src/utils/Obs_VolumeMeter.h @@ -31,69 +31,72 @@ with this program. If not, see #include "Json.h" namespace Utils { - namespace Obs { - namespace VolumeMeter { - // Some code copied from https://github.com/obsproject/obs-studio/blob/master/libobs/obs-audio-controls.c - // Keeps a running tally of the current audio levels, for a specific input - class Meter { - public: - Meter(obs_source_t *input); - ~Meter(); +namespace Obs { +namespace VolumeMeter { +// Some code copied from https://github.com/obsproject/obs-studio/blob/master/libobs/obs-audio-controls.c +// Keeps a running tally of the current audio levels, for a specific input +class Meter { +public: + Meter(obs_source_t *input); + ~Meter(); - bool InputValid(); - obs_weak_source_t *GetWeakInput() { return _input; } - json GetMeterData(); + bool InputValid(); + obs_weak_source_t *GetWeakInput() { return _input; } + json GetMeterData(); - std::atomic PeakMeterType; + std::atomic PeakMeterType; - private: - OBSWeakSourceAutoRelease _input; +private: + OBSWeakSourceAutoRelease _input; - // All values in mul - std::mutex _mutex; - bool _muted; - int _channels; - float _magnitude[MAX_AUDIO_CHANNELS]; - float _peak[MAX_AUDIO_CHANNELS]; - float _previousSamples[MAX_AUDIO_CHANNELS][4]; + // All values in mul + std::mutex _mutex; + bool _muted; + int _channels; + float _magnitude[MAX_AUDIO_CHANNELS]; + float _peak[MAX_AUDIO_CHANNELS]; + float _previousSamples[MAX_AUDIO_CHANNELS][4]; - std::atomic _lastUpdate; - std::atomic _volume; + std::atomic _lastUpdate; + std::atomic _volume; - void ResetAudioLevels(); - void ProcessAudioChannels(const struct audio_data *data); - void ProcessPeak(const struct audio_data *data); - void ProcessMagnitude(const struct audio_data *data); + void ResetAudioLevels(); + void ProcessAudioChannels(const struct audio_data *data); + void ProcessPeak(const struct audio_data *data); + void ProcessMagnitude(const struct audio_data *data); - static void InputAudioCaptureCallback(void *priv_data, obs_source_t *source, const struct audio_data *data, bool muted); - static void InputVolumeCallback(void *priv_data, calldata_t *cd); - }; + static void InputAudioCaptureCallback(void *priv_data, + obs_source_t *source, + const struct audio_data *data, + bool muted); + static void InputVolumeCallback(void *priv_data, calldata_t *cd); +}; - // Maintains an array of active inputs - class Handler { - typedef std::function)> UpdateCallback; - typedef std::unique_ptr MeterPtr; +// Maintains an array of active inputs +class Handler { + typedef std::function)> UpdateCallback; + typedef std::unique_ptr MeterPtr; - public: - Handler(UpdateCallback cb, uint64_t updatePeriod = 50); - ~Handler(); +public: + Handler(UpdateCallback cb, uint64_t updatePeriod = 50); + ~Handler(); - private: - UpdateCallback _updateCallback; +private: + UpdateCallback _updateCallback; - std::mutex _meterMutex; - std::vector _meters; - uint64_t _updatePeriod; + std::mutex _meterMutex; + std::vector _meters; + uint64_t _updatePeriod; - std::mutex _mutex; - std::condition_variable _cond; - std::atomic _running; - std::thread _updateThread; + std::mutex _mutex; + std::condition_variable _cond; + std::atomic _running; + std::thread _updateThread; - void UpdateThread(); - static void InputActivateCallback(void *priv_data, calldata_t *cd); - static void InputDeactivateCallback(void *priv_data, calldata_t *cd); - }; - } - } + void UpdateThread(); + static void InputActivateCallback(void *priv_data, calldata_t *cd); + static void InputDeactivateCallback(void *priv_data, calldata_t *cd); +}; +} +} } diff --git a/src/utils/Obs_VolumeMeter_Helpers.h b/src/utils/Obs_VolumeMeter_Helpers.h index 7af42ac3..2e3192e3 100644 --- a/src/utils/Obs_VolumeMeter_Helpers.h +++ b/src/utils/Obs_VolumeMeter_Helpers.h @@ -56,7 +56,8 @@ with this program. If not, see r = fmaxf(r, x4_mem[3]); \ } while (false) -static float GetSamplePeak(__m128 previousSamples, const float *samples, size_t sampleCount) +static float GetSamplePeak(__m128 previousSamples, const float *samples, + size_t sampleCount) { __m128 peak = previousSamples; for (size_t i = 0; (i + 3) < sampleCount; i += 4) { @@ -69,12 +70,17 @@ static float GetSamplePeak(__m128 previousSamples, const float *samples, size_t return ret; } -static float GetTruePeak(__m128 previousSamples, const float *samples, size_t sampleCount) +static float GetTruePeak(__m128 previousSamples, const float *samples, + size_t sampleCount) { - const __m128 m3 = _mm_set_ps(-0.155915f, 0.935489f, 0.233872f, -0.103943f); - const __m128 m1 = _mm_set_ps(-0.216236f, 0.756827f, 0.504551f, -0.189207f); - const __m128 p1 = _mm_set_ps(-0.189207f, 0.504551f, 0.756827f, -0.216236f); - const __m128 p3 = _mm_set_ps(-0.103943f, 0.233872f, 0.935489f, -0.155915f); + const __m128 m3 = + _mm_set_ps(-0.155915f, 0.935489f, 0.233872f, -0.103943f); + const __m128 m1 = + _mm_set_ps(-0.216236f, 0.756827f, 0.504551f, -0.189207f); + const __m128 p1 = + _mm_set_ps(-0.189207f, 0.504551f, 0.756827f, -0.216236f); + const __m128 p3 = + _mm_set_ps(-0.103943f, 0.233872f, 0.935489f, -0.155915f); __m128 work = previousSamples; __m128 peak = previousSamples; diff --git a/src/utils/Platform.cpp b/src/utils/Platform.cpp index 83b5f897..f337d9ab 100644 --- a/src/utils/Platform.cpp +++ b/src/utils/Platform.cpp @@ -53,24 +53,36 @@ std::string Utils::Platform::GetLocalAddress() std::vector> preferredAddresses; for (auto address : validAddresses) { // Attribute a priority (0 is best) to the address to choose the best picks - if (address.startsWith("192.168.1.") || address.startsWith("192.168.0.")) { // Prefer common consumer router network prefixes + if (address.startsWith("192.168.1.") || + address.startsWith( + "192.168.0.")) { // Prefer common consumer router network prefixes if (address.startsWith("192.168.56.")) - preferredAddresses.push_back(std::make_pair(address, 255)); // Ignore virtualbox default + preferredAddresses.push_back(std::make_pair( + address, + 255)); // Ignore virtualbox default else - preferredAddresses.push_back(std::make_pair(address, 0)); - } else if (address.startsWith("172.16.")) { // Slightly less common consumer router network prefixes - preferredAddresses.push_back(std::make_pair(address, 1)); - } else if (address.startsWith("10.")) { // Even less common consumer router network prefixes - preferredAddresses.push_back(std::make_pair(address, 2)); + preferredAddresses.push_back( + std::make_pair(address, 0)); + } else if (address.startsWith( + "172.16.")) { // Slightly less common consumer router network prefixes + preferredAddresses.push_back( + std::make_pair(address, 1)); + } else if (address.startsWith( + "10.")) { // Even less common consumer router network prefixes + preferredAddresses.push_back( + std::make_pair(address, 2)); } else { // Set all other addresses to equal priority - preferredAddresses.push_back(std::make_pair(address, 255)); + preferredAddresses.push_back( + std::make_pair(address, 255)); } } // Sort by priority - std::sort(preferredAddresses.begin(), preferredAddresses.end(), [=](std::pair a, std::pair b) { - return a.second < b.second; - }); + std::sort(preferredAddresses.begin(), preferredAddresses.end(), + [=](std::pair a, + std::pair b) { + return a.second < b.second; + }); // Return highest priority address return preferredAddresses[0].first.toStdString(); @@ -120,24 +132,35 @@ struct SystemTrayNotification { QString body; }; -void Utils::Platform::SendTrayNotification(QSystemTrayIcon::MessageIcon icon, QString title, QString body) +void Utils::Platform::SendTrayNotification(QSystemTrayIcon::MessageIcon icon, + QString title, QString body) { - if (!QSystemTrayIcon::isSystemTrayAvailable() || !QSystemTrayIcon::supportsMessages()) + if (!QSystemTrayIcon::isSystemTrayAvailable() || + !QSystemTrayIcon::supportsMessages()) return; - SystemTrayNotification *notification = new SystemTrayNotification{icon, title, body}; + SystemTrayNotification *notification = + new SystemTrayNotification{icon, title, body}; - obs_queue_task(OBS_TASK_UI, [](void* param) { - void *systemTrayPtr = obs_frontend_get_system_tray(); - auto systemTray = static_cast(systemTrayPtr); + obs_queue_task( + OBS_TASK_UI, + [](void *param) { + void *systemTrayPtr = obs_frontend_get_system_tray(); + auto systemTray = + static_cast(systemTrayPtr); - auto notification = static_cast(param); - systemTray->showMessage(notification->title, notification->body, notification->icon); - delete notification; - }, (void*)notification, false); + auto notification = + static_cast(param); + systemTray->showMessage(notification->title, + notification->body, + notification->icon); + delete notification; + }, + (void *)notification, false); } -bool Utils::Platform::GetTextFileContent(std::string fileName, std::string &content) +bool Utils::Platform::GetTextFileContent(std::string fileName, + std::string &content) { QFile f(QString::fromStdString(fileName)); if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) @@ -147,7 +170,8 @@ bool Utils::Platform::GetTextFileContent(std::string fileName, std::string &cont return true; } -bool Utils::Platform::SetTextFileContent(std::string fileName, std::string content, bool createNew) +bool Utils::Platform::SetTextFileContent(std::string fileName, + std::string content, bool createNew) { if (!createNew && !QFile::exists(QString::fromStdString(fileName))) return false; diff --git a/src/utils/Platform.h b/src/utils/Platform.h index a2692e15..27da5a6d 100644 --- a/src/utils/Platform.h +++ b/src/utils/Platform.h @@ -24,13 +24,15 @@ with this program. If not, see #include namespace Utils { - namespace Platform { - std::string GetLocalAddress(); - std::string GetLoopbackAddress(bool allowIpv6 = true); - QString GetCommandLineArgument(QString arg); - bool GetCommandLineFlagSet(QString arg); - void SendTrayNotification(QSystemTrayIcon::MessageIcon icon, QString title, QString body); - bool GetTextFileContent(std::string fileName, std::string &content); - bool SetTextFileContent(std::string filePath, std::string content, bool createNew = true); - } +namespace Platform { +std::string GetLocalAddress(); +std::string GetLoopbackAddress(bool allowIpv6 = true); +QString GetCommandLineArgument(QString arg); +bool GetCommandLineFlagSet(QString arg); +void SendTrayNotification(QSystemTrayIcon::MessageIcon icon, QString title, + QString body); +bool GetTextFileContent(std::string fileName, std::string &content); +bool SetTextFileContent(std::string filePath, std::string content, + bool createNew = true); +} } diff --git a/src/websocketserver/WebSocketServer.cpp b/src/websocketserver/WebSocketServer.cpp index 48bf114a..17f0a93a 100644 --- a/src/websocketserver/WebSocketServer.cpp +++ b/src/websocketserver/WebSocketServer.cpp @@ -31,9 +31,7 @@ with this program. If not, see #include "../utils/Platform.h" #include "../utils/Compat.h" -WebSocketServer::WebSocketServer() : - QObject(nullptr), - _sessions() +WebSocketServer::WebSocketServer() : QObject(nullptr), _sessions() { _server.get_alog().clear_channels(websocketpp::log::alevel::all); _server.get_elog().clear_channels(websocketpp::log::elevel::all); @@ -44,38 +42,27 @@ WebSocketServer::WebSocketServer() : #endif _server.set_validate_handler( - websocketpp::lib::bind( - &WebSocketServer::onValidate, this, websocketpp::lib::placeholders::_1 - ) - ); + websocketpp::lib::bind(&WebSocketServer::onValidate, this, + websocketpp::lib::placeholders::_1)); _server.set_open_handler( - websocketpp::lib::bind( - &WebSocketServer::onOpen, this, websocketpp::lib::placeholders::_1 - ) - ); + websocketpp::lib::bind(&WebSocketServer::onOpen, this, + websocketpp::lib::placeholders::_1)); _server.set_close_handler( - websocketpp::lib::bind( - &WebSocketServer::onClose, this, websocketpp::lib::placeholders::_1 - ) - ); + websocketpp::lib::bind(&WebSocketServer::onClose, this, + websocketpp::lib::placeholders::_1)); _server.set_message_handler( - websocketpp::lib::bind( - &WebSocketServer::onMessage, this, websocketpp::lib::placeholders::_1, websocketpp::lib::placeholders::_2 - ) - ); + websocketpp::lib::bind(&WebSocketServer::onMessage, this, + websocketpp::lib::placeholders::_1, + websocketpp::lib::placeholders::_2)); auto eventHandler = GetEventHandler(); eventHandler->SetBroadcastCallback( - std::bind( - &WebSocketServer::BroadcastEvent, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4 - ) - ); + std::bind(&WebSocketServer::BroadcastEvent, this, + std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3, std::placeholders::_4)); eventHandler->SetObsLoadedCallback( - std::bind( - &WebSocketServer::onObsLoaded, this - ) - ); + std::bind(&WebSocketServer::onObsLoaded, this)); } WebSocketServer::~WebSocketServer() @@ -89,12 +76,17 @@ void WebSocketServer::ServerRunner() blog(LOG_INFO, "[WebSocketServer::ServerRunner] IO thread started."); try { _server.run(); - } catch (websocketpp::exception const & e) { - blog(LOG_ERROR, "[WebSocketServer::ServerRunner] websocketpp instance returned an error: %s", e.what()); - } catch (const std::exception & e) { - blog(LOG_ERROR, "[WebSocketServer::ServerRunner] websocketpp instance returned an error: %s", e.what()); + } catch (websocketpp::exception const &e) { + blog(LOG_ERROR, + "[WebSocketServer::ServerRunner] websocketpp instance returned an error: %s", + e.what()); + } catch (const std::exception &e) { + blog(LOG_ERROR, + "[WebSocketServer::ServerRunner] websocketpp instance returned an error: %s", + e.what()); } catch (...) { - blog(LOG_ERROR, "[WebSocketServer::ServerRunner] websocketpp instance returned an error"); + blog(LOG_ERROR, + "[WebSocketServer::ServerRunner] websocketpp instance returned an error"); } blog(LOG_INFO, "[WebSocketServer::ServerRunner] IO thread exited."); } @@ -102,52 +94,70 @@ void WebSocketServer::ServerRunner() void WebSocketServer::Start() { if (_server.is_listening()) { - blog(LOG_WARNING, "[WebSocketServer::Start] Call to Start() but the server is already listening."); + blog(LOG_WARNING, + "[WebSocketServer::Start] Call to Start() but the server is already listening."); return; } auto conf = GetConfig(); if (!conf) { - blog(LOG_ERROR, "[WebSocketServer::Start] Unable to retreive config!"); + blog(LOG_ERROR, + "[WebSocketServer::Start] Unable to retreive config!"); return; } _authenticationSalt = Utils::Crypto::GenerateSalt(); - _authenticationSecret = Utils::Crypto::GenerateSecret(conf->ServerPassword.toStdString(), _authenticationSalt); + _authenticationSecret = Utils::Crypto::GenerateSecret( + conf->ServerPassword.toStdString(), _authenticationSalt); // Set log levels if debug is enabled if (IsDebugEnabled()) { _server.get_alog().set_channels(websocketpp::log::alevel::all); - _server.get_alog().clear_channels(websocketpp::log::alevel::frame_header | websocketpp::log::alevel::frame_payload | websocketpp::log::alevel::control); + _server.get_alog().clear_channels( + websocketpp::log::alevel::frame_header | + websocketpp::log::alevel::frame_payload | + websocketpp::log::alevel::control); _server.get_elog().set_channels(websocketpp::log::elevel::all); - _server.get_alog().clear_channels(websocketpp::log::elevel::devel | websocketpp::log::elevel::library); + _server.get_alog().clear_channels( + websocketpp::log::elevel::devel | + websocketpp::log::elevel::library); } else { - _server.get_alog().clear_channels(websocketpp::log::alevel::all); - _server.get_elog().clear_channels(websocketpp::log::elevel::all); + _server.get_alog().clear_channels( + websocketpp::log::alevel::all); + _server.get_elog().clear_channels( + websocketpp::log::elevel::all); } _server.reset(); websocketpp::lib::error_code errorCode; if (conf->BindLoopback) { - std::string addr = Utils::Platform::GetLoopbackAddress(!conf->Ipv4Only); + std::string addr = + Utils::Platform::GetLoopbackAddress(!conf->Ipv4Only); if (addr.empty()) { - blog(LOG_ERROR, "[WebSocketServer::Start] Failed to find loopback interface. Server not started."); + blog(LOG_ERROR, + "[WebSocketServer::Start] Failed to find loopback interface. Server not started."); return; } - _server.listen(addr, std::to_string(conf->ServerPort), errorCode); - blog(LOG_INFO, "[WebSocketServer::Start] Locked to loopback interface."); + _server.listen(addr, std::to_string(conf->ServerPort), + errorCode); + blog(LOG_INFO, + "[WebSocketServer::Start] Locked to loopback interface."); } else if (conf->Ipv4Only) { - _server.listen(websocketpp::lib::asio::ip::tcp::v4(), conf->ServerPort, errorCode); - blog(LOG_INFO, "[WebSocketServer::Start] Locked to IPv4 bindings."); + _server.listen(websocketpp::lib::asio::ip::tcp::v4(), + conf->ServerPort, errorCode); + blog(LOG_INFO, + "[WebSocketServer::Start] Locked to IPv4 bindings."); } else { _server.listen(conf->ServerPort, errorCode); - blog(LOG_INFO, "[WebSocketServer::Start] Bound to all interfaces."); + blog(LOG_INFO, + "[WebSocketServer::Start] Bound to all interfaces."); } if (errorCode) { std::string errorCodeMessage = errorCode.message(); - blog(LOG_ERROR, "[WebSocketServer::Start] Listen failed: %s", errorCodeMessage.c_str()); + blog(LOG_ERROR, "[WebSocketServer::Start] Listen failed: %s", + errorCodeMessage.c_str()); return; } @@ -155,30 +165,37 @@ void WebSocketServer::Start() _serverThread = std::thread(&WebSocketServer::ServerRunner, this); - blog(LOG_INFO, "[WebSocketServer::Start] Server started successfully on port %d. Possible connect address: %s", conf->ServerPort.load(), Utils::Platform::GetLocalAddress().c_str()); + blog(LOG_INFO, + "[WebSocketServer::Start] Server started successfully on port %d. Possible connect address: %s", + conf->ServerPort.load(), + Utils::Platform::GetLocalAddress().c_str()); } void WebSocketServer::Stop() { if (!_server.is_listening()) { - blog(LOG_WARNING, "[WebSocketServer::Stop] Call to Stop() but the server is not listening."); + blog(LOG_WARNING, + "[WebSocketServer::Stop] Call to Stop() but the server is not listening."); return; } _server.stop_listening(); std::unique_lock lock(_sessionMutex); - for (auto const& [hdl, session] : _sessions) { + for (auto const &[hdl, session] : _sessions) { websocketpp::lib::error_code errorCode; _server.pause_reading(hdl, errorCode); if (errorCode) { - blog(LOG_INFO, "[WebSocketServer::Stop] Error: %s", errorCode.message().c_str()); + blog(LOG_INFO, "[WebSocketServer::Stop] Error: %s", + errorCode.message().c_str()); continue; } - _server.close(hdl, websocketpp::close::status::going_away, "Server stopping.", errorCode); + _server.close(hdl, websocketpp::close::status::going_away, + "Server stopping.", errorCode); if (errorCode) { - blog(LOG_INFO, "[WebSocketServer::Stop] Error: %s", errorCode.message().c_str()); + blog(LOG_INFO, "[WebSocketServer::Stop] Error: %s", + errorCode.message().c_str()); continue; } } @@ -198,35 +215,42 @@ void WebSocketServer::Stop() void WebSocketServer::InvalidateSession(websocketpp::connection_hdl hdl) { - blog(LOG_INFO, "[WebSocketServer::InvalidateSession] Invalidating a session."); + blog(LOG_INFO, + "[WebSocketServer::InvalidateSession] Invalidating a session."); websocketpp::lib::error_code errorCode; _server.pause_reading(hdl, errorCode); if (errorCode) { - blog(LOG_INFO, "[WebSocketServer::InvalidateSession] Error: %s", errorCode.message().c_str()); + blog(LOG_INFO, "[WebSocketServer::InvalidateSession] Error: %s", + errorCode.message().c_str()); return; } - _server.close(hdl, WebSocketCloseCode::SessionInvalidated, "Your session has been invalidated.", errorCode); + _server.close(hdl, WebSocketCloseCode::SessionInvalidated, + "Your session has been invalidated.", errorCode); if (errorCode) { - blog(LOG_INFO, "[WebSocketServer::InvalidateSession] Error: %s", errorCode.message().c_str()); + blog(LOG_INFO, "[WebSocketServer::InvalidateSession] Error: %s", + errorCode.message().c_str()); return; } } -std::vector WebSocketServer::GetWebSocketSessions() +std::vector +WebSocketServer::GetWebSocketSessions() { std::vector webSocketSessions; std::unique_lock lock(_sessionMutex); - for (auto & [hdl, session] : _sessions) { + for (auto &[hdl, session] : _sessions) { uint64_t connectedAt = session->ConnectedAt(); uint64_t incomingMessages = session->IncomingMessages(); uint64_t outgoingMessages = session->OutgoingMessages(); std::string remoteAddress = session->RemoteAddress(); bool isIdentified = session->IsIdentified(); - - webSocketSessions.emplace_back(WebSocketSessionState{hdl, remoteAddress, connectedAt, incomingMessages, outgoingMessages, isIdentified}); + + webSocketSessions.emplace_back(WebSocketSessionState{ + hdl, remoteAddress, connectedAt, incomingMessages, + outgoingMessages, isIdentified}); } lock.unlock(); @@ -237,12 +261,14 @@ void WebSocketServer::onObsLoaded() { auto conf = GetConfig(); if (!conf) { - blog(LOG_ERROR, "[WebSocketServer::onObsLoaded] Unable to retreive config!"); + blog(LOG_ERROR, + "[WebSocketServer::onObsLoaded] Unable to retreive config!"); return; } if (conf->ServerEnabled) { - blog(LOG_INFO, "[WebSocketServer::onObsLoaded] WebSocket server is enabled, starting..."); + blog(LOG_INFO, + "[WebSocketServer::onObsLoaded] WebSocket server is enabled, starting..."); Start(); } } @@ -251,9 +277,11 @@ bool WebSocketServer::onValidate(websocketpp::connection_hdl hdl) { auto conn = _server.get_con_from_hdl(hdl); - std::vector requestedSubprotocols = conn->get_requested_subprotocols(); + std::vector requestedSubprotocols = + conn->get_requested_subprotocols(); for (auto subprotocol : requestedSubprotocols) { - if (subprotocol == "obswebsocket.json" || subprotocol == "obswebsocket.msgpack") { + if (subprotocol == "obswebsocket.json" || + subprotocol == "obswebsocket.msgpack") { conn->select_subprotocol(subprotocol); break; } @@ -268,13 +296,15 @@ void WebSocketServer::onOpen(websocketpp::connection_hdl hdl) auto conf = GetConfig(); if (!conf) { - blog(LOG_ERROR, "[WebSocketServer::onOpen] Unable to retreive config!"); + blog(LOG_ERROR, + "[WebSocketServer::onOpen] Unable to retreive config!"); return; } // Build new session std::unique_lock lock(_sessionMutex); - SessionPtr session = _sessions[hdl] = std::make_shared(); + SessionPtr session = _sessions[hdl] = + std::make_shared(); std::unique_lock sessionLock(session->OperationMutex); lock.unlock(); @@ -299,8 +329,10 @@ void WebSocketServer::onOpen(websocketpp::connection_hdl hdl) std::string sessionChallenge = Utils::Crypto::GenerateSalt(); session->SetChallenge(sessionChallenge); helloMessageData["authentication"] = json::object(); - helloMessageData["authentication"]["challenge"] = sessionChallenge; - helloMessageData["authentication"]["salt"] = _authenticationSalt; + helloMessageData["authentication"]["challenge"] = + sessionChallenge; + helloMessageData["authentication"]["salt"] = + _authenticationSalt; } json helloMessage; helloMessage["op"] = 0; @@ -320,20 +352,27 @@ void WebSocketServer::onOpen(websocketpp::connection_hdl hdl) emit ClientConnected(state); // Log connection - blog(LOG_INFO, "[WebSocketServer::onOpen] New WebSocket client has connected from %s", session->RemoteAddress().c_str()); + blog(LOG_INFO, + "[WebSocketServer::onOpen] New WebSocket client has connected from %s", + session->RemoteAddress().c_str()); - blog_debug("[WebSocketServer::onOpen] Sending Op 0 (Hello) message:\n%s", helloMessage.dump(2).c_str()); + blog_debug( + "[WebSocketServer::onOpen] Sending Op 0 (Hello) message:\n%s", + helloMessage.dump(2).c_str()); // Send object to client websocketpp::lib::error_code errorCode; auto sessionEncoding = session->Encoding(); if (sessionEncoding == WebSocketEncoding::Json) { std::string helloMessageJson = helloMessage.dump(); - _server.send(hdl, helloMessageJson, websocketpp::frame::opcode::text, errorCode); + _server.send(hdl, helloMessageJson, + websocketpp::frame::opcode::text, errorCode); } else if (sessionEncoding == WebSocketEncoding::MsgPack) { auto msgPackData = json::to_msgpack(helloMessage); - std::string messageMsgPack(msgPackData.begin(), msgPackData.end()); - _server.send(hdl, messageMsgPack, websocketpp::frame::opcode::binary, errorCode); + std::string messageMsgPack(msgPackData.begin(), + msgPackData.end()); + _server.send(hdl, messageMsgPack, + websocketpp::frame::opcode::binary, errorCode); } session->IncrementOutgoingMessages(); } @@ -372,24 +411,37 @@ void WebSocketServer::onClose(websocketpp::connection_hdl hdl) emit ClientDisconnected(state, conn->get_local_close_code()); // Log disconnection - blog(LOG_INFO, "[WebSocketServer::onClose] WebSocket client %s has disconnected", remoteAddress.c_str()); + blog(LOG_INFO, + "[WebSocketServer::onClose] WebSocket client %s has disconnected", + remoteAddress.c_str()); // Get config for tray notification auto conf = GetConfig(); if (!conf) { - blog(LOG_ERROR, "[WebSocketServer::onClose] Unable to retreive config!"); + blog(LOG_ERROR, + "[WebSocketServer::onClose] Unable to retreive config!"); return; } // If previously identified, not going away, and notifications enabled, send a tray notification - if (isIdentified && (conn->get_local_close_code() != websocketpp::close::status::going_away) && conf->AlertsEnabled) { - QString title = obs_module_text("OBSWebSocket.TrayNotification.Disconnected.Title"); - QString body = QString(obs_module_text("OBSWebSocket.TrayNotification.Disconnected.Body")).arg(QString::fromStdString(remoteAddress)); - Utils::Platform::SendTrayNotification(QSystemTrayIcon::Information, title, body); + if (isIdentified && + (conn->get_local_close_code() != + websocketpp::close::status::going_away) && + conf->AlertsEnabled) { + QString title = obs_module_text( + "OBSWebSocket.TrayNotification.Disconnected.Title"); + QString body = + QString(obs_module_text( + "OBSWebSocket.TrayNotification.Disconnected.Body")) + .arg(QString::fromStdString(remoteAddress)); + Utils::Platform::SendTrayNotification( + QSystemTrayIcon::Information, title, body); } } -void WebSocketServer::onMessage(websocketpp::connection_hdl hdl, websocketpp::server::message_ptr message) +void WebSocketServer::onMessage( + websocketpp::connection_hdl hdl, + websocketpp::server::message_ptr message) { auto opCode = message->get_opcode(); std::string payload = message->get_payload(); @@ -398,7 +450,7 @@ void WebSocketServer::onMessage(websocketpp::connection_hdl hdl, websocketpp::se SessionPtr session; try { session = _sessions.at(hdl); - } catch (const std::out_of_range& oor) { + } catch (const std::out_of_range &oor) { return; } lock.unlock(); @@ -412,31 +464,52 @@ void WebSocketServer::onMessage(websocketpp::connection_hdl hdl, websocketpp::se uint8_t sessionEncoding = session->Encoding(); if (sessionEncoding == WebSocketEncoding::Json) { if (opCode != websocketpp::frame::opcode::text) { - _server.close(hdl, WebSocketCloseCode::MessageDecodeError, "Your session encoding is set to Json, but a binary message was received.", errorCode); + _server.close( + hdl, + WebSocketCloseCode::MessageDecodeError, + "Your session encoding is set to Json, but a binary message was received.", + errorCode); return; } try { incomingMessage = json::parse(payload); - } catch (json::parse_error& e) { - _server.close(hdl, WebSocketCloseCode::MessageDecodeError, std::string("Unable to decode Json: ") + e.what(), errorCode); + } catch (json::parse_error &e) { + _server.close( + hdl, + WebSocketCloseCode::MessageDecodeError, + std::string("Unable to decode Json: ") + + e.what(), + errorCode); return; } } else if (sessionEncoding == WebSocketEncoding::MsgPack) { if (opCode != websocketpp::frame::opcode::binary) { - _server.close(hdl, WebSocketCloseCode::MessageDecodeError, "Your session encoding is set to MsgPack, but a text message was received.", errorCode); + _server.close( + hdl, + WebSocketCloseCode::MessageDecodeError, + "Your session encoding is set to MsgPack, but a text message was received.", + errorCode); return; } try { incomingMessage = json::from_msgpack(payload); - } catch (json::parse_error& e) { - _server.close(hdl, WebSocketCloseCode::MessageDecodeError, std::string("Unable to decode MsgPack: ") + e.what(), errorCode); + } catch (json::parse_error &e) { + _server.close( + hdl, + WebSocketCloseCode::MessageDecodeError, + std::string( + "Unable to decode MsgPack: ") + + e.what(), + errorCode); return; } } - blog_debug("[WebSocketServer::onMessage] Incoming message (decoded):\n%s", incomingMessage.dump(2).c_str()); + blog_debug( + "[WebSocketServer::onMessage] Incoming message (decoded):\n%s", + incomingMessage.dump(2).c_str()); ProcessResult ret; @@ -448,10 +521,15 @@ void WebSocketServer::onMessage(websocketpp::connection_hdl hdl, websocketpp::se } // Disconnect client if 4.x protocol is detected - if (!session->IsIdentified() && incomingMessage.contains("request-type")) { - blog(LOG_WARNING, "[WebSocketServer::onMessage] Client %s appears to be running a pre-5.0.0 protocol.", session->RemoteAddress().c_str()); - ret.closeCode = WebSocketCloseCode::UnsupportedRpcVersion; - ret.closeReason = "You appear to be attempting to connect with the pre-5.0.0 plugin protocol. Check to make sure your client is updated."; + if (!session->IsIdentified() && + incomingMessage.contains("request-type")) { + blog(LOG_WARNING, + "[WebSocketServer::onMessage] Client %s appears to be running a pre-5.0.0 protocol.", + session->RemoteAddress().c_str()); + ret.closeCode = + WebSocketCloseCode::UnsupportedRpcVersion; + ret.closeReason = + "You appear to be attempting to connect with the pre-5.0.0 plugin protocol. Check to make sure your client is updated."; goto skipProcessing; } @@ -462,31 +540,44 @@ void WebSocketServer::onMessage(websocketpp::connection_hdl hdl, websocketpp::se goto skipProcessing; } - ProcessMessage(session, ret, incomingMessage["op"], incomingMessage["d"]); + ProcessMessage(session, ret, incomingMessage["op"], + incomingMessage["d"]); -skipProcessing: + skipProcessing: if (ret.closeCode != WebSocketCloseCode::DontClose) { websocketpp::lib::error_code errorCode; - _server.close(hdl, ret.closeCode, ret.closeReason, errorCode); + _server.close(hdl, ret.closeCode, ret.closeReason, + errorCode); return; } if (!ret.result.is_null()) { websocketpp::lib::error_code errorCode; if (sessionEncoding == WebSocketEncoding::Json) { - std::string helloMessageJson = ret.result.dump(); - _server.send(hdl, helloMessageJson, websocketpp::frame::opcode::text, errorCode); - } else if (sessionEncoding == WebSocketEncoding::MsgPack) { + std::string helloMessageJson = + ret.result.dump(); + _server.send(hdl, helloMessageJson, + websocketpp::frame::opcode::text, + errorCode); + } else if (sessionEncoding == + WebSocketEncoding::MsgPack) { auto msgPackData = json::to_msgpack(ret.result); - std::string messageMsgPack(msgPackData.begin(), msgPackData.end()); - _server.send(hdl, messageMsgPack, websocketpp::frame::opcode::binary, errorCode); + std::string messageMsgPack(msgPackData.begin(), + msgPackData.end()); + _server.send(hdl, messageMsgPack, + websocketpp::frame::opcode::binary, + errorCode); } session->IncrementOutgoingMessages(); - blog_debug("[WebSocketServer::onMessage] Outgoing message:\n%s", ret.result.dump(2).c_str()); + blog_debug( + "[WebSocketServer::onMessage] Outgoing message:\n%s", + ret.result.dump(2).c_str()); if (errorCode) - blog(LOG_WARNING, "[WebSocketServer::onMessage] Sending message to client failed: %s", errorCode.message().c_str()); + blog(LOG_WARNING, + "[WebSocketServer::onMessage] Sending message to client failed: %s", + errorCode.message().c_str()); } })); } diff --git a/src/websocketserver/WebSocketServer.h b/src/websocketserver/WebSocketServer.h index 9052c793..baaafaef 100644 --- a/src/websocketserver/WebSocketServer.h +++ b/src/websocketserver/WebSocketServer.h @@ -34,73 +34,79 @@ with this program. If not, see #include "../requesthandler/rpc/Request.h" #include "../plugin-macros.generated.h" -class WebSocketServer : QObject -{ +class WebSocketServer : QObject { Q_OBJECT - public: - enum WebSocketEncoding { - Json, - MsgPack - }; +public: + enum WebSocketEncoding { Json, MsgPack }; - struct WebSocketSessionState { - websocketpp::connection_hdl hdl; - std::string remoteAddress; - uint64_t connectedAt; - uint64_t incomingMessages; - uint64_t outgoingMessages; - bool isIdentified; - }; + struct WebSocketSessionState { + websocketpp::connection_hdl hdl; + std::string remoteAddress; + uint64_t connectedAt; + uint64_t incomingMessages; + uint64_t outgoingMessages; + bool isIdentified; + }; - WebSocketServer(); - ~WebSocketServer(); + WebSocketServer(); + ~WebSocketServer(); - void Start(); - void Stop(); - void InvalidateSession(websocketpp::connection_hdl hdl); - void BroadcastEvent(uint64_t requiredIntent, const std::string &eventType, const json &eventData = nullptr, uint8_t rpcVersion = 0); + void Start(); + void Stop(); + void InvalidateSession(websocketpp::connection_hdl hdl); + void BroadcastEvent(uint64_t requiredIntent, + const std::string &eventType, + const json &eventData = nullptr, + uint8_t rpcVersion = 0); - bool IsListening() { - return _server.is_listening(); - } + bool IsListening() { return _server.is_listening(); } - std::vector GetWebSocketSessions(); + std::vector GetWebSocketSessions(); - QThreadPool *GetThreadPool() { - return &_threadPool; - } + QThreadPool *GetThreadPool() { return &_threadPool; } - signals: - void ClientConnected(WebSocketSessionState state); - void ClientDisconnected(WebSocketSessionState state, uint16_t closeCode); +signals: + void ClientConnected(WebSocketSessionState state); + void ClientDisconnected(WebSocketSessionState state, + uint16_t closeCode); - private: - struct ProcessResult { - WebSocketCloseCode::WebSocketCloseCode closeCode = WebSocketCloseCode::DontClose; - std::string closeReason; - json result; - }; +private: + struct ProcessResult { + WebSocketCloseCode::WebSocketCloseCode closeCode = + WebSocketCloseCode::DontClose; + std::string closeReason; + json result; + }; - void ServerRunner(); + void ServerRunner(); - void onObsLoaded(); - bool onValidate(websocketpp::connection_hdl hdl); - void onOpen(websocketpp::connection_hdl hdl); - void onClose(websocketpp::connection_hdl hdl); - void onMessage(websocketpp::connection_hdl hdl, websocketpp::server::message_ptr message); + void onObsLoaded(); + bool onValidate(websocketpp::connection_hdl hdl); + void onOpen(websocketpp::connection_hdl hdl); + void onClose(websocketpp::connection_hdl hdl); + void + onMessage(websocketpp::connection_hdl hdl, + websocketpp::server::message_ptr + message); - static void SetSessionParameters(SessionPtr session, WebSocketServer::ProcessResult &ret, const json &payloadData); - void ProcessMessage(SessionPtr session, ProcessResult &ret, WebSocketOpCode::WebSocketOpCode opCode, json &payloadData); + static void SetSessionParameters(SessionPtr session, + WebSocketServer::ProcessResult &ret, + const json &payloadData); + void ProcessMessage(SessionPtr session, ProcessResult &ret, + WebSocketOpCode::WebSocketOpCode opCode, + json &payloadData); - QThreadPool _threadPool; + QThreadPool _threadPool; - std::thread _serverThread; - websocketpp::server _server; + std::thread _serverThread; + websocketpp::server _server; - std::string _authenticationSecret; - std::string _authenticationSalt; + std::string _authenticationSecret; + std::string _authenticationSalt; - std::mutex _sessionMutex; - std::map> _sessions; + std::mutex _sessionMutex; + std::map> + _sessions; }; diff --git a/src/websocketserver/WebSocketServer_Protocol.cpp b/src/websocketserver/WebSocketServer_Protocol.cpp index 67c082c3..c7b92723 100644 --- a/src/websocketserver/WebSocketServer_Protocol.cpp +++ b/src/websocketserver/WebSocketServer_Protocol.cpp @@ -35,19 +35,20 @@ static bool IsSupportedRpcVersion(uint8_t requestedVersion) return (requestedVersion == 1); } -static json ConstructRequestResult(RequestResult requestResult, const json &requestJson) +static json ConstructRequestResult(RequestResult requestResult, + const json &requestJson) { json ret; ret["requestType"] = requestJson["requestType"]; - if (requestJson.contains("requestId") && !requestJson["requestId"].is_null()) + if (requestJson.contains("requestId") && + !requestJson["requestId"].is_null()) ret["requestId"] = requestJson["requestId"]; - ret["requestStatus"] = { - {"result", requestResult.StatusCode == RequestStatus::Success}, - {"code", requestResult.StatusCode} - }; + ret["requestStatus"] = {{"result", requestResult.StatusCode == + RequestStatus::Success}, + {"code", requestResult.StatusCode}}; if (!requestResult.Comment.empty()) ret["requestStatus"]["comment"] = requestResult.Comment; @@ -58,27 +59,37 @@ static json ConstructRequestResult(RequestResult requestResult, const json &requ return ret; } -void WebSocketServer::SetSessionParameters(SessionPtr session, ProcessResult &ret, const json &payloadData) +void WebSocketServer::SetSessionParameters(SessionPtr session, + ProcessResult &ret, + const json &payloadData) { if (payloadData.contains("eventSubscriptions")) { if (!payloadData["eventSubscriptions"].is_number_unsigned()) { - ret.closeCode = WebSocketCloseCode::InvalidDataFieldType; - ret.closeReason = "Your `eventSubscriptions` is not an unsigned number."; + ret.closeCode = + WebSocketCloseCode::InvalidDataFieldType; + ret.closeReason = + "Your `eventSubscriptions` is not an unsigned number."; return; } - session->SetEventSubscriptions(payloadData["eventSubscriptions"]); + session->SetEventSubscriptions( + payloadData["eventSubscriptions"]); } } -void WebSocketServer::ProcessMessage(SessionPtr session, WebSocketServer::ProcessResult &ret, WebSocketOpCode::WebSocketOpCode opCode, json &payloadData) +void WebSocketServer::ProcessMessage(SessionPtr session, + WebSocketServer::ProcessResult &ret, + WebSocketOpCode::WebSocketOpCode opCode, + json &payloadData) { if (!payloadData.is_object()) { if (payloadData.is_null()) { ret.closeCode = WebSocketCloseCode::MissingDataField; ret.closeReason = "Your payload is missing data (`d`)."; } else { - ret.closeCode = WebSocketCloseCode::InvalidDataFieldType; - ret.closeReason = "Your payload's data (`d`) is not an object."; + ret.closeCode = + WebSocketCloseCode::InvalidDataFieldType; + ret.closeReason = + "Your payload's data (`d`) is not an object."; } return; } @@ -86,223 +97,301 @@ void WebSocketServer::ProcessMessage(SessionPtr session, WebSocketServer::Proces // Only `Identify` is allowed when not identified if (!session->IsIdentified() && opCode != 1) { ret.closeCode = WebSocketCloseCode::NotIdentified; - ret.closeReason = "You attempted to send a non-Identify message while not identified."; + ret.closeReason = + "You attempted to send a non-Identify message while not identified."; return; } switch (opCode) { - case WebSocketOpCode::Identify: { // Identify - std::unique_lock sessionLock(session->OperationMutex); - if (session->IsIdentified()) { - ret.closeCode = WebSocketCloseCode::AlreadyIdentified; - ret.closeReason = "You are already Identified with the obs-websocket server."; - return; - } - - if (session->AuthenticationRequired()) { - if (!payloadData.contains("authentication")) { - ret.closeCode = WebSocketCloseCode::AuthenticationFailed; - ret.closeReason = "Your payload's data is missing an `authentication` string, however authentication is required."; - return; - } - if (!Utils::Crypto::CheckAuthenticationString(session->Secret(), session->Challenge(), payloadData["authentication"])) { - auto conf = GetConfig(); - if (conf && conf->AlertsEnabled) { - QString title = obs_module_text("OBSWebSocket.TrayNotification.AuthenticationFailed.Title"); - QString body = QString(obs_module_text("OBSWebSocket.TrayNotification.AuthenticationFailed.Body")).arg(QString::fromStdString(session->RemoteAddress())); - Utils::Platform::SendTrayNotification(QSystemTrayIcon::Warning, title, body); - } - ret.closeCode = WebSocketCloseCode::AuthenticationFailed; - ret.closeReason = "Authentication failed."; - return; - } - } - - if (!payloadData.contains("rpcVersion")) { - ret.closeCode = WebSocketCloseCode::MissingDataField; - ret.closeReason = "Your payload's data is missing an `rpcVersion`."; - return; - } - - if (!payloadData["rpcVersion"].is_number_unsigned()) { - ret.closeCode = WebSocketCloseCode::InvalidDataFieldType; - ret.closeReason = "Your `rpcVersion` is not an unsigned number."; - } - - uint8_t requestedRpcVersion = payloadData["rpcVersion"]; - if (!IsSupportedRpcVersion(requestedRpcVersion)) { - ret.closeCode = WebSocketCloseCode::UnsupportedRpcVersion; - ret.closeReason = "Your requested RPC version is not supported by this server."; - return; - } - session->SetRpcVersion(requestedRpcVersion); - - SetSessionParameters(session, ret, payloadData); - if (ret.closeCode != WebSocketCloseCode::DontClose) { - return; - } - - // Increment refs for event subscriptions - auto eventHandler = GetEventHandler(); - eventHandler->ProcessSubscription(session->EventSubscriptions()); - - // Mark session as identified - session->SetIsIdentified(true); - - // Send desktop notification. TODO: Move to UI code - auto conf = GetConfig(); - if (conf && conf->AlertsEnabled) { - QString title = obs_module_text("OBSWebSocket.TrayNotification.Identified.Title"); - QString body = QString(obs_module_text("OBSWebSocket.TrayNotification.Identified.Body")).arg(QString::fromStdString(session->RemoteAddress())); - Utils::Platform::SendTrayNotification(QSystemTrayIcon::Information, title, body); - } - - ret.result["op"] = WebSocketOpCode::Identified; - ret.result["d"]["negotiatedRpcVersion"] = session->RpcVersion(); - } return; - case WebSocketOpCode::Reidentify: { // Reidentify - std::unique_lock sessionLock(session->OperationMutex); - - // Decrement refs for current subscriptions - auto eventHandler = GetEventHandler(); - eventHandler->ProcessUnsubscription(session->EventSubscriptions()); - - SetSessionParameters(session, ret, payloadData); - if (ret.closeCode != WebSocketCloseCode::DontClose) { - return; - } - - // Increment refs for new subscriptions - eventHandler->ProcessSubscription(session->EventSubscriptions()); - - ret.result["op"] = WebSocketOpCode::Identified; - ret.result["d"]["negotiatedRpcVersion"] = session->RpcVersion(); - } return; - case WebSocketOpCode::Request: { // Request - // RequestID checking has to be done here where we are able to close the connection. - if (!payloadData.contains("requestId")) { - ret.closeCode = WebSocketCloseCode::MissingDataField; - ret.closeReason = "Your payload data is missing a `requestId`."; - return; - } - - RequestHandler requestHandler(session); - Request request(payloadData["requestType"], payloadData["requestData"]); - - RequestResult requestResult = requestHandler.ProcessRequest(request); - - json resultPayloadData; - resultPayloadData["requestType"] = payloadData["requestType"]; - resultPayloadData["requestId"] = payloadData["requestId"]; - resultPayloadData["requestStatus"] = { - {"result", requestResult.StatusCode == RequestStatus::Success}, - {"code", requestResult.StatusCode} - }; - if (!requestResult.Comment.empty()) - resultPayloadData["requestStatus"]["comment"] = requestResult.Comment; - if (requestResult.ResponseData.is_object()) - resultPayloadData["responseData"] = requestResult.ResponseData; - ret.result["op"] = WebSocketOpCode::RequestResponse; - ret.result["d"] = resultPayloadData; - } return; - case WebSocketOpCode::RequestBatch: { // RequestBatch - // RequestID checking has to be done here where we are able to close the connection. - if (!payloadData.contains("requestId")) { - ret.closeCode = WebSocketCloseCode::MissingDataField; - ret.closeReason = "Your payload data is missing a `requestId`."; - return; - } - - if (!payloadData.contains("requests")) { - ret.closeCode = WebSocketCloseCode::MissingDataField; - ret.closeReason = "Your payload data is missing a `requests`."; - return; - } - - if (!payloadData["requests"].is_array()) { - ret.closeCode = WebSocketCloseCode::InvalidDataFieldType; - ret.closeReason = "Your `requests` is not an array."; - return; - } - - RequestBatchExecutionType::RequestBatchExecutionType executionType = RequestBatchExecutionType::SerialRealtime; - if (payloadData.contains("executionType") && !payloadData["executionType"].is_null()) { - if (!payloadData["executionType"].is_number_unsigned()) { - ret.closeCode = WebSocketCloseCode::InvalidDataFieldType; - ret.closeReason = "Your `executionType` is not a number."; - return; - } - - int8_t requestedExecutionType = payloadData["executionType"]; - if (!RequestBatchExecutionType::IsValid(requestedExecutionType) || requestedExecutionType == RequestBatchExecutionType::None) { - ret.closeCode = WebSocketCloseCode::InvalidDataFieldValue; - ret.closeReason = "Your `executionType` has an invalid value."; - return; - } - - // The thread pool must support 2 or more threads else parallel requests will deadlock. - if (requestedExecutionType == RequestBatchExecutionType::Parallel && _threadPool.maxThreadCount() < 2) { - ret.closeCode = WebSocketCloseCode::UnsupportedFeature; - ret.closeReason = "Parallel request batch processing is not available on this system due to limited core count."; - return; - } - - executionType = (RequestBatchExecutionType::RequestBatchExecutionType)requestedExecutionType; - } - - if (payloadData.contains("variables") && !payloadData["variables"].is_null()) { - if (!payloadData.is_object()) { - ret.closeCode = WebSocketCloseCode::InvalidDataFieldType; - ret.closeReason = "Your `variables` is not an object."; - return; - } - - if (executionType == RequestBatchExecutionType::Parallel) { - ret.closeCode = WebSocketCloseCode::UnsupportedFeature; - ret.closeReason = "Variables are not supported in Parallel mode."; - return; - } - } - - bool haltOnFailure = false; - if (payloadData.contains("haltOnFailure") && !payloadData["haltOnFailure"].is_null()) { - if (!payloadData["haltOnFailure"].is_boolean()) { - ret.closeCode = WebSocketCloseCode::InvalidDataFieldType; - ret.closeReason = "Your `haltOnFailure` is not a boolean."; - return; - } - - haltOnFailure = payloadData["haltOnFailure"]; - } - - std::vector requests = payloadData["requests"]; - - std::vector requestsVector; - for (auto &requestJson : requests) - requestsVector.emplace_back(requestJson["requestType"], requestJson["requestData"], executionType, requestJson["inputVariables"], requestJson["outputVariables"]); - - auto resultsVector = RequestBatchHandler::ProcessRequestBatch(_threadPool, session, executionType, requestsVector, payloadData["variables"], haltOnFailure); - - size_t i = 0; - std::vector results; - for (auto &requestResult : resultsVector) { - results.push_back(ConstructRequestResult(requestResult, requests[i])); - i++; - } - - ret.result["op"] = WebSocketOpCode::RequestBatchResponse; - ret.result["d"]["requestId"] = payloadData["requestId"]; - ret.result["d"]["results"] = results; - } return; - default: - ret.closeCode = WebSocketCloseCode::UnknownOpCode; - ret.closeReason = std::string("Unknown OpCode: ") + std::to_string(opCode); + case WebSocketOpCode::Identify: { // Identify + std::unique_lock sessionLock( + session->OperationMutex); + if (session->IsIdentified()) { + ret.closeCode = WebSocketCloseCode::AlreadyIdentified; + ret.closeReason = + "You are already Identified with the obs-websocket server."; return; + } + + if (session->AuthenticationRequired()) { + if (!payloadData.contains("authentication")) { + ret.closeCode = + WebSocketCloseCode::AuthenticationFailed; + ret.closeReason = + "Your payload's data is missing an `authentication` string, however authentication is required."; + return; + } + if (!Utils::Crypto::CheckAuthenticationString( + session->Secret(), session->Challenge(), + payloadData["authentication"])) { + auto conf = GetConfig(); + if (conf && conf->AlertsEnabled) { + QString title = obs_module_text( + "OBSWebSocket.TrayNotification.AuthenticationFailed.Title"); + QString body = + QString(obs_module_text( + "OBSWebSocket.TrayNotification.AuthenticationFailed.Body")) + .arg(QString::fromStdString( + session->RemoteAddress())); + Utils::Platform::SendTrayNotification( + QSystemTrayIcon::Warning, title, + body); + } + ret.closeCode = + WebSocketCloseCode::AuthenticationFailed; + ret.closeReason = "Authentication failed."; + return; + } + } + + if (!payloadData.contains("rpcVersion")) { + ret.closeCode = WebSocketCloseCode::MissingDataField; + ret.closeReason = + "Your payload's data is missing an `rpcVersion`."; + return; + } + + if (!payloadData["rpcVersion"].is_number_unsigned()) { + ret.closeCode = + WebSocketCloseCode::InvalidDataFieldType; + ret.closeReason = + "Your `rpcVersion` is not an unsigned number."; + } + + uint8_t requestedRpcVersion = payloadData["rpcVersion"]; + if (!IsSupportedRpcVersion(requestedRpcVersion)) { + ret.closeCode = + WebSocketCloseCode::UnsupportedRpcVersion; + ret.closeReason = + "Your requested RPC version is not supported by this server."; + return; + } + session->SetRpcVersion(requestedRpcVersion); + + SetSessionParameters(session, ret, payloadData); + if (ret.closeCode != WebSocketCloseCode::DontClose) { + return; + } + + // Increment refs for event subscriptions + auto eventHandler = GetEventHandler(); + eventHandler->ProcessSubscription( + session->EventSubscriptions()); + + // Mark session as identified + session->SetIsIdentified(true); + + // Send desktop notification. TODO: Move to UI code + auto conf = GetConfig(); + if (conf && conf->AlertsEnabled) { + QString title = obs_module_text( + "OBSWebSocket.TrayNotification.Identified.Title"); + QString body = + QString(obs_module_text( + "OBSWebSocket.TrayNotification.Identified.Body")) + .arg(QString::fromStdString( + session->RemoteAddress())); + Utils::Platform::SendTrayNotification( + QSystemTrayIcon::Information, title, body); + } + + ret.result["op"] = WebSocketOpCode::Identified; + ret.result["d"]["negotiatedRpcVersion"] = session->RpcVersion(); + } + return; + case WebSocketOpCode::Reidentify: { // Reidentify + std::unique_lock sessionLock( + session->OperationMutex); + + // Decrement refs for current subscriptions + auto eventHandler = GetEventHandler(); + eventHandler->ProcessUnsubscription( + session->EventSubscriptions()); + + SetSessionParameters(session, ret, payloadData); + if (ret.closeCode != WebSocketCloseCode::DontClose) { + return; + } + + // Increment refs for new subscriptions + eventHandler->ProcessSubscription( + session->EventSubscriptions()); + + ret.result["op"] = WebSocketOpCode::Identified; + ret.result["d"]["negotiatedRpcVersion"] = session->RpcVersion(); + } + return; + case WebSocketOpCode::Request: { // Request + // RequestID checking has to be done here where we are able to close the connection. + if (!payloadData.contains("requestId")) { + ret.closeCode = WebSocketCloseCode::MissingDataField; + ret.closeReason = + "Your payload data is missing a `requestId`."; + return; + } + + RequestHandler requestHandler(session); + Request request(payloadData["requestType"], + payloadData["requestData"]); + + RequestResult requestResult = + requestHandler.ProcessRequest(request); + + json resultPayloadData; + resultPayloadData["requestType"] = payloadData["requestType"]; + resultPayloadData["requestId"] = payloadData["requestId"]; + resultPayloadData["requestStatus"] = { + {"result", + requestResult.StatusCode == RequestStatus::Success}, + {"code", requestResult.StatusCode}}; + if (!requestResult.Comment.empty()) + resultPayloadData["requestStatus"]["comment"] = + requestResult.Comment; + if (requestResult.ResponseData.is_object()) + resultPayloadData["responseData"] = + requestResult.ResponseData; + ret.result["op"] = WebSocketOpCode::RequestResponse; + ret.result["d"] = resultPayloadData; + } + return; + case WebSocketOpCode::RequestBatch: { // RequestBatch + // RequestID checking has to be done here where we are able to close the connection. + if (!payloadData.contains("requestId")) { + ret.closeCode = WebSocketCloseCode::MissingDataField; + ret.closeReason = + "Your payload data is missing a `requestId`."; + return; + } + + if (!payloadData.contains("requests")) { + ret.closeCode = WebSocketCloseCode::MissingDataField; + ret.closeReason = + "Your payload data is missing a `requests`."; + return; + } + + if (!payloadData["requests"].is_array()) { + ret.closeCode = + WebSocketCloseCode::InvalidDataFieldType; + ret.closeReason = "Your `requests` is not an array."; + return; + } + + RequestBatchExecutionType::RequestBatchExecutionType + executionType = + RequestBatchExecutionType::SerialRealtime; + if (payloadData.contains("executionType") && + !payloadData["executionType"].is_null()) { + if (!payloadData["executionType"].is_number_unsigned()) { + ret.closeCode = + WebSocketCloseCode::InvalidDataFieldType; + ret.closeReason = + "Your `executionType` is not a number."; + return; + } + + int8_t requestedExecutionType = + payloadData["executionType"]; + if (!RequestBatchExecutionType::IsValid( + requestedExecutionType) || + requestedExecutionType == + RequestBatchExecutionType::None) { + ret.closeCode = + WebSocketCloseCode::InvalidDataFieldValue; + ret.closeReason = + "Your `executionType` has an invalid value."; + return; + } + + // The thread pool must support 2 or more threads else parallel requests will deadlock. + if (requestedExecutionType == + RequestBatchExecutionType::Parallel && + _threadPool.maxThreadCount() < 2) { + ret.closeCode = + WebSocketCloseCode::UnsupportedFeature; + ret.closeReason = + "Parallel request batch processing is not available on this system due to limited core count."; + return; + } + + executionType = (RequestBatchExecutionType:: + RequestBatchExecutionType) + requestedExecutionType; + } + + if (payloadData.contains("variables") && + !payloadData["variables"].is_null()) { + if (!payloadData.is_object()) { + ret.closeCode = + WebSocketCloseCode::InvalidDataFieldType; + ret.closeReason = + "Your `variables` is not an object."; + return; + } + + if (executionType == + RequestBatchExecutionType::Parallel) { + ret.closeCode = + WebSocketCloseCode::UnsupportedFeature; + ret.closeReason = + "Variables are not supported in Parallel mode."; + return; + } + } + + bool haltOnFailure = false; + if (payloadData.contains("haltOnFailure") && + !payloadData["haltOnFailure"].is_null()) { + if (!payloadData["haltOnFailure"].is_boolean()) { + ret.closeCode = + WebSocketCloseCode::InvalidDataFieldType; + ret.closeReason = + "Your `haltOnFailure` is not a boolean."; + return; + } + + haltOnFailure = payloadData["haltOnFailure"]; + } + + std::vector requests = payloadData["requests"]; + + std::vector requestsVector; + for (auto &requestJson : requests) + requestsVector.emplace_back( + requestJson["requestType"], + requestJson["requestData"], executionType, + requestJson["inputVariables"], + requestJson["outputVariables"]); + + auto resultsVector = RequestBatchHandler::ProcessRequestBatch( + _threadPool, session, executionType, requestsVector, + payloadData["variables"], haltOnFailure); + + size_t i = 0; + std::vector results; + for (auto &requestResult : resultsVector) { + results.push_back(ConstructRequestResult(requestResult, + requests[i])); + i++; + } + + ret.result["op"] = WebSocketOpCode::RequestBatchResponse; + ret.result["d"]["requestId"] = payloadData["requestId"]; + ret.result["d"]["results"] = results; + } + return; + default: + ret.closeCode = WebSocketCloseCode::UnknownOpCode; + ret.closeReason = std::string("Unknown OpCode: ") + + std::to_string(opCode); + return; } } // It isn't consistent to directly call the WebSocketServer from the events system, but it would also be dumb to make it unnecessarily complicated. -void WebSocketServer::BroadcastEvent(uint64_t requiredIntent, const std::string &eventType, const json &eventData, uint8_t rpcVersion) +void WebSocketServer::BroadcastEvent(uint64_t requiredIntent, + const std::string &eventType, + const json &eventData, uint8_t rpcVersion) { if (!_server.is_listening()) return; @@ -322,38 +411,61 @@ void WebSocketServer::BroadcastEvent(uint64_t requiredIntent, const std::string // Recurse connected sessions and send the event to suitable sessions. std::unique_lock lock(_sessionMutex); - for (auto & it : _sessions) { + for (auto &it : _sessions) { if (!it.second->IsIdentified()) { continue; } - if (rpcVersion && it.second->RpcVersion() != rpcVersion) { + if (rpcVersion && + it.second->RpcVersion() != rpcVersion) { continue; } - if ((it.second->EventSubscriptions() & requiredIntent) != 0) { + if ((it.second->EventSubscriptions() & + requiredIntent) != 0) { websocketpp::lib::error_code errorCode; switch (it.second->Encoding()) { - case WebSocketEncoding::Json: - if (messageJson.empty()) { - messageJson = eventMessage.dump(); - } - _server.send((websocketpp::connection_hdl)it.first, messageJson, websocketpp::frame::opcode::text, errorCode); - it.second->IncrementOutgoingMessages(); - break; - case WebSocketEncoding::MsgPack: - if (messageMsgPack.empty()) { - auto msgPackData = json::to_msgpack(eventMessage); - messageMsgPack = std::string(msgPackData.begin(), msgPackData.end()); - } - _server.send((websocketpp::connection_hdl)it.first, messageMsgPack, websocketpp::frame::opcode::binary, errorCode); - it.second->IncrementOutgoingMessages(); - break; + case WebSocketEncoding::Json: + if (messageJson.empty()) { + messageJson = + eventMessage.dump(); + } + _server.send( + (websocketpp::connection_hdl) + it.first, + messageJson, + websocketpp::frame::opcode::text, + errorCode); + it.second->IncrementOutgoingMessages(); + break; + case WebSocketEncoding::MsgPack: + if (messageMsgPack.empty()) { + auto msgPackData = + json::to_msgpack( + eventMessage); + messageMsgPack = std::string( + msgPackData.begin(), + msgPackData.end()); + } + _server.send( + (websocketpp::connection_hdl) + it.first, + messageMsgPack, + websocketpp::frame::opcode::binary, + errorCode); + it.second->IncrementOutgoingMessages(); + break; } if (errorCode) - blog(LOG_ERROR, "[WebSocketServer::BroadcastEvent] Error sending event message: %s", errorCode.message().c_str()); + blog(LOG_ERROR, + "[WebSocketServer::BroadcastEvent] Error sending event message: %s", + errorCode.message().c_str()); } } lock.unlock(); - if (IsDebugEnabled() && (EventSubscription::All & requiredIntent) != 0) // Don't log high volume events - blog(LOG_INFO, "[WebSocketServer::BroadcastEvent] Outgoing event:\n%s", eventMessage.dump(2).c_str()); + if (IsDebugEnabled() && + (EventSubscription::All & requiredIntent) != + 0) // Don't log high volume events + blog(LOG_INFO, + "[WebSocketServer::BroadcastEvent] Outgoing event:\n%s", + eventMessage.dump(2).c_str()); })); } diff --git a/src/websocketserver/rpc/WebSocketSession.cpp b/src/websocketserver/rpc/WebSocketSession.cpp index ec9b8436..e5e10314 100644 --- a/src/websocketserver/rpc/WebSocketSession.cpp +++ b/src/websocketserver/rpc/WebSocketSession.cpp @@ -20,16 +20,16 @@ with this program. If not, see #include "WebSocketSession.h" #include "../../eventhandler/types/EventSubscription.h" -WebSocketSession::WebSocketSession() : - _remoteAddress(""), - _connectedAt(0), - _incomingMessages(0), - _outgoingMessages(0), - _encoding(0), - _challenge(""), - _rpcVersion(OBS_WEBSOCKET_RPC_VERSION), - _isIdentified(false), - _eventSubscriptions(EventSubscription::All) +WebSocketSession::WebSocketSession() + : _remoteAddress(""), + _connectedAt(0), + _incomingMessages(0), + _outgoingMessages(0), + _encoding(0), + _challenge(""), + _rpcVersion(OBS_WEBSOCKET_RPC_VERSION), + _isIdentified(false), + _eventSubscriptions(EventSubscription::All) { } diff --git a/src/websocketserver/rpc/WebSocketSession.h b/src/websocketserver/rpc/WebSocketSession.h index 4974500b..c3160286 100644 --- a/src/websocketserver/rpc/WebSocketSession.h +++ b/src/websocketserver/rpc/WebSocketSession.h @@ -29,59 +29,58 @@ with this program. If not, see class WebSocketSession; typedef std::shared_ptr SessionPtr; -class WebSocketSession -{ - public: - WebSocketSession(); +class WebSocketSession { +public: + WebSocketSession(); - std::string RemoteAddress(); - void SetRemoteAddress(std::string address); + std::string RemoteAddress(); + void SetRemoteAddress(std::string address); - uint64_t ConnectedAt(); - void SetConnectedAt(uint64_t at); + uint64_t ConnectedAt(); + void SetConnectedAt(uint64_t at); - uint64_t IncomingMessages(); - void IncrementIncomingMessages(); + uint64_t IncomingMessages(); + void IncrementIncomingMessages(); - uint64_t OutgoingMessages(); - void IncrementOutgoingMessages(); + uint64_t OutgoingMessages(); + void IncrementOutgoingMessages(); - uint8_t Encoding(); - void SetEncoding(uint8_t encoding); + uint8_t Encoding(); + void SetEncoding(uint8_t encoding); - bool AuthenticationRequired(); - void SetAuthenticationRequired(bool required); + bool AuthenticationRequired(); + void SetAuthenticationRequired(bool required); - std::string Secret(); - void SetSecret(std::string secret); + std::string Secret(); + void SetSecret(std::string secret); - std::string Challenge(); - void SetChallenge(std::string challenge); + std::string Challenge(); + void SetChallenge(std::string challenge); - uint8_t RpcVersion(); - void SetRpcVersion(uint8_t version); + uint8_t RpcVersion(); + void SetRpcVersion(uint8_t version); - bool IsIdentified(); - void SetIsIdentified(bool identified); + bool IsIdentified(); + void SetIsIdentified(bool identified); - uint64_t EventSubscriptions(); - void SetEventSubscriptions(uint64_t subscriptions); + uint64_t EventSubscriptions(); + void SetEventSubscriptions(uint64_t subscriptions); - std::mutex OperationMutex; + std::mutex OperationMutex; - private: - std::mutex _remoteAddressMutex; - std::string _remoteAddress; - std::atomic _connectedAt; - std::atomic _incomingMessages; - std::atomic _outgoingMessages; - std::atomic _encoding; - std::atomic _authenticationRequired; - std::mutex _secretMutex; - std::string _secret; - std::mutex _challengeMutex; - std::string _challenge; - std::atomic _rpcVersion; - std::atomic _isIdentified; - std::atomic _eventSubscriptions; +private: + std::mutex _remoteAddressMutex; + std::string _remoteAddress; + std::atomic _connectedAt; + std::atomic _incomingMessages; + std::atomic _outgoingMessages; + std::atomic _encoding; + std::atomic _authenticationRequired; + std::mutex _secretMutex; + std::string _secret; + std::mutex _challengeMutex; + std::string _challenge; + std::atomic _rpcVersion; + std::atomic _isIdentified; + std::atomic _eventSubscriptions; }; diff --git a/src/websocketserver/types/WebSocketCloseCode.h b/src/websocketserver/types/WebSocketCloseCode.h index 51904140..79c13d0d 100644 --- a/src/websocketserver/types/WebSocketCloseCode.h +++ b/src/websocketserver/types/WebSocketCloseCode.h @@ -20,8 +20,8 @@ with this program. If not, see #pragma once namespace WebSocketCloseCode { - enum WebSocketCloseCode { - /** +enum WebSocketCloseCode { + /** * For internal use only to tell the request handler not to perform any close action. * * @enumIdentifier DontClose @@ -31,8 +31,8 @@ namespace WebSocketCloseCode { * @initialVersion 5.0.0 * @api enums */ - DontClose = 0, - /** + DontClose = 0, + /** * Unknown reason, should never be used. * * @enumIdentifier UnknownReason @@ -42,8 +42,8 @@ namespace WebSocketCloseCode { * @initialVersion 5.0.0 * @api enums */ - UnknownReason = 4000, - /** + UnknownReason = 4000, + /** * The server was unable to decode the incoming websocket message. * * @enumIdentifier MessageDecodeError @@ -53,8 +53,8 @@ namespace WebSocketCloseCode { * @initialVersion 5.0.0 * @api enums */ - MessageDecodeError = 4002, - /** + MessageDecodeError = 4002, + /** * A data field is required but missing from the payload. * * @enumIdentifier MissingDataField @@ -64,8 +64,8 @@ namespace WebSocketCloseCode { * @initialVersion 5.0.0 * @api enums */ - MissingDataField = 4003, - /** + MissingDataField = 4003, + /** * A data field's value type is invalid. * * @enumIdentifier InvalidDataFieldType @@ -75,8 +75,8 @@ namespace WebSocketCloseCode { * @initialVersion 5.0.0 * @api enums */ - InvalidDataFieldType = 4004, - /** + InvalidDataFieldType = 4004, + /** * A data field's value is invalid. * * @enumIdentifier InvalidDataFieldValue @@ -86,8 +86,8 @@ namespace WebSocketCloseCode { * @initialVersion 5.0.0 * @api enums */ - InvalidDataFieldValue = 4005, - /** + InvalidDataFieldValue = 4005, + /** * The specified `op` was invalid or missing. * * @enumIdentifier UnknownOpCode @@ -97,8 +97,8 @@ namespace WebSocketCloseCode { * @initialVersion 5.0.0 * @api enums */ - UnknownOpCode = 4006, - /** + UnknownOpCode = 4006, + /** * The client sent a websocket message without first sending `Identify` message. * * @enumIdentifier NotIdentified @@ -108,8 +108,8 @@ namespace WebSocketCloseCode { * @initialVersion 5.0.0 * @api enums */ - NotIdentified = 4007, - /** + NotIdentified = 4007, + /** * The client sent an `Identify` message while already identified. * * Note: Once a client has identified, only `Reidentify` may be used to change session parameters. @@ -121,8 +121,8 @@ namespace WebSocketCloseCode { * @initialVersion 5.0.0 * @api enums */ - AlreadyIdentified = 4008, - /** + AlreadyIdentified = 4008, + /** * The authentication attempt (via `Identify`) failed. * * @enumIdentifier AuthenticationFailed @@ -132,8 +132,8 @@ namespace WebSocketCloseCode { * @initialVersion 5.0.0 * @api enums */ - AuthenticationFailed = 4009, - /** + AuthenticationFailed = 4009, + /** * The server detected the usage of an old version of the obs-websocket RPC protocol. * * @enumIdentifier UnsupportedRpcVersion @@ -143,8 +143,8 @@ namespace WebSocketCloseCode { * @initialVersion 5.0.0 * @api enums */ - UnsupportedRpcVersion = 4010, - /** + UnsupportedRpcVersion = 4010, + /** * The websocket session has been invalidated by the obs-websocket server. * * Note: This is the code used by the `Kick` button in the UI Session List. If you receive this code, you must not automatically reconnect. @@ -156,8 +156,8 @@ namespace WebSocketCloseCode { * @initialVersion 5.0.0 * @api enums */ - SessionInvalidated = 4011, - /** + SessionInvalidated = 4011, + /** * A requested feature is not supported due to hardware/software limitations. * * @enumIdentifier UnsupportedFeature @@ -167,6 +167,6 @@ namespace WebSocketCloseCode { * @initialVersion 5.0.0 * @api enums */ - UnsupportedFeature = 4012, - }; + UnsupportedFeature = 4012, +}; } diff --git a/src/websocketserver/types/WebSocketOpCode.h b/src/websocketserver/types/WebSocketOpCode.h index 2611bf3c..614bc7e0 100644 --- a/src/websocketserver/types/WebSocketOpCode.h +++ b/src/websocketserver/types/WebSocketOpCode.h @@ -20,8 +20,8 @@ with this program. If not, see #pragma once namespace WebSocketOpCode { - enum WebSocketOpCode: uint8_t { - /** +enum WebSocketOpCode : uint8_t { + /** * The initial message sent by obs-websocket to newly connected clients. * * @enumIdentifier Hello @@ -31,8 +31,8 @@ namespace WebSocketOpCode { * @initialVersion 5.0.0 * @api enums */ - Hello = 0, - /** + Hello = 0, + /** * The message sent by a newly connected client to obs-websocket in response to a `Hello`. * * @enumIdentifier Identify @@ -42,8 +42,8 @@ namespace WebSocketOpCode { * @initialVersion 5.0.0 * @api enums */ - Identify = 1, - /** + Identify = 1, + /** * The response sent by obs-websocket to a client after it has successfully identified with obs-websocket. * * @enumIdentifier Identified @@ -53,8 +53,8 @@ namespace WebSocketOpCode { * @initialVersion 5.0.0 * @api enums */ - Identified = 2, - /** + Identified = 2, + /** * The message sent by an already-identified client to update identification parameters. * * @enumIdentifier Reidentify @@ -64,8 +64,8 @@ namespace WebSocketOpCode { * @initialVersion 5.0.0 * @api enums */ - Reidentify = 3, - /** + Reidentify = 3, + /** * The message sent by obs-websocket containing an event payload. * * @enumIdentifier Event @@ -75,8 +75,8 @@ namespace WebSocketOpCode { * @initialVersion 5.0.0 * @api enums */ - Event = 5, - /** + Event = 5, + /** * The message sent by a client to obs-websocket to perform a request. * * @enumIdentifier Request @@ -86,8 +86,8 @@ namespace WebSocketOpCode { * @initialVersion 5.0.0 * @api enums */ - Request = 6, - /** + Request = 6, + /** * The message sent by obs-websocket in response to a particular request from a client. * * @enumIdentifier RequestResponse @@ -97,8 +97,8 @@ namespace WebSocketOpCode { * @initialVersion 5.0.0 * @api enums */ - RequestResponse = 7, - /** + RequestResponse = 7, + /** * The message sent by a client to obs-websocket to perform a batch of requests. * * @enumIdentifier RequestBatch @@ -108,8 +108,8 @@ namespace WebSocketOpCode { * @initialVersion 5.0.0 * @api enums */ - RequestBatch = 8, - /** + RequestBatch = 8, + /** * The message sent by obs-websocket in response to a particular batch of requests from a client. * * @enumIdentifier RequestBatchResponse @@ -119,11 +119,11 @@ namespace WebSocketOpCode { * @initialVersion 5.0.0 * @api enums */ - RequestBatchResponse = 9, - }; + RequestBatchResponse = 9, +}; - inline bool IsValid(uint8_t opCode) - { - return opCode >= Hello && opCode <= RequestBatchResponse; - } +inline bool IsValid(uint8_t opCode) +{ + return opCode >= Hello && opCode <= RequestBatchResponse; +} }