General: refactor continued

This commit is contained in:
Stéphane L 2017-08-05 03:21:28 +02:00
parent 586f9076f0
commit dba599c127
12 changed files with 2113 additions and 2113 deletions

View File

@ -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;
}

View File

@ -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:

552
Utils.cpp
View File

@ -28,448 +28,448 @@ with this program. If not, see <https://www.gnu.org/licenses/>
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<obs_data_array_t*>(param);
obs_data_array_t* data = static_cast<obs_data_array_t*>(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<current_search*>(param);
current_search* search = static_cast<current_search*>(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<QSpinBox*>("transitionDuration");
QMainWindow* window = (QMainWindow*)obs_frontend_get_main_window();
return window->findChild<QSpinBox*>("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<QPushButton*>("modeSwitch");
QMainWindow* main = (QMainWindow*)obs_frontend_get_main_window();
return main->findChild<QPushButton*>("modeSwitch");
}
QListWidget* Utils::GetSceneListControl() {
QMainWindow* main = (QMainWindow*)obs_frontend_get_main_window();
return main->findChild<QListWidget*>("scenes");
QMainWindow* main = (QMainWindow*)obs_frontend_get_main_window();
return main->findChild<QListWidget*>("scenes");
}
obs_scene_t* Utils::SceneListItemToScene(QListWidgetItem* item) {
if (!item)
return nullptr;
if (!item)
return nullptr;
QVariant item_data = item->data(static_cast<int>(Qt::UserRole));
return item_data.value<OBSScene>();
QVariant item_data = item->data(static_cast<int>(Qt::UserRole));
return item_data.value<OBSScene>();
}
QLayout* Utils::GetPreviewLayout() {
QMainWindow* main = (QMainWindow*)obs_frontend_get_main_window();
return main->findChild<QLayout*>("previewLayout");
QMainWindow* main = (QMainWindow*)obs_frontend_get_main_window();
return main->findChild<QLayout*>("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<QListWidgetItem*> selected = sceneList->selectedItems();
if (IsPreviewModeActive()) {
QListWidget* sceneList = GetSceneListControl();
QList<QListWidgetItem*> 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<QListWidgetItem*> matchingItems =
sceneList->findItems(name, Qt::MatchExactly);
if (IsPreviewModeActive()) {
QListWidget* sceneList = GetSceneListControl();
QList<QListWidgetItem*> 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<QPushButton*>(transitionBtnWidget);
// Try to cast that widget into a button
QPushButton* transitionBtn = qobject_cast<QPushButton*>(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<QSystemTrayIcon*>().first();
QMainWindow* main = (QMainWindow*)obs_frontend_get_main_window();
return main->findChildren<QSystemTrayIcon*>().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;
}

View File

@ -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);
};

View File

@ -29,555 +29,555 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#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<WSEvents*>(private_data);
WSEvents* owner = static_cast<WSEvents*>(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<WSEvents*>(param);
instance->broadcastUpdate("TransitionBegin");
WSEvents* instance = static_cast<WSEvents*>(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<WSEvents*>(param);
WSEvents* instance = static_cast<WSEvents*>(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<WSEvents*>(param);
WSEvents* instance = static_cast<WSEvents*>(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<WSEvents*>(param);
WSEvents* instance = static_cast<WSEvents*>(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<WSEvents*>(param);
WSEvents* instance = static_cast<WSEvents*>(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);
}

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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<QWebSocket*>(sender());
if (pSocket) {
WSRequestHandler handler(pSocket);
handler.processIncomingMessage(message);
}
QWebSocket* pSocket = qobject_cast<QWebSocket*>(sender());
if (pSocket) {
WSRequestHandler handler(pSocket);
handler.processIncomingMessage(message);
}
}
void WSServer::onSocketDisconnected() {
QWebSocket* pSocket = qobject_cast<QWebSocket*>(sender());
if (pSocket) {
pSocket->setProperty(PROP_AUTHENTICATED, false);
QWebSocket* pSocket = qobject_cast<QWebSocket*>(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")));
}
}

View File

@ -41,7 +41,7 @@ class WSServer : public QObject {
private slots:
void onNewConnection();
void onTextMessageReceived(QString message);
void onSocketDisconnected();
void onSocketDisconnected();
private:
QWebSocketServer* _wsServer;

View File

@ -27,87 +27,87 @@ with this program. If not, see <https://www.gnu.org/licenses/>
#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;
}

View File

@ -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

View File

@ -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!");
}