From 66285a0d3d3b2cd17027370d64f64bb867bd9e63 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sun, 23 May 2021 09:32:25 +0200 Subject: [PATCH] Add option to synchronize preview scene via network tab --- data/locale/en-US.ini | 1 + forms/advanced-scene-switcher.ui | 41 +++++++++++++++---------- src/advanced-scene-switcher.cpp | 22 +++++++++++++ src/headers/advanced-scene-switcher.hpp | 2 ++ src/headers/switch-network.hpp | 3 +- src/switch-network.cpp | 33 +++++++++++++++++--- 6 files changed, 79 insertions(+), 23 deletions(-) diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index cd17b4ef..00385fbf 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -362,6 +362,7 @@ AdvSceneSwitcher.networkTab.server="Start server (Sends scene switch messages to AdvSceneSwitcher.networkTab.server.port="Port" AdvSceneSwitcher.networkTab.server.lockToIPv4="Lock server to only using IPv4" AdvSceneSwitcher.networkTab.server.restrictSendToAutomatedSwitches="Only send messages for automated scene switches" +AdvSceneSwitcher.networkTab.server.sendPreview="Synchronize preview scene when running in Studio mode" AdvSceneSwitcher.networkTab.startFailed.message="The WebSockets server failed to start, maybe because:\n - TCP port %1 may currently be in use elsewhere on this system, possibly by another application. Try setting a different TCP port in the WebSocket server settings, or stop any application that could be using this port.\n - Error message: %2" AdvSceneSwitcher.networkTab.server.status.currentStatus="Current status" AdvSceneSwitcher.networkTab.server.status.notRunning="Not running" diff --git a/forms/advanced-scene-switcher.ui b/forms/advanced-scene-switcher.ui index 4726e039..f2297f9b 100644 --- a/forms/advanced-scene-switcher.ui +++ b/forms/advanced-scene-switcher.ui @@ -3727,6 +3727,13 @@ + + + + AdvSceneSwitcher.networkTab.server.status.notRunning + + + @@ -3740,13 +3747,6 @@ - - - - AdvSceneSwitcher.networkTab.server.port - - - @@ -3754,17 +3754,10 @@ - - + + - AdvSceneSwitcher.networkTab.server.status.currentStatus - - - - - - - AdvSceneSwitcher.networkTab.server.status.notRunning + AdvSceneSwitcher.networkTab.server.port @@ -3775,6 +3768,20 @@ + + + + AdvSceneSwitcher.networkTab.server.status.currentStatus + + + + + + + AdvSceneSwitcher.networkTab.server.sendPreview + + + diff --git a/src/advanced-scene-switcher.cpp b/src/advanced-scene-switcher.cpp index 95808908..2839d88b 100644 --- a/src/advanced-scene-switcher.cpp +++ b/src/advanced-scene-switcher.cpp @@ -351,6 +351,13 @@ void switchScene(const sceneSwitchInfo &sceneSwitch) obs_source_release(source); } +void switchPreviewScene(const OBSWeakSource &ws) +{ + auto source = obs_weak_source_get_source(ws); + obs_frontend_set_current_preview_scene(source); + obs_source_release(source); +} + void SwitcherData::Start() { if (!(th && th->isRunning())) { @@ -472,6 +479,18 @@ void checkAutoStartStreaming() switcher->Start(); } +void handlePeviewSceneChange() +{ + if (switcher->networkConfig.ServerEnabled && + switcher->networkConfig.SendPreview) { + auto source = obs_frontend_get_current_preview_scene(); + auto weak = obs_source_get_weak_source(source); + switcher->server.sendMessage({weak, nullptr, 0}, true); + obs_weak_source_release(weak); + obs_source_release(source); + } +} + // Note to future self: // be careful using switcher->m here as there is potential for deadlocks when using // frontend functions such as obs_frontend_set_current_scene() @@ -488,6 +507,9 @@ static void OBSEvent(enum obs_frontend_event event, void *switcher) case OBS_FRONTEND_EVENT_SCENE_CHANGED: handleSceneChange(); break; + case OBS_FRONTEND_EVENT_PREVIEW_SCENE_CHANGED: + handlePeviewSceneChange(); + break; case OBS_FRONTEND_EVENT_RECORDING_STARTED: setLiveTime(); checkAutoStartRecording(); diff --git a/src/headers/advanced-scene-switcher.hpp b/src/headers/advanced-scene-switcher.hpp index fa23cb96..e197fd1a 100644 --- a/src/headers/advanced-scene-switcher.hpp +++ b/src/headers/advanced-scene-switcher.hpp @@ -212,6 +212,7 @@ public slots: void on_clientHostname_textChanged(const QString &text); void on_clientPort_valueChanged(int value); void on_restrictSend_stateChanged(int state); + void on_sendPreview_stateChanged(int state); void on_clientReconnect_clicked(); void updateClientStatus(); @@ -254,6 +255,7 @@ void overwriteTransitionOverride(const sceneSwitchInfo &ssi, transitionData &td); void restoreTransitionOverride(obs_source_t *scene, const transitionData &td); void switchScene(const sceneSwitchInfo &ssi); +void switchPreviewScene(const OBSWeakSource &ws); /****************************************************************************** * Main SwitcherData diff --git a/src/headers/switch-network.hpp b/src/headers/switch-network.hpp index 4e52061f..2a834df4 100644 --- a/src/headers/switch-network.hpp +++ b/src/headers/switch-network.hpp @@ -43,6 +43,7 @@ public: std::string Address; uint64_t ClientPort; bool SendAll; + bool SendPreview; }; class WSServer : public QObject { @@ -53,7 +54,7 @@ public: virtual ~WSServer(); void start(quint16 port, bool lockToIPv4); void stop(); - void sendMessage(sceneSwitchInfo sceneSwitch); + void sendMessage(sceneSwitchInfo sceneSwitch, bool preview = false); QThreadPool *threadPool() { return &_threadPool; } private: diff --git a/src/switch-network.cpp b/src/switch-network.cpp index 865e4bf0..068d7b6b 100644 --- a/src/switch-network.cpp +++ b/src/switch-network.cpp @@ -18,12 +18,14 @@ Most of this code is based on https://github.com/Palakis/obs-websocket #define PARAM_CLIENT_PORT "ClientPort" #define PARAM_ADDRESS "Address" #define PARAM_CLIENT_SENDALL "SendAll" +#define PARAM_CLIENT_SENDPREVIEW "SendPreview" #define RECONNECT_DELAY 10 #define SCENE_ENTRY "scene" #define TRANSITION_ENTRY "transition" #define TRANSITION_DURATION "duration" +#define SET_PREVIEW "preview" using websocketpp::lib::placeholders::_1; using websocketpp::lib::placeholders::_2; @@ -36,7 +38,8 @@ NetworkConfig::NetworkConfig() ClientEnabled(false), Address(""), ClientPort(55555), - SendAll(true) + SendAll(true), + SendPreview(true) { } @@ -52,6 +55,7 @@ void NetworkConfig::Load(obs_data_t *obj) Address = obs_data_get_string(obj, PARAM_ADDRESS); ClientPort = obs_data_get_int(obj, PARAM_CLIENT_PORT); SendAll = obs_data_get_bool(obj, PARAM_CLIENT_SENDALL); + SendPreview = obs_data_get_bool(obj, PARAM_CLIENT_SENDPREVIEW); } void NetworkConfig::Save(obs_data_t *obj) @@ -64,6 +68,7 @@ void NetworkConfig::Save(obs_data_t *obj) obs_data_set_string(obj, PARAM_ADDRESS, Address.c_str()); obs_data_set_int(obj, PARAM_CLIENT_PORT, ClientPort); obs_data_set_bool(obj, PARAM_CLIENT_SENDALL, SendAll); + obs_data_set_bool(obj, PARAM_CLIENT_SENDPREVIEW, SendPreview); } void NetworkConfig::SetDefaults(obs_data_t *obj) @@ -76,6 +81,7 @@ void NetworkConfig::SetDefaults(obs_data_t *obj) obs_data_set_default_string(obj, PARAM_ADDRESS, Address.c_str()); obs_data_set_default_int(obj, PARAM_CLIENT_PORT, ClientPort); obs_data_set_default_bool(obj, PARAM_CLIENT_SENDALL, SendAll); + obs_data_set_default_bool(obj, PARAM_CLIENT_SENDPREVIEW, SendPreview); } std::string NetworkConfig::GetClientUri() @@ -192,7 +198,7 @@ void WSServer::stop() blog(LOG_INFO, "server stopped successfully"); } -void WSServer::sendMessage(sceneSwitchInfo sceneSwitch) +void WSServer::sendMessage(sceneSwitchInfo sceneSwitch, bool preview) { if (!sceneSwitch.scene) { return; @@ -204,6 +210,7 @@ void WSServer::sendMessage(sceneSwitchInfo sceneSwitch) obs_data_set_string(data, TRANSITION_ENTRY, GetWeakSourceName(sceneSwitch.transition).c_str()); obs_data_set_int(data, TRANSITION_DURATION, sceneSwitch.duration); + obs_data_set_bool(data, SET_PREVIEW, preview); std::string message = obs_data_get_json(data); obs_data_release(data); @@ -248,7 +255,8 @@ std::string processMessage(std::string payload) if (!obs_data_has_user_value(data, SCENE_ENTRY) || !obs_data_has_user_value(data, TRANSITION_ENTRY) || - !obs_data_has_user_value(data, TRANSITION_DURATION)) { + !obs_data_has_user_value(data, TRANSITION_DURATION) || + !obs_data_has_user_value(data, SET_PREVIEW)) { return "missing request parameters"; } @@ -256,6 +264,7 @@ std::string processMessage(std::string payload) std::string transitionName = obs_data_get_string(data, TRANSITION_ENTRY); int duration = obs_data_get_int(data, TRANSITION_DURATION); + bool preview = obs_data_get_bool(data, SET_PREVIEW); obs_data_release(data); @@ -271,8 +280,11 @@ std::string processMessage(std::string payload) ret += " - ignoring invalid transition: '" + transitionName + "'"; } - - switchScene({scene, transition, duration}); + if (preview) { + switchPreviewScene(scene); + } else { + switchScene({scene, transition, duration}); + } return ret; } @@ -479,6 +491,7 @@ void AdvSceneSwitcher::setupNetworkTab() ui->clientHostname->setText(switcher->networkConfig.Address.c_str()); ui->clientPort->setValue(switcher->networkConfig.ClientPort); ui->restrictSend->setChecked(!switcher->networkConfig.SendAll); + ui->sendPreview->setChecked(switcher->networkConfig.SendPreview); QTimer *statusTimer = new QTimer(this); connect(statusTimer, SIGNAL(timeout()), this, @@ -602,6 +615,16 @@ void AdvSceneSwitcher::on_restrictSend_stateChanged(int state) switcher->networkConfig.SendAll = !state; } +void AdvSceneSwitcher::on_sendPreview_stateChanged(int state) +{ + if (loading) { + return; + } + + std::lock_guard lock(switcher->m); + switcher->networkConfig.SendPreview = state; +} + void AdvSceneSwitcher::on_clientReconnect_clicked() { if (loading) {