From 66a059ecdfc935001f32b2d2e4a34e32e848411a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20L?= Date: Mon, 13 Nov 2017 08:44:26 +0100 Subject: [PATCH] Automatic function-scope OBS _release() + refactor to camelCase (#149) - Refactor all internal variables to camelCase - Use obs pointers with *AutoRelease classes for automatic refcounting - Important: some pointers require prior investigation to determine if refcounting is needed, or which between OBSRef and *AutoRelease should be used. --- Config.cpp | 111 ++--- Config.h | 18 +- Utils.cpp | 130 +++--- Utils.h | 22 +- WSEvents.cpp | 358 ++++++++-------- WSEvents.h | 17 +- WSRequestHandler.cpp | 842 +++++++++++++++----------------------- WSRequestHandler.h | 7 +- forms/settings-dialog.cpp | 13 +- obs-websocket.cpp | 6 + obs-websocket.h | 19 + 11 files changed, 684 insertions(+), 859 deletions(-) diff --git a/Config.cpp b/Config.cpp index 037658ec..c1649961 100644 --- a/Config.cpp +++ b/Config.cpp @@ -32,6 +32,7 @@ with this program. If not, see #define PARAM_SALT "AuthSalt" #include "Config.h" +#include "Utils.h" Config* Config::_instance = new Config(); @@ -46,24 +47,24 @@ Config::Config() : SettingsLoaded(false) { // OBS Config defaults - config_t* obs_config = obs_frontend_get_global_config(); - if (obs_config) { - config_set_default_bool(obs_config, + config_t* obsConfig = obs_frontend_get_global_config(); + if (obsConfig) { + config_set_default_bool(obsConfig, SECTION_NAME, PARAM_ENABLE, ServerEnabled); - config_set_default_uint(obs_config, + config_set_default_uint(obsConfig, SECTION_NAME, PARAM_PORT, ServerPort); - config_set_default_bool(obs_config, + config_set_default_bool(obsConfig, SECTION_NAME, PARAM_DEBUG, DebugEnabled); - config_set_default_bool(obs_config, + config_set_default_bool(obsConfig, SECTION_NAME, PARAM_ALERT, AlertsEnabled); - config_set_default_bool(obs_config, + config_set_default_bool(obsConfig, SECTION_NAME, PARAM_AUTHREQUIRED, AuthRequired); - config_set_default_string(obs_config, - SECTION_NAME, PARAM_SECRET, Secret); - config_set_default_string(obs_config, - SECTION_NAME, PARAM_SALT, Salt); + config_set_default_string(obsConfig, + SECTION_NAME, PARAM_SECRET, qstring_data_copy(Secret)); + config_set_default_string(obsConfig, + SECTION_NAME, PARAM_SALT, qstring_data_copy(Salt)); } mbedtls_entropy_init(&entropy); @@ -79,110 +80,112 @@ Config::~Config() { } void Config::Load() { - config_t* obs_config = obs_frontend_get_global_config(); + config_t* obsConfig = obs_frontend_get_global_config(); - ServerEnabled = config_get_bool(obs_config, SECTION_NAME, PARAM_ENABLE); - ServerPort = config_get_uint(obs_config, SECTION_NAME, PARAM_PORT); + ServerEnabled = config_get_bool(obsConfig, SECTION_NAME, PARAM_ENABLE); + ServerPort = config_get_uint(obsConfig, SECTION_NAME, PARAM_PORT); - DebugEnabled = config_get_bool(obs_config, SECTION_NAME, PARAM_DEBUG); - AlertsEnabled = config_get_bool(obs_config, SECTION_NAME, PARAM_ALERT); + DebugEnabled = config_get_bool(obsConfig, SECTION_NAME, PARAM_DEBUG); + AlertsEnabled = config_get_bool(obsConfig, SECTION_NAME, PARAM_ALERT); - AuthRequired = config_get_bool(obs_config, SECTION_NAME, PARAM_AUTHREQUIRED); - Secret = config_get_string(obs_config, SECTION_NAME, PARAM_SECRET); - Salt = config_get_string(obs_config, SECTION_NAME, PARAM_SALT); + AuthRequired = config_get_bool(obsConfig, SECTION_NAME, PARAM_AUTHREQUIRED); + Secret = config_get_string(obsConfig, SECTION_NAME, PARAM_SECRET); + Salt = config_get_string(obsConfig, SECTION_NAME, PARAM_SALT); } void Config::Save() { - config_t* obs_config = obs_frontend_get_global_config(); + config_t* obsConfig = obs_frontend_get_global_config(); - config_set_bool(obs_config, SECTION_NAME, PARAM_ENABLE, ServerEnabled); - config_set_uint(obs_config, SECTION_NAME, PARAM_PORT, ServerPort); + config_set_bool(obsConfig, SECTION_NAME, PARAM_ENABLE, ServerEnabled); + config_set_uint(obsConfig, SECTION_NAME, PARAM_PORT, ServerPort); - config_set_bool(obs_config, SECTION_NAME, PARAM_DEBUG, DebugEnabled); - config_set_bool(obs_config, SECTION_NAME, PARAM_ALERT, AlertsEnabled); + config_set_bool(obsConfig, SECTION_NAME, PARAM_DEBUG, DebugEnabled); + config_set_bool(obsConfig, SECTION_NAME, PARAM_ALERT, AlertsEnabled); - config_set_bool(obs_config, SECTION_NAME, PARAM_AUTHREQUIRED, AuthRequired); - config_set_string(obs_config, SECTION_NAME, PARAM_SECRET, Secret); - config_set_string(obs_config, SECTION_NAME, PARAM_SALT, Salt); + config_set_bool(obsConfig, SECTION_NAME, PARAM_AUTHREQUIRED, AuthRequired); + config_set_string(obsConfig, SECTION_NAME, PARAM_SECRET, + qstring_data_copy(Secret)); + config_set_string(obsConfig, SECTION_NAME, PARAM_SALT, + qstring_data_copy(Salt)); - config_save(obs_config); + config_save(obsConfig); } -const char* Config::GenerateSalt() { +QString Config::GenerateSalt() { // Generate 32 random chars - unsigned char* random_chars = (unsigned char*)bzalloc(32); - mbedtls_ctr_drbg_random(&rng, random_chars, 32); + unsigned char* randomChars = (unsigned char*)bzalloc(32); + mbedtls_ctr_drbg_random(&rng, randomChars, 32); // Convert the 32 random chars to a base64 string char* salt = (char*)bzalloc(64); - size_t salt_bytes; + size_t saltBytes; mbedtls_base64_encode( - (unsigned char*)salt, 64, &salt_bytes, - random_chars, 32); + (unsigned char*)salt, 64, &saltBytes, + randomChars, 32); - bfree(random_chars); + bfree(randomChars); return salt; } -const char* Config::GenerateSecret(const char* password, const char* salt) { +QString Config::GenerateSecret(QString password, QString salt) { // Concatenate the password and the salt - std::string passAndSalt = ""; + QString passAndSalt = ""; passAndSalt += password; passAndSalt += salt; // Generate a SHA256 hash of the password unsigned char* challengeHash = (unsigned char*)bzalloc(32); mbedtls_sha256( - (unsigned char*)passAndSalt.c_str(), passAndSalt.length(), + (unsigned char*)passAndSalt.toUtf8().constData(), passAndSalt.length(), challengeHash, 0); // Encode SHA256 hash to Base64 char* challenge = (char*)bzalloc(64); - size_t challenge_bytes = 0; + size_t challengeBytes = 0; mbedtls_base64_encode( - (unsigned char*)challenge, 64, &challenge_bytes, + (unsigned char*)challenge, 64, &challengeBytes, challengeHash, 32); bfree(challengeHash); return challenge; } -void Config::SetPassword(const char* password) { - const char* new_salt = GenerateSalt(); - const char* new_challenge = GenerateSecret(password, new_salt); +void Config::SetPassword(QString password) { + QString newSalt = GenerateSalt(); + QString newChallenge = GenerateSecret(password, newSalt); - this->Salt = new_salt; - this->Secret = new_challenge; + this->Salt = newSalt; + this->Secret = newChallenge; } -bool Config::CheckAuth(const char* response) { +bool Config::CheckAuth(QString response) { // Concatenate auth secret with the challenge sent to the user - std::string challengeAndResponse = ""; - challengeAndResponse += this->Secret; - challengeAndResponse += this->SessionChallenge; + QString challengeAndResponse = ""; + challengeAndResponse += Secret; + challengeAndResponse += SessionChallenge; // Generate a SHA256 hash of challengeAndResponse unsigned char* hash = (unsigned char*)bzalloc(32); mbedtls_sha256( - (unsigned char*)challengeAndResponse.c_str(), + (unsigned char*)challengeAndResponse.toUtf8().constData(), challengeAndResponse.length(), hash, 0); // Encode the SHA256 hash to Base64 - char* expected_response = (char*)bzalloc(64); + char* expectedResponse = (char*)bzalloc(64); size_t base64_size = 0; mbedtls_base64_encode( - (unsigned char*)expected_response, 64, &base64_size, + (unsigned char*)expectedResponse, 64, &base64_size, hash, 32); bool authSuccess = false; - if (strcmp(expected_response, response) == 0) { + if (response == QString(expectedResponse)) { SessionChallenge = GenerateSalt(); authSuccess = true; } bfree(hash); - bfree(expected_response); + bfree(expectedResponse); return authSuccess; } diff --git a/Config.h b/Config.h index 798fecd8..66e4a25d 100644 --- a/Config.h +++ b/Config.h @@ -19,6 +19,8 @@ with this program. If not, see #ifndef CONFIG_H #define CONFIG_H +#include + #include #include @@ -29,11 +31,11 @@ class Config { void Load(); void Save(); - void SetPassword(const char* password); - bool CheckAuth(const char* userChallenge); - const char* GenerateSalt(); - static const char* GenerateSecret( - const char* password, const char* salt); + void SetPassword(QString password); + bool CheckAuth(QString userChallenge); + QString GenerateSalt(); + static QString GenerateSecret( + QString password, QString salt); bool ServerEnabled; uint64_t ServerPort; @@ -42,9 +44,9 @@ class Config { bool AlertsEnabled; bool AuthRequired; - const char* Secret; - const char* Salt; - const char* SessionChallenge; + QString Secret; + QString Salt; + QString SessionChallenge; bool SettingsLoaded; static Config* Current(); diff --git a/Utils.cpp b/Utils.cpp index a0ae68ad..dcf924dc 100644 --- a/Utils.cpp +++ b/Utils.cpp @@ -28,7 +28,14 @@ with this program. If not, see Q_DECLARE_METATYPE(OBSScene); -obs_data_array_t* string_list_to_array(char** strings, char* key) { +const char* qstring_data_copy(QString value) { + QByteArray stringData = value.toUtf8(); + const char* constStringData = new const char[stringData.size()](); + memcpy((void*)constStringData, stringData.constData(), stringData.size()); + return constStringData; +} + +obs_data_array_t* stringListToArray(char** strings, char* key) { if (!strings) return obs_data_array_create(); @@ -38,13 +45,11 @@ obs_data_array_t* string_list_to_array(char** strings, char* key) { for (int i = 0; value != nullptr; i++) { value = strings[i]; - obs_data_t* item = obs_data_create(); + OBSDataAutoRelease item = obs_data_create(); obs_data_set_string(item, key, value); if (value) obs_data_array_push_back(list, item); - - obs_data_release(item); } return list; @@ -52,7 +57,7 @@ obs_data_array_t* string_list_to_array(char** strings, char* key) { obs_data_array_t* Utils::GetSceneItems(obs_source_t* source) { obs_data_array_t* items = obs_data_array_create(); - obs_scene_t* scene = obs_scene_from_source(source); + OBSScene scene = obs_scene_from_source(source); if (!scene) return nullptr; @@ -64,10 +69,8 @@ obs_data_array_t* Utils::GetSceneItems(obs_source_t* source) { { obs_data_array_t* data = static_cast(param); - obs_data_t* item_data = GetSceneItemData(currentItem); - obs_data_array_insert(data, 0, item_data); - - obs_data_release(item_data); + OBSDataAutoRelease itemData = GetSceneItemData(currentItem); + obs_data_array_insert(data, 0, itemData); return true; }, items); @@ -84,9 +87,10 @@ obs_data_t* Utils::GetSceneItemData(obs_sceneitem_t* item) { vec2 scale; obs_sceneitem_get_scale(item, &scale); - obs_source_t* item_source = obs_sceneitem_get_source(item); - float item_width = float(obs_source_get_width(item_source)); - float item_height = float(obs_source_get_height(item_source)); + // obs_sceneitem_get_source doesn't increase the refcount + OBSSource itemSource = obs_sceneitem_get_source(item); + float item_width = float(obs_source_get_width(itemSource)); + float item_height = float(obs_source_get_height(itemSource)); obs_data_t* data = obs_data_create(); obs_data_set_string(data, "name", @@ -106,9 +110,9 @@ obs_data_t* Utils::GetSceneItemData(obs_sceneitem_t* item) { return data; } -obs_sceneitem_t* Utils::GetSceneItemFromName(obs_source_t* source, const char* name) { +obs_sceneitem_t* Utils::GetSceneItemFromName(obs_source_t* source, QString name) { struct current_search { - const char* query; + QString query; obs_sceneitem_t* result; }; @@ -116,8 +120,8 @@ obs_sceneitem_t* Utils::GetSceneItemFromName(obs_source_t* source, const char* n search.query = name; search.result = nullptr; - obs_scene_t* scene = obs_scene_from_source(source); - if (scene == nullptr) + OBSScene scene = obs_scene_from_source(source); + if (!scene) return nullptr; obs_scene_enum_items(scene, []( @@ -127,10 +131,10 @@ obs_sceneitem_t* Utils::GetSceneItemFromName(obs_source_t* source, const char* n { current_search* search = static_cast(param); - const char* currentItemName = + QString currentItemName = obs_source_get_name(obs_sceneitem_get_source(currentItem)); - if (strcmp(currentItemName, search->query) == 0) { + if (currentItemName == search->query) { search->result = currentItem; obs_sceneitem_addref(search->result); return false; @@ -159,36 +163,36 @@ bool Utils::IsValidAlignment(const uint32_t alignment) { return false; } -obs_source_t* Utils::GetTransitionFromName(const char* search_name) { - obs_source_t* found_transition = NULL; +obs_source_t* Utils::GetTransitionFromName(QString searchName) { + obs_source_t* foundTransition = nullptr; obs_frontend_source_list transition_list = {}; obs_frontend_get_transitions(&transition_list); for (size_t i = 0; i < transition_list.sources.num; i++) { obs_source_t* transition = transition_list.sources.array[i]; + QString transitionName = obs_source_get_name(transition); - const char* transition_name = obs_source_get_name(transition); - if (strcmp(transition_name, search_name) == 0) - { - found_transition = transition; - obs_source_addref(found_transition); + if (transitionName == searchName) { + foundTransition = transition; + obs_source_addref(foundTransition); break; } } obs_frontend_source_list_free(&transition_list); - - return found_transition; + return foundTransition; } -obs_source_t* Utils::GetSceneFromNameOrCurrent(const char* scene_name) { +obs_source_t* Utils::GetSceneFromNameOrCurrent(QString sceneName) { + // Both obs_frontend_get_current_scene() and obs_get_source_by_name() + // do addref on the return source, so no need to use an OBSSource helper obs_source_t* scene = nullptr; - if (!scene_name || !strlen(scene_name)) + if (sceneName.isEmpty() || sceneName.isNull()) scene = obs_frontend_get_current_scene(); else - scene = obs_get_source_by_name(scene_name); + scene = obs_get_source_by_name(sceneName.toUtf8()); return scene; } @@ -200,40 +204,35 @@ obs_data_array_t* Utils::GetScenes() { obs_data_array_t* scenes = obs_data_array_create(); for (size_t i = 0; i < sceneList.sources.num; i++) { obs_source_t* scene = sceneList.sources.array[i]; - - obs_data_t* scene_data = GetSceneData(scene); - obs_data_array_push_back(scenes, scene_data); - - obs_data_release(scene_data); + OBSDataAutoRelease sceneData = GetSceneData(scene); + obs_data_array_push_back(scenes, sceneData); } obs_frontend_source_list_free(&sceneList); - return scenes; } -obs_data_t* Utils::GetSceneData(obs_source* source) { - obs_data_array_t* scene_items = GetSceneItems(source); +obs_data_t* Utils::GetSceneData(obs_source_t* source) { + OBSDataArrayAutoRelease sceneItems = GetSceneItems(source); obs_data_t* sceneData = obs_data_create(); obs_data_set_string(sceneData, "name", obs_source_get_name(source)); - obs_data_set_array(sceneData, "sources", scene_items); + obs_data_set_array(sceneData, "sources", sceneItems); - obs_data_array_release(scene_items); return sceneData; } obs_data_array_t* Utils::GetSceneCollections() { - char** scene_collections = obs_frontend_get_scene_collections(); - obs_data_array_t* list = string_list_to_array(scene_collections, "sc-name"); + char** sceneCollections = obs_frontend_get_scene_collections(); + obs_data_array_t* list = stringListToArray(sceneCollections, "sc-name"); - bfree(scene_collections); + bfree(sceneCollections); return list; } obs_data_array_t* Utils::GetProfiles() { char** profiles = obs_frontend_get_profiles(); - obs_data_array_t* list = string_list_to_array(profiles, "profile-name"); + obs_data_array_t* list = stringListToArray(profiles, "profile-name"); bfree(profiles); return list; @@ -258,12 +257,11 @@ void Utils::SetTransitionDuration(int ms) { control->setValue(ms); } -bool Utils::SetTransitionByName(const char* transition_name) { - obs_source_t* transition = GetTransitionFromName(transition_name); +bool Utils::SetTransitionByName(QString transitionName) { + OBSSourceAutoRelease transition = GetTransitionFromName(transitionName); if (transition) { obs_frontend_set_current_transition(transition); - obs_source_release(transition); return true; } else { return false; @@ -284,8 +282,8 @@ obs_scene_t* Utils::SceneListItemToScene(QListWidgetItem* item) { if (!item) return nullptr; - QVariant item_data = item->data(static_cast(Qt::UserRole)); - return item_data.value(); + QVariant itemData = item->data(static_cast(Qt::UserRole)); + return itemData.value(); } QLayout* Utils::GetPreviewLayout() { @@ -357,9 +355,9 @@ QString Utils::FormatIPAddress(QHostAddress &addr) { const char* Utils::GetRecordingFolder() { config_t* profile = obs_frontend_get_profile_config(); - const char* outputMode = config_get_string(profile, "Output", "Mode"); + QString outputMode = config_get_string(profile, "Output", "Mode"); - if (strcmp(outputMode, "Advanced") == 0) { + if (outputMode == "Advanced") { // Advanced mode return config_get_string(profile, "AdvOut", "RecFilePath"); } else { @@ -373,9 +371,9 @@ bool Utils::SetRecordingFolder(const char* path) { return false; config_t* profile = obs_frontend_get_profile_config(); - const char* outputMode = config_get_string(profile, "Output", "Mode"); + QString outputMode = config_get_string(profile, "Output", "Mode"); - if (strcmp(outputMode, "Advanced") == 0) { + if (outputMode == "Advanced") { config_set_string(profile, "AdvOut", "RecFilePath", path); } else { config_set_string(profile, "SimpleOutput", "FilePath", path); @@ -442,9 +440,9 @@ QString Utils::ParseDataToQueryString(obs_data_t* data) { return query; } -obs_hotkey_t* Utils::FindHotkeyByName(const char* name) { +obs_hotkey_t* Utils::FindHotkeyByName(QString name) { struct current_search { - const char* query; + QString query; obs_hotkey_t* result; }; @@ -456,11 +454,11 @@ obs_hotkey_t* Utils::FindHotkeyByName(const char* name) { current_search* search = static_cast(data); const char* hk_name = obs_hotkey_get_name(hotkey); - if (strcmp(hk_name, search->query) == 0) { + if (hk_name == search->query) { search->result = hotkey; - blog(LOG_INFO, "Utils::FindHotkeyByName: found %s", hk_name); return false; } + return true; }, &search); @@ -469,12 +467,12 @@ obs_hotkey_t* Utils::FindHotkeyByName(const char* name) { bool Utils::ReplayBufferEnabled() { config_t* profile = obs_frontend_get_profile_config(); - const char* outputMode = config_get_string(profile, "Output", "Mode"); + QString outputMode = config_get_string(profile, "Output", "Mode"); - if (strcmp(outputMode, "Simple") == 0) { + if (outputMode == "Simple") { return config_get_bool(profile, "SimpleOutput", "RecRB"); } - else if (strcmp(outputMode, "Advanced") == 0) { + else if (outputMode == "Advanced") { return config_get_bool(profile, "AdvOut", "RecRB"); } @@ -511,17 +509,11 @@ void Utils::StartReplayBuffer() { } bool Utils::IsRPHotkeySet() { - obs_output_t* rp_output = obs_frontend_get_replay_buffer_output(); - - obs_data_t *hotkeys = obs_hotkeys_save_output(rp_output); - obs_data_array_t *bindings = obs_data_get_array(hotkeys, + OBSOutputAutoRelease rpOutput = obs_frontend_get_replay_buffer_output(); + OBSDataAutoRelease hotkeys = obs_hotkeys_save_output(rpOutput); + OBSDataArrayAutoRelease bindings = obs_data_get_array(hotkeys, "ReplayBuffer.Save"); size_t count = obs_data_array_count(bindings); - - obs_data_array_release(bindings); - obs_data_release(hotkeys); - obs_output_release(rp_output); - return (count > 0); } diff --git a/Utils.h b/Utils.h index f313e5c8..3eb2759c 100644 --- a/Utils.h +++ b/Utils.h @@ -19,6 +19,8 @@ with this program. If not, see #ifndef UTILS_H #define UTILS_H +#include + #include #include #include @@ -26,23 +28,25 @@ with this program. If not, see #include #include -#include +#include #include #include +const char* qstring_data_copy(QString value); + class Utils { public: static obs_data_array_t* GetSceneItems(obs_source_t* source); - static obs_data_t* GetSceneItemData(obs_scene_item* item); + static obs_data_t* GetSceneItemData(obs_sceneitem_t* item); static obs_sceneitem_t* GetSceneItemFromName( - obs_source_t* source, const char* name); - static obs_source_t* GetTransitionFromName(const char* search_name); - static obs_source_t* GetSceneFromNameOrCurrent(const char* scene_name); + obs_source_t* source, QString name); + static obs_source_t* GetTransitionFromName(QString transitionName); + static obs_source_t* GetSceneFromNameOrCurrent(QString sceneName); static bool IsValidAlignment(const uint32_t alignment); static obs_data_array_t* GetScenes(); - static obs_data_t* GetSceneData(obs_source* source); + static obs_data_t* GetSceneData(obs_source_t* source); static obs_data_array_t* GetSceneCollections(); static obs_data_array_t* GetProfiles(); @@ -51,7 +55,7 @@ class Utils { static int GetTransitionDuration(); static void SetTransitionDuration(int ms); - static bool SetTransitionByName(const char* transition_name); + static bool SetTransitionByName(QString transitionName); static QPushButton* GetPreviewModeButtonControl(); static QLayout* GetPreviewLayout(); @@ -72,8 +76,8 @@ class Utils { static const char* GetRecordingFolder(); static bool SetRecordingFolder(const char* path); - static QString ParseDataToQueryString(obs_data_t * data); - static obs_hotkey_t* FindHotkeyByName(const char* name); + static QString ParseDataToQueryString(obs_data_t* data); + static obs_hotkey_t* FindHotkeyByName(QString name); static bool ReplayBufferEnabled(); static void StartReplayBuffer(); static bool IsRPHotkeySet(); diff --git a/WSEvents.cpp b/WSEvents.cpp index b8c5168d..7a7cf572 100644 --- a/WSEvents.cpp +++ b/WSEvents.cpp @@ -28,42 +28,48 @@ #include "obs-websocket.h" -bool transition_is_cut(obs_source_t* transition) { +bool transitionIsCut(obs_source_t* transition) { if (!transition) return false; if (obs_source_get_type(transition) == OBS_SOURCE_TYPE_TRANSITION - && strcmp(obs_source_get_id(transition), "cut_transition") == 0) { + && QString(obs_source_get_id(transition)) == "cut_transition") { return true; } return false; } -const char* ns_to_timestamp(uint64_t ns) { +const char* nsToTimestamp(uint64_t ns) { uint64_t ms = ns / (1000 * 1000); uint64_t secs = ms / 1000; uint64_t minutes = secs / 60; - uint64_t hours_part = minutes / 60; - uint64_t minutes_part = minutes % 60; - uint64_t secs_part = secs % 60; - uint64_t ms_part = ms % 1000; + uint64_t hoursPart = minutes / 60; + uint64_t minutesPart = minutes % 60; + uint64_t secsPart = secs % 60; + uint64_t msPart = ms % 1000; char* ts = (char*)bmalloc(64); sprintf(ts, "%02d:%02d:%02d.%03d", - hours_part, minutes_part, secs_part, ms_part); + hoursPart, minutesPart, secsPart, msPart); return ts; } +void* calldata_get_ptr(const calldata_t* data, const char* name) { + void* ptr = nullptr; + calldata_get_ptr(data, name, &ptr); + return ptr; +} + WSEvents* WSEvents::Instance = nullptr; WSEvents::WSEvents(WSServer* srv) { _srv = srv; obs_frontend_add_event_callback(WSEvents::FrontendEventHandler, this); - QSpinBox* duration_control = Utils::GetTransitionDurationControl(); - connect(duration_control, SIGNAL(valueChanged(int)), + QSpinBox* durationControl = Utils::GetTransitionDurationControl(); + connect(durationControl, SIGNAL(valueChanged(int)), this, SLOT(TransitionDurationChanged(int))); QTimer* statusTimer = new QTimer(); @@ -78,18 +84,18 @@ WSEvents::WSEvents(WSServer* srv) { connect(sceneList, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), this, SLOT(SelectedSceneChanged(QListWidgetItem*, QListWidgetItem*))); - transition_handler = nullptr; - scene_handler = nullptr; + transitionHandler = nullptr; + sceneHandler = nullptr; QTimer::singleShot(1000, this, SLOT(deferredInitOperations())); - Heartbeat_active = false; + HeartbeatIsActive = false; - _streaming_active = false; - _recording_active = false; + _streamingActive = false; + _recordingActive = false; - _stream_starttime = 0; - _rec_starttime = 0; + _streamStarttime = 0; + _recStarttime = 0; } WSEvents::~WSEvents() { @@ -97,13 +103,11 @@ WSEvents::~WSEvents() { } void WSEvents::deferredInitOperations() { - obs_source_t* transition = obs_frontend_get_current_transition(); + OBSSourceAutoRelease transition = obs_frontend_get_current_transition(); connectTransitionSignals(transition); - obs_source_release(transition); - obs_source_t* scene = obs_frontend_get_current_scene(); + OBSSourceAutoRelease scene = obs_frontend_get_current_scene(); connectSceneSignals(scene); - obs_source_release(scene); } void WSEvents::FrontendEventHandler(enum obs_frontend_event event, void* private_data) { @@ -140,28 +144,28 @@ void WSEvents::FrontendEventHandler(enum obs_frontend_event event, void* private owner->OnStreamStarting(); } else if (event == OBS_FRONTEND_EVENT_STREAMING_STARTED) { - owner->_streaming_active = true; + owner->_streamingActive = true; owner->OnStreamStarted(); } else if (event == OBS_FRONTEND_EVENT_STREAMING_STOPPING) { owner->OnStreamStopping(); } else if (event == OBS_FRONTEND_EVENT_STREAMING_STOPPED) { - owner->_streaming_active = false; + owner->_streamingActive = false; owner->OnStreamStopped(); } else if (event == OBS_FRONTEND_EVENT_RECORDING_STARTING) { owner->OnRecordingStarting(); } else if (event == OBS_FRONTEND_EVENT_RECORDING_STARTED) { - owner->_recording_active = true; + owner->_recordingActive = true; owner->OnRecordingStarted(); } else if (event == OBS_FRONTEND_EVENT_RECORDING_STOPPING) { owner->OnRecordingStopping(); } else if (event == OBS_FRONTEND_EVENT_RECORDING_STOPPED) { - owner->_recording_active = false; + owner->_recordingActive = false; owner->OnRecordingStopped(); } else if (event == OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTING) { @@ -188,93 +192,93 @@ void WSEvents::FrontendEventHandler(enum obs_frontend_event event, void* private } void WSEvents::broadcastUpdate(const char* updateType, - obs_data_t* additionalFields = NULL) { - obs_data_t* update = obs_data_create(); + obs_data_t* additionalFields = nullptr) +{ + OBSDataAutoRelease update = obs_data_create(); obs_data_set_string(update, "update-type", updateType); const char* ts = nullptr; - if (_streaming_active) { - ts = ns_to_timestamp(os_gettime_ns() - _stream_starttime); + if (_streamingActive) { + ts = nsToTimestamp(os_gettime_ns() - _streamStarttime); obs_data_set_string(update, "stream-timecode", ts); bfree((void*)ts); } - if (_recording_active) { - ts = ns_to_timestamp(os_gettime_ns() - _rec_starttime); + if (_recordingActive) { + ts = nsToTimestamp(os_gettime_ns() - _recStarttime); obs_data_set_string(update, "rec-timecode", ts); bfree((void*)ts); } - if (additionalFields != NULL) + if (additionalFields) obs_data_apply(update, additionalFields); - const char *json = obs_data_get_json(update); + QString json = obs_data_get_json(update); _srv->broadcast(json); - if (Config::Current()->DebugEnabled) - blog(LOG_DEBUG, "Update << '%s'", json); - obs_data_release(update); + if (Config::Current()->DebugEnabled) + blog(LOG_DEBUG, "Update << '%s'", json.toUtf8().constData()); } void WSEvents::connectTransitionSignals(obs_source_t* transition) { - if (transition_handler) { - signal_handler_disconnect(transition_handler, + if (transitionHandler) { + signal_handler_disconnect(transitionHandler, "transition_start", OnTransitionBegin, this); } - if (!transition_is_cut(transition)) { - transition_handler = obs_source_get_signal_handler(transition); - signal_handler_connect(transition_handler, + if (!transitionIsCut(transition)) { + transitionHandler = obs_source_get_signal_handler(transition); + signal_handler_connect(transitionHandler, "transition_start", OnTransitionBegin, this); } else { - transition_handler = nullptr; + transitionHandler = nullptr; } } void WSEvents::connectSceneSignals(obs_source_t* scene) { - if (scene_handler) { - signal_handler_disconnect(scene_handler, + if (sceneHandler) { + signal_handler_disconnect(sceneHandler, "reorder", OnSceneReordered, this); - signal_handler_disconnect(scene_handler, + signal_handler_disconnect(sceneHandler, "item_add", OnSceneItemAdd, this); - signal_handler_disconnect(scene_handler, + signal_handler_disconnect(sceneHandler, "item_remove", OnSceneItemDelete, this); - signal_handler_disconnect(scene_handler, + signal_handler_disconnect(sceneHandler, "item_visible", OnSceneItemVisibilityChanged, this); } // TODO : connect to all scenes, not just the current one. - scene_handler = obs_source_get_signal_handler(scene); - signal_handler_connect(scene_handler, + sceneHandler = obs_source_get_signal_handler(scene); + signal_handler_connect(sceneHandler, "reorder", OnSceneReordered, this); - signal_handler_connect(scene_handler, + signal_handler_connect(sceneHandler, "item_add", OnSceneItemAdd, this); - signal_handler_connect(scene_handler, + signal_handler_connect(sceneHandler, "item_remove", OnSceneItemDelete, this); - signal_handler_connect(scene_handler, + signal_handler_connect(sceneHandler, "item_visible", OnSceneItemVisibilityChanged, this); } uint64_t WSEvents::GetStreamingTime() { - if (_streaming_active) - return (os_gettime_ns() - _stream_starttime); + if (_streamingActive) + return (os_gettime_ns() - _streamStarttime); else return 0; } const char* WSEvents::GetStreamingTimecode() { - return ns_to_timestamp(GetStreamingTime()); + return nsToTimestamp(GetStreamingTime()); } uint64_t WSEvents::GetRecordingTime() { - if (_recording_active) - return (os_gettime_ns() - _rec_starttime); + if (_recordingActive) + return (os_gettime_ns() - _recStarttime); else return 0; } const char* WSEvents::GetRecordingTimecode() { - return ns_to_timestamp(GetRecordingTime()); + return nsToTimestamp(GetRecordingTime()); } /** @@ -289,21 +293,16 @@ const char* WSEvents::GetRecordingTimecode() { * @since 0.3 */ void WSEvents::OnSceneChange() { - obs_data_t* data = obs_data_create(); + OBSSourceAutoRelease currentScene = obs_frontend_get_current_scene(); + OBSDataArrayAutoRelease sceneItems = Utils::GetSceneItems(currentScene); + connectSceneSignals(currentScene); - obs_source_t* current_scene = obs_frontend_get_current_scene(); - obs_data_array_t* scene_items = Utils::GetSceneItems(current_scene); - connectSceneSignals(current_scene); - - obs_data_set_string(data, "scene-name", obs_source_get_name(current_scene)); - obs_data_set_array(data, "sources", scene_items); + OBSDataAutoRelease data = obs_data_create(); + obs_data_set_string(data, "scene-name", obs_source_get_name(currentScene)); + obs_data_set_array(data, "sources", sceneItems); broadcastUpdate("SwitchScenes", data); - obs_data_array_release(scene_items); - obs_source_release(current_scene); - obs_data_release(data); - // Dirty fix : OBS blocks signals when swapping scenes in Studio Mode // after transition end, so SelectedSceneChanged is never called... if (obs_frontend_preview_program_mode_active()) { @@ -336,8 +335,8 @@ void WSEvents::OnSceneListChange() { void WSEvents::OnSceneCollectionChange() { broadcastUpdate("SceneCollectionChanged"); - scene_handler = nullptr; - transition_handler = nullptr; + sceneHandler = nullptr; + transitionHandler = nullptr; OnTransitionListChange(); OnTransitionChange(); @@ -369,17 +368,14 @@ void WSEvents::OnSceneCollectionListChange() { * @since 4.0.0 */ void WSEvents::OnTransitionChange() { - obs_source_t* current_transition = obs_frontend_get_current_transition(); - connectTransitionSignals(current_transition); + OBSSourceAutoRelease currentTransition = obs_frontend_get_current_transition(); + connectTransitionSignals(currentTransition); - obs_data_t* data = obs_data_create(); + OBSDataAutoRelease data = obs_data_create(); obs_data_set_string(data, "transition-name", - obs_source_get_name(current_transition)); + obs_source_get_name(currentTransition)); broadcastUpdate("SwitchTransition", data); - - obs_data_release(data); - obs_source_release(current_transition); } /** @@ -430,12 +426,10 @@ void WSEvents::OnProfileListChange() { * @since 0.3 */ void WSEvents::OnStreamStarting() { - obs_data_t* data = obs_data_create(); + OBSDataAutoRelease data = obs_data_create(); obs_data_set_bool(data, "preview-only", false); broadcastUpdate("StreamStarting", data); - - obs_data_release(data); } /** @@ -447,7 +441,7 @@ void WSEvents::OnStreamStarting() { * @since 0.3 */ void WSEvents::OnStreamStarted() { - _stream_starttime = os_gettime_ns(); + _streamStarttime = os_gettime_ns(); _lastBytesSent = 0; broadcastUpdate("StreamStarted"); } @@ -463,12 +457,10 @@ void WSEvents::OnStreamStarted() { * @since 0.3 */ void WSEvents::OnStreamStopping() { - obs_data_t* data = obs_data_create(); + OBSDataAutoRelease data = obs_data_create(); obs_data_set_bool(data, "preview-only", false); broadcastUpdate("StreamStopping", data); - - obs_data_release(data); } /** @@ -480,7 +472,7 @@ void WSEvents::OnStreamStopping() { * @since 0.3 */ void WSEvents::OnStreamStopped() { - _stream_starttime = 0; + _streamStarttime = 0; broadcastUpdate("StreamStopped"); } @@ -505,7 +497,7 @@ void WSEvents::OnRecordingStarting() { * @since 0.3 */ void WSEvents::OnRecordingStarted() { - _rec_starttime = os_gettime_ns(); + _recStarttime = os_gettime_ns(); broadcastUpdate("RecordingStarted"); } @@ -530,7 +522,7 @@ void WSEvents::OnRecordingStopping() { * @since 0.3 */ void WSEvents::OnRecordingStopped() { - _rec_starttime = 0; + _recStarttime = 0; broadcastUpdate("RecordingStopped"); } @@ -614,60 +606,54 @@ void WSEvents::OnExit() { * @since 0.3 */ void WSEvents::StreamStatus() { - bool streaming_active = obs_frontend_streaming_active(); - bool recording_active = obs_frontend_recording_active(); + bool streamingActive = obs_frontend_streaming_active(); + bool recordingActive = obs_frontend_recording_active(); - obs_output_t* stream_output = obs_frontend_get_streaming_output(); + OBSOutputAutoRelease streamOutput = obs_frontend_get_streaming_output(); - if (!stream_output || !streaming_active) { - if (stream_output) { - obs_output_release(stream_output); - } + if (!streamOutput || !streamingActive) { return; } - uint64_t bytes_sent = obs_output_get_total_bytes(stream_output); - uint64_t bytes_sent_time = os_gettime_ns(); + uint64_t bytesSent = obs_output_get_total_bytes(streamOutput); + uint64_t bytesSentTime = os_gettime_ns(); - if (bytes_sent < _lastBytesSent) - bytes_sent = 0; + if (bytesSent < _lastBytesSent) + bytesSent = 0; - if (bytes_sent == 0) + if (bytesSent == 0) _lastBytesSent = 0; - uint64_t bytes_between = bytes_sent - _lastBytesSent; - double time_passed = - double(bytes_sent_time - _lastBytesSentTime) / 1000000000.0; + uint64_t bytesBetween = bytesSent - _lastBytesSent; + double timePassed = + double(bytesSentTime - _lastBytesSentTime) / 1000000000.0; - uint64_t bytes_per_sec = bytes_between / time_passed; + uint64_t bytesPerSec = bytesBetween / timePassed; - _lastBytesSent = bytes_sent; - _lastBytesSentTime = bytes_sent_time; + _lastBytesSent = bytesSent; + _lastBytesSentTime = bytesSentTime; uint64_t totalStreamTime = - (os_gettime_ns() - _stream_starttime) / 1000000000; + (os_gettime_ns() - _streamStarttime) / 1000000000; - int total_frames = obs_output_get_total_frames(stream_output); - int dropped_frames = obs_output_get_frames_dropped(stream_output); + int totalFrames = obs_output_get_total_frames(streamOutput); + int droppedFrames = obs_output_get_frames_dropped(streamOutput); - float strain = obs_output_get_congestion(stream_output); + float strain = obs_output_get_congestion(streamOutput); - obs_data_t* data = obs_data_create(); - obs_data_set_bool(data, "streaming", streaming_active); - obs_data_set_bool(data, "recording", recording_active); - obs_data_set_int(data, "bytes-per-sec", bytes_per_sec); - obs_data_set_int(data, "kbits-per-sec", (bytes_per_sec * 8) / 1024); + OBSDataAutoRelease data = obs_data_create(); + obs_data_set_bool(data, "streaming", streamingActive); + obs_data_set_bool(data, "recording", recordingActive); + obs_data_set_int(data, "bytes-per-sec", bytesPerSec); + obs_data_set_int(data, "kbits-per-sec", (bytesPerSec * 8) / 1024); obs_data_set_int(data, "total-stream-time", totalStreamTime); - obs_data_set_int(data, "num-total-frames", total_frames); - obs_data_set_int(data, "num-dropped-frames", dropped_frames); + obs_data_set_int(data, "num-total-frames", totalFrames); + obs_data_set_int(data, "num-dropped-frames", droppedFrames); obs_data_set_double(data, "fps", obs_get_active_fps()); obs_data_set_double(data, "strain", strain); obs_data_set_bool(data, "preview-only", false); // Retrocompat with OBSRemote broadcastUpdate("StreamStatus", data); - - obs_data_release(data); - obs_output_release(stream_output); } /** @@ -691,44 +677,40 @@ void WSEvents::StreamStatus() { */ void WSEvents::Heartbeat() { - if (!Heartbeat_active) return; + if (!HeartbeatIsActive) return; - bool streaming_active = obs_frontend_streaming_active(); - bool recording_active = obs_frontend_recording_active(); - obs_data_t* data = obs_data_create(); - obs_output_t* record_output = obs_frontend_get_recording_output(); - obs_output_t* stream_output = obs_frontend_get_streaming_output(); + bool streamingActive = obs_frontend_streaming_active(); + bool recordingActive = obs_frontend_recording_active(); + + OBSDataAutoRelease data = obs_data_create(); + OBSOutputAutoRelease recordOutput = obs_frontend_get_recording_output(); + OBSOutputAutoRelease streamOutput = obs_frontend_get_streaming_output(); pulse = !pulse; obs_data_set_bool(data, "pulse", pulse); obs_data_set_string(data, "current-profile", obs_frontend_get_current_profile()); - obs_source_t* current_scene = obs_frontend_get_current_scene(); - const char* name = obs_source_get_name(current_scene); - obs_source_release(current_scene); - obs_data_set_string(data, "current-scene", name); + OBSSourceAutoRelease currentScene = obs_frontend_get_current_scene(); + obs_data_set_string(data, "current-scene", obs_source_get_name(currentScene)); - obs_data_set_bool(data, "streaming", streaming_active); - if (streaming_active) { - uint64_t totalStreamTime = (os_gettime_ns() - _stream_starttime) / 1000000000; + obs_data_set_bool(data, "streaming", streamingActive); + if (streamingActive) { + uint64_t totalStreamTime = (os_gettime_ns() - _streamStarttime) / 1000000000; obs_data_set_int(data, "total-stream-time", totalStreamTime); - obs_data_set_int(data, "total-stream-bytes", (uint64_t)obs_output_get_total_bytes(stream_output)); - obs_data_set_int(data, "total-stream-frames", obs_output_get_total_frames(stream_output)); + obs_data_set_int(data, "total-stream-bytes", (uint64_t)obs_output_get_total_bytes(streamOutput)); + obs_data_set_int(data, "total-stream-frames", obs_output_get_total_frames(streamOutput)); } - obs_data_set_bool(data, "recording", recording_active); - if (recording_active) { - uint64_t totalRecordTime = (os_gettime_ns() - _rec_starttime) / 1000000000; + obs_data_set_bool(data, "recording", recordingActive); + if (recordingActive) { + uint64_t totalRecordTime = (os_gettime_ns() - _recStarttime) / 1000000000; obs_data_set_int(data, "total-record-time", totalRecordTime); - obs_data_set_int(data, "total-record-bytes", (uint64_t)obs_output_get_total_bytes(record_output)); - obs_data_set_int(data, "total-record-frames", obs_output_get_total_frames(record_output)); + obs_data_set_int(data, "total-record-bytes", (uint64_t)obs_output_get_total_bytes(recordOutput)); + obs_data_set_int(data, "total-record-frames", obs_output_get_total_frames(recordOutput)); } broadcastUpdate("Heartbeat", data); - obs_data_release(data); - obs_output_release(record_output); - obs_output_release(stream_output); } /** @@ -742,11 +724,10 @@ void WSEvents::Heartbeat() { * @since 4.0.0 */ void WSEvents::TransitionDurationChanged(int ms) { - obs_data_t* fields = obs_data_create(); + OBSDataAutoRelease fields = obs_data_create(); obs_data_set_int(fields, "new-duration", ms); broadcastUpdate("TransitionDurationChanged", fields); - obs_data_release(fields); } /** @@ -764,17 +745,13 @@ void WSEvents::OnTransitionBegin(void* param, calldata_t* data) { UNUSED_PARAMETER(data); WSEvents* instance = static_cast(param); - obs_source_t* current_transition = obs_frontend_get_current_transition(); - const char* name = obs_source_get_name(current_transition); - int duration = Utils::GetTransitionDuration(); + OBSSourceAutoRelease currentTransition = obs_frontend_get_current_transition(); - obs_data_t* fields = obs_data_create(); - obs_data_set_string(fields, "name", name); - obs_data_set_int(fields, "duration", duration); + OBSDataAutoRelease fields = obs_data_create(); + obs_data_set_string(fields, "name", obs_source_get_name(currentTransition)); + obs_data_set_int(fields, "duration", Utils::GetTransitionDuration()); instance->broadcastUpdate("TransitionBegin", fields); - obs_data_release(fields); - obs_source_release(current_transition); } /** @@ -793,12 +770,11 @@ void WSEvents::OnSceneReordered(void* param, calldata_t* data) { obs_scene_t* scene = nullptr; calldata_get_ptr(data, "scene", &scene); - obs_data_t* fields = obs_data_create(); + OBSDataAutoRelease fields = obs_data_create(); obs_data_set_string(fields, "scene-name", obs_source_get_name(obs_scene_get_source(scene))); instance->broadcastUpdate("SourceOrderChanged", fields); - obs_data_release(fields); } /** @@ -818,20 +794,19 @@ void WSEvents::OnSceneItemAdd(void* param, calldata_t* data) { obs_scene_t* scene = nullptr; calldata_get_ptr(data, "scene", &scene); - obs_sceneitem_t* scene_item = nullptr; - calldata_get_ptr(data, "item", &scene_item); + obs_sceneitem_t* sceneItem = nullptr; + calldata_get_ptr(data, "item", &sceneItem); - const char* scene_name = + const char* sceneName = obs_source_get_name(obs_scene_get_source(scene)); - const char* sceneitem_name = - obs_source_get_name(obs_sceneitem_get_source(scene_item)); + const char* sceneItemName = + obs_source_get_name(obs_sceneitem_get_source(sceneItem)); - obs_data_t* fields = obs_data_create(); - obs_data_set_string(fields, "scene-name", scene_name); - obs_data_set_string(fields, "item-name", sceneitem_name); + OBSDataAutoRelease fields = obs_data_create(); + obs_data_set_string(fields, "scene-name", sceneName); + obs_data_set_string(fields, "item-name", sceneItemName); instance->broadcastUpdate("SceneItemAdded", fields); - obs_data_release(fields); } /** @@ -851,20 +826,19 @@ void WSEvents::OnSceneItemDelete(void* param, calldata_t* data) { obs_scene_t* scene = nullptr; calldata_get_ptr(data, "scene", &scene); - obs_sceneitem_t* scene_item = nullptr; - calldata_get_ptr(data, "item", &scene_item); + obs_sceneitem_t* sceneItem = nullptr; + calldata_get_ptr(data, "item", &sceneItem); - const char* scene_name = + const char* sceneName = obs_source_get_name(obs_scene_get_source(scene)); - const char* sceneitem_name = - obs_source_get_name(obs_sceneitem_get_source(scene_item)); + const char* sceneItemName = + obs_source_get_name(obs_sceneitem_get_source(sceneItem)); - obs_data_t* fields = obs_data_create(); - obs_data_set_string(fields, "scene-name", scene_name); - obs_data_set_string(fields, "item-name", sceneitem_name); + OBSDataAutoRelease fields = obs_data_create(); + obs_data_set_string(fields, "scene-name", sceneName); + obs_data_set_string(fields, "item-name", sceneItemName); instance->broadcastUpdate("SceneItemRemoved", fields); - obs_data_release(fields); } /** @@ -885,24 +859,23 @@ void WSEvents::OnSceneItemVisibilityChanged(void* param, calldata_t* data) { obs_scene_t* scene = nullptr; calldata_get_ptr(data, "scene", &scene); - obs_sceneitem_t* scene_item = nullptr; - calldata_get_ptr(data, "item", &scene_item); + obs_sceneitem_t* sceneItem = nullptr; + calldata_get_ptr(data, "item", &sceneItem); bool visible = false; calldata_get_bool(data, "visible", &visible); - const char* scene_name = + const char* sceneName = obs_source_get_name(obs_scene_get_source(scene)); - const char* sceneitem_name = - obs_source_get_name(obs_sceneitem_get_source(scene_item)); + const char* sceneItemName = + obs_source_get_name(obs_sceneitem_get_source(sceneItem)); - obs_data_t* fields = obs_data_create(); - obs_data_set_string(fields, "scene-name", scene_name); - obs_data_set_string(fields, "item-name", sceneitem_name); + OBSDataAutoRelease fields = obs_data_create(); + obs_data_set_string(fields, "scene-name", sceneName); + obs_data_set_string(fields, "item-name", sceneItemName); obs_data_set_bool(fields, "item-visible", visible); instance->broadcastUpdate("SceneItemVisibilityChanged", fields); - obs_data_release(fields); } /** @@ -918,20 +891,18 @@ void WSEvents::OnSceneItemVisibilityChanged(void* param, calldata_t* data) { */ void WSEvents::SelectedSceneChanged(QListWidgetItem* current, QListWidgetItem* prev) { if (obs_frontend_preview_program_mode_active()) { - obs_scene_t* scene = Utils::SceneListItemToScene(current); - if (!scene) return; + OBSScene scene = Utils::SceneListItemToScene(current); + if (!scene) + return; - obs_source_t* scene_source = obs_scene_get_source(scene); - obs_data_array_t* scene_items = Utils::GetSceneItems(scene_source); + OBSSource sceneSource = obs_scene_get_source(scene); + OBSDataArrayAutoRelease sceneItems = Utils::GetSceneItems(sceneSource); - obs_data_t* data = obs_data_create(); - obs_data_set_string(data, "scene-name", obs_source_get_name(scene_source)); - obs_data_set_array(data, "sources", scene_items); + OBSDataAutoRelease data = obs_data_create(); + obs_data_set_string(data, "scene-name", obs_source_get_name(sceneSource)); + obs_data_set_array(data, "sources", sceneItems); broadcastUpdate("PreviewSceneChanged", data); - - obs_data_array_release(scene_items); - obs_data_release(data); } } @@ -946,9 +917,8 @@ void WSEvents::SelectedSceneChanged(QListWidgetItem* current, QListWidgetItem* p * @since 4.1.0 */ void WSEvents::OnStudioModeSwitched(bool checked) { - obs_data_t* data = obs_data_create(); + OBSDataAutoRelease data = obs_data_create(); obs_data_set_bool(data, "new-state", checked); broadcastUpdate("StudioModeSwitched", data); - obs_data_release(data); } diff --git a/WSEvents.h b/WSEvents.h index 6a0458b3..cb46817d 100644 --- a/WSEvents.h +++ b/WSEvents.h @@ -20,6 +20,7 @@ with this program. If not, see #ifndef WSEVENTS_H #define WSEVENTS_H +#include #include #include #include "WSServer.h" @@ -30,7 +31,7 @@ class WSEvents : public QObject { explicit WSEvents(WSServer* srv); ~WSEvents(); static void FrontendEventHandler( - enum obs_frontend_event event, void* private_data); + enum obs_frontend_event event, void* privateData); static WSEvents* Instance; void connectTransitionSignals(obs_source_t* transition); void connectSceneSignals(obs_source_t* scene); @@ -40,7 +41,7 @@ class WSEvents : public QObject { uint64_t GetRecordingTime(); const char* GetRecordingTimecode(); - bool Heartbeat_active; + bool HeartbeatIsActive; private slots: void deferredInitOperations(); @@ -52,16 +53,16 @@ class WSEvents : public QObject { private: WSServer* _srv; - signal_handler_t* transition_handler; - signal_handler_t* scene_handler; + signal_handler_t* transitionHandler; + signal_handler_t* sceneHandler; bool pulse; - bool _streaming_active; - bool _recording_active; + bool _streamingActive; + bool _recordingActive; - uint64_t _stream_starttime; - uint64_t _rec_starttime; + uint64_t _streamStarttime; + uint64_t _recStarttime; uint64_t _lastBytesSent; uint64_t _lastBytesSentTime; diff --git a/WSRequestHandler.cpp b/WSRequestHandler.cpp index 79db3b37..1bf2042e 100644 --- a/WSRequestHandler.cpp +++ b/WSRequestHandler.cpp @@ -24,7 +24,6 @@ #include #include "WSEvents.h" -#include "obs-websocket.h" #include "Config.h" #include "Utils.h" @@ -32,10 +31,6 @@ #define STREAM_SERVICE_ID "websocket_custom_service" -bool str_valid(const char* str) { - return (str != nullptr && strlen(str) > 0); -} - QHash WSRequestHandler::messageMap { { "GetVersion", WSRequestHandler::HandleGetVersion }, { "GetAuthRequired", WSRequestHandler::HandleGetAuthRequired }, @@ -133,7 +128,7 @@ WSRequestHandler::WSRequestHandler(QWebSocket* client) : void WSRequestHandler::processIncomingMessage(QString textMessage) { QByteArray msgData = textMessage.toUtf8(); - const char* msg = msgData; + const char* msg = msgData.constData(); data = obs_data_create_from_json(msg); if (!data) { @@ -149,8 +144,9 @@ void WSRequestHandler::processIncomingMessage(QString textMessage) { blog(LOG_DEBUG, "Request >> '%s'", msg); } - if (!hasField("request-type") || - !hasField("message-id")) { + if (!hasField("request-type") + || !hasField("message-id")) + { SendErrorResponse("missing request parameters"); return; } @@ -160,26 +156,25 @@ void WSRequestHandler::processIncomingMessage(QString textMessage) { if (Config::Current()->AuthRequired && (_client->property(PROP_AUTHENTICATED).toBool() == false) - && (authNotRequired.find(_requestType) == authNotRequired.end())) { + && (authNotRequired.find(_requestType) == authNotRequired.end())) + { SendErrorResponse("Not Authenticated"); return; } void (*handlerFunc)(WSRequestHandler*) = (messageMap[_requestType]); - if (handlerFunc != NULL) + if (handlerFunc != nullptr) handlerFunc(this); else SendErrorResponse("invalid request type"); - - obs_data_release(data); } WSRequestHandler::~WSRequestHandler() { } void WSRequestHandler::SendOKResponse(obs_data_t* additionalFields) { - obs_data_t* response = obs_data_create(); + OBSDataAutoRelease response = obs_data_create(); obs_data_set_string(response, "status", "ok"); obs_data_set_string(response, "message-id", _messageId); @@ -190,7 +185,7 @@ void WSRequestHandler::SendOKResponse(obs_data_t* additionalFields) { } void WSRequestHandler::SendErrorResponse(const char* errorMessage) { - obs_data_t* response = obs_data_create(); + OBSDataAutoRelease response = obs_data_create(); obs_data_set_string(response, "status", "error"); obs_data_set_string(response, "error", errorMessage); obs_data_set_string(response, "message-id", _messageId); @@ -199,7 +194,7 @@ void WSRequestHandler::SendErrorResponse(const char* errorMessage) { } void WSRequestHandler::SendErrorResponse(obs_data_t* additionalFields) { - obs_data_t* response = obs_data_create(); + OBSDataAutoRelease response = obs_data_create(); obs_data_set_string(response, "status", "error"); obs_data_set_string(response, "message-id", _messageId); @@ -210,19 +205,18 @@ void WSRequestHandler::SendErrorResponse(obs_data_t* additionalFields) { } void WSRequestHandler::SendResponse(obs_data_t* response) { - const char *json = obs_data_get_json(response); + QString json = obs_data_get_json(response); _client->sendTextMessage(json); - if (Config::Current()->DebugEnabled) - blog(LOG_DEBUG, "Response << '%s'", json); - obs_data_release(response); + if (Config::Current()->DebugEnabled) + blog(LOG_DEBUG, "Response << '%s'", json.toUtf8().constData()); } -bool WSRequestHandler::hasField(const char* name) { - if (!name || !data) +bool WSRequestHandler::hasField(QString name) { + if (!data || name.isEmpty() || name.isNull()) return false; - return obs_data_has_user_value(data, name); + return obs_data_has_user_value(data, name.toUtf8()); } /** @@ -239,25 +233,24 @@ bool WSRequestHandler::hasField(const char* name) { * @since 0.3 */ void WSRequestHandler::HandleGetVersion(WSRequestHandler* req) { - const char* obs_version = Utils::OBSVersionString(); + QString obsVersion = Utils::OBSVersionString(); - // (Palakis) OBS' data arrays only support object arrays, so I improvised. QList names = req->messageMap.keys(); names.sort(Qt::CaseInsensitive); + + // (Palakis) OBS' data arrays only support object arrays, so I improvised. QString requests; requests += names.takeFirst(); for (QString reqName : names) { requests += ("," + reqName); } - obs_data_t* data = obs_data_create(); + OBSDataAutoRelease data = obs_data_create(); obs_data_set_string(data, "obs-websocket-version", OBS_WEBSOCKET_VERSION); - obs_data_set_string(data, "obs-studio-version", obs_version); - obs_data_set_string(data, "available-requests", requests.toUtf8().constData()); + obs_data_set_string(data, "obs-studio-version", obsVersion.toUtf8()); + obs_data_set_string(data, "available-requests", requests.toUtf8()); req->SendOKResponse(data); - obs_data_release(data); - bfree((void*)obs_version); } /** @@ -276,19 +269,17 @@ void WSRequestHandler::HandleGetVersion(WSRequestHandler* req) { void WSRequestHandler::HandleGetAuthRequired(WSRequestHandler* req) { bool authRequired = Config::Current()->AuthRequired; - obs_data_t* data = obs_data_create(); + OBSDataAutoRelease data = obs_data_create(); obs_data_set_bool(data, "authRequired", authRequired); if (authRequired) { obs_data_set_string(data, "challenge", - Config::Current()->SessionChallenge); + Config::Current()->SessionChallenge.toUtf8()); obs_data_set_string(data, "salt", - Config::Current()->Salt); + Config::Current()->Salt.toUtf8()); } req->SendOKResponse(data); - - obs_data_release(data); } /** @@ -307,14 +298,15 @@ void WSRequestHandler::HandleAuthenticate(WSRequestHandler* req) { return; } - const char* auth = obs_data_get_string(req->data, "auth"); - if (!str_valid(auth)) { + QString auth = obs_data_get_string(req->data, "auth"); + if (auth.isEmpty()) { req->SendErrorResponse("auth not specified!"); return; } if ((req->_client->property(PROP_AUTHENTICATED).toBool() == false) - && Config::Current()->CheckAuth(auth)) { + && Config::Current()->CheckAuth(auth)) + { req->_client->setProperty(PROP_AUTHENTICATED, true); req->SendOKResponse(); } else { @@ -337,15 +329,13 @@ void WSRequestHandler::HandleSetHeartbeat(WSRequestHandler* req) { return; } - WSEvents::Instance->Heartbeat_active = + WSEvents::Instance->HeartbeatIsActive = obs_data_get_bool(req->data, "enable"); - obs_data_t* response = obs_data_create(); + OBSDataAutoRelease response = obs_data_create(); obs_data_set_bool(response, "enable", - WSEvents::Instance->Heartbeat_active); + WSEvents::Instance->HeartbeatIsActive); req->SendOKResponse(response); - - obs_data_release(response); } /** @@ -365,7 +355,7 @@ void WSRequestHandler::HandleSetCurrentScene(WSRequestHandler* req) { } const char* sceneName = obs_data_get_string(req->data, "scene-name"); - obs_source_t* source = obs_get_source_by_name(sceneName); + OBSSourceAutoRelease source = obs_get_source_by_name(sceneName); if (source) { obs_frontend_set_current_scene(source); @@ -373,8 +363,6 @@ void WSRequestHandler::HandleSetCurrentScene(WSRequestHandler* req) { } else { req->SendErrorResponse("requested scene does not exist"); } - - obs_source_release(source); } /** @@ -389,20 +377,14 @@ void WSRequestHandler::HandleSetCurrentScene(WSRequestHandler* req) { * @since 0.3 */ void WSRequestHandler::HandleGetCurrentScene(WSRequestHandler* req) { - obs_source_t* current_scene = obs_frontend_get_current_scene(); - const char* name = obs_source_get_name(current_scene); + OBSSourceAutoRelease currentScene = obs_frontend_get_current_scene(); + OBSDataArrayAutoRelease sceneItems = Utils::GetSceneItems(currentScene); - obs_data_array_t* scene_items = Utils::GetSceneItems(current_scene); - - obs_data_t* data = obs_data_create(); - obs_data_set_string(data, "name", name); - obs_data_set_array(data, "sources", scene_items); + OBSDataAutoRelease data = obs_data_create(); + obs_data_set_string(data, "name", obs_source_get_name(currentScene)); + obs_data_set_array(data, "sources", sceneItems); req->SendOKResponse(data); - - obs_data_release(data); - obs_data_array_release(scene_items); - obs_source_release(current_scene); } /** @@ -417,19 +399,15 @@ void WSRequestHandler::HandleGetCurrentScene(WSRequestHandler* req) { * @since 0.3 */ void WSRequestHandler::HandleGetSceneList(WSRequestHandler* req) { - obs_source_t* current_scene = obs_frontend_get_current_scene(); - obs_data_array_t* scenes = Utils::GetScenes(); + OBSSourceAutoRelease currentScene = obs_frontend_get_current_scene(); + OBSDataArrayAutoRelease scenes = Utils::GetScenes(); - obs_data_t* data = obs_data_create(); + OBSDataAutoRelease data = obs_data_create(); obs_data_set_string(data, "current-scene", - obs_source_get_name(current_scene)); + obs_source_get_name(currentScene)); obs_data_set_array(data, "scenes", scenes); req->SendOKResponse(data); - - obs_data_release(data); - obs_data_array_release(scenes); - obs_source_release(current_scene); } /** @@ -447,7 +425,8 @@ void WSRequestHandler::HandleGetSceneList(WSRequestHandler* req) { */ void WSRequestHandler::HandleSetSceneItemRender(WSRequestHandler* req) { if (!req->hasField("source") || - !req->hasField("render")) { + !req->hasField("render")) + { req->SendErrorResponse("missing request parameters"); return; } @@ -461,22 +440,20 @@ void WSRequestHandler::HandleSetSceneItemRender(WSRequestHandler* req) { } const char* sceneName = obs_data_get_string(req->data, "scene-name"); - obs_source_t* scene = Utils::GetSceneFromNameOrCurrent(sceneName); + OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName); if (!scene) { req->SendErrorResponse("requested scene doesn't exist"); return; } - obs_sceneitem_t* sceneItem = Utils::GetSceneItemFromName(scene, itemName); + OBSSceneItemAutoRelease sceneItem = + Utils::GetSceneItemFromName(scene, itemName); if (sceneItem) { obs_sceneitem_set_visible(sceneItem, isVisible); - obs_sceneitem_release(sceneItem); req->SendOKResponse(); } else { req->SendErrorResponse("specified scene item doesn't exist"); } - - obs_source_release(scene); } /** @@ -494,7 +471,7 @@ void WSRequestHandler::HandleSetSceneItemRender(WSRequestHandler* req) { * @since 0.3 */ void WSRequestHandler::HandleGetStreamingStatus(WSRequestHandler* req) { - obs_data_t* data = obs_data_create(); + OBSDataAutoRelease data = obs_data_create(); obs_data_set_bool(data, "streaming", obs_frontend_streaming_active()); obs_data_set_bool(data, "recording", obs_frontend_recording_active()); obs_data_set_bool(data, "preview-only", false); @@ -513,7 +490,6 @@ void WSRequestHandler::HandleGetStreamingStatus(WSRequestHandler* req) { } req->SendOKResponse(data); - obs_data_release(data); } /** @@ -539,8 +515,7 @@ void WSRequestHandler::HandleStartStopStreaming(WSRequestHandler* req) { * @category recording * @since 0.3 */ -void WSRequestHandler::HandleStartStopRecording(WSRequestHandler* req) -{ +void WSRequestHandler::HandleStartStopRecording(WSRequestHandler* req) { if (obs_frontend_recording_active()) obs_frontend_recording_stop(); else @@ -568,21 +543,17 @@ void WSRequestHandler::HandleStartStopRecording(WSRequestHandler* req) * @category streaming * @since 4.1.0 */ -void WSRequestHandler::HandleStartStreaming(WSRequestHandler* req) -{ +void WSRequestHandler::HandleStartStreaming(WSRequestHandler* req) { if (obs_frontend_streaming_active() == false) { - obs_service_t* configuredService = obs_frontend_get_streaming_service(); - // get_streaming_service doesn't addref, so let's do it ourselves - obs_service_addref(configuredService); - - obs_service_t* newService = nullptr; + OBSService configuredService = obs_frontend_get_streaming_service(); + OBSService newService = nullptr; if (req->hasField("stream")) { - obs_data_t* streamData = obs_data_get_obj(req->data, "stream"); - obs_data_t* newSettings = obs_data_get_obj(streamData, "settings"); - obs_data_t* newMetadata = obs_data_get_obj(streamData, "metadata"); + OBSDataAutoRelease streamData = obs_data_get_obj(req->data, "stream"); + OBSDataAutoRelease newSettings = obs_data_get_obj(streamData, "settings"); + OBSDataAutoRelease newMetadata = obs_data_get_obj(streamData, "metadata"); - obs_data_t* csHotkeys = + OBSDataAutoRelease csHotkeys = obs_hotkeys_save_service(configuredService); QString currentType = obs_service_get_type(configuredService); @@ -618,14 +589,14 @@ void WSRequestHandler::HandleStartStreaming(WSRequestHandler* req) } if (newType == currentType) { - // Service type doesn't change: merge settings to current (previous) service. + // Service type doesn't change: apply settings to current service // By doing this, you can send a request to the websocket // that only contains settings you want to change, instead of // having to do a get and then change them - obs_data_t* currentSettings = obs_service_get_settings(configuredService); - obs_data_t* updatedSettings = obs_data_create(); + OBSDataAutoRelease currentSettings = obs_service_get_settings(configuredService); + OBSDataAutoRelease updatedSettings = obs_data_create(); obs_data_apply(updatedSettings, currentSettings); //first apply the existing settings obs_data_apply(updatedSettings, newSettings); //then apply the settings from the request should they exist @@ -633,9 +604,6 @@ void WSRequestHandler::HandleStartStreaming(WSRequestHandler* req) newService = obs_service_create( newType.toUtf8(), STREAM_SERVICE_ID, updatedSettings, csHotkeys); - - obs_data_release(updatedSettings); - obs_data_release(currentSettings); } else { // Service type changed: override service settings @@ -645,11 +613,6 @@ void WSRequestHandler::HandleStartStreaming(WSRequestHandler* req) } obs_frontend_set_streaming_service(newService); - - obs_data_release(csHotkeys); - obs_data_release(newMetadata); - obs_data_release(newSettings); - obs_data_release(streamData); } obs_frontend_streaming_start(); @@ -660,11 +623,6 @@ void WSRequestHandler::HandleStartStreaming(WSRequestHandler* req) } req->SendOKResponse(); - - obs_service_release(configuredService); - - // No need to release newService: it would destroy it immediately, because - // obs_service_create inits the instance's refcount to 0 } else { req->SendErrorResponse("streaming already active"); } @@ -802,15 +760,14 @@ void WSRequestHandler::HandleSaveReplayBuffer(WSRequestHandler* req) { return; } - calldata_t cd = {0}; - obs_output_t* replay_output = obs_frontend_get_replay_buffer_output(); - proc_handler_t* ph = obs_output_get_proc_handler(replay_output); + OBSOutputAutoRelease replayOutput = obs_frontend_get_replay_buffer_output(); + + calldata_t cd = { 0 }; + proc_handler_t* ph = obs_output_get_proc_handler(replayOutput); proc_handler_call(ph, "save", &cd); + calldata_free(&cd); req->SendOKResponse(); - - calldata_free(&cd); - obs_output_release(replay_output); } /** @@ -826,32 +783,26 @@ void WSRequestHandler::HandleSaveReplayBuffer(WSRequestHandler* req) { * @since 4.1.0 */ void WSRequestHandler::HandleGetTransitionList(WSRequestHandler* req) { - obs_source_t* current_transition = obs_frontend_get_current_transition(); + OBSSourceAutoRelease currentTransition = obs_frontend_get_current_transition(); obs_frontend_source_list transitionList = {}; obs_frontend_get_transitions(&transitionList); - obs_data_array_t* transitions = obs_data_array_create(); + OBSDataArrayAutoRelease transitions = obs_data_array_create(); for (size_t i = 0; i < transitionList.sources.num; i++) { - obs_source_t* transition = transitionList.sources.array[i]; + OBSSource transition = transitionList.sources.array[i]; - obs_data_t* obj = obs_data_create(); + OBSDataAutoRelease obj = obs_data_create(); obs_data_set_string(obj, "name", obs_source_get_name(transition)); - obs_data_array_push_back(transitions, obj); - obs_data_release(obj); } obs_frontend_source_list_free(&transitionList); - obs_data_t* response = obs_data_create(); + OBSDataAutoRelease response = obs_data_create(); obs_data_set_string(response, "current-transition", - obs_source_get_name(current_transition)); + obs_source_get_name(currentTransition)); obs_data_set_array(response, "transitions", transitions); req->SendOKResponse(response); - - obs_data_release(response); - obs_data_array_release(transitions); - obs_source_release(current_transition); } /** @@ -866,19 +817,16 @@ void WSRequestHandler::HandleGetTransitionList(WSRequestHandler* req) { * @since 0.3 */ void WSRequestHandler::HandleGetCurrentTransition(WSRequestHandler* req) { - obs_source_t* current_transition = obs_frontend_get_current_transition(); + OBSSourceAutoRelease currentTransition = obs_frontend_get_current_transition(); - obs_data_t* response = obs_data_create(); + OBSDataAutoRelease response = obs_data_create(); obs_data_set_string(response, "name", - obs_source_get_name(current_transition)); + obs_source_get_name(currentTransition)); - if (!obs_transition_fixed(current_transition)) + if (!obs_transition_fixed(currentTransition)) obs_data_set_int(response, "duration", Utils::GetTransitionDuration()); req->SendOKResponse(response); - - obs_data_release(response); - obs_source_release(current_transition); } /** @@ -897,7 +845,7 @@ void WSRequestHandler::HandleSetCurrentTransition(WSRequestHandler* req) { return; } - const char* name = obs_data_get_string(req->data, "transition-name"); + QString name = obs_data_get_string(req->data, "transition-name"); bool success = Utils::SetTransitionByName(name); if (success) req->SendOKResponse(); @@ -937,12 +885,11 @@ void WSRequestHandler::HandleSetTransitionDuration(WSRequestHandler* req) { * @since 4.1.0 */ void WSRequestHandler::HandleGetTransitionDuration(WSRequestHandler* req) { - obs_data_t* response = obs_data_create(); + OBSDataAutoRelease response = obs_data_create(); obs_data_set_int(response, "transition-duration", Utils::GetTransitionDuration()); req->SendOKResponse(response); - obs_data_release(response); } /** @@ -958,30 +905,29 @@ void WSRequestHandler::HandleGetTransitionDuration(WSRequestHandler* req) { */ void WSRequestHandler::HandleSetVolume(WSRequestHandler* req) { if (!req->hasField("source") || - !req->hasField("volume")) { + !req->hasField("volume")) + { req->SendErrorResponse("missing request parameters"); return; } - const char* source_name = obs_data_get_string(req->data, "source"); - float source_volume = obs_data_get_double(req->data, "volume"); + QString sourceName = obs_data_get_string(req->data, "source"); + float sourceVolume = obs_data_get_double(req->data, "volume"); - if (source_name == NULL || strlen(source_name) < 1 || - source_volume < 0.0 || source_volume > 1.0) { + if (sourceName.isEmpty() || + sourceVolume < 0.0 || sourceVolume > 1.0) { req->SendErrorResponse("invalid request parameters"); return; } - obs_source_t* source = obs_get_source_by_name(source_name); + OBSSourceAutoRelease source = obs_get_source_by_name(sourceName.toUtf8()); if (!source) { req->SendErrorResponse("specified source doesn't exist"); return; } - obs_source_set_volume(source, source_volume); + obs_source_set_volume(source, sourceVolume); req->SendOKResponse(); - - obs_source_release(source); } /** @@ -1004,19 +950,16 @@ void WSRequestHandler::HandleGetVolume(WSRequestHandler* req) { return; } - const char* source_name = obs_data_get_string(req->data, "source"); - if (str_valid(source_name)) { - obs_source_t* source = obs_get_source_by_name(source_name); + QString sourceName = obs_data_get_string(req->data, "source"); + if (!sourceName.isEmpty()) { + OBSSourceAutoRelease source = obs_get_source_by_name(sourceName.toUtf8()); - obs_data_t* response = obs_data_create(); - obs_data_set_string(response, "name", source_name); + OBSDataAutoRelease response = obs_data_create(); + obs_data_set_string(response, "name", sourceName.toUtf8()); obs_data_set_double(response, "volume", obs_source_get_volume(source)); obs_data_set_bool(response, "muted", obs_source_muted(source)); req->SendOKResponse(response); - - obs_data_release(response); - obs_source_release(source); } else { req->SendErrorResponse("invalid request parameters"); } @@ -1038,13 +981,13 @@ void WSRequestHandler::HandleToggleMute(WSRequestHandler* req) { return; } - const char* source_name = obs_data_get_string(req->data, "source"); - if (!str_valid(source_name)) { + QString sourceName = obs_data_get_string(req->data, "source"); + if (sourceName.isEmpty()) { req->SendErrorResponse("invalid request parameters"); return; } - obs_source_t* source = obs_get_source_by_name(source_name); + OBSSourceAutoRelease source = obs_get_source_by_name(sourceName.toUtf8()); if (!source) { req->SendErrorResponse("invalid request parameters"); return; @@ -1052,8 +995,6 @@ void WSRequestHandler::HandleToggleMute(WSRequestHandler* req) { obs_source_set_muted(source, !obs_source_muted(source)); req->SendOKResponse(); - - obs_source_release(source); } /** @@ -1074,15 +1015,15 @@ void WSRequestHandler::HandleSetMute(WSRequestHandler* req) { return; } - const char* source_name = obs_data_get_string(req->data, "source"); + QString sourceName = obs_data_get_string(req->data, "source"); bool mute = obs_data_get_bool(req->data, "mute"); - if (!str_valid(source_name)) { + if (sourceName.isEmpty()) { req->SendErrorResponse("invalid request parameters"); return; } - obs_source_t* source = obs_get_source_by_name(source_name); + OBSSourceAutoRelease source = obs_get_source_by_name(sourceName.toUtf8()); if (!source) { req->SendErrorResponse("specified source doesn't exist"); return; @@ -1090,8 +1031,6 @@ void WSRequestHandler::HandleSetMute(WSRequestHandler* req) { obs_source_set_muted(source, mute); req->SendOKResponse(); - - obs_source_release(source); } /** @@ -1113,26 +1052,23 @@ void WSRequestHandler::HandleGetMute(WSRequestHandler* req) { return; } - const char* source_name = obs_data_get_string(req->data, "source"); - if (!str_valid(source_name)) { + QString sourceName = obs_data_get_string(req->data, "source"); + if (sourceName.isEmpty()) { req->SendErrorResponse("invalid request parameters"); return; } - obs_source_t* source = obs_get_source_by_name(source_name); + OBSSourceAutoRelease source = obs_get_source_by_name(sourceName.toUtf8()); if (!source) { req->SendErrorResponse("specified source doesn't exist"); return; } - obs_data_t* response = obs_data_create(); + OBSDataAutoRelease response = obs_data_create(); obs_data_set_string(response, "name", obs_source_get_name(source)); obs_data_set_bool(response, "muted", obs_source_muted(source)); req->SendOKResponse(response); - - obs_source_release(source); - obs_data_release(response); } /** @@ -1152,24 +1088,22 @@ void WSRequestHandler::HandleSetSyncOffset(WSRequestHandler* req) { return; } - const char* source_name = obs_data_get_string(req->data, "source"); - int64_t source_sync_offset = (int64_t)obs_data_get_int(req->data, "offset"); + QString sourceName = obs_data_get_string(req->data, "source"); + int64_t sourceSyncOffset = (int64_t)obs_data_get_int(req->data, "offset"); - if (!source_name || strlen(source_name) < 1 || source_sync_offset < 0) { + if (sourceName.isEmpty() || sourceSyncOffset < 0) { req->SendErrorResponse("invalid request parameters"); return; } - obs_source_t* source = obs_get_source_by_name(source_name); + OBSSourceAutoRelease source = obs_get_source_by_name(sourceName.toUtf8()); if (!source) { req->SendErrorResponse("specified source doesn't exist"); return; } - obs_source_set_sync_offset(source, source_sync_offset); + obs_source_set_sync_offset(source, sourceSyncOffset); req->SendOKResponse(); - - obs_source_release(source); } /** @@ -1191,18 +1125,15 @@ void WSRequestHandler::HandleGetSyncOffset(WSRequestHandler* req) { return; } - const char* source_name = obs_data_get_string(req->data, "source"); - if (str_valid(source_name)) { - obs_source_t* source = obs_get_source_by_name(source_name); + QString sourceName = obs_data_get_string(req->data, "source"); + if (!sourceName.isEmpty()) { + OBSSourceAutoRelease source = obs_get_source_by_name(sourceName.toUtf8()); - obs_data_t* response = obs_data_create(); - obs_data_set_string(response, "name", source_name); + OBSDataAutoRelease response = obs_data_create(); + obs_data_set_string(response, "name", sourceName.toUtf8()); obs_data_set_int(response, "offset", obs_source_get_sync_offset(source)); req->SendOKResponse(response); - - obs_data_release(response); - obs_source_release(source); } else { req->SendErrorResponse("invalid request parameters"); } @@ -1230,34 +1161,30 @@ void WSRequestHandler::HandleSetSceneItemPosition(WSRequestHandler* req) { return; } - const char* item_name = obs_data_get_string(req->data, "item"); - if (!str_valid(item_name)) { + QString itemName = obs_data_get_string(req->data, "item"); + if (itemName.isEmpty()) { req->SendErrorResponse("invalid request parameters"); return; } - const char* scene_name = obs_data_get_string(req->data, "scene-name"); - obs_source_t* scene = Utils::GetSceneFromNameOrCurrent(scene_name); + QString sceneName = obs_data_get_string(req->data, "scene-name"); + OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName); if (!scene) { req->SendErrorResponse("requested scene could not be found"); return; } - obs_sceneitem_t* scene_item = Utils::GetSceneItemFromName(scene, item_name); - if (scene_item) { + OBSSceneItem sceneItem = Utils::GetSceneItemFromName(scene, itemName); + if (sceneItem) { vec2 item_position = { 0 }; item_position.x = obs_data_get_double(req->data, "x"); item_position.y = obs_data_get_double(req->data, "y"); + obs_sceneitem_set_pos(sceneItem, &item_position); - obs_sceneitem_set_pos(scene_item, &item_position); - - obs_sceneitem_release(scene_item); req->SendOKResponse(); } else { req->SendErrorResponse("specified scene item doesn't exist"); } - - obs_source_release(scene); } /** @@ -1279,19 +1206,20 @@ void WSRequestHandler::HandleSetSceneItemTransform(WSRequestHandler* req) { if (!req->hasField("item") || !req->hasField("x-scale") || !req->hasField("y-scale") || - !req->hasField("rotation")) { + !req->hasField("rotation")) + { req->SendErrorResponse("missing request parameters"); return; } - const char* item_name = obs_data_get_string(req->data, "item"); - if (!str_valid(item_name)) { + QString itemName = obs_data_get_string(req->data, "item"); + if (itemName.isEmpty()) { req->SendErrorResponse("invalid request parameters"); return; } - const char* scene_name = obs_data_get_string(req->data, "scene-name"); - obs_source_t* scene = Utils::GetSceneFromNameOrCurrent(scene_name); + QString sceneName = obs_data_get_string(req->data, "scene-name"); + OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName); if (!scene) { req->SendErrorResponse("requested scene doesn't exist"); return; @@ -1302,18 +1230,14 @@ void WSRequestHandler::HandleSetSceneItemTransform(WSRequestHandler* req) { scale.y = obs_data_get_double(req->data, "y-scale"); float rotation = obs_data_get_double(req->data, "rotation"); - obs_sceneitem_t* scene_item = Utils::GetSceneItemFromName(scene, item_name); - if (scene_item) { - obs_sceneitem_set_scale(scene_item, &scale); - obs_sceneitem_set_rot(scene_item, rotation); - - obs_sceneitem_release(scene_item); + OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromName(scene, itemName); + if (sceneItem) { + obs_sceneitem_set_scale(sceneItem, &scale); + obs_sceneitem_set_rot(sceneItem, rotation); req->SendOKResponse(); } else { req->SendErrorResponse("specified scene item doesn't exist"); } - - obs_source_release(scene); } /** @@ -1338,36 +1262,33 @@ void WSRequestHandler::HandleSetSceneItemCrop(WSRequestHandler* req) { return; } - const char* item_name = obs_data_get_string(req->data, "item"); - if (!str_valid(item_name)) { + QString itemName = obs_data_get_string(req->data, "item"); + if (itemName.isEmpty()) { req->SendErrorResponse("invalid request parameters"); return; } - const char* scene_name = obs_data_get_string(req->data, "scene-name"); - obs_source_t* scene = Utils::GetSceneFromNameOrCurrent(scene_name); + QString sceneName = obs_data_get_string(req->data, "scene-name"); + OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName); if (!scene) { req->SendErrorResponse("requested scene doesn't exist"); return; } - obs_sceneitem_t* scene_item = Utils::GetSceneItemFromName(scene, item_name); - if (scene_item) { + OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromName(scene, itemName); + if (sceneItem) { struct obs_sceneitem_crop crop = { 0 }; crop.top = obs_data_get_int(req->data, "top"); crop.bottom = obs_data_get_int(req->data, "bottom"); crop.left = obs_data_get_int(req->data, "left"); crop.right = obs_data_get_int(req->data, "right"); - obs_sceneitem_set_crop(scene_item, &crop); + obs_sceneitem_set_crop(sceneItem, &crop); - obs_sceneitem_release(scene_item); req->SendOKResponse(); } else { req->SendErrorResponse("specified scene item doesn't exist"); } - - obs_source_release(scene); } /** @@ -1404,101 +1325,98 @@ void WSRequestHandler::HandleGetSceneItemProperties(WSRequestHandler* req) { return; } - const char* item_name = obs_data_get_string(req->data, "item"); - if (!str_valid(item_name)) { + QString itemName = obs_data_get_string(req->data, "item"); + if (itemName.isEmpty()) { req->SendErrorResponse("invalid request parameters"); return; } - const char* scene_name = obs_data_get_string(req->data, "scene-name"); - obs_source_t* scene = Utils::GetSceneFromNameOrCurrent(scene_name); + QString sceneName = obs_data_get_string(req->data, "scene-name"); + OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName); if (!scene) { req->SendErrorResponse("requested scene doesn't exist"); return; } - obs_sceneitem_t* scene_item = Utils::GetSceneItemFromName(scene, item_name); - if (!scene_item) { + OBSSceneItemAutoRelease sceneItem = + Utils::GetSceneItemFromName(scene, itemName); + if (!sceneItem) { req->SendErrorResponse("specified scene item doesn't exist"); - obs_source_release(scene); return; } - obs_data_t* data = obs_data_create(); + OBSDataAutoRelease data = obs_data_create(); + obs_data_set_string(data, "name", itemName.toUtf8()); - obs_data_set_string(data, "name", item_name); - - obs_data_t* pos_data = obs_data_create(); + OBSDataAutoRelease posData = obs_data_create(); vec2 pos; - obs_sceneitem_get_pos(scene_item, &pos); - obs_data_set_double(pos_data, "x", pos.x); - obs_data_set_double(pos_data, "y", pos.y); - obs_data_set_int(pos_data, "alignment", obs_sceneitem_get_alignment(scene_item)); - obs_data_set_obj(data, "position", pos_data); + obs_sceneitem_get_pos(sceneItem, &pos); + obs_data_set_double(posData, "x", pos.x); + obs_data_set_double(posData, "y", pos.y); + obs_data_set_int(posData, "alignment", obs_sceneitem_get_alignment(sceneItem)); + obs_data_set_obj(data, "position", posData); - obs_data_set_double(data, "rotation", obs_sceneitem_get_rot(scene_item)); + obs_data_set_double(data, "rotation", obs_sceneitem_get_rot(sceneItem)); - obs_data_t* scale_data = obs_data_create(); + OBSDataAutoRelease scaleData = obs_data_create(); vec2 scale; - obs_sceneitem_get_scale(scene_item, &scale); - obs_data_set_double(scale_data, "x", scale.x); - obs_data_set_double(scale_data, "y", scale.y); - obs_data_set_obj(data, "scale", scale_data); + obs_sceneitem_get_scale(sceneItem, &scale); + obs_data_set_double(scaleData, "x", scale.x); + obs_data_set_double(scaleData, "y", scale.y); + obs_data_set_obj(data, "scale", scaleData); - obs_data_t* crop_data = obs_data_create(); + OBSDataAutoRelease cropData = obs_data_create(); obs_sceneitem_crop crop; - obs_sceneitem_get_crop(scene_item, &crop); - obs_data_set_int(crop_data, "left", crop.left); - obs_data_set_int(crop_data, "top", crop.top); - obs_data_set_int(crop_data, "right", crop.right); - obs_data_set_int(crop_data, "bottom", crop.bottom); - obs_data_set_obj(data, "crop", crop_data); + obs_sceneitem_get_crop(sceneItem, &crop); + obs_data_set_int(cropData, "left", crop.left); + obs_data_set_int(cropData, "top", crop.top); + obs_data_set_int(cropData, "right", crop.right); + obs_data_set_int(cropData, "bottom", crop.bottom); + obs_data_set_obj(data, "crop", cropData); - obs_data_set_bool(data, "visible", obs_sceneitem_visible(scene_item)); + obs_data_set_bool(data, "visible", obs_sceneitem_visible(sceneItem)); - obs_data_t* bounds_data = obs_data_create(); - obs_bounds_type bounds_type = obs_sceneitem_get_bounds_type(scene_item); - if (bounds_type == OBS_BOUNDS_NONE) { - obs_data_set_string(bounds_data, "type", "OBS_BOUNDS_NONE"); + OBSDataAutoRelease boundsData = obs_data_create(); + obs_bounds_type boundsType = obs_sceneitem_get_bounds_type(sceneItem); + if (boundsType == OBS_BOUNDS_NONE) { + obs_data_set_string(boundsData, "type", "OBS_BOUNDS_NONE"); } else { - switch(bounds_type) { + switch(boundsType) { case OBS_BOUNDS_STRETCH: { - obs_data_set_string(bounds_data, "type", "OBS_BOUNDS_STRETCH"); + obs_data_set_string(boundsData, "type", "OBS_BOUNDS_STRETCH"); break; } case OBS_BOUNDS_SCALE_INNER: { - obs_data_set_string(bounds_data, "type", "OBS_BOUNDS_SCALE_INNER"); + obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_INNER"); break; } case OBS_BOUNDS_SCALE_OUTER: { - obs_data_set_string(bounds_data, "type", "OBS_BOUNDS_SCALE_OUTER"); + obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_OUTER"); break; } case OBS_BOUNDS_SCALE_TO_WIDTH: { - obs_data_set_string(bounds_data, "type", "OBS_BOUNDS_SCALE_TO_WIDTH"); + obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_TO_WIDTH"); break; } case OBS_BOUNDS_SCALE_TO_HEIGHT: { - obs_data_set_string(bounds_data, "type", "OBS_BOUNDS_SCALE_TO_HEIGHT"); + obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_TO_HEIGHT"); break; } case OBS_BOUNDS_MAX_ONLY: { - obs_data_set_string(bounds_data, "type", "OBS_BOUNDS_MAX_ONLY"); + obs_data_set_string(boundsData, "type", "OBS_BOUNDS_MAX_ONLY"); break; } } - obs_data_set_int(bounds_data, "alignment", obs_sceneitem_get_bounds_alignment(scene_item)); + obs_data_set_int(boundsData, "alignment", obs_sceneitem_get_bounds_alignment(sceneItem)); vec2 bounds; - obs_sceneitem_get_bounds(scene_item, &bounds); - obs_data_set_double(bounds_data, "x", bounds.x); - obs_data_set_double(bounds_data, "y", bounds.y); + obs_sceneitem_get_bounds(sceneItem, &bounds); + obs_data_set_double(boundsData, "x", bounds.x); + obs_data_set_double(boundsData, "y", bounds.y); } - obs_data_set_obj(data, "bounds", bounds_data); + obs_data_set_obj(data, "bounds", boundsData); - obs_sceneitem_release(scene_item); req->SendOKResponse(data); - obs_source_release(scene); } /** @@ -1533,159 +1451,157 @@ void WSRequestHandler::HandleSetSceneItemProperties(WSRequestHandler* req) { return; } - const char* item_name = obs_data_get_string(req->data, "item"); - if (!str_valid(item_name)) { + QString itemName = obs_data_get_string(req->data, "item"); + if (itemName.isEmpty()) { req->SendErrorResponse("invalid request parameters"); return; } - const char* scene_name = obs_data_get_string(req->data, "scene-name"); - obs_source_t* scene = Utils::GetSceneFromNameOrCurrent(scene_name); + QString sceneName = obs_data_get_string(req->data, "scene-name"); + OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName); if (!scene) { req->SendErrorResponse("requested scene doesn't exist"); return; } - obs_sceneitem_t* scene_item = Utils::GetSceneItemFromName(scene, item_name); - if (!scene_item) { + OBSSceneItemAutoRelease sceneItem = + Utils::GetSceneItemFromName(scene, itemName); + if (!sceneItem) { req->SendErrorResponse("specified scene item doesn't exist"); - obs_source_release(scene); return; } - bool bad_request = false; - obs_data_t* error_message = obs_data_create(); + bool badRequest = false; + OBSDataAutoRelease errorMessage = obs_data_create(); if (req->hasField("position")) { - vec2 old_position; - obs_data_t* position_error = obs_data_create(); - obs_sceneitem_get_pos(scene_item, &old_position); - obs_data_t* req_position = obs_data_get_obj(req->data, "position"); - vec2 new_position = old_position; - if (obs_data_has_user_value(req_position, "x")) { - new_position.x = obs_data_get_int(req_position, "x"); + vec2 oldPosition; + OBSDataAutoRelease positionError = obs_data_create(); + obs_sceneitem_get_pos(sceneItem, &oldPosition); + OBSDataAutoRelease reqPosition = obs_data_get_obj(req->data, "position"); + vec2 newPosition = oldPosition; + if (obs_data_has_user_value(reqPosition, "x")) { + newPosition.x = obs_data_get_int(reqPosition, "x"); } - if (obs_data_has_user_value(req_position, "y")) { - new_position.y = obs_data_get_int(req_position, "y"); + if (obs_data_has_user_value(reqPosition, "y")) { + newPosition.y = obs_data_get_int(reqPosition, "y"); } - if (obs_data_has_user_value(req_position, "alignment")) { - const uint32_t alignment = obs_data_get_int(req_position, "alignment"); + if (obs_data_has_user_value(reqPosition, "alignment")) { + const uint32_t alignment = obs_data_get_int(reqPosition, "alignment"); if (Utils::IsValidAlignment(alignment)) { - obs_sceneitem_set_alignment(scene_item, alignment); + obs_sceneitem_set_alignment(sceneItem, alignment); } else { - bad_request = true; - obs_data_set_string(position_error, "alignment", "invalid"); - obs_data_set_obj(error_message, "position", position_error); + badRequest = true; + obs_data_set_string(positionError, "alignment", "invalid"); + obs_data_set_obj(errorMessage, "position", positionError); } } - obs_sceneitem_set_pos(scene_item, &new_position); + obs_sceneitem_set_pos(sceneItem, &newPosition); } if (req->hasField("rotation")) { - obs_sceneitem_set_rot(scene_item, (float)obs_data_get_double(req->data, "rotation")); + obs_sceneitem_set_rot(sceneItem, (float)obs_data_get_double(req->data, "rotation")); } if (req->hasField("scale")) { - vec2 old_scale; - obs_sceneitem_get_scale(scene_item, &old_scale); - obs_data_t* req_scale = obs_data_get_obj(req->data, "scale"); - vec2 new_scale = old_scale; - if (obs_data_has_user_value(req_scale, "x")) { - new_scale.x = obs_data_get_double(req_scale, "x"); + vec2 oldScale; + obs_sceneitem_get_scale(sceneItem, &oldScale); + OBSDataAutoRelease reqScale = obs_data_get_obj(req->data, "scale"); + vec2 newScale = oldScale; + if (obs_data_has_user_value(reqScale, "x")) { + newScale.x = obs_data_get_double(reqScale, "x"); } - if (obs_data_has_user_value(req_scale, "y")) { - new_scale.y = obs_data_get_double(req_scale, "y"); + if (obs_data_has_user_value(reqScale, "y")) { + newScale.y = obs_data_get_double(reqScale, "y"); } - obs_sceneitem_set_scale(scene_item, &new_scale); + obs_sceneitem_set_scale(sceneItem, &newScale); } if (req->hasField("crop")) { - obs_sceneitem_crop old_crop; - obs_sceneitem_get_crop(scene_item, &old_crop); - obs_data_t* req_crop = obs_data_get_obj(req->data, "crop"); - obs_sceneitem_crop new_crop = old_crop; - if (obs_data_has_user_value(req_crop, "top")) { - new_crop.top = obs_data_get_int(req_crop, "top"); + obs_sceneitem_crop oldCrop; + obs_sceneitem_get_crop(sceneItem, &oldCrop); + OBSDataAutoRelease reqCrop = obs_data_get_obj(req->data, "crop"); + obs_sceneitem_crop newCrop = oldCrop; + if (obs_data_has_user_value(reqCrop, "top")) { + newCrop.top = obs_data_get_int(reqCrop, "top"); } - if (obs_data_has_user_value(req_crop, "right")) { - new_crop.right = obs_data_get_int(req_crop, "right"); + if (obs_data_has_user_value(reqCrop, "right")) { + newCrop.right = obs_data_get_int(reqCrop, "right"); } - if (obs_data_has_user_value(req_crop, "bottom")) { - new_crop.bottom = obs_data_get_int(req_crop, "bottom"); + if (obs_data_has_user_value(reqCrop, "bottom")) { + newCrop.bottom = obs_data_get_int(reqCrop, "bottom"); } - if (obs_data_has_user_value(req_crop, "left")) { - new_crop.left = obs_data_get_int(req_crop, "left"); + if (obs_data_has_user_value(reqCrop, "left")) { + newCrop.left = obs_data_get_int(reqCrop, "left"); } - obs_sceneitem_set_crop(scene_item, &new_crop); + obs_sceneitem_set_crop(sceneItem, &newCrop); } if (req->hasField("visible")) { - obs_sceneitem_set_visible(scene_item, obs_data_get_bool(req->data, "visible")); + obs_sceneitem_set_visible(sceneItem, obs_data_get_bool(req->data, "visible")); } if (req->hasField("bounds")) { - bool bad_bounds = false; - obs_data_t* bounds_error = obs_data_create(); - obs_data_t* req_bounds = obs_data_get_obj(req->data, "bounds"); - if (obs_data_has_user_value(req_bounds, "type")) { - const char* new_bounds_type = obs_data_get_string(req_bounds, "type"); - if (new_bounds_type == "OBS_BOUNDS_NONE") { - obs_sceneitem_set_bounds_type(scene_item, OBS_BOUNDS_NONE); + bool badBounds = false; + OBSDataAutoRelease boundsError = obs_data_create(); + OBSDataAutoRelease reqBounds = obs_data_get_obj(req->data, "bounds"); + if (obs_data_has_user_value(reqBounds, "type")) { + const char* newBoundsType = obs_data_get_string(reqBounds, "type"); + if (newBoundsType == "OBS_BOUNDS_NONE") { + obs_sceneitem_set_bounds_type(sceneItem, OBS_BOUNDS_NONE); } - else if (new_bounds_type == "OBS_BOUNDS_STRETCH") { - obs_sceneitem_set_bounds_type(scene_item, OBS_BOUNDS_STRETCH); + else if (newBoundsType == "OBS_BOUNDS_STRETCH") { + obs_sceneitem_set_bounds_type(sceneItem, OBS_BOUNDS_STRETCH); } - else if (new_bounds_type == "OBS_BOUNDS_SCALE_INNER") { - obs_sceneitem_set_bounds_type(scene_item, OBS_BOUNDS_SCALE_INNER); + else if (newBoundsType == "OBS_BOUNDS_SCALE_INNER") { + obs_sceneitem_set_bounds_type(sceneItem, OBS_BOUNDS_SCALE_INNER); } - else if (new_bounds_type == "OBS_BOUNDS_SCALE_OUTER") { - obs_sceneitem_set_bounds_type(scene_item, OBS_BOUNDS_SCALE_OUTER); + else if (newBoundsType == "OBS_BOUNDS_SCALE_OUTER") { + obs_sceneitem_set_bounds_type(sceneItem, OBS_BOUNDS_SCALE_OUTER); } - else if (new_bounds_type == "OBS_BOUNDS_SCALE_TO_WIDTH") { - obs_sceneitem_set_bounds_type(scene_item, OBS_BOUNDS_SCALE_TO_WIDTH); + else if (newBoundsType == "OBS_BOUNDS_SCALE_TO_WIDTH") { + obs_sceneitem_set_bounds_type(sceneItem, OBS_BOUNDS_SCALE_TO_WIDTH); } - else if (new_bounds_type == "OBS_BOUNDS_SCALE_TO_HEIGHT") { - obs_sceneitem_set_bounds_type(scene_item, OBS_BOUNDS_SCALE_TO_HEIGHT); + else if (newBoundsType == "OBS_BOUNDS_SCALE_TO_HEIGHT") { + obs_sceneitem_set_bounds_type(sceneItem, OBS_BOUNDS_SCALE_TO_HEIGHT); } - else if (new_bounds_type == "OBS_BOUNDS_MAX_ONLY") { - obs_sceneitem_set_bounds_type(scene_item, OBS_BOUNDS_MAX_ONLY); + else if (newBoundsType == "OBS_BOUNDS_MAX_ONLY") { + obs_sceneitem_set_bounds_type(sceneItem, OBS_BOUNDS_MAX_ONLY); } else { - bad_request = bad_bounds = true; - obs_data_set_string(bounds_error, "type", "invalid"); + badRequest = badBounds = true; + obs_data_set_string(boundsError, "type", "invalid"); } } - vec2 old_bounds; - obs_sceneitem_get_bounds(scene_item, &old_bounds); - vec2 new_bounds = old_bounds; - if (obs_data_has_user_value(req_bounds, "x")) { - new_bounds.x = obs_data_get_double(req_bounds, "x"); + vec2 oldBounds; + obs_sceneitem_get_bounds(sceneItem, &oldBounds); + vec2 newBounds = oldBounds; + if (obs_data_has_user_value(reqBounds, "x")) { + newBounds.x = obs_data_get_double(reqBounds, "x"); } - if (obs_data_has_user_value(req_bounds, "y")) { - new_bounds.y = obs_data_get_double(req_bounds, "y"); + if (obs_data_has_user_value(reqBounds, "y")) { + newBounds.y = obs_data_get_double(reqBounds, "y"); } - obs_sceneitem_set_bounds(scene_item, &new_bounds); - if (obs_data_has_user_value(req_bounds, "alignment")) { - const uint32_t bounds_alignment = obs_data_get_int(req_bounds, "alignment"); + obs_sceneitem_set_bounds(sceneItem, &newBounds); + if (obs_data_has_user_value(reqBounds, "alignment")) { + const uint32_t bounds_alignment = obs_data_get_int(reqBounds, "alignment"); if (Utils::IsValidAlignment(bounds_alignment)) { - obs_sceneitem_set_bounds_alignment(scene_item, bounds_alignment); + obs_sceneitem_set_bounds_alignment(sceneItem, bounds_alignment); } else { - bad_request = bad_bounds = true; - obs_data_set_string(bounds_error, "alignment", "invalid"); + badRequest = badBounds = true; + obs_data_set_string(boundsError, "alignment", "invalid"); } } - if (bad_bounds) { - obs_data_set_obj(error_message, "bounds", bounds_error); + if (badBounds) { + obs_data_set_obj(errorMessage, "bounds", boundsError); } } - obs_sceneitem_release(scene_item); - if (bad_request) { - req->SendErrorResponse(error_message); + if (badRequest) { + req->SendErrorResponse(errorMessage); } else { req->SendOKResponse(); } - obs_source_release(scene); } /** @@ -1704,10 +1620,10 @@ void WSRequestHandler::HandleSetCurrentSceneCollection(WSRequestHandler* req) { return; } - const char* scene_collection = obs_data_get_string(req->data, "sc-name"); - if (str_valid(scene_collection)) { + QString sceneCollection = obs_data_get_string(req->data, "sc-name"); + if (!sceneCollection.isEmpty()) { // TODO : Check if specified profile exists and if changing is allowed - obs_frontend_set_current_scene_collection(scene_collection); + obs_frontend_set_current_scene_collection(sceneCollection.toUtf8()); req->SendOKResponse(); } else { req->SendErrorResponse("invalid request parameters"); @@ -1725,23 +1641,20 @@ void WSRequestHandler::HandleSetCurrentSceneCollection(WSRequestHandler* req) { * @since 4.0.0 */ void WSRequestHandler::HandleGetCurrentSceneCollection(WSRequestHandler* req) { - obs_data_t* response = obs_data_create(); + OBSDataAutoRelease response = obs_data_create(); obs_data_set_string(response, "sc-name", obs_frontend_get_current_scene_collection()); req->SendOKResponse(response); - obs_data_release(response); } void WSRequestHandler::HandleListSceneCollections(WSRequestHandler* req) { - obs_data_array_t* scene_collections = Utils::GetSceneCollections(); + OBSDataArrayAutoRelease sceneCollections = Utils::GetSceneCollections(); - obs_data_t* response = obs_data_create(); - obs_data_set_array(response, "scene-collections", scene_collections); + OBSDataAutoRelease response = obs_data_create(); + obs_data_set_array(response, "scene-collections", sceneCollections); req->SendOKResponse(response); - obs_data_release(response); - obs_data_array_release(scene_collections); } /** @@ -1760,10 +1673,10 @@ void WSRequestHandler::HandleSetCurrentProfile(WSRequestHandler* req) { return; } - const char* profile_name = obs_data_get_string(req->data, "profile-name"); - if (str_valid(profile_name)) { + QString profileName = obs_data_get_string(req->data, "profile-name"); + if (!profileName.isEmpty()) { // TODO : check if profile exists - obs_frontend_set_current_profile(profile_name); + obs_frontend_set_current_profile(profileName.toUtf8()); req->SendOKResponse(); } else { req->SendErrorResponse("invalid request parameters"); @@ -1781,12 +1694,11 @@ void WSRequestHandler::HandleSetCurrentProfile(WSRequestHandler* req) { * @since 4.0.0 */ void WSRequestHandler::HandleGetCurrentProfile(WSRequestHandler* req) { - obs_data_t* response = obs_data_create(); + OBSDataAutoRelease response = obs_data_create(); obs_data_set_string(response, "profile-name", obs_frontend_get_current_profile()); req->SendOKResponse(response); - obs_data_release(response); } /** @@ -1807,11 +1719,9 @@ void WSRequestHandler::HandleGetCurrentProfile(WSRequestHandler* req) { * @since 4.1.0 */ void WSRequestHandler::HandleSetStreamSettings(WSRequestHandler* req) { - obs_service_t* service = obs_frontend_get_streaming_service(); - // get_streaming_service doesn't addref, so let's do it ourselves - obs_service_addref(service); + OBSService service = obs_frontend_get_streaming_service(); - obs_data_t* requestSettings = obs_data_get_obj(req->data, "settings"); + OBSDataAutoRelease requestSettings = obs_data_get_obj(req->data, "settings"); if (!requestSettings) { req->SendErrorResponse("'settings' are required'"); return; @@ -1821,25 +1731,17 @@ void WSRequestHandler::HandleSetStreamSettings(WSRequestHandler* req) { QString requestedType = obs_data_get_string(req->data, "type"); if (requestedType != nullptr && requestedType != serviceType) { - obs_data_t* hotkeys = obs_hotkeys_save_service(service); - - // Release current service pointer before creating the new one - obs_service_release(service); - + OBSDataAutoRelease hotkeys = obs_hotkeys_save_service(service); service = obs_service_create( requestedType.toUtf8(), STREAM_SERVICE_ID, requestSettings, hotkeys); - - obs_service_addref(service); - - obs_data_release(hotkeys); } else { // If type isn't changing, we should overlay the settings we got // to the existing settings. By doing so, you can send a request that // only contains the settings you want to change, instead of having to // do a get and then change them - obs_data_t* existingSettings = obs_service_get_settings(service); - obs_data_t* newSettings = obs_data_create(); + OBSDataAutoRelease existingSettings = obs_service_get_settings(service); + OBSDataAutoRelease newSettings = obs_data_create(); // Apply existing settings obs_data_apply(newSettings, existingSettings); @@ -1847,9 +1749,6 @@ void WSRequestHandler::HandleSetStreamSettings(WSRequestHandler* req) { obs_data_apply(newSettings, requestSettings); obs_service_update(service, newSettings); - - obs_data_release(newSettings); - obs_data_release(existingSettings); } //if save is specified we should immediately save the streaming service @@ -1857,18 +1756,13 @@ void WSRequestHandler::HandleSetStreamSettings(WSRequestHandler* req) { obs_frontend_save_streaming_service(); } - obs_data_t* serviceSettings = obs_service_get_settings(service); + OBSDataAutoRelease serviceSettings = obs_service_get_settings(service); - obs_data_t* response = obs_data_create(); + OBSDataAutoRelease response = obs_data_create(); obs_data_set_string(response, "type", requestedType.toUtf8()); obs_data_set_obj(response, "settings", serviceSettings); req->SendOKResponse(response); - - obs_data_release(response); - obs_data_release(serviceSettings); - obs_data_release(requestSettings); - obs_service_release(service); } /** @@ -1888,22 +1782,16 @@ void WSRequestHandler::HandleSetStreamSettings(WSRequestHandler* req) { * @since 4.1.0 */ void WSRequestHandler::HandleGetStreamSettings(WSRequestHandler* req) { - obs_service_t* service = obs_frontend_get_streaming_service(); - // get_streaming_service doesn't addref, so let's do it ourselves - obs_service_addref(service); + OBSService service = obs_frontend_get_streaming_service(); const char* serviceType = obs_service_get_type(service); - obs_data_t* settings = obs_service_get_settings(service); + OBSDataAutoRelease settings = obs_service_get_settings(service); - obs_data_t* response = obs_data_create(); + OBSDataAutoRelease response = obs_data_create(); obs_data_set_string(response, "type", serviceType); obs_data_set_obj(response, "settings", settings); req->SendOKResponse(response); - - obs_data_release(response); - obs_data_release(settings); - obs_service_release(service); } /** @@ -1930,14 +1818,12 @@ void WSRequestHandler::HandleSaveStreamSettings(WSRequestHandler* req) { * @since 4.0.0 */ void WSRequestHandler::HandleListProfiles(WSRequestHandler* req) { - obs_data_array_t* profiles = Utils::GetProfiles(); + OBSDataArrayAutoRelease profiles = Utils::GetProfiles(); - obs_data_t* response = obs_data_create(); + OBSDataAutoRelease response = obs_data_create(); obs_data_set_array(response, "profiles", profiles); req->SendOKResponse(response); - obs_data_release(response); - obs_data_array_release(profiles); } /** @@ -1953,11 +1839,10 @@ void WSRequestHandler::HandleListProfiles(WSRequestHandler* req) { void WSRequestHandler::HandleGetStudioModeStatus(WSRequestHandler* req) { bool previewActive = obs_frontend_preview_program_mode_active(); - obs_data_t* response = obs_data_create(); + OBSDataAutoRelease response = obs_data_create(); obs_data_set_bool(response, "studio-mode", previewActive); req->SendOKResponse(response); - obs_data_release(response); } /** @@ -1978,16 +1863,14 @@ void WSRequestHandler::HandleGetPreviewScene(WSRequestHandler* req) { return; } - obs_source_t* scene = obs_frontend_get_current_preview_scene(); - obs_data_array_t* scene_items = Utils::GetSceneItems(scene); + OBSSourceAutoRelease scene = obs_frontend_get_current_preview_scene(); + OBSDataArrayAutoRelease sceneItems = Utils::GetSceneItems(scene); - obs_data_t* data = obs_data_create(); + OBSDataAutoRelease data = obs_data_create(); obs_data_set_string(data, "name", obs_source_get_name(scene)); - obs_data_set_array(data, "sources", scene_items); + obs_data_set_array(data, "sources", sceneItems); req->SendOKResponse(data); - obs_data_release(data); - obs_data_array_release(scene_items); } /** @@ -2013,7 +1896,7 @@ void WSRequestHandler::HandleSetPreviewScene(WSRequestHandler* req) { } const char* scene_name = obs_data_get_string(req->data, "scene-name"); - obs_source_t* scene = Utils::GetSceneFromNameOrCurrent(scene_name); + OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(scene_name); if (scene) { obs_frontend_set_current_preview_scene(scene); @@ -2021,8 +1904,6 @@ void WSRequestHandler::HandleSetPreviewScene(WSRequestHandler* req) { } else { req->SendErrorResponse("specified scene doesn't exist"); } - - obs_source_release(scene); } /** @@ -2045,13 +1926,13 @@ void WSRequestHandler::HandleTransitionToProgram(WSRequestHandler* req) { } if (req->hasField("with-transition")) { - obs_data_t* transitionInfo = + OBSDataAutoRelease transitionInfo = obs_data_get_obj(req->data, "with-transition"); if (obs_data_has_user_value(transitionInfo, "name")) { - const char* transitionName = + QString transitionName = obs_data_get_string(transitionInfo, "name"); - if (!str_valid(transitionName)) { + if (transitionName.isEmpty()) { req->SendErrorResponse("invalid request parameters"); return; } @@ -2059,7 +1940,6 @@ void WSRequestHandler::HandleTransitionToProgram(WSRequestHandler* req) { bool success = Utils::SetTransitionByName(transitionName); if (!success) { req->SendErrorResponse("specified transition doesn't exist"); - obs_data_release(transitionInfo); return; } } @@ -2069,8 +1949,6 @@ void WSRequestHandler::HandleTransitionToProgram(WSRequestHandler* req) { obs_data_get_int(transitionInfo, "duration"); Utils::SetTransitionDuration(transitionDuration); } - - obs_data_release(transitionInfo); } Utils::TransitionToProgram(); @@ -2132,7 +2010,7 @@ void WSRequestHandler::HandleToggleStudioMode(WSRequestHandler* req) { * @since 4.1.0 */ void WSRequestHandler::HandleGetSpecialSources(WSRequestHandler* req) { - obs_data_t* response = obs_data_create(); + OBSDataAutoRelease response = obs_data_create(); QMap sources; sources["desktop-1"] = 1; @@ -2146,17 +2024,13 @@ void WSRequestHandler::HandleGetSpecialSources(WSRequestHandler* req) { i.next(); const char* id = i.key(); - obs_source_t* source = obs_get_output_source(i.value()); - blog(LOG_INFO, "%s : %p", id, source); - + OBSSourceAutoRelease source = obs_get_output_source(i.value()); if (source) { obs_data_set_string(response, id, obs_source_get_name(source)); - obs_source_release(source); } } req->SendOKResponse(response); - obs_data_release(response); } /** @@ -2196,11 +2070,10 @@ void WSRequestHandler::HandleSetRecordingFolder(WSRequestHandler* req) { void WSRequestHandler::HandleGetRecordingFolder(WSRequestHandler* req) { const char* recFolder = Utils::GetRecordingFolder(); - obs_data_t* response = obs_data_create(); + OBSDataAutoRelease response = obs_data_create(); obs_data_set_string(response, "rec-folder", recFolder); req->SendOKResponse(response); - obs_data_release(response); } /** @@ -2251,36 +2124,31 @@ void WSRequestHandler::HandleGetTextGDIPlusProperties(WSRequestHandler* req) { } const char* sceneName = obs_data_get_string(req->data, "scene-name"); - obs_source_t* scene = Utils::GetSceneFromNameOrCurrent(sceneName); + OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName); if (!scene) { req->SendErrorResponse("requested scene doesn't exist"); return; } - obs_sceneitem_t* sceneItem = Utils::GetSceneItemFromName(scene, itemName); + OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromName(scene, itemName); if (sceneItem) { - obs_source_t* sceneItemSource = obs_sceneitem_get_source(sceneItem); + OBSSource sceneItemSource = obs_sceneitem_get_source(sceneItem); const char* sceneItemSourceId = obs_source_get_id(sceneItemSource); if (strcmp(sceneItemSourceId, "text_gdiplus") == 0) { - obs_data_t* response = obs_source_get_settings(sceneItemSource); + OBSDataAutoRelease response = obs_source_get_settings(sceneItemSource); obs_data_set_string(response, "source", itemName); obs_data_set_string(response, "scene-name", sceneName); obs_data_set_bool(response, "render", obs_sceneitem_visible(sceneItem)); req->SendOKResponse(response); - - obs_data_release(response); - obs_sceneitem_release(sceneItem); } else { req->SendErrorResponse("not text gdi plus source"); } } else { req->SendErrorResponse("specified scene item doesn't exist"); } - - obs_source_release(scene); } /** @@ -2335,19 +2203,19 @@ void WSRequestHandler::HandleSetTextGDIPlusProperties(WSRequestHandler* req) { } const char* sceneName = obs_data_get_string(req->data, "scene-name"); - obs_source_t* scene = Utils::GetSceneFromNameOrCurrent(sceneName); + OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName); if (!scene) { req->SendErrorResponse("requested scene doesn't exist"); return; } - obs_sceneitem_t* sceneItem = Utils::GetSceneItemFromName(scene, itemName); + OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromName(scene, itemName); if (sceneItem) { - obs_source_t* sceneItemSource = obs_sceneitem_get_source(sceneItem); + OBSSource sceneItemSource = obs_sceneitem_get_source(sceneItem); const char* sceneItemSourceId = obs_source_get_id(sceneItemSource); if (strcmp(sceneItemSourceId, "text_gdiplus") == 0) { - obs_data_t* settings = obs_source_get_settings(sceneItemSource); + OBSDataAutoRelease settings = obs_source_get_settings(sceneItemSource); if (req->hasField("align")) { obs_data_set_string(settings, "align", @@ -2405,9 +2273,9 @@ void WSRequestHandler::HandleSetTextGDIPlusProperties(WSRequestHandler* req) { } if (req->hasField("font")) { - obs_data_t* font_obj = obs_data_get_obj(settings, "font"); + OBSDataAutoRelease font_obj = obs_data_get_obj(settings, "font"); if (font_obj) { - obs_data_t* req_font_obj = obs_data_get_obj(req->data, "font"); + OBSDataAutoRelease req_font_obj = obs_data_get_obj(req->data, "font"); if (obs_data_has_user_value(req_font_obj, "face")) { obs_data_set_string(font_obj, "face", @@ -2428,9 +2296,6 @@ void WSRequestHandler::HandleSetTextGDIPlusProperties(WSRequestHandler* req) { obs_data_set_string(font_obj, "style", obs_data_get_string(req_font_obj, "style")); } - - obs_data_release(req_font_obj); - obs_data_release(font_obj); } } @@ -2502,16 +2367,12 @@ void WSRequestHandler::HandleSetTextGDIPlusProperties(WSRequestHandler* req) { } req->SendOKResponse(); - obs_data_release(settings); - obs_sceneitem_release(sceneItem); } else { req->SendErrorResponse("not text gdi plus source"); } } else { req->SendErrorResponse("specified scene item doesn't exist"); } - - obs_source_release(scene); } /** @@ -2542,35 +2403,31 @@ void WSRequestHandler::HandleGetBrowserSourceProperties(WSRequestHandler* req) { } const char* sceneName = obs_data_get_string(req->data, "scene-name"); - obs_source_t* scene = Utils::GetSceneFromNameOrCurrent(sceneName); + OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName); if (!scene) { req->SendErrorResponse("requested scene doesn't exist"); return; } - obs_sceneitem_t* sceneItem = Utils::GetSceneItemFromName(scene, itemName); + OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromName(scene, itemName); if (sceneItem) { - obs_source_t* sceneItemSource = obs_sceneitem_get_source(sceneItem); + OBSSource sceneItemSource = obs_sceneitem_get_source(sceneItem); const char* sceneItemSourceId = obs_source_get_id(sceneItemSource); if (strcmp(sceneItemSourceId, "browser_source") == 0) { - obs_data_t* response = obs_source_get_settings(sceneItemSource); + OBSDataAutoRelease response = obs_source_get_settings(sceneItemSource); obs_data_set_string(response, "source", itemName); obs_data_set_string(response, "scene-name", sceneName); obs_data_set_bool(response, "render", obs_sceneitem_visible(sceneItem)); req->SendOKResponse(response); - - obs_data_release(response); - obs_sceneitem_release(sceneItem); } else { req->SendErrorResponse("not browser source"); } } else { req->SendErrorResponse("specified scene item doesn't exist"); } - obs_source_release(scene); } /** @@ -2605,19 +2462,19 @@ void WSRequestHandler::HandleSetBrowserSourceProperties(WSRequestHandler* req) { } const char* sceneName = obs_data_get_string(req->data, "scene-name"); - obs_source_t* scene = Utils::GetSceneFromNameOrCurrent(sceneName); + OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName); if (!scene) { req->SendErrorResponse("requested scene doesn't exist"); return; } - obs_sceneitem_t* sceneItem = Utils::GetSceneItemFromName(scene, itemName); + OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromName(scene, itemName); if (sceneItem) { - obs_source_t* sceneItemSource = obs_sceneitem_get_source(sceneItem); + OBSSource sceneItemSource = obs_sceneitem_get_source(sceneItem); const char* sceneItemSourceId = obs_source_get_id(sceneItemSource); if (strcmp(sceneItemSourceId, "browser_source") == 0) { - obs_data_t* settings = obs_source_get_settings(sceneItemSource); + OBSDataAutoRelease settings = obs_source_get_settings(sceneItemSource); if (req->hasField("restart_when_active")) { obs_data_set_bool(settings, "restart_when_active", @@ -2667,16 +2524,12 @@ void WSRequestHandler::HandleSetBrowserSourceProperties(WSRequestHandler* req) { } req->SendOKResponse(); - - obs_data_release(settings); - obs_sceneitem_release(sceneItem); } else { req->SendErrorResponse("not browser source"); } } else { req->SendErrorResponse("specified scene item doesn't exist"); } - obs_source_release(scene); } /** @@ -2703,26 +2556,23 @@ void WSRequestHandler::HandleResetSceneItem(WSRequestHandler* req) { } const char* sceneName = obs_data_get_string(req->data, "scene-name"); - obs_source_t* scene = Utils::GetSceneFromNameOrCurrent(sceneName); + OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(sceneName); if (!scene) { req->SendErrorResponse("requested scene doesn't exist"); return; } - obs_sceneitem_t* sceneItem = Utils::GetSceneItemFromName(scene, itemName); + OBSSceneItemAutoRelease sceneItem = Utils::GetSceneItemFromName(scene, itemName); if (sceneItem) { - obs_source_t* sceneItemSource = obs_sceneitem_get_source(sceneItem); + OBSSource sceneItemSource = obs_sceneitem_get_source(sceneItem); - obs_data_t* settings = obs_source_get_settings(sceneItemSource); + OBSDataAutoRelease settings = obs_source_get_settings(sceneItemSource); obs_source_update(sceneItemSource, settings); - obs_sceneitem_release(sceneItem); req->SendOKResponse(); } else { req->SendErrorResponse("specified scene item doesn't exist"); } - - obs_source_release(scene); } /** @@ -2738,33 +2588,25 @@ void WSRequestHandler::HandleResetSceneItem(WSRequestHandler* req) { * @since unreleased */ void WSRequestHandler::HandleGetSourcesList(WSRequestHandler* req) { - obs_data_array_t* sourcesArray = obs_data_array_create(); + OBSDataArrayAutoRelease sourcesArray = obs_data_array_create(); - auto source_enum = [](void* privateData, obs_source_t* source) -> bool { + auto sourceEnumProc = [](void* privateData, obs_source_t* source) -> bool { obs_data_array_t* sourcesArray = (obs_data_array_t*)privateData; - obs_data_t* sourceSettings = obs_source_get_settings(source); + OBSDataAutoRelease sourceSettings = obs_source_get_settings(source); - obs_data_t* sourceData = obs_data_create(); + OBSDataAutoRelease sourceData = obs_data_create(); obs_data_set_string(sourceData, "name", obs_source_get_name(source)); obs_data_set_string(sourceData, "type", obs_source_get_id(source)); obs_data_array_push_back(sourcesArray, sourceData); - - obs_data_release(sourceSettings); - obs_data_release(sourceData); - return true; }; - obs_enum_sources(source_enum, sourcesArray); + obs_enum_sources(sourceEnumProc, sourcesArray); - - obs_data_t* response = obs_data_create(); + OBSDataAutoRelease response = obs_data_create(); obs_data_set_array(response, "sources", sourcesArray); req->SendOKResponse(response); - - obs_data_release(response); - obs_data_array_release(sourcesArray); } /** @@ -2789,7 +2631,7 @@ void WSRequestHandler::HandleGetSourceSettings(WSRequestHandler* req) { } const char* sourceName = obs_data_get_string(req->data, "sourceName"); - obs_source_t* source = obs_get_source_by_name(sourceName); + OBSSourceAutoRelease source = obs_get_source_by_name(sourceName); if (!source) { req->SendErrorResponse("specified source doesn't exist"); return; @@ -2801,22 +2643,17 @@ void WSRequestHandler::HandleGetSourceSettings(WSRequestHandler* req) { if (actualSourceType != requestedType) { req->SendErrorResponse("specified source exists but is not of expected type"); - obs_source_release(source); return; } } - obs_data_t* sourceSettings = obs_source_get_settings(source); + OBSDataAutoRelease sourceSettings = obs_source_get_settings(source); - obs_data_t* response = obs_data_create(); + OBSDataAutoRelease response = obs_data_create(); obs_data_set_string(response, "sourceName", obs_source_get_name(source)); obs_data_set_string(response, "sourceType", obs_source_get_id(source)); obs_data_set_obj(response, "sourceSettings", sourceSettings); req->SendOKResponse(response); - - obs_data_release(response); - obs_data_release(sourceSettings); - obs_source_release(source); } /** @@ -2842,7 +2679,7 @@ void WSRequestHandler::HandleSetSourceSettings(WSRequestHandler* req) { } const char* sourceName = obs_data_get_string(req->data, "sourceName"); - obs_source_t* source = obs_get_source_by_name(sourceName); + OBSSourceAutoRelease source = obs_get_source_by_name(sourceName); if (!source) { req->SendErrorResponse("specified source doesn't exist"); return; @@ -2854,30 +2691,23 @@ void WSRequestHandler::HandleSetSourceSettings(WSRequestHandler* req) { if (actualSourceType != requestedType) { req->SendErrorResponse("specified source exists but is not of expected type"); - obs_source_release(source); return; } } - obs_data_t* currentSettings = obs_source_get_settings(source); - obs_data_t* newSettings = obs_data_get_obj(req->data, "sourceSettings"); + OBSDataAutoRelease currentSettings = obs_source_get_settings(source); + OBSDataAutoRelease newSettings = obs_data_get_obj(req->data, "sourceSettings"); - obs_data_t* sourceSettings = obs_data_create(); + OBSDataAutoRelease sourceSettings = obs_data_create(); obs_data_apply(sourceSettings, currentSettings); obs_data_apply(sourceSettings, newSettings); obs_source_update(source, sourceSettings); obs_source_update_properties(source); - obs_data_t* response = obs_data_create(); + OBSDataAutoRelease response = obs_data_create(); obs_data_set_string(response, "sourceName", obs_source_get_name(source)); obs_data_set_string(response, "sourceType", obs_source_get_id(source)); obs_data_set_obj(response, "sourceSettings", sourceSettings); req->SendOKResponse(response); - - obs_data_release(response); - obs_data_release(sourceSettings); - obs_data_release(newSettings); - obs_data_release(currentSettings); - obs_source_release(source); } diff --git a/WSRequestHandler.h b/WSRequestHandler.h index b622892a..9c8f52a0 100644 --- a/WSRequestHandler.h +++ b/WSRequestHandler.h @@ -24,8 +24,11 @@ with this program. If not, see #include #include +#include #include +#include "obs-websocket.h" + class WSRequestHandler : public QObject { Q_OBJECT @@ -33,13 +36,13 @@ class WSRequestHandler : public QObject { explicit WSRequestHandler(QWebSocket* client); ~WSRequestHandler(); void processIncomingMessage(QString textMessage); - bool hasField(const char* name); + bool hasField(QString name); private: QWebSocket* _client; const char* _messageId; const char* _requestType; - obs_data_t* data; + OBSDataAutoRelease data; void SendOKResponse(obs_data_t* additionalFields = NULL); void SendErrorResponse(const char* errorMessage); diff --git a/forms/settings-dialog.cpp b/forms/settings-dialog.cpp index 33be8370..85268a32 100644 --- a/forms/settings-dialog.cpp +++ b/forms/settings-dialog.cpp @@ -77,17 +77,12 @@ void SettingsDialog::FormAccepted() { conf->DebugEnabled = ui->debugEnabled->isChecked(); conf->AlertsEnabled = ui->alertsEnabled->isChecked(); - if (ui->authRequired->isChecked()) - { - if (ui->password->text() != CHANGE_ME) - { - QByteArray pwd = ui->password->text().toUtf8(); - const char *new_password = pwd; - - conf->SetPassword(new_password); + if (ui->authRequired->isChecked()) { + if (ui->password->text() != CHANGE_ME) { + conf->SetPassword(ui->password->text()); } - if (strcmp(Config::Current()->Secret, "") != 0) + if (!Config::Current()->Secret.isEmpty()) conf->AuthRequired = true; else conf->AuthRequired = false; diff --git a/obs-websocket.cpp b/obs-websocket.cpp index 1c989ca3..4fd72f0d 100644 --- a/obs-websocket.cpp +++ b/obs-websocket.cpp @@ -28,6 +28,12 @@ with this program. If not, see #include "Config.h" #include "forms/settings-dialog.h" +void ___source_dummy_addref(obs_source_t*) {} +void ___sceneitem_dummy_addref(obs_sceneitem_t*) {} +void ___data_dummy_addref(obs_data_t*) {} +void ___data_array_dummy_addref(obs_data_array_t*) {} +void ___output_dummy_addref(obs_output_t*) {} + OBS_DECLARE_MODULE() OBS_MODULE_USE_DEFAULT_LOCALE("obs-websocket", "en-US") diff --git a/obs-websocket.h b/obs-websocket.h index 88f4f2cf..c1c9fb88 100644 --- a/obs-websocket.h +++ b/obs-websocket.h @@ -19,6 +19,25 @@ with this program. If not, see #ifndef OBSWEBSOCKET_H #define OBSWEBSOCKET_H +#include + +void ___source_dummy_addref(obs_source_t*); +void ___sceneitem_dummy_addref(obs_sceneitem_t*); +void ___data_dummy_addref(obs_data_t*); +void ___data_array_dummy_addref(obs_data_array_t*); +void ___output_dummy_addref(obs_output_t*); + +using OBSSourceAutoRelease = + OBSRef; +using OBSSceneItemAutoRelease = + OBSRef; +using OBSDataAutoRelease = + OBSRef; +using OBSDataArrayAutoRelease = + OBSRef; +using OBSOutputAutoRelease = + OBSRef; + #define PROP_AUTHENTICATED "wsclient_authenticated" #define OBS_WEBSOCKET_VERSION "4.2.1"