diff --git a/Config.cpp b/Config.cpp index be37ed27..9235ae3a 100644 --- a/Config.cpp +++ b/Config.cpp @@ -42,143 +42,143 @@ Config::Config() : Secret(""), Salt(""), SettingsLoaded(false) { - // OBS Config defaults - config_t* obs_config = obs_frontend_get_global_config(); - if (obs_config) { - config_set_default_bool(obs_config, - SECTION_NAME, PARAM_ENABLE, ServerEnabled); - config_set_default_uint(obs_config, - SECTION_NAME, PARAM_PORT, ServerPort); - - config_set_default_bool(obs_config, - SECTION_NAME, PARAM_DEBUG, DebugEnabled); + // OBS Config defaults + config_t* obs_config = obs_frontend_get_global_config(); + if (obs_config) { + config_set_default_bool(obs_config, + SECTION_NAME, PARAM_ENABLE, ServerEnabled); + config_set_default_uint(obs_config, + SECTION_NAME, PARAM_PORT, ServerPort); + + config_set_default_bool(obs_config, + SECTION_NAME, PARAM_DEBUG, DebugEnabled); - config_set_default_bool(obs_config, - 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_bool(obs_config, + 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); + } - mbedtls_entropy_init(&entropy); - mbedtls_ctr_drbg_init(&rng); - mbedtls_ctr_drbg_seed(&rng, mbedtls_entropy_func, &entropy, nullptr, 0); + mbedtls_entropy_init(&entropy); + mbedtls_ctr_drbg_init(&rng); + mbedtls_ctr_drbg_seed(&rng, mbedtls_entropy_func, &entropy, nullptr, 0); - SessionChallenge = GenerateSalt(); + SessionChallenge = GenerateSalt(); } Config::~Config() { - mbedtls_ctr_drbg_free(&rng); - mbedtls_entropy_free(&entropy); + mbedtls_ctr_drbg_free(&rng); + mbedtls_entropy_free(&entropy); } void Config::Load() { - config_t* obs_config = obs_frontend_get_global_config(); + config_t* obs_config = 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); - - DebugEnabled = config_get_bool(obs_config, SECTION_NAME, PARAM_DEBUG); + ServerEnabled = config_get_bool(obs_config, SECTION_NAME, PARAM_ENABLE); + ServerPort = config_get_uint(obs_config, SECTION_NAME, PARAM_PORT); + + DebugEnabled = config_get_bool(obs_config, SECTION_NAME, PARAM_DEBUG); - 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(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); } void Config::Save() { - config_t* obs_config = obs_frontend_get_global_config(); + config_t* obs_config = 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(obs_config, SECTION_NAME, PARAM_DEBUG, DebugEnabled); + config_set_bool(obs_config, SECTION_NAME, PARAM_ENABLE, ServerEnabled); + config_set_uint(obs_config, SECTION_NAME, PARAM_PORT, ServerPort); + + config_set_bool(obs_config, SECTION_NAME, PARAM_DEBUG, DebugEnabled); - 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(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_save(obs_config); + config_save(obs_config); } const char* Config::GenerateSalt() { - // Generate 32 random chars - unsigned char* random_chars = (unsigned char*)bzalloc(32); - mbedtls_ctr_drbg_random(&rng, random_chars, 32); + // Generate 32 random chars + unsigned char* random_chars = (unsigned char*)bzalloc(32); + mbedtls_ctr_drbg_random(&rng, random_chars, 32); - // Convert the 32 random chars to a base64 string - char* salt = (char*)bzalloc(64); - size_t salt_bytes; - mbedtls_base64_encode( - (unsigned char*)salt, 64, &salt_bytes, - random_chars, 32); + // Convert the 32 random chars to a base64 string + char* salt = (char*)bzalloc(64); + size_t salt_bytes; + mbedtls_base64_encode( + (unsigned char*)salt, 64, &salt_bytes, + random_chars, 32); - bfree(random_chars); - return salt; + bfree(random_chars); + return salt; } const char* Config::GenerateSecret(const char* password, const char* salt) { - // Concatenate the password and the salt - std::string passAndSalt = ""; - passAndSalt += password; - passAndSalt += salt; + // Concatenate the password and the salt + std::string 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(), - challengeHash, 0); - - // Encode SHA256 hash to Base64 - char* challenge = (char*)bzalloc(64); - size_t challenge_bytes = 0; - mbedtls_base64_encode( - (unsigned char*)challenge, 64, &challenge_bytes, - challengeHash, 32); + // Generate a SHA256 hash of the password + unsigned char* challengeHash = (unsigned char*)bzalloc(32); + mbedtls_sha256( + (unsigned char*)passAndSalt.c_str(), passAndSalt.length(), + challengeHash, 0); + + // Encode SHA256 hash to Base64 + char* challenge = (char*)bzalloc(64); + size_t challenge_bytes = 0; + mbedtls_base64_encode( + (unsigned char*)challenge, 64, &challenge_bytes, + challengeHash, 32); - bfree(challengeHash); - return challenge; + bfree(challengeHash); + return challenge; } void Config::SetPassword(const char* password) { - const char* new_salt = GenerateSalt(); - const char* new_challenge = GenerateSecret(password, new_salt); + const char* new_salt = GenerateSalt(); + const char* new_challenge = GenerateSecret(password, new_salt); - this->Salt = new_salt; - this->Secret = new_challenge; + this->Salt = new_salt; + this->Secret = new_challenge; } bool Config::CheckAuth(const char* response) { - // Concatenate auth secret with the challenge sent to the user - std::string challengeAndResponse = ""; - challengeAndResponse += this->Secret; - challengeAndResponse += this->SessionChallenge; + // Concatenate auth secret with the challenge sent to the user + std::string challengeAndResponse = ""; + challengeAndResponse += this->Secret; + challengeAndResponse += this->SessionChallenge; - // Generate a SHA256 hash of challengeAndResponse - unsigned char* hash = (unsigned char*)bzalloc(32); - mbedtls_sha256( - (unsigned char*)challengeAndResponse.c_str(), - challengeAndResponse.length(), - hash, 0); + // Generate a SHA256 hash of challengeAndResponse + unsigned char* hash = (unsigned char*)bzalloc(32); + mbedtls_sha256( + (unsigned char*)challengeAndResponse.c_str(), + challengeAndResponse.length(), + hash, 0); - // Encode the SHA256 hash to Base64 - char* expected_response = (char*)bzalloc(64); - size_t base64_size = 0; - mbedtls_base64_encode( - (unsigned char*)expected_response, 64, &base64_size, - hash, 32); + // Encode the SHA256 hash to Base64 + char* expected_response = (char*)bzalloc(64); + size_t base64_size = 0; + mbedtls_base64_encode( + (unsigned char*)expected_response, 64, &base64_size, + hash, 32); - bool authSuccess = false; - if (strcmp(expected_response, response) == 0) { - SessionChallenge = GenerateSalt(); - authSuccess = true; - } + bool authSuccess = false; + if (strcmp(expected_response, response) == 0) { + SessionChallenge = GenerateSalt(); + authSuccess = true; + } - bfree(hash); - bfree(expected_response); - return authSuccess; + bfree(hash); + bfree(expected_response); + return authSuccess; } Config* Config::Current() { - return _instance; + return _instance; } diff --git a/Config.h b/Config.h index 420236a9..94e9ec28 100644 --- a/Config.h +++ b/Config.h @@ -37,7 +37,7 @@ class Config { bool ServerEnabled; uint64_t ServerPort; - + bool DebugEnabled; bool AuthRequired; @@ -45,7 +45,7 @@ class Config { const char* Salt; const char* SessionChallenge; bool SettingsLoaded; - + static Config* Current(); private: diff --git a/Utils.cpp b/Utils.cpp index 66e0ad38..98cca62b 100644 --- a/Utils.cpp +++ b/Utils.cpp @@ -28,448 +28,448 @@ with this program. If not, see Q_DECLARE_METATYPE(OBSScene); obs_data_array_t* string_list_to_array(char** strings, char* key) { - if (!strings) - return obs_data_array_create(); + if (!strings) + return obs_data_array_create(); - obs_data_array_t* list = obs_data_array_create(); + obs_data_array_t* list = obs_data_array_create(); - char* value = ""; - for (int i = 0; value != nullptr; i++) { - value = strings[i]; + char* value = ""; + for (int i = 0; value != nullptr; i++) { + value = strings[i]; - obs_data_t* item = obs_data_create(); - obs_data_set_string(item, key, value); + obs_data_t* item = obs_data_create(); + obs_data_set_string(item, key, value); - if (value) - obs_data_array_push_back(list, item); + if (value) + obs_data_array_push_back(list, item); - obs_data_release(item); - } + obs_data_release(item); + } - return list; + return list; } 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); + obs_data_array_t* items = obs_data_array_create(); + obs_scene_t* scene = obs_scene_from_source(source); - if (!scene) - return nullptr; + if (!scene) + return nullptr; - obs_scene_enum_items(scene, []( + obs_scene_enum_items(scene, []( obs_scene_t* scene, obs_sceneitem_t* currentItem, void* param) { - obs_data_array_t* data = static_cast(param); + 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_t* item_data = GetSceneItemData(currentItem); + obs_data_array_insert(data, 0, item_data); - obs_data_release(item_data); - return true; - }, items); + obs_data_release(item_data); + return true; + }, items); - return items; + return items; } obs_data_t* Utils::GetSceneItemData(obs_sceneitem_t* item) { - if (!item) - return nullptr; + if (!item) + return nullptr; - vec2 pos; - obs_sceneitem_get_pos(item, &pos); + vec2 pos; + obs_sceneitem_get_pos(item, &pos); - vec2 scale; - obs_sceneitem_get_scale(item, &scale); + 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_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_data_t* data = obs_data_create(); - obs_data_set_string(data, "name", - obs_source_get_name(obs_sceneitem_get_source(item))); - obs_data_set_string(data, "type", - obs_source_get_id(obs_sceneitem_get_source(item))); - obs_data_set_double(data, "volume", - obs_source_get_volume(obs_sceneitem_get_source(item))); - obs_data_set_double(data, "x", pos.x); - obs_data_set_double(data, "y", pos.y); - obs_data_set_int(data, "source_cx", (int)item_width); - obs_data_set_int(data, "source_cy", (int)item_height); - obs_data_set_double(data, "cx", item_width* scale.x); - obs_data_set_double(data, "cy", item_height* scale.y); - obs_data_set_bool(data, "render", obs_sceneitem_visible(item)); + obs_data_t* data = obs_data_create(); + obs_data_set_string(data, "name", + obs_source_get_name(obs_sceneitem_get_source(item))); + obs_data_set_string(data, "type", + obs_source_get_id(obs_sceneitem_get_source(item))); + obs_data_set_double(data, "volume", + obs_source_get_volume(obs_sceneitem_get_source(item))); + obs_data_set_double(data, "x", pos.x); + obs_data_set_double(data, "y", pos.y); + obs_data_set_int(data, "source_cx", (int)item_width); + obs_data_set_int(data, "source_cy", (int)item_height); + obs_data_set_double(data, "cx", item_width* scale.x); + obs_data_set_double(data, "cy", item_height* scale.y); + obs_data_set_bool(data, "render", obs_sceneitem_visible(item)); - return data; + return data; } obs_sceneitem_t* Utils::GetSceneItemFromName(obs_source_t* source, const char* name) { - struct current_search { - const char* query; - obs_sceneitem_t* result; - }; + struct current_search { + const char* query; + obs_sceneitem_t* result; + }; - current_search search; - search.query = name; - search.result = nullptr; + current_search search; + search.query = name; + search.result = nullptr; - obs_scene_t* scene = obs_scene_from_source(source); - if (scene == nullptr) - return nullptr; + obs_scene_t* scene = obs_scene_from_source(source); + if (scene == nullptr) + return nullptr; - obs_scene_enum_items(scene, []( + obs_scene_enum_items(scene, []( obs_scene_t* scene, obs_sceneitem_t* currentItem, void* param) { - current_search* search = static_cast(param); + current_search* search = static_cast(param); - const char* currentItemName = - obs_source_get_name(obs_sceneitem_get_source(currentItem)); + const char* currentItemName = + obs_source_get_name(obs_sceneitem_get_source(currentItem)); - if (strcmp(currentItemName, search->query) == 0) { - search->result = currentItem; - obs_sceneitem_addref(search->result); - return false; - } + if (strcmp(currentItemName, search->query) == 0) { + search->result = currentItem; + obs_sceneitem_addref(search->result); + return false; + } - return true; - }, &search); + return true; + }, &search); - return search.result; + return search.result; } obs_source_t* Utils::GetTransitionFromName(const char* search_name) { - obs_source_t* found_transition = NULL; + obs_source_t* found_transition = NULL; - obs_frontend_source_list transition_list = {}; - obs_frontend_get_transitions(&transition_list); + 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]; + for (size_t i = 0; i < transition_list.sources.num; i++) { + obs_source_t* transition = transition_list.sources.array[i]; - const char* transition_name = obs_source_get_name(transition); - if (strcmp(transition_name, search_name) == 0) - { - found_transition = transition; - obs_source_addref(found_transition); - break; - } - } + const char* transition_name = obs_source_get_name(transition); + if (strcmp(transition_name, search_name) == 0) + { + found_transition = transition; + obs_source_addref(found_transition); + break; + } + } - obs_frontend_source_list_free(&transition_list); + obs_frontend_source_list_free(&transition_list); - return found_transition; + return found_transition; } obs_source_t* Utils::GetSceneFromNameOrCurrent(const char* scene_name) { - obs_source_t* scene = nullptr; + obs_source_t* scene = nullptr; - if (!scene_name || !strlen(scene_name)) - scene = obs_frontend_get_current_scene(); - else - scene = obs_get_source_by_name(scene_name); + if (!scene_name || !strlen(scene_name)) + scene = obs_frontend_get_current_scene(); + else + scene = obs_get_source_by_name(scene_name); - return scene; + return scene; } obs_data_array_t* Utils::GetScenes() { - obs_frontend_source_list sceneList = {}; - obs_frontend_get_scenes(&sceneList); + obs_frontend_source_list sceneList = {}; + obs_frontend_get_scenes(&sceneList); - 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_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_t* scene_data = GetSceneData(scene); + obs_data_array_push_back(scenes, scene_data); - obs_data_release(scene_data); - } + obs_data_release(scene_data); + } - obs_frontend_source_list_free(&sceneList); + obs_frontend_source_list_free(&sceneList); - return scenes; + return scenes; } obs_data_t* Utils::GetSceneData(obs_source* source) { - obs_data_array_t* scene_items = GetSceneItems(source); + obs_data_array_t* scene_items = 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_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_array_release(scene_items); - return sceneData; + 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** scene_collections = obs_frontend_get_scene_collections(); + obs_data_array_t* list = string_list_to_array(scene_collections, "sc-name"); - bfree(scene_collections); - return list; + bfree(scene_collections); + 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"); + char** profiles = obs_frontend_get_profiles(); + obs_data_array_t* list = string_list_to_array(profiles, "profile-name"); - bfree(profiles); - return list; + bfree(profiles); + return list; } QSpinBox* Utils::GetTransitionDurationControl() { - QMainWindow* window = (QMainWindow*)obs_frontend_get_main_window(); - return window->findChild("transitionDuration"); + QMainWindow* window = (QMainWindow*)obs_frontend_get_main_window(); + return window->findChild("transitionDuration"); } int Utils::GetTransitionDuration() { - QSpinBox* control = GetTransitionDurationControl(); - if (control) - return control->value(); - else - return -1; + QSpinBox* control = GetTransitionDurationControl(); + if (control) + return control->value(); + else + return -1; } void Utils::SetTransitionDuration(int ms) { - QSpinBox* control = GetTransitionDurationControl(); - if (control && ms >= 0) - control->setValue(ms); + QSpinBox* control = GetTransitionDurationControl(); + if (control && ms >= 0) + control->setValue(ms); } bool Utils::SetTransitionByName(const char* transition_name) { - obs_source_t* transition = GetTransitionFromName(transition_name); + obs_source_t* transition = GetTransitionFromName(transition_name); - if (transition) { - obs_frontend_set_current_transition(transition); - obs_source_release(transition); - return true; - } else { - return false; - } + if (transition) { + obs_frontend_set_current_transition(transition); + obs_source_release(transition); + return true; + } else { + return false; + } } QPushButton* Utils::GetPreviewModeButtonControl() { - QMainWindow* main = (QMainWindow*)obs_frontend_get_main_window(); - return main->findChild("modeSwitch"); + QMainWindow* main = (QMainWindow*)obs_frontend_get_main_window(); + return main->findChild("modeSwitch"); } QListWidget* Utils::GetSceneListControl() { - QMainWindow* main = (QMainWindow*)obs_frontend_get_main_window(); - return main->findChild("scenes"); + QMainWindow* main = (QMainWindow*)obs_frontend_get_main_window(); + return main->findChild("scenes"); } obs_scene_t* Utils::SceneListItemToScene(QListWidgetItem* item) { - if (!item) - return nullptr; + if (!item) + return nullptr; - QVariant item_data = item->data(static_cast(Qt::UserRole)); - return item_data.value(); + QVariant item_data = item->data(static_cast(Qt::UserRole)); + return item_data.value(); } QLayout* Utils::GetPreviewLayout() { - QMainWindow* main = (QMainWindow*)obs_frontend_get_main_window(); - return main->findChild("previewLayout"); + QMainWindow* main = (QMainWindow*)obs_frontend_get_main_window(); + return main->findChild("previewLayout"); } bool Utils::IsPreviewModeActive() { - QMainWindow* main = (QMainWindow*)obs_frontend_get_main_window(); + QMainWindow* main = (QMainWindow*)obs_frontend_get_main_window(); - // Clue 1 : "Studio Mode" button is toggled on - bool buttonToggledOn = GetPreviewModeButtonControl()->isChecked(); + // Clue 1 : "Studio Mode" button is toggled on + bool buttonToggledOn = GetPreviewModeButtonControl()->isChecked(); - // Clue 2 : Preview layout has more than one item - int previewChildCount = GetPreviewLayout()->count(); - blog(LOG_INFO, "preview layout children count : %d", previewChildCount); + // Clue 2 : Preview layout has more than one item + int previewChildCount = GetPreviewLayout()->count(); + blog(LOG_INFO, "preview layout children count : %d", previewChildCount); - return buttonToggledOn || (previewChildCount >= 2); + return buttonToggledOn || (previewChildCount >= 2); } void Utils::EnablePreviewMode() { - if (!IsPreviewModeActive()) - GetPreviewModeButtonControl()->click(); + if (!IsPreviewModeActive()) + GetPreviewModeButtonControl()->click(); } void Utils::DisablePreviewMode() { - if (IsPreviewModeActive()) - GetPreviewModeButtonControl()->click(); + if (IsPreviewModeActive()) + GetPreviewModeButtonControl()->click(); } void Utils::TogglePreviewMode() { - GetPreviewModeButtonControl()->click(); + GetPreviewModeButtonControl()->click(); } obs_scene_t* Utils::GetPreviewScene() { - if (IsPreviewModeActive()) { - QListWidget* sceneList = GetSceneListControl(); - QList selected = sceneList->selectedItems(); + if (IsPreviewModeActive()) { + QListWidget* sceneList = GetSceneListControl(); + QList selected = sceneList->selectedItems(); - // Qt::UserRole == QtUserRole::OBSRef - obs_scene_t* scene = Utils::SceneListItemToScene(selected.first()); + // Qt::UserRole == QtUserRole::OBSRef + obs_scene_t* scene = Utils::SceneListItemToScene(selected.first()); - obs_scene_addref(scene); - return scene; - } + obs_scene_addref(scene); + return scene; + } - return nullptr; + return nullptr; } bool Utils::SetPreviewScene(const char* name) { - if (IsPreviewModeActive()) { - QListWidget* sceneList = GetSceneListControl(); - QList matchingItems = - sceneList->findItems(name, Qt::MatchExactly); + if (IsPreviewModeActive()) { + QListWidget* sceneList = GetSceneListControl(); + QList matchingItems = + sceneList->findItems(name, Qt::MatchExactly); - if (matchingItems.count() > 0) { - sceneList->setCurrentItem(matchingItems.first()); - return true; - } else { - return false; - } - } + if (matchingItems.count() > 0) { + sceneList->setCurrentItem(matchingItems.first()); + return true; + } else { + return false; + } + } - return false; + return false; } void Utils::TransitionToProgram() { - if (!IsPreviewModeActive()) - return; + if (!IsPreviewModeActive()) + return; - // WARNING : if the layout created in OBS' CreateProgramOptions() changes - // then this won't work as expected + // WARNING : if the layout created in OBS' CreateProgramOptions() changes + // then this won't work as expected - QMainWindow* main = (QMainWindow*)obs_frontend_get_main_window(); + QMainWindow* main = (QMainWindow*)obs_frontend_get_main_window(); - // The program options widget is the second item in the left-to-right layout - QWidget* programOptions = GetPreviewLayout()->itemAt(1)->widget(); + // The program options widget is the second item in the left-to-right layout + QWidget* programOptions = GetPreviewLayout()->itemAt(1)->widget(); - // The "Transition" button lies in the mainButtonLayout - // which is the first itemin the program options' layout - QLayout* mainButtonLayout = programOptions->layout()->itemAt(1)->layout(); - QWidget* transitionBtnWidget = mainButtonLayout->itemAt(0)->widget(); + // The "Transition" button lies in the mainButtonLayout + // which is the first itemin the program options' layout + QLayout* mainButtonLayout = programOptions->layout()->itemAt(1)->layout(); + QWidget* transitionBtnWidget = mainButtonLayout->itemAt(0)->widget(); - // Try to cast that widget into a button - QPushButton* transitionBtn = qobject_cast(transitionBtnWidget); + // Try to cast that widget into a button + QPushButton* transitionBtn = qobject_cast(transitionBtnWidget); - // Perform a click on that button - transitionBtn->click(); + // Perform a click on that button + transitionBtn->click(); } const char* Utils::OBSVersionString() { - uint32_t version = obs_get_version(); + uint32_t version = obs_get_version(); - uint8_t major, minor, patch; - major = (version >> 24) & 0xFF; - minor = (version >> 16) & 0xFF; - patch = version & 0xFF; + uint8_t major, minor, patch; + major = (version >> 24) & 0xFF; + minor = (version >> 16) & 0xFF; + patch = version & 0xFF; - char* result = (char*)bmalloc(sizeof(char) * 12); - sprintf(result, "%d.%d.%d", major, minor, patch); + char* result = (char*)bmalloc(sizeof(char) * 12); + sprintf(result, "%d.%d.%d", major, minor, patch); - return result; + return result; } QSystemTrayIcon* Utils::GetTrayIcon() { - QMainWindow* main = (QMainWindow*)obs_frontend_get_main_window(); - return main->findChildren().first(); + QMainWindow* main = (QMainWindow*)obs_frontend_get_main_window(); + return main->findChildren().first(); } void Utils::SysTrayNotify(QString &text, QSystemTrayIcon::MessageIcon icon, QString title) { - if (!QSystemTrayIcon::supportsMessages()) - return; + if (!QSystemTrayIcon::supportsMessages()) + return; - QSystemTrayIcon* trayIcon = GetTrayIcon(); - if (trayIcon) - trayIcon->showMessage(title, text, icon); + QSystemTrayIcon* trayIcon = GetTrayIcon(); + if (trayIcon) + trayIcon->showMessage(title, text, icon); } QString Utils::FormatIPAddress(QHostAddress &addr) { - if (addr.protocol() == QAbstractSocket::IPv4Protocol) - QString v4addr = addr.toString().replace("::fff:", ""); + if (addr.protocol() == QAbstractSocket::IPv4Protocol) + QString v4addr = addr.toString().replace("::fff:", ""); - return addr.toString(); + return addr.toString(); } const char* Utils::GetRecordingFolder() { - config_t* profile = obs_frontend_get_profile_config(); - const char* outputMode = config_get_string(profile, "Output", "Mode"); + config_t* profile = obs_frontend_get_profile_config(); + const char* outputMode = config_get_string(profile, "Output", "Mode"); - if (strcmp(outputMode, "Advanced") == 0) { - // Advanced mode - return config_get_string(profile, "AdvOut", "RecFilePath"); - } else { - // Simple mode - return config_get_string(profile, "SimpleOutput", "FilePath"); - } + if (strcmp(outputMode, "Advanced") == 0) { + // Advanced mode + return config_get_string(profile, "AdvOut", "RecFilePath"); + } else { + // Simple mode + return config_get_string(profile, "SimpleOutput", "FilePath"); + } } bool Utils::SetRecordingFolder(const char* path) { - if (!QDir(path).exists()) - return false; + if (!QDir(path).exists()) + return false; - config_t* profile = obs_frontend_get_profile_config(); - const char* outputMode = config_get_string(profile, "Output", "Mode"); + config_t* profile = obs_frontend_get_profile_config(); + const char* outputMode = config_get_string(profile, "Output", "Mode"); - if (strcmp(outputMode, "Advanced") == 0) { - config_set_string(profile, "AdvOut", "RecFilePath", path); - } else { - config_set_string(profile, "SimpleOutput", "FilePath", path); - } + if (strcmp(outputMode, "Advanced") == 0) { + config_set_string(profile, "AdvOut", "RecFilePath", path); + } else { + config_set_string(profile, "SimpleOutput", "FilePath", path); + } - config_save(profile); - return true; + config_save(profile); + return true; } QString* Utils::ParseDataToQueryString(obs_data_t* data) { - QString* query = nullptr; - if (data) { - obs_data_item_t* item = obs_data_first(data); - if (item) { - query = new QString(); - bool isFirst = true; - do { - if (!obs_data_item_has_user_value(item)) - continue; - - if (!isFirst) - query->append('&'); - else - isFirst = false; - - const char* attrName = obs_data_item_get_name(item); - query->append(attrName).append("="); + QString* query = nullptr; + if (data) { + obs_data_item_t* item = obs_data_first(data); + if (item) { + query = new QString(); + bool isFirst = true; + do { + if (!obs_data_item_has_user_value(item)) + continue; + + if (!isFirst) + query->append('&'); + else + isFirst = false; + + const char* attrName = obs_data_item_get_name(item); + query->append(attrName).append("="); - switch (obs_data_item_gettype(item)) { - case OBS_DATA_BOOLEAN: - query->append(obs_data_item_get_bool(item)?"true":"false"); - break; - case OBS_DATA_NUMBER: - switch (obs_data_item_numtype(item)) - { - case OBS_DATA_NUM_DOUBLE: - query->append( + switch (obs_data_item_gettype(item)) { + case OBS_DATA_BOOLEAN: + query->append(obs_data_item_get_bool(item)?"true":"false"); + break; + case OBS_DATA_NUMBER: + switch (obs_data_item_numtype(item)) + { + case OBS_DATA_NUM_DOUBLE: + query->append( QString::number(obs_data_item_get_double(item))); - break; - case OBS_DATA_NUM_INT: - query->append( + break; + case OBS_DATA_NUM_INT: + query->append( QString::number(obs_data_item_get_int(item))); - break; - case OBS_DATA_NUM_INVALID: - break; - } - break; - case OBS_DATA_STRING: - query->append(QUrl::toPercentEncoding( + break; + case OBS_DATA_NUM_INVALID: + break; + } + break; + case OBS_DATA_STRING: + query->append(QUrl::toPercentEncoding( QString(obs_data_item_get_string(item)))); - break; - default: - //other types are not supported - break; - } - } while (obs_data_item_next(&item)); - } - } - return query; + break; + default: + //other types are not supported + break; + } + } while (obs_data_item_next(&item)); + } + } + return query; } diff --git a/Utils.h b/Utils.h index 19065a7d..568fabef 100644 --- a/Utils.h +++ b/Utils.h @@ -49,7 +49,7 @@ class Utils { static int GetTransitionDuration(); static void SetTransitionDuration(int ms); - static bool SetTransitionByName(const char* transition_name); + static bool SetTransitionByName(const char* transition_name); static QPushButton* GetPreviewModeButtonControl(); static QLayout* GetPreviewLayout(); @@ -76,7 +76,7 @@ class Utils { static QString FormatIPAddress(QHostAddress &addr); static const char* GetRecordingFolder(); static bool SetRecordingFolder(const char* path); - + static QString* ParseDataToQueryString(obs_data_t * data); }; diff --git a/WSEvents.cpp b/WSEvents.cpp index 790ddbc0..3bf6d5b0 100644 --- a/WSEvents.cpp +++ b/WSEvents.cpp @@ -29,555 +29,555 @@ with this program. If not, see #include "obs-websocket.h" bool transition_is_cut(obs_source_t* transition) { - if (!transition) - return false; + if (!transition) + return false; - if (obs_source_get_type(transition) == OBS_SOURCE_TYPE_TRANSITION - && strcmp(obs_source_get_id(transition), "cut_transition") == 0) { - return true; - } - return false; + if (obs_source_get_type(transition) == OBS_SOURCE_TYPE_TRANSITION + && strcmp(obs_source_get_id(transition), "cut_transition") == 0) { + return true; + } + return false; } const char* ns_to_timestamp(uint64_t ns) { - uint64_t ms = ns / (1000 * 1000); - uint64_t secs = ms / 1000; - uint64_t minutes = secs / 60; + 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 hours_part = minutes / 60; + uint64_t minutes_part = minutes % 60; + uint64_t secs_part = secs % 60; + uint64_t ms_part = ms % 1000; - char* ts = (char*)bmalloc(64); - sprintf(ts, "%02d:%02d:%02d.%03d", - hours_part, minutes_part, secs_part, ms_part); + char* ts = (char*)bmalloc(64); + sprintf(ts, "%02d:%02d:%02d.%03d", + hours_part, minutes_part, secs_part, ms_part); - return ts; + return ts; } WSEvents* WSEvents::Instance = nullptr; WSEvents::WSEvents(WSServer* srv) { - _srv = srv; - obs_frontend_add_event_callback(WSEvents::FrontendEventHandler, this); + _srv = srv; + obs_frontend_add_event_callback(WSEvents::FrontendEventHandler, this); - QSpinBox* duration_control = Utils::GetTransitionDurationControl(); - connect(duration_control, SIGNAL(valueChanged(int)), - this, SLOT(TransitionDurationChanged(int))); + QSpinBox* duration_control = Utils::GetTransitionDurationControl(); + connect(duration_control, SIGNAL(valueChanged(int)), + this, SLOT(TransitionDurationChanged(int))); - QTimer* statusTimer = new QTimer(); - connect(statusTimer, SIGNAL(timeout()), - this, SLOT(StreamStatus())); - statusTimer->start(2000); // equal to frontend's constant BITRATE_UPDATE_SECONDS + QTimer* statusTimer = new QTimer(); + connect(statusTimer, SIGNAL(timeout()), + this, SLOT(StreamStatus())); + statusTimer->start(2000); // equal to frontend's constant BITRATE_UPDATE_SECONDS - QListWidget* sceneList = Utils::GetSceneListControl(); - connect(sceneList, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), - this, SLOT(SelectedSceneChanged(QListWidgetItem*, QListWidgetItem*))); + QListWidget* sceneList = Utils::GetSceneListControl(); + connect(sceneList, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), + this, SLOT(SelectedSceneChanged(QListWidgetItem*, QListWidgetItem*))); - QPushButton* modeSwitch = Utils::GetPreviewModeButtonControl(); - connect(modeSwitch, SIGNAL(clicked(bool)), this, SLOT(ModeSwitchClicked(bool))); + QPushButton* modeSwitch = Utils::GetPreviewModeButtonControl(); + connect(modeSwitch, SIGNAL(clicked(bool)), this, SLOT(ModeSwitchClicked(bool))); - transition_handler = nullptr; - scene_handler = nullptr; + transition_handler = nullptr; + scene_handler = nullptr; - QTimer::singleShot(1000, this, SLOT(deferredInitOperations())); + QTimer::singleShot(1000, this, SLOT(deferredInitOperations())); - _streaming_active = false; - _recording_active = false; + _streaming_active = false; + _recording_active = false; - _stream_starttime = 0; - _rec_starttime = 0; + _stream_starttime = 0; + _rec_starttime = 0; } WSEvents::~WSEvents() { - obs_frontend_remove_event_callback(WSEvents::FrontendEventHandler, this); + obs_frontend_remove_event_callback(WSEvents::FrontendEventHandler, this); } void WSEvents::deferredInitOperations() { - obs_source_t* transition = obs_frontend_get_current_transition(); - connectTransitionSignals(transition); - obs_source_release(transition); + obs_source_t* transition = obs_frontend_get_current_transition(); + connectTransitionSignals(transition); + obs_source_release(transition); - obs_source_t* scene = obs_frontend_get_current_scene(); - connectSceneSignals(scene); - obs_source_release(scene); + obs_source_t* scene = obs_frontend_get_current_scene(); + connectSceneSignals(scene); + obs_source_release(scene); } void WSEvents::FrontendEventHandler(enum obs_frontend_event event, void* private_data) { - WSEvents* owner = static_cast(private_data); + WSEvents* owner = static_cast(private_data); - if (!owner->_srv) - return; + if (!owner->_srv) + return; - // TODO : implement SourceOrderChanged and RepopulateSources + // TODO : implement SourceOrderChanged and RepopulateSources - if (event == OBS_FRONTEND_EVENT_SCENE_CHANGED) { - owner->OnSceneChange(); - } - else if (event == OBS_FRONTEND_EVENT_SCENE_LIST_CHANGED) { - owner->OnSceneListChange(); - } - else if (event == OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGED) { - owner->OnSceneCollectionChange(); - } - else if (event == OBS_FRONTEND_EVENT_SCENE_COLLECTION_LIST_CHANGED) { - owner->OnSceneCollectionListChange(); - } - else if (event == OBS_FRONTEND_EVENT_TRANSITION_CHANGED) { - owner->OnTransitionChange(); - } - else if (event == OBS_FRONTEND_EVENT_TRANSITION_LIST_CHANGED) { - owner->OnTransitionListChange(); - } - else if (event == OBS_FRONTEND_EVENT_PROFILE_CHANGED) { - owner->OnProfileChange(); - } - else if (event == OBS_FRONTEND_EVENT_PROFILE_LIST_CHANGED) { - owner->OnProfileListChange(); - } - else if (event == OBS_FRONTEND_EVENT_STREAMING_STARTING) { - owner->OnStreamStarting(); - } - else if (event == OBS_FRONTEND_EVENT_STREAMING_STARTED) { - owner->_streaming_active = 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->OnStreamStopped(); - } - else if (event == OBS_FRONTEND_EVENT_RECORDING_STARTING) { - owner->OnRecordingStarting(); - } - else if (event == OBS_FRONTEND_EVENT_RECORDING_STARTED) { - owner->_recording_active = 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->OnRecordingStopped(); - } - else if (event == OBS_FRONTEND_EVENT_EXIT) { - owner->OnExit(); - } + if (event == OBS_FRONTEND_EVENT_SCENE_CHANGED) { + owner->OnSceneChange(); + } + else if (event == OBS_FRONTEND_EVENT_SCENE_LIST_CHANGED) { + owner->OnSceneListChange(); + } + else if (event == OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGED) { + owner->OnSceneCollectionChange(); + } + else if (event == OBS_FRONTEND_EVENT_SCENE_COLLECTION_LIST_CHANGED) { + owner->OnSceneCollectionListChange(); + } + else if (event == OBS_FRONTEND_EVENT_TRANSITION_CHANGED) { + owner->OnTransitionChange(); + } + else if (event == OBS_FRONTEND_EVENT_TRANSITION_LIST_CHANGED) { + owner->OnTransitionListChange(); + } + else if (event == OBS_FRONTEND_EVENT_PROFILE_CHANGED) { + owner->OnProfileChange(); + } + else if (event == OBS_FRONTEND_EVENT_PROFILE_LIST_CHANGED) { + owner->OnProfileListChange(); + } + else if (event == OBS_FRONTEND_EVENT_STREAMING_STARTING) { + owner->OnStreamStarting(); + } + else if (event == OBS_FRONTEND_EVENT_STREAMING_STARTED) { + owner->_streaming_active = 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->OnStreamStopped(); + } + else if (event == OBS_FRONTEND_EVENT_RECORDING_STARTING) { + owner->OnRecordingStarting(); + } + else if (event == OBS_FRONTEND_EVENT_RECORDING_STARTED) { + owner->_recording_active = 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->OnRecordingStopped(); + } + else if (event == OBS_FRONTEND_EVENT_EXIT) { + owner->OnExit(); + } } void WSEvents::broadcastUpdate(const char* updateType, obs_data_t* additionalFields = NULL) { - obs_data_t* update = obs_data_create(); - obs_data_set_string(update, "update-type", updateType); + obs_data_t* 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); - obs_data_set_string(update, "stream-timecode", ts); - bfree((void*)ts); - } + const char* ts = nullptr; + if (_streaming_active) { + ts = ns_to_timestamp(os_gettime_ns() - _stream_starttime); + obs_data_set_string(update, "stream-timecode", ts); + bfree((void*)ts); + } - if (_recording_active) { - ts = ns_to_timestamp(os_gettime_ns() - _rec_starttime); - obs_data_set_string(update, "rec-timecode", ts); - bfree((void*)ts); - } + if (_recording_active) { + ts = ns_to_timestamp(os_gettime_ns() - _rec_starttime); + obs_data_set_string(update, "rec-timecode", ts); + bfree((void*)ts); + } - if (additionalFields != NULL) - obs_data_apply(update, additionalFields); + if (additionalFields != NULL) + obs_data_apply(update, additionalFields); - const char *json = obs_data_get_json(update); - _srv->broadcast(json); - if (Config::Current()->DebugEnabled) - blog(LOG_DEBUG, "Update << '%s'", json); + const char *json = obs_data_get_json(update); + _srv->broadcast(json); + if (Config::Current()->DebugEnabled) + blog(LOG_DEBUG, "Update << '%s'", json); - obs_data_release(update); + obs_data_release(update); } void WSEvents::connectTransitionSignals(obs_source_t* transition) { - if (transition_handler) { - signal_handler_disconnect(transition_handler, - "transition_start", OnTransitionBegin, this); - } + if (transition_handler) { + signal_handler_disconnect(transition_handler, + "transition_start", OnTransitionBegin, this); + } - if (!transition_is_cut(transition)) { - transition_handler = obs_source_get_signal_handler(transition); - signal_handler_connect(transition_handler, - "transition_start", OnTransitionBegin, this); - } else { - transition_handler = nullptr; - } + if (!transition_is_cut(transition)) { + transition_handler = obs_source_get_signal_handler(transition); + signal_handler_connect(transition_handler, + "transition_start", OnTransitionBegin, this); + } else { + transition_handler = nullptr; + } } void WSEvents::connectSceneSignals(obs_source_t* scene) { - if (scene_handler) { - signal_handler_disconnect(scene_handler, - "reorder", OnSceneReordered, this); - signal_handler_disconnect(scene_handler, - "item_add", OnSceneItemAdd, this); - signal_handler_disconnect(scene_handler, - "item_remove", OnSceneItemDelete, this); - signal_handler_disconnect(scene_handler, - "item_visible", OnSceneItemVisibilityChanged, this); - } + if (scene_handler) { + signal_handler_disconnect(scene_handler, + "reorder", OnSceneReordered, this); + signal_handler_disconnect(scene_handler, + "item_add", OnSceneItemAdd, this); + signal_handler_disconnect(scene_handler, + "item_remove", OnSceneItemDelete, this); + signal_handler_disconnect(scene_handler, + "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, - "reorder", OnSceneReordered, this); - signal_handler_connect(scene_handler, - "item_add", OnSceneItemAdd, this); - signal_handler_connect(scene_handler, - "item_remove", OnSceneItemDelete, this); - signal_handler_connect(scene_handler, - "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, + "reorder", OnSceneReordered, this); + signal_handler_connect(scene_handler, + "item_add", OnSceneItemAdd, this); + signal_handler_connect(scene_handler, + "item_remove", OnSceneItemDelete, this); + signal_handler_connect(scene_handler, + "item_visible", OnSceneItemVisibilityChanged, this); } uint64_t WSEvents::GetStreamingTime() { - if (_streaming_active) - return (os_gettime_ns() - _stream_starttime); - else - return 0; + if (_streaming_active) + return (os_gettime_ns() - _stream_starttime); + else + return 0; } const char* WSEvents::GetStreamingTimecode() { - return ns_to_timestamp(GetStreamingTime()); + return ns_to_timestamp(GetStreamingTime()); } uint64_t WSEvents::GetRecordingTime() { - if (_recording_active) - return (os_gettime_ns() - _rec_starttime); - else - return 0; + if (_recording_active) + return (os_gettime_ns() - _rec_starttime); + else + return 0; } const char* WSEvents::GetRecordingTimecode() { - return ns_to_timestamp(GetRecordingTime()); + return ns_to_timestamp(GetRecordingTime()); } void WSEvents::OnSceneChange() { - // Implements an existing update type from bilhamil's OBS Remote - obs_data_t* data = obs_data_create(); + // Implements an existing update type from bilhamil's OBS Remote + obs_data_t* data = obs_data_create(); - obs_source_t* current_scene = obs_frontend_get_current_scene(); - obs_data_array_t* scene_items = Utils::GetSceneItems(current_scene); - connectSceneSignals(current_scene); + 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); + obs_data_set_string(data, "scene-name", obs_source_get_name(current_scene)); + obs_data_set_array(data, "sources", scene_items); - broadcastUpdate("SwitchScenes", data); + broadcastUpdate("SwitchScenes", data); - obs_data_array_release(scene_items); - obs_source_release(current_scene); - obs_data_release(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 (Utils::IsPreviewModeActive()) { - QListWidget* list = Utils::GetSceneListControl(); - SelectedSceneChanged(list->currentItem(), nullptr); - } + // Dirty fix : OBS blocks signals when swapping scenes in Studio Mode + // after transition end, so SelectedSceneChanged is never called... + if (Utils::IsPreviewModeActive()) { + QListWidget* list = Utils::GetSceneListControl(); + SelectedSceneChanged(list->currentItem(), nullptr); + } } void WSEvents::OnSceneListChange() { - broadcastUpdate("ScenesChanged"); + broadcastUpdate("ScenesChanged"); } void WSEvents::OnSceneCollectionChange() { - broadcastUpdate("SceneCollectionChanged"); + broadcastUpdate("SceneCollectionChanged"); - scene_handler = nullptr; - transition_handler = nullptr; + scene_handler = nullptr; + transition_handler = nullptr; - OnTransitionListChange(); - OnTransitionChange(); + OnTransitionListChange(); + OnTransitionChange(); - OnSceneListChange(); - OnSceneChange(); + OnSceneListChange(); + OnSceneChange(); } void WSEvents::OnSceneCollectionListChange() { - broadcastUpdate("SceneCollectionListChanged"); + broadcastUpdate("SceneCollectionListChanged"); } void WSEvents::OnTransitionChange() { - obs_source_t* current_transition = obs_frontend_get_current_transition(); - connectTransitionSignals(current_transition); + obs_source_t* current_transition = obs_frontend_get_current_transition(); + connectTransitionSignals(current_transition); - obs_data_t* data = obs_data_create(); - obs_data_set_string(data, "transition-name", - obs_source_get_name(current_transition)); + obs_data_t* data = obs_data_create(); + obs_data_set_string(data, "transition-name", + obs_source_get_name(current_transition)); - broadcastUpdate("SwitchTransition", data); + broadcastUpdate("SwitchTransition", data); - obs_data_release(data); - obs_source_release(current_transition); + obs_data_release(data); + obs_source_release(current_transition); } void WSEvents::OnTransitionListChange() { - broadcastUpdate("TransitionListChanged"); + broadcastUpdate("TransitionListChanged"); } void WSEvents::OnProfileChange() { - broadcastUpdate("ProfileChanged"); + broadcastUpdate("ProfileChanged"); } void WSEvents::OnProfileListChange() { - broadcastUpdate("ProfileListChanged"); + broadcastUpdate("ProfileListChanged"); } void WSEvents::OnStreamStarting() { - // Implements an existing update type from bilhamil's OBS Remote - obs_data_t* data = obs_data_create(); - obs_data_set_bool(data, "preview-only", false); + // Implements an existing update type from bilhamil's OBS Remote + obs_data_t* data = obs_data_create(); + obs_data_set_bool(data, "preview-only", false); - broadcastUpdate("StreamStarting", data); + broadcastUpdate("StreamStarting", data); - obs_data_release(data); + obs_data_release(data); } void WSEvents::OnStreamStarted() { - // New update type specific to OBS Studio - _stream_starttime = os_gettime_ns(); - _lastBytesSent = 0; - broadcastUpdate("StreamStarted"); + // New update type specific to OBS Studio + _stream_starttime = os_gettime_ns(); + _lastBytesSent = 0; + broadcastUpdate("StreamStarted"); } void WSEvents::OnStreamStopping() { - // Implements an existing update type from bilhamil's OBS Remote - obs_data_t* data = obs_data_create(); - obs_data_set_bool(data, "preview-only", false); + // Implements an existing update type from bilhamil's OBS Remote + obs_data_t* data = obs_data_create(); + obs_data_set_bool(data, "preview-only", false); - broadcastUpdate("StreamStopping", data); + broadcastUpdate("StreamStopping", data); - obs_data_release(data); + obs_data_release(data); } void WSEvents::OnStreamStopped() { - // New update type specific to OBS Studio - _stream_starttime = 0; - broadcastUpdate("StreamStopped"); + // New update type specific to OBS Studio + _stream_starttime = 0; + broadcastUpdate("StreamStopped"); } void WSEvents::OnRecordingStarting() { - // New update type specific to OBS Studio - broadcastUpdate("RecordingStarting"); + // New update type specific to OBS Studio + broadcastUpdate("RecordingStarting"); } void WSEvents::OnRecordingStarted() { - // New update type specific to OBS Studio - _rec_starttime = os_gettime_ns(); - broadcastUpdate("RecordingStarted"); + // New update type specific to OBS Studio + _rec_starttime = os_gettime_ns(); + broadcastUpdate("RecordingStarted"); } void WSEvents::OnRecordingStopping() { - // New update type specific to OBS Studio - broadcastUpdate("RecordingStopping"); + // New update type specific to OBS Studio + broadcastUpdate("RecordingStopping"); } void WSEvents::OnRecordingStopped() { - // New update type specific to OBS Studio - _rec_starttime = 0; - broadcastUpdate("RecordingStopped"); + // New update type specific to OBS Studio + _rec_starttime = 0; + broadcastUpdate("RecordingStopped"); } void WSEvents::OnExit() { - // New update type specific to OBS Studio - broadcastUpdate("Exiting"); + // New update type specific to OBS Studio + broadcastUpdate("Exiting"); } void WSEvents::StreamStatus() { - bool streaming_active = obs_frontend_streaming_active(); - bool recording_active = obs_frontend_recording_active(); + bool streaming_active = obs_frontend_streaming_active(); + bool recording_active = obs_frontend_recording_active(); - obs_output_t* stream_output = obs_frontend_get_streaming_output(); + obs_output_t* stream_output = obs_frontend_get_streaming_output(); - if (!stream_output || !streaming_active) { + if (!stream_output || !streaming_active) { if (stream_output) { obs_output_release(stream_output); } - return; - } + return; + } - uint64_t bytes_sent = obs_output_get_total_bytes(stream_output); - uint64_t bytes_sent_time = os_gettime_ns(); + uint64_t bytes_sent = obs_output_get_total_bytes(stream_output); + uint64_t bytes_sent_time = os_gettime_ns(); - if (bytes_sent < _lastBytesSent) - bytes_sent = 0; + if (bytes_sent < _lastBytesSent) + bytes_sent = 0; - if (bytes_sent == 0) - _lastBytesSent = 0; + if (bytes_sent == 0) + _lastBytesSent = 0; - uint64_t bytes_between = bytes_sent - _lastBytesSent; - double time_passed = - double(bytes_sent_time - _lastBytesSentTime) / 1000000000.0; + uint64_t bytes_between = bytes_sent - _lastBytesSent; + double time_passed = + double(bytes_sent_time - _lastBytesSentTime) / 1000000000.0; - uint64_t bytes_per_sec = bytes_between / time_passed; + uint64_t bytes_per_sec = bytes_between / time_passed; - _lastBytesSent = bytes_sent; - _lastBytesSentTime = bytes_sent_time; + _lastBytesSent = bytes_sent; + _lastBytesSentTime = bytes_sent_time; - uint64_t totalStreamTime = - (os_gettime_ns() - _stream_starttime) / 1000000000; + uint64_t totalStreamTime = + (os_gettime_ns() - _stream_starttime) / 1000000000; - int total_frames = obs_output_get_total_frames(stream_output); - int dropped_frames = obs_output_get_frames_dropped(stream_output); + int total_frames = obs_output_get_total_frames(stream_output); + int dropped_frames = obs_output_get_frames_dropped(stream_output); - float strain = obs_output_get_congestion(stream_output); + float strain = obs_output_get_congestion(stream_output); - 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); - 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_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 + 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); + 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_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); + broadcastUpdate("StreamStatus", data); - obs_data_release(data); - obs_output_release(stream_output); + obs_data_release(data); + obs_output_release(stream_output); } void WSEvents::TransitionDurationChanged(int ms) { - obs_data_t* fields = obs_data_create(); - obs_data_set_int(fields, "new-duration", ms); + obs_data_t* fields = obs_data_create(); + obs_data_set_int(fields, "new-duration", ms); - broadcastUpdate("TransitionDurationChanged", fields); + broadcastUpdate("TransitionDurationChanged", fields); - obs_data_release(fields); + obs_data_release(fields); } void WSEvents::OnTransitionBegin(void* param, calldata_t* data) { - UNUSED_PARAMETER(data); + UNUSED_PARAMETER(data); - WSEvents* instance = static_cast(param); - instance->broadcastUpdate("TransitionBegin"); + WSEvents* instance = static_cast(param); + instance->broadcastUpdate("TransitionBegin"); - blog(LOG_INFO, "transition begin"); + blog(LOG_INFO, "transition begin"); } void WSEvents::OnSceneReordered(void* param, calldata_t* data) { - WSEvents* instance = static_cast(param); + WSEvents* instance = static_cast(param); - obs_scene_t* scene = nullptr; - calldata_get_ptr(data, "scene", &scene); + obs_scene_t* scene = nullptr; + calldata_get_ptr(data, "scene", &scene); - obs_data_t* fields = obs_data_create(); - obs_data_set_string(fields, "scene-name", - obs_source_get_name(obs_scene_get_source(scene))); + obs_data_t* fields = obs_data_create(); + obs_data_set_string(fields, "scene-name", + obs_source_get_name(obs_scene_get_source(scene))); - instance->broadcastUpdate("SourceOrderChanged", fields); + instance->broadcastUpdate("SourceOrderChanged", fields); - obs_data_release(fields); + obs_data_release(fields); } void WSEvents::OnSceneItemAdd(void* param, calldata_t* data) { - WSEvents* instance = static_cast(param); + WSEvents* instance = static_cast(param); - obs_scene_t* scene = nullptr; - calldata_get_ptr(data, "scene", &scene); + 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* scene_item = nullptr; + calldata_get_ptr(data, "item", &scene_item); - const char* scene_name = - 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* scene_name = + obs_source_get_name(obs_scene_get_source(scene)); + const char* sceneitem_name = + obs_source_get_name(obs_sceneitem_get_source(scene_item)); - 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); + 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); - instance->broadcastUpdate("SceneItemAdded", fields); + instance->broadcastUpdate("SceneItemAdded", fields); - obs_data_release(fields); + obs_data_release(fields); } void WSEvents::OnSceneItemDelete(void* param, calldata_t* data) { - WSEvents* instance = static_cast(param); + WSEvents* instance = static_cast(param); - obs_scene_t* scene = nullptr; - calldata_get_ptr(data, "scene", &scene); + 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* scene_item = nullptr; + calldata_get_ptr(data, "item", &scene_item); - const char* scene_name = - 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* scene_name = + obs_source_get_name(obs_scene_get_source(scene)); + const char* sceneitem_name = + obs_source_get_name(obs_sceneitem_get_source(scene_item)); - 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); + 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); - instance->broadcastUpdate("SceneItemRemoved", fields); + instance->broadcastUpdate("SceneItemRemoved", fields); - obs_data_release(fields); + obs_data_release(fields); } void WSEvents::OnSceneItemVisibilityChanged(void* param, calldata_t* data) { - WSEvents* instance = static_cast(param); + WSEvents* instance = static_cast(param); - obs_scene_t* scene = nullptr; - calldata_get_ptr(data, "scene", &scene); + 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* scene_item = nullptr; + calldata_get_ptr(data, "item", &scene_item); - bool visible = false; - calldata_get_bool(data, "visible", &visible); + bool visible = false; + calldata_get_bool(data, "visible", &visible); - const char* scene_name = - 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* scene_name = + obs_source_get_name(obs_scene_get_source(scene)); + const char* sceneitem_name = + obs_source_get_name(obs_sceneitem_get_source(scene_item)); - 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); - obs_data_set_bool(fields, "item-visible", visible); + 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); + obs_data_set_bool(fields, "item-visible", visible); - instance->broadcastUpdate("SceneItemVisibilityChanged", fields); + instance->broadcastUpdate("SceneItemVisibilityChanged", fields); - obs_data_release(fields); + obs_data_release(fields); } void WSEvents::SelectedSceneChanged(QListWidgetItem* current, QListWidgetItem* prev) { - if (Utils::IsPreviewModeActive()) { - obs_scene_t* scene = Utils::SceneListItemToScene(current); - if (!scene) return; + if (Utils::IsPreviewModeActive()) { + obs_scene_t* 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); + obs_source_t* scene_source = obs_scene_get_source(scene); + obs_data_array_t* scene_items = Utils::GetSceneItems(scene_source); - 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); + 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); - broadcastUpdate("PreviewSceneChanged", data); + broadcastUpdate("PreviewSceneChanged", data); - obs_data_array_release(scene_items); - obs_data_release(data); - } + obs_data_array_release(scene_items); + obs_data_release(data); + } } void WSEvents::ModeSwitchClicked(bool checked) { - obs_data_t* data = obs_data_create(); - obs_data_set_bool(data, "new-state", checked); + obs_data_t* data = obs_data_create(); + obs_data_set_bool(data, "new-state", checked); - broadcastUpdate("StudioModeSwitched", data); + broadcastUpdate("StudioModeSwitched", data); - obs_data_release(data); + obs_data_release(data); } diff --git a/WSRequestHandler.cpp b/WSRequestHandler.cpp index e026da16..0ad42083 100644 --- a/WSRequestHandler.cpp +++ b/WSRequestHandler.cpp @@ -27,133 +27,133 @@ with this program. If not, see bool str_valid(const char* str) { - return (str != nullptr && strlen(str) > 0); + return (str != nullptr && strlen(str) > 0); } obs_service_t* WSRequestHandler::_service = nullptr; WSRequestHandler::WSRequestHandler(QWebSocket* client) : - _messageId(0), - _requestType(""), - data(nullptr) + _messageId(0), + _requestType(""), + data(nullptr) { - _client = client; + _client = client; - messageMap["GetVersion"] = WSRequestHandler::HandleGetVersion; - messageMap["GetAuthRequired"] = WSRequestHandler::HandleGetAuthRequired; - messageMap["Authenticate"] = WSRequestHandler::HandleAuthenticate; + messageMap["GetVersion"] = WSRequestHandler::HandleGetVersion; + messageMap["GetAuthRequired"] = WSRequestHandler::HandleGetAuthRequired; + messageMap["Authenticate"] = WSRequestHandler::HandleAuthenticate; - messageMap["SetCurrentScene"] = WSRequestHandler::HandleSetCurrentScene; - messageMap["GetCurrentScene"] = WSRequestHandler::HandleGetCurrentScene; - messageMap["GetSceneList"] = WSRequestHandler::HandleGetSceneList; + messageMap["SetCurrentScene"] = WSRequestHandler::HandleSetCurrentScene; + messageMap["GetCurrentScene"] = WSRequestHandler::HandleGetCurrentScene; + messageMap["GetSceneList"] = WSRequestHandler::HandleGetSceneList; - messageMap["SetSourceRender"] = WSRequestHandler::HandleSetSceneItemRender; // Retrocompat - messageMap["SetSceneItemRender"] = WSRequestHandler::HandleSetSceneItemRender; - messageMap["SetSceneItemPosition"] = WSRequestHandler::HandleSetSceneItemPosition; - messageMap["SetSceneItemTransform"] = WSRequestHandler::HandleSetSceneItemTransform; - messageMap["SetSceneItemCrop"] = WSRequestHandler::HandleSetSceneItemCrop; + messageMap["SetSourceRender"] = WSRequestHandler::HandleSetSceneItemRender; // Retrocompat + messageMap["SetSceneItemRender"] = WSRequestHandler::HandleSetSceneItemRender; + messageMap["SetSceneItemPosition"] = WSRequestHandler::HandleSetSceneItemPosition; + messageMap["SetSceneItemTransform"] = WSRequestHandler::HandleSetSceneItemTransform; + messageMap["SetSceneItemCrop"] = WSRequestHandler::HandleSetSceneItemCrop; - messageMap["GetStreamingStatus"] = WSRequestHandler::HandleGetStreamingStatus; - messageMap["StartStopStreaming"] = WSRequestHandler::HandleStartStopStreaming; - messageMap["StartStopRecording"] = WSRequestHandler::HandleStartStopRecording; - messageMap["StartStreaming"] = WSRequestHandler::HandleStartStreaming; - messageMap["StopStreaming"] = WSRequestHandler::HandleStopStreaming; - messageMap["StartRecording"] = WSRequestHandler::HandleStartRecording; - messageMap["StopRecording"] = WSRequestHandler::HandleStopRecording; + messageMap["GetStreamingStatus"] = WSRequestHandler::HandleGetStreamingStatus; + messageMap["StartStopStreaming"] = WSRequestHandler::HandleStartStopStreaming; + messageMap["StartStopRecording"] = WSRequestHandler::HandleStartStopRecording; + messageMap["StartStreaming"] = WSRequestHandler::HandleStartStreaming; + messageMap["StopStreaming"] = WSRequestHandler::HandleStopStreaming; + messageMap["StartRecording"] = WSRequestHandler::HandleStartRecording; + messageMap["StopRecording"] = WSRequestHandler::HandleStopRecording; - messageMap["SetRecordingFolder"] = WSRequestHandler::HandleSetRecordingFolder; - messageMap["GetRecordingFolder"] = WSRequestHandler::HandleGetRecordingFolder; + messageMap["SetRecordingFolder"] = WSRequestHandler::HandleSetRecordingFolder; + messageMap["GetRecordingFolder"] = WSRequestHandler::HandleGetRecordingFolder; - messageMap["GetTransitionList"] = WSRequestHandler::HandleGetTransitionList; - messageMap["GetCurrentTransition"] = WSRequestHandler::HandleGetCurrentTransition; - messageMap["SetCurrentTransition"] = WSRequestHandler::HandleSetCurrentTransition; - messageMap["SetTransitionDuration"] = WSRequestHandler::HandleSetTransitionDuration; - messageMap["GetTransitionDuration"] = WSRequestHandler::HandleGetTransitionDuration; + messageMap["GetTransitionList"] = WSRequestHandler::HandleGetTransitionList; + messageMap["GetCurrentTransition"] = WSRequestHandler::HandleGetCurrentTransition; + messageMap["SetCurrentTransition"] = WSRequestHandler::HandleSetCurrentTransition; + messageMap["SetTransitionDuration"] = WSRequestHandler::HandleSetTransitionDuration; + messageMap["GetTransitionDuration"] = WSRequestHandler::HandleGetTransitionDuration; - messageMap["SetVolume"] = WSRequestHandler::HandleSetVolume; - messageMap["GetVolume"] = WSRequestHandler::HandleGetVolume; - messageMap["ToggleMute"] = WSRequestHandler::HandleToggleMute; - messageMap["SetMute"] = WSRequestHandler::HandleSetMute; - messageMap["GetMute"] = WSRequestHandler::HandleGetMute; - messageMap["GetSpecialSources"] = WSRequestHandler::HandleGetSpecialSources; + messageMap["SetVolume"] = WSRequestHandler::HandleSetVolume; + messageMap["GetVolume"] = WSRequestHandler::HandleGetVolume; + messageMap["ToggleMute"] = WSRequestHandler::HandleToggleMute; + messageMap["SetMute"] = WSRequestHandler::HandleSetMute; + messageMap["GetMute"] = WSRequestHandler::HandleGetMute; + messageMap["GetSpecialSources"] = WSRequestHandler::HandleGetSpecialSources; - messageMap["SetCurrentSceneCollection"] = WSRequestHandler::HandleSetCurrentSceneCollection; - messageMap["GetCurrentSceneCollection"] = WSRequestHandler::HandleGetCurrentSceneCollection; - messageMap["ListSceneCollections"] = WSRequestHandler::HandleListSceneCollections; + messageMap["SetCurrentSceneCollection"] = WSRequestHandler::HandleSetCurrentSceneCollection; + messageMap["GetCurrentSceneCollection"] = WSRequestHandler::HandleGetCurrentSceneCollection; + messageMap["ListSceneCollections"] = WSRequestHandler::HandleListSceneCollections; - messageMap["SetCurrentProfile"] = WSRequestHandler::HandleSetCurrentProfile; - messageMap["GetCurrentProfile"] = WSRequestHandler::HandleGetCurrentProfile; - messageMap["ListProfiles"] = WSRequestHandler::HandleListProfiles; + messageMap["SetCurrentProfile"] = WSRequestHandler::HandleSetCurrentProfile; + messageMap["GetCurrentProfile"] = WSRequestHandler::HandleGetCurrentProfile; + messageMap["ListProfiles"] = WSRequestHandler::HandleListProfiles; - messageMap["SetStreamSettings"] = WSRequestHandler::HandleSetStreamSettings; - messageMap["GetStreamSettings"] = WSRequestHandler::HandleGetStreamSettings; - messageMap["SaveStreamSettings"] = WSRequestHandler::HandleSaveStreamSettings; + messageMap["SetStreamSettings"] = WSRequestHandler::HandleSetStreamSettings; + messageMap["GetStreamSettings"] = WSRequestHandler::HandleGetStreamSettings; + messageMap["SaveStreamSettings"] = WSRequestHandler::HandleSaveStreamSettings; - messageMap["GetStudioModeStatus"] = WSRequestHandler::HandleGetStudioModeStatus; - messageMap["GetPreviewScene"] = WSRequestHandler::HandleGetPreviewScene; - messageMap["SetPreviewScene"] = WSRequestHandler::HandleSetPreviewScene; - messageMap["TransitionToProgram"] = WSRequestHandler::HandleTransitionToProgram; - messageMap["EnableStudioMode"] = WSRequestHandler::HandleEnableStudioMode; - messageMap["DisableStudioMode"] = WSRequestHandler::HandleDisableStudioMode; - messageMap["ToggleStudioMode"] = WSRequestHandler::HandleToggleStudioMode; + messageMap["GetStudioModeStatus"] = WSRequestHandler::HandleGetStudioModeStatus; + messageMap["GetPreviewScene"] = WSRequestHandler::HandleGetPreviewScene; + messageMap["SetPreviewScene"] = WSRequestHandler::HandleSetPreviewScene; + messageMap["TransitionToProgram"] = WSRequestHandler::HandleTransitionToProgram; + messageMap["EnableStudioMode"] = WSRequestHandler::HandleEnableStudioMode; + messageMap["DisableStudioMode"] = WSRequestHandler::HandleDisableStudioMode; + messageMap["ToggleStudioMode"] = WSRequestHandler::HandleToggleStudioMode; - messageMap["SetTextGDIPlusProperties"] = WSRequestHandler::HandleSetTextGDIPlusProperties; - messageMap["GetTextGDIPlusProperties"] = WSRequestHandler::HandleGetTextGDIPlusProperties; + messageMap["SetTextGDIPlusProperties"] = WSRequestHandler::HandleSetTextGDIPlusProperties; + messageMap["GetTextGDIPlusProperties"] = WSRequestHandler::HandleGetTextGDIPlusProperties; - messageMap["GetBrowserSourceProperties"] = WSRequestHandler::HandleGetBrowserSourceProperties; - messageMap["SetBrowserSourceProperties"] = WSRequestHandler::HandleSetBrowserSourceProperties; + messageMap["GetBrowserSourceProperties"] = WSRequestHandler::HandleGetBrowserSourceProperties; + messageMap["SetBrowserSourceProperties"] = WSRequestHandler::HandleSetBrowserSourceProperties; - authNotRequired.insert("GetVersion"); - authNotRequired.insert("GetAuthRequired"); - authNotRequired.insert("Authenticate"); + authNotRequired.insert("GetVersion"); + authNotRequired.insert("GetAuthRequired"); + authNotRequired.insert("Authenticate"); } void WSRequestHandler::processIncomingMessage(QString textMessage) { - QByteArray msgData = textMessage.toUtf8(); - const char* msg = msgData; + QByteArray msgData = textMessage.toUtf8(); + const char* msg = msgData; - data = obs_data_create_from_json(msg); - if (!data) - { - if (!msg) - msg = ""; + data = obs_data_create_from_json(msg); + if (!data) + { + if (!msg) + msg = ""; - blog(LOG_ERROR, "invalid JSON payload received for '%s'", msg); - SendErrorResponse("invalid JSON payload"); - return; - } - - if (Config::Current()->DebugEnabled) - blog(LOG_DEBUG, "Request >> '%s'", msg); + blog(LOG_ERROR, "invalid JSON payload received for '%s'", msg); + SendErrorResponse("invalid JSON payload"); + return; + } + + if (Config::Current()->DebugEnabled) + blog(LOG_DEBUG, "Request >> '%s'", msg); - if (!hasField("request-type") || - !hasField("message-id")) - { - SendErrorResponse("missing request parameters"); - return; - } + if (!hasField("request-type") || + !hasField("message-id")) + { + SendErrorResponse("missing request parameters"); + return; + } - _requestType = obs_data_get_string(data, "request-type"); - _messageId = obs_data_get_string(data, "message-id"); + _requestType = obs_data_get_string(data, "request-type"); + _messageId = obs_data_get_string(data, "message-id"); - if (Config::Current()->AuthRequired - && (_client->property(PROP_AUTHENTICATED).toBool() == false) - && (authNotRequired.find(_requestType) == authNotRequired.end())) - { - SendErrorResponse("Not Authenticated"); - return; - } + if (Config::Current()->AuthRequired + && (_client->property(PROP_AUTHENTICATED).toBool() == false) + && (authNotRequired.find(_requestType) == authNotRequired.end())) + { + SendErrorResponse("Not Authenticated"); + return; + } - void (*handlerFunc)(WSRequestHandler*) = (messageMap[_requestType]); + void (*handlerFunc)(WSRequestHandler*) = (messageMap[_requestType]); - if (handlerFunc != NULL) - handlerFunc(this); - else - SendErrorResponse("invalid request type"); + if (handlerFunc != NULL) + handlerFunc(this); + else + SendErrorResponse("invalid request type"); - obs_data_release(data); + obs_data_release(data); } WSRequestHandler::~WSRequestHandler() @@ -162,1550 +162,1550 @@ WSRequestHandler::~WSRequestHandler() void WSRequestHandler::SendOKResponse(obs_data_t* additionalFields) { - obs_data_t* response = obs_data_create(); - obs_data_set_string(response, "status", "ok"); - obs_data_set_string(response, "message-id", _messageId); + obs_data_t* response = obs_data_create(); + obs_data_set_string(response, "status", "ok"); + obs_data_set_string(response, "message-id", _messageId); - if (additionalFields) - obs_data_apply(response, additionalFields); + if (additionalFields) + obs_data_apply(response, additionalFields); - SendResponse(response); + SendResponse(response); } void WSRequestHandler::SendErrorResponse(const char* errorMessage) { - obs_data_t* 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); + obs_data_t* 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); - SendResponse(response); + SendResponse(response); } void WSRequestHandler::SendResponse(obs_data_t* response) { - const char *json = obs_data_get_json(response); - _client->sendTextMessage(json); - if (Config::Current()->DebugEnabled) - blog(LOG_DEBUG, "Response << '%s'", json); - - obs_data_release(response); + const char *json = obs_data_get_json(response); + _client->sendTextMessage(json); + if (Config::Current()->DebugEnabled) + blog(LOG_DEBUG, "Response << '%s'", json); + + obs_data_release(response); } bool WSRequestHandler::hasField(const char* name) { - if (!name || !data) - return false; + if (!name || !data) + return false; - return obs_data_has_user_value(data, name); + return obs_data_has_user_value(data, name); } void WSRequestHandler::HandleGetVersion(WSRequestHandler* req) { - const char* obs_version = Utils::OBSVersionString(); + const char* obs_version = Utils::OBSVersionString(); - obs_data_t* data = obs_data_create(); - obs_data_set_double(data, "version", API_VERSION); - obs_data_set_string(data, "obs-websocket-version", OBS_WEBSOCKET_VERSION); - obs_data_set_string(data, "obs-studio-version", obs_version); + obs_data_t* data = obs_data_create(); + obs_data_set_double(data, "version", API_VERSION); + obs_data_set_string(data, "obs-websocket-version", OBS_WEBSOCKET_VERSION); + obs_data_set_string(data, "obs-studio-version", obs_version); - req->SendOKResponse(data); + req->SendOKResponse(data); - obs_data_release(data); - bfree((void*)obs_version); + obs_data_release(data); + bfree((void*)obs_version); } void WSRequestHandler::HandleGetAuthRequired(WSRequestHandler* req) { - bool authRequired = Config::Current()->AuthRequired; + bool authRequired = Config::Current()->AuthRequired; - obs_data_t* data = obs_data_create(); - obs_data_set_bool(data, "authRequired", authRequired); + obs_data_t* data = obs_data_create(); + obs_data_set_bool(data, "authRequired", authRequired); - if (authRequired) - { - obs_data_set_string(data, "challenge", - Config::Current()->SessionChallenge); - obs_data_set_string(data, "salt", - Config::Current()->Salt); - } + if (authRequired) + { + obs_data_set_string(data, "challenge", + Config::Current()->SessionChallenge); + obs_data_set_string(data, "salt", + Config::Current()->Salt); + } - req->SendOKResponse(data); + req->SendOKResponse(data); - obs_data_release(data); + obs_data_release(data); } void WSRequestHandler::HandleAuthenticate(WSRequestHandler* req) { - if (!req->hasField("auth")) - { - req->SendErrorResponse("missing request parameters"); - return; - } + if (!req->hasField("auth")) + { + req->SendErrorResponse("missing request parameters"); + return; + } - const char* auth = obs_data_get_string(req->data, "auth"); - if (!str_valid(auth)) - { - req->SendErrorResponse("auth not specified!"); - return; - } + const char* auth = obs_data_get_string(req->data, "auth"); + if (!str_valid(auth)) + { + req->SendErrorResponse("auth not specified!"); + return; + } - if ((req->_client->property(PROP_AUTHENTICATED).toBool() == false) - && Config::Current()->CheckAuth(auth)) - { - req->_client->setProperty(PROP_AUTHENTICATED, true); - req->SendOKResponse(); - } - else - { - req->SendErrorResponse("Authentication Failed."); - } + if ((req->_client->property(PROP_AUTHENTICATED).toBool() == false) + && Config::Current()->CheckAuth(auth)) + { + req->_client->setProperty(PROP_AUTHENTICATED, true); + req->SendOKResponse(); + } + else + { + req->SendErrorResponse("Authentication Failed."); + } } void WSRequestHandler::HandleSetCurrentScene(WSRequestHandler* req) { - if (!req->hasField("scene-name")) - { - req->SendErrorResponse("missing request parameters"); - return; - } + if (!req->hasField("scene-name")) + { + req->SendErrorResponse("missing request parameters"); + return; + } - const char* sceneName = obs_data_get_string(req->data, "scene-name"); - obs_source_t* source = obs_get_source_by_name(sceneName); + const char* sceneName = obs_data_get_string(req->data, "scene-name"); + obs_source_t* source = obs_get_source_by_name(sceneName); - if (source) - { - obs_frontend_set_current_scene(source); - req->SendOKResponse(); - } - else - { - req->SendErrorResponse("requested scene does not exist"); - } + if (source) + { + obs_frontend_set_current_scene(source); + req->SendOKResponse(); + } + else + { + req->SendErrorResponse("requested scene does not exist"); + } - obs_source_release(source); + obs_source_release(source); } void WSRequestHandler::HandleGetCurrentScene(WSRequestHandler* req) { - obs_source_t* current_scene = obs_frontend_get_current_scene(); - const char* name = obs_source_get_name(current_scene); + obs_source_t* current_scene = obs_frontend_get_current_scene(); + const char* name = obs_source_get_name(current_scene); - obs_data_array_t* scene_items = Utils::GetSceneItems(current_scene); + 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); + obs_data_t* data = obs_data_create(); + obs_data_set_string(data, "name", name); + obs_data_set_array(data, "sources", scene_items); - req->SendOKResponse(data); + req->SendOKResponse(data); - obs_data_release(data); - obs_data_array_release(scene_items); - obs_source_release(current_scene); + obs_data_release(data); + obs_data_array_release(scene_items); + obs_source_release(current_scene); } void WSRequestHandler::HandleGetSceneList(WSRequestHandler* req) { - obs_source_t* current_scene = obs_frontend_get_current_scene(); - obs_data_array_t* scenes = Utils::GetScenes(); + obs_source_t* current_scene = obs_frontend_get_current_scene(); + obs_data_array_t* scenes = Utils::GetScenes(); - obs_data_t* data = obs_data_create(); - obs_data_set_string(data, "current-scene", - obs_source_get_name(current_scene)); - obs_data_set_array(data, "scenes", scenes); + obs_data_t* data = obs_data_create(); + obs_data_set_string(data, "current-scene", + obs_source_get_name(current_scene)); + obs_data_set_array(data, "scenes", scenes); - req->SendOKResponse(data); + req->SendOKResponse(data); - obs_data_release(data); - obs_data_array_release(scenes); - obs_source_release(current_scene); + obs_data_release(data); + obs_data_array_release(scenes); + obs_source_release(current_scene); } void WSRequestHandler::HandleSetSceneItemRender(WSRequestHandler* req) { - if (!req->hasField("source") || - !req->hasField("render")) - { - req->SendErrorResponse("missing request parameters"); - return; - } + if (!req->hasField("source") || + !req->hasField("render")) + { + req->SendErrorResponse("missing request parameters"); + return; + } - const char* itemName = obs_data_get_string(req->data, "source"); - bool isVisible = obs_data_get_bool(req->data, "render"); + const char* itemName = obs_data_get_string(req->data, "source"); + bool isVisible = obs_data_get_bool(req->data, "render"); - if (!itemName) - { - req->SendErrorResponse("invalid request parameters"); - return; - } + if (!itemName) + { + req->SendErrorResponse("invalid request parameters"); + return; + } - const char* sceneName = obs_data_get_string(req->data, "scene-name"); - obs_source_t* scene = Utils::GetSceneFromNameOrCurrent(sceneName); - if (scene == NULL) { - req->SendErrorResponse("requested scene doesn't exist"); - return; - } + const char* sceneName = obs_data_get_string(req->data, "scene-name"); + obs_source_t* scene = Utils::GetSceneFromNameOrCurrent(sceneName); + if (scene == NULL) { + req->SendErrorResponse("requested scene doesn't exist"); + return; + } - obs_sceneitem_t* sceneItem = Utils::GetSceneItemFromName(scene, itemName); - if (sceneItem != NULL) - { - obs_sceneitem_set_visible(sceneItem, isVisible); - obs_sceneitem_release(sceneItem); - req->SendOKResponse(); - } - else - { - req->SendErrorResponse("specified scene item doesn't exist"); - } + obs_sceneitem_t* sceneItem = Utils::GetSceneItemFromName(scene, itemName); + if (sceneItem != NULL) + { + 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); + obs_source_release(scene); } void WSRequestHandler::HandleGetStreamingStatus(WSRequestHandler* req) { - obs_data_t* 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); + obs_data_t* 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); - const char* tc = nullptr; - if (obs_frontend_streaming_active()) - { - tc = WSEvents::Instance->GetStreamingTimecode(); - obs_data_set_string(data, "stream-timecode", tc); - bfree((void*)tc); - } + const char* tc = nullptr; + if (obs_frontend_streaming_active()) + { + tc = WSEvents::Instance->GetStreamingTimecode(); + obs_data_set_string(data, "stream-timecode", tc); + bfree((void*)tc); + } - if (obs_frontend_recording_active()) - { - tc = WSEvents::Instance->GetRecordingTimecode(); - obs_data_set_string(data, "rec-timecode", tc); - bfree((void*)tc); - } + if (obs_frontend_recording_active()) + { + tc = WSEvents::Instance->GetRecordingTimecode(); + obs_data_set_string(data, "rec-timecode", tc); + bfree((void*)tc); + } - req->SendOKResponse(data); - obs_data_release(data); + req->SendOKResponse(data); + obs_data_release(data); } void WSRequestHandler::HandleStartStopStreaming(WSRequestHandler* req) { - if (obs_frontend_streaming_active()) - { - HandleStopStreaming(req); - } - else - { - HandleStartStreaming(req); - } + if (obs_frontend_streaming_active()) + { + HandleStopStreaming(req); + } + else + { + HandleStartStreaming(req); + } } void WSRequestHandler::HandleStartStopRecording(WSRequestHandler* req) { - if (obs_frontend_recording_active()) - obs_frontend_recording_stop(); - else - obs_frontend_recording_start(); + if (obs_frontend_recording_active()) + obs_frontend_recording_stop(); + else + obs_frontend_recording_start(); - req->SendOKResponse(); + req->SendOKResponse(); } void WSRequestHandler::HandleStartStreaming(WSRequestHandler* req) { - if (obs_frontend_streaming_active() == false) - { - obs_data_t* streamData = obs_data_get_obj(req->data, "stream"); - obs_service_t* currentService = nullptr; - - if (streamData) - { - currentService = obs_frontend_get_streaming_service(); - obs_service_addref(currentService); - - obs_service_t* service = _service; - const char* currentServiceType = obs_service_get_type(currentService); - - const char* requestedType = obs_data_has_user_value(streamData, "type") ? obs_data_get_string(streamData, "type") : currentServiceType; - const char* serviceType = service != nullptr ? obs_service_get_type(service) : currentServiceType; - obs_data_t* settings = obs_data_get_obj(streamData, "settings"); - - - obs_data_t* metadata = obs_data_get_obj(streamData, "metadata"); - QString* query = Utils::ParseDataToQueryString(metadata); - - if (strcmp(requestedType, serviceType) != 0) - { - if (settings) - { - obs_service_release(service); - service = nullptr; //different type so we can't reuse the existing service instance - } - else - { - req->SendErrorResponse("Service type requested does not match currently configured type and no 'settings' were provided"); - return; - } - } - else - { - //if type isn't changing we should overlay the settings we got with the existing settings - obs_data_t* existingSettings = obs_service_get_settings(currentService); - obs_data_t* newSettings = obs_data_create(); //by doing this you can send a request to the websocket that only contains a setting you want to change instead of having to do a get and then change them - - obs_data_apply(newSettings, existingSettings); //first apply the existing settings - - obs_data_apply(newSettings, settings); //then apply the settings from the request should they exist - obs_data_release(settings); - - settings = newSettings; - obs_data_release(existingSettings); - } - - if (service == nullptr) - { //create the new custom service setup by the websocket - service = obs_service_create(requestedType, "websocket_custom_service", settings, nullptr); - } - - //Supporting adding metadata parameters to key query string - if (query && query->length() > 0) { - const char* key = obs_data_get_string(settings, "key"); - int keylen = strlen(key); - bool hasQuestionMark = false; - for (int i = 0; i < keylen; i++) { - if (key[i] == '?') { - hasQuestionMark = true; - break; - } - } - if (hasQuestionMark) { - query->prepend('&'); - } else { - query->prepend('?'); - } - query->prepend(key); - key = query->toUtf8(); - obs_data_set_string(settings, "key", key); - } - - obs_service_update(service, settings); - obs_data_release(settings); - obs_data_release(metadata); - _service = service; - obs_frontend_set_streaming_service(_service); - } else if (_service != nullptr) { - obs_service_release(_service); - _service = nullptr; - } - - obs_frontend_streaming_start(); - - if (_service != nullptr) { - obs_frontend_set_streaming_service(currentService); - } - - req->SendOKResponse(); - obs_service_release(currentService); - } - else - { - req->SendErrorResponse("streaming already active"); - } + if (obs_frontend_streaming_active() == false) + { + obs_data_t* streamData = obs_data_get_obj(req->data, "stream"); + obs_service_t* currentService = nullptr; + + if (streamData) + { + currentService = obs_frontend_get_streaming_service(); + obs_service_addref(currentService); + + obs_service_t* service = _service; + const char* currentServiceType = obs_service_get_type(currentService); + + const char* requestedType = obs_data_has_user_value(streamData, "type") ? obs_data_get_string(streamData, "type") : currentServiceType; + const char* serviceType = service != nullptr ? obs_service_get_type(service) : currentServiceType; + obs_data_t* settings = obs_data_get_obj(streamData, "settings"); + + + obs_data_t* metadata = obs_data_get_obj(streamData, "metadata"); + QString* query = Utils::ParseDataToQueryString(metadata); + + if (strcmp(requestedType, serviceType) != 0) + { + if (settings) + { + obs_service_release(service); + service = nullptr; //different type so we can't reuse the existing service instance + } + else + { + req->SendErrorResponse("Service type requested does not match currently configured type and no 'settings' were provided"); + return; + } + } + else + { + //if type isn't changing we should overlay the settings we got with the existing settings + obs_data_t* existingSettings = obs_service_get_settings(currentService); + obs_data_t* newSettings = obs_data_create(); //by doing this you can send a request to the websocket that only contains a setting you want to change instead of having to do a get and then change them + + obs_data_apply(newSettings, existingSettings); //first apply the existing settings + + obs_data_apply(newSettings, settings); //then apply the settings from the request should they exist + obs_data_release(settings); + + settings = newSettings; + obs_data_release(existingSettings); + } + + if (service == nullptr) + { //create the new custom service setup by the websocket + service = obs_service_create(requestedType, "websocket_custom_service", settings, nullptr); + } + + //Supporting adding metadata parameters to key query string + if (query && query->length() > 0) { + const char* key = obs_data_get_string(settings, "key"); + int keylen = strlen(key); + bool hasQuestionMark = false; + for (int i = 0; i < keylen; i++) { + if (key[i] == '?') { + hasQuestionMark = true; + break; + } + } + if (hasQuestionMark) { + query->prepend('&'); + } else { + query->prepend('?'); + } + query->prepend(key); + key = query->toUtf8(); + obs_data_set_string(settings, "key", key); + } + + obs_service_update(service, settings); + obs_data_release(settings); + obs_data_release(metadata); + _service = service; + obs_frontend_set_streaming_service(_service); + } else if (_service != nullptr) { + obs_service_release(_service); + _service = nullptr; + } + + obs_frontend_streaming_start(); + + if (_service != nullptr) { + obs_frontend_set_streaming_service(currentService); + } + + req->SendOKResponse(); + obs_service_release(currentService); + } + else + { + req->SendErrorResponse("streaming already active"); + } } void WSRequestHandler::HandleStopStreaming(WSRequestHandler* req) { - if (obs_frontend_streaming_active() == true) - { - obs_frontend_streaming_stop(); - req->SendOKResponse(); - } - else - { - req->SendErrorResponse("streaming not active"); - } + if (obs_frontend_streaming_active() == true) + { + obs_frontend_streaming_stop(); + req->SendOKResponse(); + } + else + { + req->SendErrorResponse("streaming not active"); + } } void WSRequestHandler::HandleStartRecording(WSRequestHandler* req) { - if (obs_frontend_recording_active() == false) - { - obs_frontend_recording_start(); - req->SendOKResponse(); - } - else - { - req->SendErrorResponse("recording already active"); - } + if (obs_frontend_recording_active() == false) + { + obs_frontend_recording_start(); + req->SendOKResponse(); + } + else + { + req->SendErrorResponse("recording already active"); + } } void WSRequestHandler::HandleStopRecording(WSRequestHandler* req) { - if (obs_frontend_recording_active() == true) - { - obs_frontend_recording_stop(); - req->SendOKResponse(); - } - else - { - req->SendErrorResponse("recording not active"); - } + if (obs_frontend_recording_active() == true) + { + obs_frontend_recording_stop(); + req->SendOKResponse(); + } + else + { + req->SendErrorResponse("recording not active"); + } } void WSRequestHandler::HandleGetTransitionList(WSRequestHandler* req) { - obs_source_t* current_transition = obs_frontend_get_current_transition(); - obs_frontend_source_list transitionList = {}; - obs_frontend_get_transitions(&transitionList); + obs_source_t* current_transition = obs_frontend_get_current_transition(); + obs_frontend_source_list transitionList = {}; + obs_frontend_get_transitions(&transitionList); - obs_data_array_t* transitions = obs_data_array_create(); - for (size_t i = 0; i < transitionList.sources.num; i++) - { - obs_source_t* transition = transitionList.sources.array[i]; + obs_data_array_t* transitions = obs_data_array_create(); + for (size_t i = 0; i < transitionList.sources.num; i++) + { + obs_source_t* transition = transitionList.sources.array[i]; - obs_data_t* obj = obs_data_create(); - obs_data_set_string(obj, "name", obs_source_get_name(transition)); + obs_data_t* 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_array_push_back(transitions, obj); + obs_data_release(obj); + } + obs_frontend_source_list_free(&transitionList); - obs_data_t* response = obs_data_create(); - obs_data_set_string(response, "current-transition", - obs_source_get_name(current_transition)); - obs_data_set_array(response, "transitions", transitions); + obs_data_t* response = obs_data_create(); + obs_data_set_string(response, "current-transition", + obs_source_get_name(current_transition)); + obs_data_set_array(response, "transitions", transitions); - req->SendOKResponse(response); + req->SendOKResponse(response); - obs_data_release(response); - obs_data_array_release(transitions); - obs_source_release(current_transition); + obs_data_release(response); + obs_data_array_release(transitions); + obs_source_release(current_transition); } void WSRequestHandler::HandleGetCurrentTransition(WSRequestHandler* req) { - obs_source_t* current_transition = obs_frontend_get_current_transition(); + obs_source_t* current_transition = obs_frontend_get_current_transition(); - obs_data_t* response = obs_data_create(); - obs_data_set_string(response, "name", - obs_source_get_name(current_transition)); + obs_data_t* response = obs_data_create(); + obs_data_set_string(response, "name", + obs_source_get_name(current_transition)); - if (!obs_transition_fixed(current_transition)) - obs_data_set_int(response, "duration", Utils::GetTransitionDuration()); + if (!obs_transition_fixed(current_transition)) + obs_data_set_int(response, "duration", Utils::GetTransitionDuration()); - req->SendOKResponse(response); + req->SendOKResponse(response); - obs_data_release(response); - obs_source_release(current_transition); + obs_data_release(response); + obs_source_release(current_transition); } void WSRequestHandler::HandleSetCurrentTransition(WSRequestHandler* req) { - if (!req->hasField("transition-name")) - { - req->SendErrorResponse("missing request parameters"); - return; - } + if (!req->hasField("transition-name")) + { + req->SendErrorResponse("missing request parameters"); + return; + } - const char* name = obs_data_get_string(req->data, "transition-name"); + const char* name = obs_data_get_string(req->data, "transition-name"); - bool success = Utils::SetTransitionByName(name); + bool success = Utils::SetTransitionByName(name); - if (success) - req->SendOKResponse(); - else - req->SendErrorResponse("requested transition does not exist"); + if (success) + req->SendOKResponse(); + else + req->SendErrorResponse("requested transition does not exist"); } void WSRequestHandler::HandleSetTransitionDuration(WSRequestHandler* req) { - if (!req->hasField("duration")) - { - req->SendErrorResponse("missing request parameters"); - return; - } + if (!req->hasField("duration")) + { + req->SendErrorResponse("missing request parameters"); + return; + } - int ms = obs_data_get_int(req->data, "duration"); - Utils::SetTransitionDuration(ms); - req->SendOKResponse(); + int ms = obs_data_get_int(req->data, "duration"); + Utils::SetTransitionDuration(ms); + req->SendOKResponse(); } void WSRequestHandler::HandleGetTransitionDuration(WSRequestHandler* req) { - obs_data_t* response = obs_data_create(); - obs_data_set_int(response, "transition-duration", - Utils::GetTransitionDuration()); + obs_data_t* response = obs_data_create(); + obs_data_set_int(response, "transition-duration", + Utils::GetTransitionDuration()); - req->SendOKResponse(response); - obs_data_release(response); + req->SendOKResponse(response); + obs_data_release(response); } void WSRequestHandler::HandleSetVolume(WSRequestHandler* req) { - if (!req->hasField("source") || - !req->hasField("volume")) - { - req->SendErrorResponse("missing request parameters"); - return; - } + if (!req->hasField("source") || + !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"); + const char* source_name = obs_data_get_string(req->data, "source"); + float source_volume = obs_data_get_double(req->data, "volume"); - if (source_name == NULL || strlen(source_name) < 1 || - source_volume < 0.0 || source_volume > 1.0) - { - req->SendErrorResponse("invalid request parameters"); - return; - } + if (source_name == NULL || strlen(source_name) < 1 || + source_volume < 0.0 || source_volume > 1.0) + { + req->SendErrorResponse("invalid request parameters"); + return; + } - obs_source_t* source = obs_get_source_by_name(source_name); - if (!source) - { - req->SendErrorResponse("specified source doesn't exist"); - return; - } + obs_source_t* source = obs_get_source_by_name(source_name); + if (!source) + { + req->SendErrorResponse("specified source doesn't exist"); + return; + } - obs_source_set_volume(source, source_volume); - req->SendOKResponse(); + obs_source_set_volume(source, source_volume); + req->SendOKResponse(); - obs_source_release(source); + obs_source_release(source); } void WSRequestHandler::HandleGetVolume(WSRequestHandler* req) { - if (!req->hasField("source")) - { - req->SendErrorResponse("missing request parameters"); - return; - } + if (!req->hasField("source")) + { + req->SendErrorResponse("missing request parameters"); + return; + } - const char* source_name = obs_data_get_string(req->data, "source"); + 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); + if (str_valid(source_name)) + { + obs_source_t* source = obs_get_source_by_name(source_name); - obs_data_t* response = obs_data_create(); - obs_data_set_string(response, "name", source_name); - obs_data_set_double(response, "volume", obs_source_get_volume(source)); - obs_data_set_bool(response, "muted", obs_source_muted(source)); + obs_data_t* response = obs_data_create(); + obs_data_set_string(response, "name", source_name); + obs_data_set_double(response, "volume", obs_source_get_volume(source)); + obs_data_set_bool(response, "muted", obs_source_muted(source)); - req->SendOKResponse(response); + req->SendOKResponse(response); - obs_data_release(response); - obs_source_release(source); - } - else - { - req->SendErrorResponse("invalid request parameters"); - } + obs_data_release(response); + obs_source_release(source); + } + else + { + req->SendErrorResponse("invalid request parameters"); + } } void WSRequestHandler::HandleToggleMute(WSRequestHandler* req) { - if (!req->hasField("source")) - { - req->SendErrorResponse("missing request parameters"); - return; - } + if (!req->hasField("source")) + { + req->SendErrorResponse("missing request parameters"); + return; + } - const char* source_name = obs_data_get_string(req->data, "source"); - if (!str_valid(source_name)) - { - req->SendErrorResponse("invalid request parameters"); - return; - } + const char* source_name = obs_data_get_string(req->data, "source"); + if (!str_valid(source_name)) + { + req->SendErrorResponse("invalid request parameters"); + return; + } - obs_source_t* source = obs_get_source_by_name(source_name); - if (!source) - { - req->SendErrorResponse("invalid request parameters"); - return; - } + obs_source_t* source = obs_get_source_by_name(source_name); + if (!source) + { + req->SendErrorResponse("invalid request parameters"); + return; + } - obs_source_set_muted(source, !obs_source_muted(source)); - req->SendOKResponse(); + obs_source_set_muted(source, !obs_source_muted(source)); + req->SendOKResponse(); - obs_source_release(source); + obs_source_release(source); } void WSRequestHandler::HandleSetMute(WSRequestHandler* req) { - if (!req->hasField("source") || - !req->hasField("mute")) - { - req->SendErrorResponse("mssing request parameters"); - return; - } + if (!req->hasField("source") || + !req->hasField("mute")) + { + req->SendErrorResponse("mssing request parameters"); + return; + } - const char* source_name = obs_data_get_string(req->data, "source"); - bool mute = obs_data_get_bool(req->data, "mute"); + const char* source_name = obs_data_get_string(req->data, "source"); + bool mute = obs_data_get_bool(req->data, "mute"); - if (!str_valid(source_name)) - { - req->SendErrorResponse("invalid request parameters"); - return; - } + if (!str_valid(source_name)) + { + req->SendErrorResponse("invalid request parameters"); + return; + } - obs_source_t* source = obs_get_source_by_name(source_name); - if (!source) - { - req->SendErrorResponse("specified source doesn't exist"); - return; - } + obs_source_t* source = obs_get_source_by_name(source_name); + if (!source) + { + req->SendErrorResponse("specified source doesn't exist"); + return; + } - obs_source_set_muted(source, mute); - req->SendOKResponse(); + obs_source_set_muted(source, mute); + req->SendOKResponse(); - obs_source_release(source); + obs_source_release(source); } void WSRequestHandler::HandleGetMute(WSRequestHandler* req) { - if (!req->hasField("source")) - { - req->SendErrorResponse("mssing request parameters"); - return; - } + if (!req->hasField("source")) + { + req->SendErrorResponse("mssing request parameters"); + return; + } - const char* source_name = obs_data_get_string(req->data, "source"); + const char* source_name = obs_data_get_string(req->data, "source"); - if (!str_valid(source_name)) - { - req->SendErrorResponse("invalid request parameters"); - return; - } + if (!str_valid(source_name)) + { + req->SendErrorResponse("invalid request parameters"); + return; + } - obs_source_t* source = obs_get_source_by_name(source_name); - if (!source) - { - req->SendErrorResponse("specified source doesn't exist"); - return; - } + obs_source_t* source = obs_get_source_by_name(source_name); + if (!source) + { + req->SendErrorResponse("specified source doesn't exist"); + return; + } - obs_data_t* 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)); + obs_data_t* 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); + req->SendOKResponse(response); - obs_source_release(source); - obs_data_release(response); + obs_source_release(source); + obs_data_release(response); } void WSRequestHandler::HandleSetSceneItemPosition(WSRequestHandler* req) { - if (!req->hasField("item") || - !req->hasField("x") || !req->hasField("y")) - { - req->SendErrorResponse("missing request parameters"); - return; - } + if (!req->hasField("item") || + !req->hasField("x") || !req->hasField("y")) + { + req->SendErrorResponse("missing request parameters"); + return; + } - const char* item_name = obs_data_get_string(req->data, "item"); - if (!str_valid(item_name)) - { - req->SendErrorResponse("invalid request parameters"); - return; - } + const char* item_name = obs_data_get_string(req->data, "item"); + if (!str_valid(item_name)) + { + 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); - if (!scene) { - req->SendErrorResponse("requested scene could not be found"); - return; - } + const char* scene_name = obs_data_get_string(req->data, "scene-name"); + obs_source_t* scene = Utils::GetSceneFromNameOrCurrent(scene_name); + if (!scene) { + req->SendErrorResponse("requested scene could not be found"); + return; + } - obs_sceneitem_t* scene_item = Utils::GetSceneItemFromName(scene, item_name); + obs_sceneitem_t* scene_item = Utils::GetSceneItemFromName(scene, item_name); - if (scene_item) - { - vec2 item_position = { 0 }; - item_position.x = obs_data_get_double(req->data, "x"); - item_position.y = obs_data_get_double(req->data, "y"); + if (scene_item) + { + 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(scene_item, &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_sceneitem_release(scene_item); + req->SendOKResponse(); + } + else + { + req->SendErrorResponse("specified scene item doesn't exist"); + } - obs_source_release(scene); + obs_source_release(scene); } void WSRequestHandler::HandleSetSceneItemTransform(WSRequestHandler* req) { - if (!req->hasField("item") || - !req->hasField("x-scale") || - !req->hasField("y-scale") || - !req->hasField("rotation")) - { - req->SendErrorResponse("missing request parameters"); - return; - } + if (!req->hasField("item") || + !req->hasField("x-scale") || + !req->hasField("y-scale") || + !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)) - { - req->SendErrorResponse("invalid request parameters"); - return; - } + const char* item_name = obs_data_get_string(req->data, "item"); + if (!str_valid(item_name)) + { + 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); - if (!scene) { - req->SendErrorResponse("requested scene doesn't exist"); - return; - } + const char* scene_name = obs_data_get_string(req->data, "scene-name"); + obs_source_t* scene = Utils::GetSceneFromNameOrCurrent(scene_name); + if (!scene) { + req->SendErrorResponse("requested scene doesn't exist"); + return; + } - vec2 scale; - scale.x = obs_data_get_double(req->data, "x-scale"); - scale.y = obs_data_get_double(req->data, "y-scale"); + vec2 scale; + scale.x = obs_data_get_double(req->data, "x-scale"); + scale.y = obs_data_get_double(req->data, "y-scale"); - float rotation = obs_data_get_double(req->data, "rotation"); + float rotation = obs_data_get_double(req->data, "rotation"); - obs_sceneitem_t* scene_item = Utils::GetSceneItemFromName(scene, item_name); + 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); + if (scene_item) + { + obs_sceneitem_set_scale(scene_item, &scale); + obs_sceneitem_set_rot(scene_item, rotation); - obs_sceneitem_release(scene_item); - req->SendOKResponse(); - } - else - { - req->SendErrorResponse("specified scene item doesn't exist"); - } + obs_sceneitem_release(scene_item); + req->SendOKResponse(); + } + else + { + req->SendErrorResponse("specified scene item doesn't exist"); + } - obs_source_release(scene); + obs_source_release(scene); } void WSRequestHandler::HandleSetSceneItemCrop(WSRequestHandler* req) { - if (!req->hasField("item")) - { - req->SendErrorResponse("missing request parameters"); - return; - } + if (!req->hasField("item")) + { + req->SendErrorResponse("missing request parameters"); + return; + } - const char* item_name = obs_data_get_string(req->data, "item"); - if (!str_valid(item_name)) - { - req->SendErrorResponse("invalid request parameters"); - return; - } + const char* item_name = obs_data_get_string(req->data, "item"); + if (!str_valid(item_name)) + { + 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); - if (!scene) { - req->SendErrorResponse("requested scene doesn't exist"); - return; - } + const char* scene_name = obs_data_get_string(req->data, "scene-name"); + obs_source_t* scene = Utils::GetSceneFromNameOrCurrent(scene_name); + if (!scene) { + req->SendErrorResponse("requested scene doesn't exist"); + return; + } - obs_sceneitem_t* scene_item = Utils::GetSceneItemFromName(scene, item_name); + obs_sceneitem_t* scene_item = Utils::GetSceneItemFromName(scene, item_name); - if (scene_item) - { - 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"); + if (scene_item) + { + 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(scene_item, &crop); - obs_sceneitem_release(scene_item); - req->SendOKResponse(); - } - else - { - req->SendErrorResponse("specified scene item doesn't exist"); - } + obs_sceneitem_release(scene_item); + req->SendOKResponse(); + } + else + { + req->SendErrorResponse("specified scene item doesn't exist"); + } - obs_source_release(scene); + obs_source_release(scene); } void WSRequestHandler::HandleSetCurrentSceneCollection(WSRequestHandler* req) { - if (!req->hasField("sc-name")) - { - req->SendErrorResponse("missing request parameters"); - return; - } + if (!req->hasField("sc-name")) + { + req->SendErrorResponse("missing request parameters"); + return; + } - const char* scene_collection = obs_data_get_string(req->data, "sc-name"); + const char* scene_collection = obs_data_get_string(req->data, "sc-name"); - if (str_valid(scene_collection)) - { - // TODO : Check if specified profile exists and if changing is allowed - obs_frontend_set_current_scene_collection(scene_collection); - req->SendOKResponse(); - } - else - { - req->SendErrorResponse("invalid request parameters"); - } + if (str_valid(scene_collection)) + { + // TODO : Check if specified profile exists and if changing is allowed + obs_frontend_set_current_scene_collection(scene_collection); + req->SendOKResponse(); + } + else + { + req->SendErrorResponse("invalid request parameters"); + } } void WSRequestHandler::HandleGetCurrentSceneCollection(WSRequestHandler* req) { - obs_data_t* response = obs_data_create(); - obs_data_set_string(response, "sc-name", - obs_frontend_get_current_scene_collection()); + obs_data_t* response = obs_data_create(); + obs_data_set_string(response, "sc-name", + obs_frontend_get_current_scene_collection()); - req->SendOKResponse(response); + req->SendOKResponse(response); - obs_data_release(response); + obs_data_release(response); } void WSRequestHandler::HandleListSceneCollections(WSRequestHandler* req) { - obs_data_array_t* scene_collections = Utils::GetSceneCollections(); + obs_data_array_t* scene_collections = Utils::GetSceneCollections(); - obs_data_t* response = obs_data_create(); - obs_data_set_array(response, "scene-collections", scene_collections); + obs_data_t* response = obs_data_create(); + obs_data_set_array(response, "scene-collections", scene_collections); - req->SendOKResponse(response); + req->SendOKResponse(response); - obs_data_release(response); - obs_data_array_release(scene_collections); + obs_data_release(response); + obs_data_array_release(scene_collections); } void WSRequestHandler::HandleSetCurrentProfile(WSRequestHandler* req) { - if (!req->hasField("profile-name")) - { - req->SendErrorResponse("missing request parameters"); - return; - } + if (!req->hasField("profile-name")) + { + req->SendErrorResponse("missing request parameters"); + return; + } - const char* profile_name = obs_data_get_string(req->data, "profile-name"); + const char* profile_name = obs_data_get_string(req->data, "profile-name"); - if (str_valid(profile_name)) - { - // TODO : check if profile exists - obs_frontend_set_current_profile(profile_name); - req->SendOKResponse(); - } - else - { - req->SendErrorResponse("invalid request parameters"); - } + if (str_valid(profile_name)) + { + // TODO : check if profile exists + obs_frontend_set_current_profile(profile_name); + req->SendOKResponse(); + } + else + { + req->SendErrorResponse("invalid request parameters"); + } } void WSRequestHandler::HandleGetCurrentProfile(WSRequestHandler* req) { - obs_data_t* response = obs_data_create(); - obs_data_set_string(response, "profile-name", - obs_frontend_get_current_profile()); + obs_data_t* response = obs_data_create(); + obs_data_set_string(response, "profile-name", + obs_frontend_get_current_profile()); - req->SendOKResponse(response); + req->SendOKResponse(response); - obs_data_release(response); + obs_data_release(response); } void WSRequestHandler::HandleSetStreamSettings(WSRequestHandler* req) { - obs_service_t* service = obs_frontend_get_streaming_service(); - - obs_data_t* settings = obs_data_get_obj(req->data, "settings"); - if (!settings) - { - req->SendErrorResponse("'settings' are required'"); - return; - } - - const char* serviceType = obs_service_get_type(service); - const char* requestedType = obs_data_get_string(req->data, "type"); - - if (requestedType != nullptr && strcmp(requestedType, serviceType) != 0) - { - obs_data_t* hotkeys = obs_hotkeys_save_service(service); - obs_service_release(service); - service = obs_service_create(requestedType, "websocket_custom_service", settings, hotkeys); - obs_data_release(hotkeys); - } - else - { - obs_data_t* existingSettings = obs_service_get_settings(service); //if type isn't changing we should overlay the settings we got with the existing settings - obs_data_t* newSettings = obs_data_create(); //by doing this you can send a request to the websocket that only contains a setting you want to change instead of having to do a get and then change them - obs_data_apply(newSettings, existingSettings); //first apply the existing settings - obs_data_apply(newSettings, settings); //then apply the settings from the request - obs_data_release(settings); - obs_data_release(existingSettings); - obs_service_update(service, settings); - settings = newSettings; - } - - if (obs_data_get_bool(req->data, "save")) //if save is specified we should immediately save the streaming service - { - obs_frontend_save_streaming_service(); - } - - obs_data_t* response = obs_data_create(); - obs_data_set_string(response, "type", requestedType); - obs_data_set_obj(response, "settings", settings); - - req->SendOKResponse(response); - - obs_data_release(settings); - obs_data_release(response); + obs_service_t* service = obs_frontend_get_streaming_service(); + + obs_data_t* settings = obs_data_get_obj(req->data, "settings"); + if (!settings) + { + req->SendErrorResponse("'settings' are required'"); + return; + } + + const char* serviceType = obs_service_get_type(service); + const char* requestedType = obs_data_get_string(req->data, "type"); + + if (requestedType != nullptr && strcmp(requestedType, serviceType) != 0) + { + obs_data_t* hotkeys = obs_hotkeys_save_service(service); + obs_service_release(service); + service = obs_service_create(requestedType, "websocket_custom_service", settings, hotkeys); + obs_data_release(hotkeys); + } + else + { + obs_data_t* existingSettings = obs_service_get_settings(service); //if type isn't changing we should overlay the settings we got with the existing settings + obs_data_t* newSettings = obs_data_create(); //by doing this you can send a request to the websocket that only contains a setting you want to change instead of having to do a get and then change them + obs_data_apply(newSettings, existingSettings); //first apply the existing settings + obs_data_apply(newSettings, settings); //then apply the settings from the request + obs_data_release(settings); + obs_data_release(existingSettings); + obs_service_update(service, settings); + settings = newSettings; + } + + if (obs_data_get_bool(req->data, "save")) //if save is specified we should immediately save the streaming service + { + obs_frontend_save_streaming_service(); + } + + obs_data_t* response = obs_data_create(); + obs_data_set_string(response, "type", requestedType); + obs_data_set_obj(response, "settings", settings); + + req->SendOKResponse(response); + + obs_data_release(settings); + obs_data_release(response); } void WSRequestHandler::HandleGetStreamSettings(WSRequestHandler* req) { - obs_service_t* service = obs_frontend_get_streaming_service(); - - const char* serviceType = obs_service_get_type(service); - obs_data_t* settings = obs_service_get_settings(service); - - obs_data_t* response = obs_data_create(); - obs_data_set_string(response, "type", serviceType); - obs_data_set_obj(response, "settings", settings); - - req->SendOKResponse(response); - - obs_data_release(settings); - obs_data_release(response); + obs_service_t* service = obs_frontend_get_streaming_service(); + + const char* serviceType = obs_service_get_type(service); + obs_data_t* settings = obs_service_get_settings(service); + + obs_data_t* response = obs_data_create(); + obs_data_set_string(response, "type", serviceType); + obs_data_set_obj(response, "settings", settings); + + req->SendOKResponse(response); + + obs_data_release(settings); + obs_data_release(response); } void WSRequestHandler::HandleSaveStreamSettings(WSRequestHandler* req) { - obs_frontend_save_streaming_service(); - req->SendOKResponse(); + obs_frontend_save_streaming_service(); + req->SendOKResponse(); } void WSRequestHandler::HandleListProfiles(WSRequestHandler* req) { - obs_data_array_t* profiles = Utils::GetProfiles(); + obs_data_array_t* profiles = Utils::GetProfiles(); - obs_data_t* response = obs_data_create(); - obs_data_set_array(response, "profiles", profiles); + obs_data_t* response = obs_data_create(); + obs_data_set_array(response, "profiles", profiles); - req->SendOKResponse(response); + req->SendOKResponse(response); - obs_data_release(response); - obs_data_array_release(profiles); + obs_data_release(response); + obs_data_array_release(profiles); } void WSRequestHandler::HandleGetStudioModeStatus(WSRequestHandler* req) { - bool previewActive = Utils::IsPreviewModeActive(); + bool previewActive = Utils::IsPreviewModeActive(); - obs_data_t* response = obs_data_create(); - obs_data_set_bool(response, "studio-mode", previewActive); + obs_data_t* response = obs_data_create(); + obs_data_set_bool(response, "studio-mode", previewActive); - req->SendOKResponse(response); + req->SendOKResponse(response); - obs_data_release(response); + obs_data_release(response); } void WSRequestHandler::HandleGetPreviewScene(WSRequestHandler* req) { - if (!Utils::IsPreviewModeActive()) - { - req->SendErrorResponse("studio mode not enabled"); - return; - } + if (!Utils::IsPreviewModeActive()) + { + req->SendErrorResponse("studio mode not enabled"); + return; + } - obs_scene_t* preview_scene = Utils::GetPreviewScene(); - obs_source_t* source = obs_scene_get_source(preview_scene); - const char* name = obs_source_get_name(source); + obs_scene_t* preview_scene = Utils::GetPreviewScene(); + obs_source_t* source = obs_scene_get_source(preview_scene); + const char* name = obs_source_get_name(source); - obs_data_array_t* scene_items = Utils::GetSceneItems(source); + obs_data_array_t* scene_items = Utils::GetSceneItems(source); - obs_data_t* data = obs_data_create(); - obs_data_set_string(data, "name", name); - obs_data_set_array(data, "sources", scene_items); + obs_data_t* data = obs_data_create(); + obs_data_set_string(data, "name", name); + obs_data_set_array(data, "sources", scene_items); - req->SendOKResponse(data); + req->SendOKResponse(data); - obs_data_release(data); - obs_data_array_release(scene_items); + obs_data_release(data); + obs_data_array_release(scene_items); - obs_scene_release(preview_scene); + obs_scene_release(preview_scene); } void WSRequestHandler::HandleSetPreviewScene(WSRequestHandler* req) { - if (!Utils::IsPreviewModeActive()) - { - req->SendErrorResponse("studio mode not enabled"); - return; - } + if (!Utils::IsPreviewModeActive()) + { + req->SendErrorResponse("studio mode not enabled"); + return; + } - if (!req->hasField("scene-name")) - { - req->SendErrorResponse("missing request parameters"); - return; - } + if (!req->hasField("scene-name")) + { + req->SendErrorResponse("missing request parameters"); + return; + } - const char* scene_name = obs_data_get_string(req->data, "scene-name"); - bool success = Utils::SetPreviewScene(scene_name); + const char* scene_name = obs_data_get_string(req->data, "scene-name"); + bool success = Utils::SetPreviewScene(scene_name); - if (success) - req->SendOKResponse(); - else - req->SendErrorResponse("specified scene doesn't exist"); + if (success) + req->SendOKResponse(); + else + req->SendErrorResponse("specified scene doesn't exist"); } void WSRequestHandler::HandleTransitionToProgram(WSRequestHandler* req) { - if (!Utils::IsPreviewModeActive()) - { - req->SendErrorResponse("studio mode not enabled"); - return; - } + if (!Utils::IsPreviewModeActive()) + { + req->SendErrorResponse("studio mode not enabled"); + return; + } - if (req->hasField("with-transition")) - { - obs_data_t* transitionInfo = - obs_data_get_obj(req->data, "with-transition"); + if (req->hasField("with-transition")) + { + obs_data_t* transitionInfo = + obs_data_get_obj(req->data, "with-transition"); - if (obs_data_has_user_value(transitionInfo, "name")) - { - const char* transitionName = - obs_data_get_string(transitionInfo, "name"); + if (obs_data_has_user_value(transitionInfo, "name")) + { + const char* transitionName = + obs_data_get_string(transitionInfo, "name"); - if (!str_valid(transitionName)) - { - req->SendErrorResponse("invalid request parameters"); - return; - } + if (!str_valid(transitionName)) + { + req->SendErrorResponse("invalid request parameters"); + return; + } - bool success = Utils::SetTransitionByName(transitionName); - if (!success) - { - req->SendErrorResponse("specified transition doesn't exist"); - obs_data_release(transitionInfo); - return; - } - } + bool success = Utils::SetTransitionByName(transitionName); + if (!success) + { + req->SendErrorResponse("specified transition doesn't exist"); + obs_data_release(transitionInfo); + return; + } + } - if (obs_data_has_user_value(transitionInfo, "duration")) - { - int transitionDuration = - obs_data_get_int(transitionInfo, "duration"); + if (obs_data_has_user_value(transitionInfo, "duration")) + { + int transitionDuration = + obs_data_get_int(transitionInfo, "duration"); - Utils::SetTransitionDuration(transitionDuration); - } + Utils::SetTransitionDuration(transitionDuration); + } - obs_data_release(transitionInfo); - } + obs_data_release(transitionInfo); + } - Utils::TransitionToProgram(); - req->SendOKResponse(); + Utils::TransitionToProgram(); + req->SendOKResponse(); } void WSRequestHandler::HandleEnableStudioMode(WSRequestHandler* req) { - Utils::EnablePreviewMode(); - req->SendOKResponse(); + Utils::EnablePreviewMode(); + req->SendOKResponse(); } void WSRequestHandler::HandleDisableStudioMode(WSRequestHandler* req) { - Utils::DisablePreviewMode(); - req->SendOKResponse(); + Utils::DisablePreviewMode(); + req->SendOKResponse(); } void WSRequestHandler::HandleToggleStudioMode(WSRequestHandler* req) { - Utils::TogglePreviewMode(); - req->SendOKResponse(); + Utils::TogglePreviewMode(); + req->SendOKResponse(); } void WSRequestHandler::HandleGetSpecialSources(WSRequestHandler* req) { - obs_data_t* response = obs_data_create(); + obs_data_t* response = obs_data_create(); - QMap sources; - sources["desktop-1"] = 1; - sources["desktop-2"] = 2; - sources["mic-1"] = 3; - sources["mic-2"] = 4; - sources["mic-3"] = 5; + QMap sources; + sources["desktop-1"] = 1; + sources["desktop-2"] = 2; + sources["mic-1"] = 3; + sources["mic-2"] = 4; + sources["mic-3"] = 5; - QMapIterator i(sources); - while (i.hasNext()) - { - i.next(); + QMapIterator i(sources); + while (i.hasNext()) + { + i.next(); - const char* id = i.key(); - obs_source_t* source = obs_get_output_source(i.value()); - blog(LOG_INFO, "%s : %p", id, source); + const char* id = i.key(); + obs_source_t* source = obs_get_output_source(i.value()); + blog(LOG_INFO, "%s : %p", id, source); - if (source) - { - obs_data_set_string(response, id, obs_source_get_name(source)); - obs_source_release(source); - } - } + if (source) + { + obs_data_set_string(response, id, obs_source_get_name(source)); + obs_source_release(source); + } + } - req->SendOKResponse(response); + req->SendOKResponse(response); - obs_data_release(response); + obs_data_release(response); } void WSRequestHandler::HandleSetRecordingFolder(WSRequestHandler* req) { - if (!req->hasField("rec-folder")) - { - req->SendErrorResponse("missing request parameters"); - return; - } + if (!req->hasField("rec-folder")) + { + req->SendErrorResponse("missing request parameters"); + return; + } - const char* newRecFolder = obs_data_get_string(req->data, "rec-folder"); - bool success = Utils::SetRecordingFolder(newRecFolder); + const char* newRecFolder = obs_data_get_string(req->data, "rec-folder"); + bool success = Utils::SetRecordingFolder(newRecFolder); - if (success) - req->SendOKResponse(); - else - req->SendErrorResponse("invalid request parameters"); + if (success) + req->SendOKResponse(); + else + req->SendErrorResponse("invalid request parameters"); } void WSRequestHandler::HandleGetRecordingFolder(WSRequestHandler* req) { - const char* recFolder = Utils::GetRecordingFolder(); + const char* recFolder = Utils::GetRecordingFolder(); - obs_data_t* response = obs_data_create(); - obs_data_set_string(response, "rec-folder", recFolder); + obs_data_t* response = obs_data_create(); + obs_data_set_string(response, "rec-folder", recFolder); - req->SendOKResponse(response); - obs_data_release(response); + req->SendOKResponse(response); + obs_data_release(response); } void WSRequestHandler::HandleGetTextGDIPlusProperties(WSRequestHandler* req) { - const char* itemName = obs_data_get_string(req->data, "source"); - if (!itemName) - { - req->SendErrorResponse("invalid request parameters"); - return; - } + const char* itemName = obs_data_get_string(req->data, "source"); + if (!itemName) + { + req->SendErrorResponse("invalid request parameters"); + return; + } - const char* sceneName = obs_data_get_string(req->data, "scene-name"); - obs_source_t* scene = Utils::GetSceneFromNameOrCurrent(sceneName); - if (!scene) { - req->SendErrorResponse("requested scene doesn't exist"); - return; - } + const char* sceneName = obs_data_get_string(req->data, "scene-name"); + obs_source_t* scene = Utils::GetSceneFromNameOrCurrent(sceneName); + if (!scene) { + req->SendErrorResponse("requested scene doesn't exist"); + return; + } - obs_sceneitem_t* sceneItem = Utils::GetSceneItemFromName(scene, itemName); - if (sceneItem) - { - obs_source_t* sceneItemSource = obs_sceneitem_get_source(sceneItem); - const char* sceneItemSourceId = obs_source_get_id(sceneItemSource); + obs_sceneitem_t* sceneItem = Utils::GetSceneItemFromName(scene, itemName); + if (sceneItem) + { + obs_source_t* 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); - 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)); + if (strcmp(sceneItemSourceId, "text_gdiplus") == 0) + { + obs_data_t* 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); + req->SendOKResponse(response); - obs_data_release(response); - obs_sceneitem_release(sceneItem); - } - else - { - req->SendErrorResponse("not text gdi plus source"); - } + 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"); - } + } + else + { + req->SendErrorResponse("specified scene item doesn't exist"); + } - obs_source_release(scene); + obs_source_release(scene); } void WSRequestHandler::HandleSetTextGDIPlusProperties(WSRequestHandler* req) { - if (!req->hasField("source")) - { - req->SendErrorResponse("missing request parameters"); - return; - } + if (!req->hasField("source")) + { + req->SendErrorResponse("missing request parameters"); + return; + } - const char* itemName = obs_data_get_string(req->data, "source"); - if (!itemName) - { - req->SendErrorResponse("invalid request parameters"); - return; - } + const char* itemName = obs_data_get_string(req->data, "source"); + if (!itemName) + { + req->SendErrorResponse("invalid request parameters"); + return; + } - const char* sceneName = obs_data_get_string(req->data, "scene-name"); - obs_source_t* scene = Utils::GetSceneFromNameOrCurrent(sceneName); - if (!scene) { - req->SendErrorResponse("requested scene doesn't exist"); - return; - } + const char* sceneName = obs_data_get_string(req->data, "scene-name"); + obs_source_t* scene = Utils::GetSceneFromNameOrCurrent(sceneName); + if (!scene) { + req->SendErrorResponse("requested scene doesn't exist"); + return; + } - obs_sceneitem_t* sceneItem = Utils::GetSceneItemFromName(scene, itemName); - if (sceneItem) - { - obs_source_t* sceneItemSource = obs_sceneitem_get_source(sceneItem); - const char* sceneItemSourceId = obs_source_get_id(sceneItemSource); + obs_sceneitem_t* sceneItem = Utils::GetSceneItemFromName(scene, itemName); + if (sceneItem) + { + obs_source_t* 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); + if (strcmp(sceneItemSourceId, "text_gdiplus") == 0) + { + obs_data_t* settings = obs_source_get_settings(sceneItemSource); - if (req->hasField("align")) - { - obs_data_set_string(settings, "align", - obs_data_get_string(req->data, "align")); - } + if (req->hasField("align")) + { + obs_data_set_string(settings, "align", + obs_data_get_string(req->data, "align")); + } - if (req->hasField("bk_color")) - { - obs_data_set_int(settings, "bk_color", - obs_data_get_int(req->data, "bk_color")); - } + if (req->hasField("bk_color")) + { + obs_data_set_int(settings, "bk_color", + obs_data_get_int(req->data, "bk_color")); + } - if (req->hasField("bk-opacity")) - { - obs_data_set_int(settings, "bk_opacity", - obs_data_get_int(req->data, "bk_opacity")); - } + if (req->hasField("bk-opacity")) + { + obs_data_set_int(settings, "bk_opacity", + obs_data_get_int(req->data, "bk_opacity")); + } - if (req->hasField("chatlog")) - { - obs_data_set_bool(settings, "chatlog", - obs_data_get_bool(req->data, "chatlog")); - } - - if (req->hasField("chatlog_lines")) - { - obs_data_set_int(settings, "chatlog_lines", - obs_data_get_int(req->data, "chatlog_lines")); - } + if (req->hasField("chatlog")) + { + obs_data_set_bool(settings, "chatlog", + obs_data_get_bool(req->data, "chatlog")); + } + + if (req->hasField("chatlog_lines")) + { + obs_data_set_int(settings, "chatlog_lines", + obs_data_get_int(req->data, "chatlog_lines")); + } - if (req->hasField("color")) - { - obs_data_set_int(settings, "color", - obs_data_get_int(req->data, "color")); - } + if (req->hasField("color")) + { + obs_data_set_int(settings, "color", + obs_data_get_int(req->data, "color")); + } - if (req->hasField("extents")) - { - obs_data_set_bool(settings, "extents", - obs_data_get_bool(req->data, "extents")); - } + if (req->hasField("extents")) + { + obs_data_set_bool(settings, "extents", + obs_data_get_bool(req->data, "extents")); + } - if (req->hasField("extents_wrap")) - { - obs_data_set_bool(settings, "extents_wrap", - obs_data_get_bool(req->data, "extents_wrap")); - } + if (req->hasField("extents_wrap")) + { + obs_data_set_bool(settings, "extents_wrap", + obs_data_get_bool(req->data, "extents_wrap")); + } - if (req->hasField("extents_cx")) - { - obs_data_set_int(settings, "extents_cx", - obs_data_get_int(req->data, "extents_cx")); - } + if (req->hasField("extents_cx")) + { + obs_data_set_int(settings, "extents_cx", + obs_data_get_int(req->data, "extents_cx")); + } - if (req->hasField("extents_cy")) - { - obs_data_set_int(settings, "extents_cy", - obs_data_get_int(req->data, "extents_cy")); - } + if (req->hasField("extents_cy")) + { + obs_data_set_int(settings, "extents_cy", + obs_data_get_int(req->data, "extents_cy")); + } - if (req->hasField("file")) - { - obs_data_set_string(settings, "file", - obs_data_get_string(req->data, "file")); - } + if (req->hasField("file")) + { + obs_data_set_string(settings, "file", + obs_data_get_string(req->data, "file")); + } - if (req->hasField("font")) - { - obs_data_t* font_obj = obs_data_get_obj(settings, "font"); - if (font_obj) - { - obs_data_t* req_font_obj = obs_data_get_obj(req->data, "font"); + if (req->hasField("font")) + { + obs_data_t* font_obj = obs_data_get_obj(settings, "font"); + if (font_obj) + { + obs_data_t* 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", - obs_data_get_string(req_font_obj, "face")); - } + if (obs_data_has_user_value(req_font_obj, "face")) { + obs_data_set_string(font_obj, "face", + obs_data_get_string(req_font_obj, "face")); + } - if (obs_data_has_user_value(req_font_obj, "flags")) { - obs_data_set_int(font_obj, "flags", - obs_data_get_int(req_font_obj, "flags")); - } + if (obs_data_has_user_value(req_font_obj, "flags")) { + obs_data_set_int(font_obj, "flags", + obs_data_get_int(req_font_obj, "flags")); + } - if (obs_data_has_user_value(req_font_obj, "size")) { - obs_data_set_int(font_obj, "size", - obs_data_get_int(req_font_obj, "size")); - } + if (obs_data_has_user_value(req_font_obj, "size")) { + obs_data_set_int(font_obj, "size", + obs_data_get_int(req_font_obj, "size")); + } - if (obs_data_has_user_value(req_font_obj, "style")) { - obs_data_set_string(font_obj, "style", - obs_data_get_string(req_font_obj, "style")); - } + if (obs_data_has_user_value(req_font_obj, "style")) { + 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); - } - } + obs_data_release(req_font_obj); + obs_data_release(font_obj); + } + } - if (req->hasField("gradient")) - { - obs_data_set_bool(settings, "gradient", - obs_data_get_bool(req->data, "gradient")); - } + if (req->hasField("gradient")) + { + obs_data_set_bool(settings, "gradient", + obs_data_get_bool(req->data, "gradient")); + } - if (req->hasField("gradient_color")) - { - obs_data_set_int(settings, "gradient_color", - obs_data_get_int(req->data, "gradient_color")); - } + if (req->hasField("gradient_color")) + { + obs_data_set_int(settings, "gradient_color", + obs_data_get_int(req->data, "gradient_color")); + } - if (req->hasField("gradient_dir")) - { - obs_data_set_double(settings, "gradient_dir", - obs_data_get_double(req->data, "gradient_dir")); - } + if (req->hasField("gradient_dir")) + { + obs_data_set_double(settings, "gradient_dir", + obs_data_get_double(req->data, "gradient_dir")); + } - if (req->hasField("gradient_opacity")) - { - obs_data_set_int(settings, "gradient_opacity", - obs_data_get_int(req->data, "gradient_opacity")); - } + if (req->hasField("gradient_opacity")) + { + obs_data_set_int(settings, "gradient_opacity", + obs_data_get_int(req->data, "gradient_opacity")); + } - if (req->hasField("outline")) - { - obs_data_set_bool(settings, "outline", - obs_data_get_bool(req->data, "outline")); - } + if (req->hasField("outline")) + { + obs_data_set_bool(settings, "outline", + obs_data_get_bool(req->data, "outline")); + } - if (req->hasField("outline_size")) - { - obs_data_set_int(settings, "outline_size", - obs_data_get_int(req->data, "outline_size")); - } + if (req->hasField("outline_size")) + { + obs_data_set_int(settings, "outline_size", + obs_data_get_int(req->data, "outline_size")); + } - if (req->hasField("outline_color")) - { - obs_data_set_int(settings, "outline_color", - obs_data_get_int(req->data, "outline_color")); - } + if (req->hasField("outline_color")) + { + obs_data_set_int(settings, "outline_color", + obs_data_get_int(req->data, "outline_color")); + } - if (req->hasField("outline_opacity")) - { - obs_data_set_int(settings, "outline_opacity", - obs_data_get_int(req->data, "outline_opacity")); - } + if (req->hasField("outline_opacity")) + { + obs_data_set_int(settings, "outline_opacity", + obs_data_get_int(req->data, "outline_opacity")); + } - if (req->hasField("read_from_file")) - { - obs_data_set_bool(settings, "read_from_file", - obs_data_get_bool(req->data, "read_from_file")); - } + if (req->hasField("read_from_file")) + { + obs_data_set_bool(settings, "read_from_file", + obs_data_get_bool(req->data, "read_from_file")); + } - if (req->hasField("text")) - { - obs_data_set_string(settings, "text", - obs_data_get_string(req->data, "text")); - } + if (req->hasField("text")) + { + obs_data_set_string(settings, "text", + obs_data_get_string(req->data, "text")); + } - if (req->hasField("valign")) - { - obs_data_set_string(settings, "valign", - obs_data_get_string(req->data, "valign")); - } + if (req->hasField("valign")) + { + obs_data_set_string(settings, "valign", + obs_data_get_string(req->data, "valign")); + } - if (req->hasField("vertical")) - { - obs_data_set_bool(settings, "vertical", - obs_data_get_bool(req->data, "vertical")); - } + if (req->hasField("vertical")) + { + obs_data_set_bool(settings, "vertical", + obs_data_get_bool(req->data, "vertical")); + } - obs_source_update(sceneItemSource, settings); + obs_source_update(sceneItemSource, settings); - if (req->hasField("render")) - { - obs_sceneitem_set_visible(sceneItem, - obs_data_get_bool(req->data, "render")); - } + if (req->hasField("render")) + { + obs_sceneitem_set_visible(sceneItem, + obs_data_get_bool(req->data, "render")); + } - req->SendOKResponse(); + 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); + 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); } void WSRequestHandler::HandleGetBrowserSourceProperties(WSRequestHandler* req) { - const char* itemName = obs_data_get_string(req->data, "source"); - if (!itemName) - { - req->SendErrorResponse("invalid request parameters"); - return; - } + const char* itemName = obs_data_get_string(req->data, "source"); + if (!itemName) + { + req->SendErrorResponse("invalid request parameters"); + return; + } - const char* sceneName = obs_data_get_string(req->data, "scene-name"); - obs_source_t* scene = Utils::GetSceneFromNameOrCurrent(sceneName); - if (!scene) { - req->SendErrorResponse("requested scene doesn't exist"); - return; - } + const char* sceneName = obs_data_get_string(req->data, "scene-name"); + obs_source_t* scene = Utils::GetSceneFromNameOrCurrent(sceneName); + if (!scene) { + req->SendErrorResponse("requested scene doesn't exist"); + return; + } - obs_sceneitem_t* sceneItem = Utils::GetSceneItemFromName(scene, itemName); - if (sceneItem) - { - obs_source_t* sceneItemSource = obs_sceneitem_get_source(sceneItem); - const char* sceneItemSourceId = obs_source_get_id(sceneItemSource); + obs_sceneitem_t* sceneItem = Utils::GetSceneItemFromName(scene, itemName); + if (sceneItem) + { + obs_source_t* 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); - 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)); + if (strcmp(sceneItemSourceId, "browser_source") == 0) + { + obs_data_t* 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); + 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); + 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); } void WSRequestHandler::HandleSetBrowserSourceProperties(WSRequestHandler* req) { - if (!req->hasField("source")) - { - req->SendErrorResponse("missing request parameters"); - return; - } + if (!req->hasField("source")) + { + req->SendErrorResponse("missing request parameters"); + return; + } - const char* itemName = obs_data_get_string(req->data, "source"); - if (!itemName) - { - req->SendErrorResponse("invalid request parameters"); - return; - } + const char* itemName = obs_data_get_string(req->data, "source"); + if (!itemName) + { + req->SendErrorResponse("invalid request parameters"); + return; + } - const char* sceneName = obs_data_get_string(req->data, "scene-name"); - obs_source_t* scene = Utils::GetSceneFromNameOrCurrent(sceneName); - if (!scene) { - req->SendErrorResponse("requested scene doesn't exist"); - return; - } + const char* sceneName = obs_data_get_string(req->data, "scene-name"); + obs_source_t* scene = Utils::GetSceneFromNameOrCurrent(sceneName); + if (!scene) { + req->SendErrorResponse("requested scene doesn't exist"); + return; + } - obs_sceneitem_t* sceneItem = Utils::GetSceneItemFromName(scene, itemName); - if (sceneItem) - { - obs_source_t* sceneItemSource = obs_sceneitem_get_source(sceneItem); - const char* sceneItemSourceId = obs_source_get_id(sceneItemSource); + obs_sceneitem_t* sceneItem = Utils::GetSceneItemFromName(scene, itemName); + if (sceneItem) + { + obs_source_t* 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); + if (strcmp(sceneItemSourceId, "browser_source") == 0) + { + obs_data_t* settings = obs_source_get_settings(sceneItemSource); - if (req->hasField("restart_when_active")) - { - obs_data_set_bool(settings, "restart_when_active", - obs_data_get_bool(req->data, "restart_when_active")); - } + if (req->hasField("restart_when_active")) + { + obs_data_set_bool(settings, "restart_when_active", + obs_data_get_bool(req->data, "restart_when_active")); + } - if (req->hasField("shutdown")) - { - obs_data_set_bool(settings, "shutdown", - obs_data_get_bool(req->data, "shutdown")); - } + if (req->hasField("shutdown")) + { + obs_data_set_bool(settings, "shutdown", + obs_data_get_bool(req->data, "shutdown")); + } - if (req->hasField("is_local_file")) - { - obs_data_set_bool(settings, "is_local_file", - obs_data_get_bool(req->data, "is_local_file")); - } + if (req->hasField("is_local_file")) + { + obs_data_set_bool(settings, "is_local_file", + obs_data_get_bool(req->data, "is_local_file")); + } - if (req->hasField("url")) - { - obs_data_set_string(settings, "url", - obs_data_get_string(req->data, "url")); - } + if (req->hasField("url")) + { + obs_data_set_string(settings, "url", + obs_data_get_string(req->data, "url")); + } - if (req->hasField("css")) - { - obs_data_set_string(settings, "css", - obs_data_get_string(req->data, "css")); - } + if (req->hasField("css")) + { + obs_data_set_string(settings, "css", + obs_data_get_string(req->data, "css")); + } - if (req->hasField("width")) - { - obs_data_set_int(settings, "width", - obs_data_get_int(req->data, "width")); - } + if (req->hasField("width")) + { + obs_data_set_int(settings, "width", + obs_data_get_int(req->data, "width")); + } - if (req->hasField("height")) - { - obs_data_set_int(settings, "height", - obs_data_get_int(req->data, "height")); - } - - if (req->hasField("fps")) - { - obs_data_set_int(settings, "fps", - obs_data_get_int(req->data, "fps")); - } + if (req->hasField("height")) + { + obs_data_set_int(settings, "height", + obs_data_get_int(req->data, "height")); + } + + if (req->hasField("fps")) + { + obs_data_set_int(settings, "fps", + obs_data_get_int(req->data, "fps")); + } - obs_source_update(sceneItemSource, settings); + obs_source_update(sceneItemSource, settings); - if (req->hasField("render")) - { - obs_sceneitem_set_visible(sceneItem, - obs_data_get_bool(req->data, "render")); - } + if (req->hasField("render")) + { + obs_sceneitem_set_visible(sceneItem, + obs_data_get_bool(req->data, "render")); + } - req->SendOKResponse(); + 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); + 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); } diff --git a/WSRequestHandler.h b/WSRequestHandler.h index 044039f9..f2650c1f 100644 --- a/WSRequestHandler.h +++ b/WSRequestHandler.h @@ -105,7 +105,7 @@ class WSRequestHandler : public QObject { static void HandleEnableStudioMode(WSRequestHandler* req); static void HandleDisableStudioMode(WSRequestHandler* req); static void HandleToggleStudioMode(WSRequestHandler* req); - + static void HandleSetTextGDIPlusProperties(WSRequestHandler* req); static void HandleGetTextGDIPlusProperties(WSRequestHandler* req); static void HandleSetBrowserSourceProperties(WSRequestHandler* req); diff --git a/WSServer.cpp b/WSServer.cpp index 839c712b..726f76c1 100644 --- a/WSServer.cpp +++ b/WSServer.cpp @@ -31,68 +31,68 @@ QT_USE_NAMESPACE WSServer* WSServer::Instance = nullptr; WSServer::WSServer(QObject* parent) : - QObject(parent), - _wsServer(Q_NULLPTR), - _clients(), - _clMutex(QMutex::Recursive) { - _serverThread = new QThread(); - _wsServer = new QWebSocketServer( - QStringLiteral("obs-websocket"), - QWebSocketServer::NonSecureMode, - _serverThread); - _serverThread->start(); + QObject(parent), + _wsServer(Q_NULLPTR), + _clients(), + _clMutex(QMutex::Recursive) { + _serverThread = new QThread(); + _wsServer = new QWebSocketServer( + QStringLiteral("obs-websocket"), + QWebSocketServer::NonSecureMode, + _serverThread); + _serverThread->start(); } WSServer::~WSServer() { - Stop(); - delete _serverThread; + Stop(); + delete _serverThread; } void WSServer::Start(quint16 port) { - if (port == _wsServer->serverPort()) - return; + if (port == _wsServer->serverPort()) + return; - if(_wsServer->isListening()) - Stop(); + if(_wsServer->isListening()) + Stop(); - bool serverStarted = _wsServer->listen(QHostAddress::Any, port); - if (serverStarted) { + bool serverStarted = _wsServer->listen(QHostAddress::Any, port); + if (serverStarted) { connect(_wsServer, SIGNAL(newConnection()), this, SLOT(onNewConnection())); - } + } } void WSServer::Stop() { - _clMutex.lock(); - for(QWebSocket* pClient : _clients) { - pClient->close(); - } - _clMutex.unlock(); + _clMutex.lock(); + for(QWebSocket* pClient : _clients) { + pClient->close(); + } + _clMutex.unlock(); - _wsServer->close(); + _wsServer->close(); } void WSServer::broadcast(QString message) { - _clMutex.lock(); - for(QWebSocket* pClient : _clients) { - if (Config::Current()->AuthRequired - && (pClient->property(PROP_AUTHENTICATED).toBool() == false)) { - // Skip this client if unauthenticated - continue; - } + _clMutex.lock(); + for(QWebSocket* pClient : _clients) { + if (Config::Current()->AuthRequired + && (pClient->property(PROP_AUTHENTICATED).toBool() == false)) { + // Skip this client if unauthenticated + continue; + } - pClient->sendTextMessage(message); - } - _clMutex.unlock(); + pClient->sendTextMessage(message); + } + _clMutex.unlock(); } void WSServer::onNewConnection() { - QWebSocket* pSocket = _wsServer->nextPendingConnection(); - if (pSocket) { - connect(pSocket, &QWebSocket::textMessageReceived, - this, &WSServer::onTextMessageReceived); - connect(pSocket, &QWebSocket::disconnected, - this, &WSServer::onSocketDisconnected); + QWebSocket* pSocket = _wsServer->nextPendingConnection(); + if (pSocket) { + connect(pSocket, &QWebSocket::textMessageReceived, + this, &WSServer::onTextMessageReceived); + connect(pSocket, &QWebSocket::disconnected, + this, &WSServer::onSocketDisconnected); connect(pSocket, SIGNAL(textMessageReceived(const QString&)), this, SLOT(onTextMessageReceived(QString))); @@ -101,57 +101,57 @@ void WSServer::onNewConnection() { pSocket->setProperty(PROP_AUTHENTICATED, false); - _clMutex.lock(); - _clients << pSocket; - _clMutex.unlock(); + _clMutex.lock(); + _clients << pSocket; + _clMutex.unlock(); - QHostAddress clientAddr = pSocket->peerAddress(); - QString clientIp = Utils::FormatIPAddress(clientAddr); + QHostAddress clientAddr = pSocket->peerAddress(); + QString clientIp = Utils::FormatIPAddress(clientAddr); - blog(LOG_INFO, "new client connection from %s:%d", - clientIp.toUtf8().constData(), pSocket->peerPort()); + blog(LOG_INFO, "new client connection from %s:%d", + clientIp.toUtf8().constData(), pSocket->peerPort()); - QString msg = QString(obs_module_text("OBSWebsocket.ConnectNotify.ClientIP")) - + QString(" ") - + clientAddr.toString(); + QString msg = QString(obs_module_text("OBSWebsocket.ConnectNotify.ClientIP")) + + QString(" ") + + clientAddr.toString(); - Utils::SysTrayNotify(msg, - QSystemTrayIcon::Information, - QString(obs_module_text("OBSWebsocket.ConnectNotify.Connected"))); - } + Utils::SysTrayNotify(msg, + QSystemTrayIcon::Information, + QString(obs_module_text("OBSWebsocket.ConnectNotify.Connected"))); + } } void WSServer::onTextMessageReceived(QString message) { - QWebSocket* pSocket = qobject_cast(sender()); - if (pSocket) { - WSRequestHandler handler(pSocket); - handler.processIncomingMessage(message); - } + QWebSocket* pSocket = qobject_cast(sender()); + if (pSocket) { + WSRequestHandler handler(pSocket); + handler.processIncomingMessage(message); + } } void WSServer::onSocketDisconnected() { - QWebSocket* pSocket = qobject_cast(sender()); - if (pSocket) { - pSocket->setProperty(PROP_AUTHENTICATED, false); + QWebSocket* pSocket = qobject_cast(sender()); + if (pSocket) { + pSocket->setProperty(PROP_AUTHENTICATED, false); - _clMutex.lock(); - _clients.removeAll(pSocket); - _clMutex.unlock(); + _clMutex.lock(); + _clients.removeAll(pSocket); + _clMutex.unlock(); - pSocket->deleteLater(); + pSocket->deleteLater(); - QHostAddress clientAddr = pSocket->peerAddress(); - QString clientIp = Utils::FormatIPAddress(clientAddr); + QHostAddress clientAddr = pSocket->peerAddress(); + QString clientIp = Utils::FormatIPAddress(clientAddr); - blog(LOG_INFO, "client %s:%d disconnected", - clientIp.toUtf8().constData(), pSocket->peerPort()); + blog(LOG_INFO, "client %s:%d disconnected", + clientIp.toUtf8().constData(), pSocket->peerPort()); - QString msg = QString(obs_module_text("OBSWebsocket.ConnectNotify.ClientIP")) - + QString(" ") - + clientAddr.toString(); + QString msg = QString(obs_module_text("OBSWebsocket.ConnectNotify.ClientIP")) + + QString(" ") + + clientAddr.toString(); - Utils::SysTrayNotify(msg, - QSystemTrayIcon::Information, - QString(obs_module_text("OBSWebsocket.ConnectNotify.Disconnected"))); - } + Utils::SysTrayNotify(msg, + QSystemTrayIcon::Information, + QString(obs_module_text("OBSWebsocket.ConnectNotify.Disconnected"))); + } } diff --git a/WSServer.h b/WSServer.h index cdf7a8a8..6ab6ea0e 100644 --- a/WSServer.h +++ b/WSServer.h @@ -41,7 +41,7 @@ class WSServer : public QObject { private slots: void onNewConnection(); void onTextMessageReceived(QString message); - void onSocketDisconnected(); + void onSocketDisconnected(); private: QWebSocketServer* _wsServer; diff --git a/forms/settings-dialog.cpp b/forms/settings-dialog.cpp index e51eb2f2..f4cff0a4 100644 --- a/forms/settings-dialog.cpp +++ b/forms/settings-dialog.cpp @@ -27,87 +27,87 @@ with this program. If not, see #define CHANGE_ME "changeme" SettingsDialog::SettingsDialog(QWidget* parent) : - QDialog(parent, Qt::Dialog), - ui(new Ui::SettingsDialog) + QDialog(parent, Qt::Dialog), + ui(new Ui::SettingsDialog) { - ui->setupUi(this); + ui->setupUi(this); - connect(ui->authRequired, &QCheckBox::stateChanged, - this, &SettingsDialog::AuthCheckboxChanged); - connect(ui->buttonBox, &QDialogButtonBox::accepted, - this, &SettingsDialog::FormAccepted); + connect(ui->authRequired, &QCheckBox::stateChanged, + this, &SettingsDialog::AuthCheckboxChanged); + connect(ui->buttonBox, &QDialogButtonBox::accepted, + this, &SettingsDialog::FormAccepted); - AuthCheckboxChanged(); + AuthCheckboxChanged(); } void SettingsDialog::showEvent(QShowEvent* event) { - Config* conf = Config::Current(); + Config* conf = Config::Current(); - ui->serverEnabled->setChecked(conf->ServerEnabled); - ui->serverPort->setValue(conf->ServerPort); - - ui->debugEnabled->setChecked(conf->DebugEnabled); + ui->serverEnabled->setChecked(conf->ServerEnabled); + ui->serverPort->setValue(conf->ServerPort); + + ui->debugEnabled->setChecked(conf->DebugEnabled); - ui->authRequired->setChecked(conf->AuthRequired); - ui->password->setText(CHANGE_ME); + ui->authRequired->setChecked(conf->AuthRequired); + ui->password->setText(CHANGE_ME); } void SettingsDialog::ToggleShowHide() { - if (!isVisible()) - setVisible(true); - else - setVisible(false); + if (!isVisible()) + setVisible(true); + else + setVisible(false); } void SettingsDialog::AuthCheckboxChanged() { - if (ui->authRequired->isChecked()) - ui->password->setEnabled(true); - else - ui->password->setEnabled(false); + if (ui->authRequired->isChecked()) + ui->password->setEnabled(true); + else + ui->password->setEnabled(false); } void SettingsDialog::FormAccepted() { - Config* conf = Config::Current(); + Config* conf = Config::Current(); - conf->ServerEnabled = ui->serverEnabled->isChecked(); - conf->ServerPort = ui->serverPort->value(); - - conf->DebugEnabled = ui->debugEnabled->isChecked(); + conf->ServerEnabled = ui->serverEnabled->isChecked(); + conf->ServerPort = ui->serverPort->value(); + + conf->DebugEnabled = ui->debugEnabled->isChecked(); - if (ui->authRequired->isChecked()) - { - if (ui->password->text() != CHANGE_ME) - { - QByteArray pwd = ui->password->text().toUtf8(); - const char *new_password = pwd; + 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); - } + conf->SetPassword(new_password); + } - if (strcmp(Config::Current()->Secret, "") != 0) - conf->AuthRequired = true; - else - conf->AuthRequired = false; - } - else - { - conf->AuthRequired = false; - } + if (strcmp(Config::Current()->Secret, "") != 0) + conf->AuthRequired = true; + else + conf->AuthRequired = false; + } + else + { + conf->AuthRequired = false; + } - conf->Save(); + conf->Save(); - if (conf->ServerEnabled) - WSServer::Instance->Start(conf->ServerPort); - else - WSServer::Instance->Stop(); + if (conf->ServerEnabled) + WSServer::Instance->Start(conf->ServerPort); + else + WSServer::Instance->Stop(); } SettingsDialog::~SettingsDialog() { - delete ui; + delete ui; } diff --git a/forms/settings-dialog.h b/forms/settings-dialog.h index b4401eb2..1043926f 100644 --- a/forms/settings-dialog.h +++ b/forms/settings-dialog.h @@ -27,20 +27,20 @@ class SettingsDialog; class SettingsDialog : public QDialog { - Q_OBJECT + Q_OBJECT public: - explicit SettingsDialog(QWidget* parent = 0); - ~SettingsDialog(); - void showEvent(QShowEvent* event); - void ToggleShowHide(); + explicit SettingsDialog(QWidget* parent = 0); + ~SettingsDialog(); + void showEvent(QShowEvent* event); + void ToggleShowHide(); private Q_SLOTS: - void AuthCheckboxChanged(); - void FormAccepted(); + void AuthCheckboxChanged(); + void FormAccepted(); private: - Ui::SettingsDialog* ui; + Ui::SettingsDialog* ui; }; #endif // SETTINGSDIALOG_H diff --git a/obs-websocket.cpp b/obs-websocket.cpp index 9b9dfc8e..5b6fa04b 100644 --- a/obs-websocket.cpp +++ b/obs-websocket.cpp @@ -34,39 +34,39 @@ OBS_MODULE_USE_DEFAULT_LOCALE("obs-websocket", "en-US") SettingsDialog* settings_dialog; bool obs_module_load(void) { - blog(LOG_INFO, "you can haz websockets (version %s)", OBS_WEBSOCKET_VERSION); + blog(LOG_INFO, "you can haz websockets (version %s)", OBS_WEBSOCKET_VERSION); - // Core setup - Config* config = Config::Current(); - config->Load(); + // Core setup + Config* config = Config::Current(); + config->Load(); - WSServer::Instance = new WSServer(); - WSEvents::Instance = new WSEvents(WSServer::Instance); + WSServer::Instance = new WSServer(); + WSEvents::Instance = new WSEvents(WSServer::Instance); - if (config->ServerEnabled) - WSServer::Instance->Start(config->ServerPort); + if (config->ServerEnabled) + WSServer::Instance->Start(config->ServerPort); - // UI setup - QAction* menu_action = (QAction*)obs_frontend_add_tools_menu_qaction( - obs_module_text("OBSWebsocket.Menu.SettingsItem")); + // UI setup + QAction* menu_action = (QAction*)obs_frontend_add_tools_menu_qaction( + obs_module_text("OBSWebsocket.Menu.SettingsItem")); - obs_frontend_push_ui_translation(obs_module_get_string); - QMainWindow* main_window = (QMainWindow*)obs_frontend_get_main_window(); - settings_dialog = new SettingsDialog(main_window); - obs_frontend_pop_ui_translation(); + obs_frontend_push_ui_translation(obs_module_get_string); + QMainWindow* main_window = (QMainWindow*)obs_frontend_get_main_window(); + settings_dialog = new SettingsDialog(main_window); + obs_frontend_pop_ui_translation(); - auto menu_cb = [] { - settings_dialog->ToggleShowHide(); - }; - menu_action->connect(menu_action, &QAction::triggered, menu_cb); + auto menu_cb = [] { + settings_dialog->ToggleShowHide(); + }; + menu_action->connect(menu_action, &QAction::triggered, menu_cb); - // Loading finished - blog(LOG_INFO, "module loaded!"); + // Loading finished + blog(LOG_INFO, "module loaded!"); - return true; + return true; } void obs_module_unload() { - blog(LOG_INFO, "goodbye!"); + blog(LOG_INFO, "goodbye!"); }