Add option to synchronize preview scene via network tab

This commit is contained in:
WarmUpTill 2021-05-23 09:32:25 +02:00 committed by WarmUpTill
parent e83a9e8d94
commit 66285a0d3d
6 changed files with 79 additions and 23 deletions

View File

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

View File

@ -3727,6 +3727,13 @@
<layout class="QVBoxLayout" name="verticalLayout_31">
<item>
<layout class="QGridLayout" name="gridLayout_24">
<item row="4" column="1">
<widget class="QLabel" name="serverStatus">
<property name="text">
<string>AdvSceneSwitcher.networkTab.server.status.notRunning</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="serverPort">
<property name="minimum">
@ -3740,13 +3747,6 @@
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_17">
<property name="text">
<string>AdvSceneSwitcher.networkTab.server.port</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="lockToIPv4">
<property name="text">
@ -3754,17 +3754,10 @@
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_19">
<item row="0" column="0">
<widget class="QLabel" name="label_17">
<property name="text">
<string>AdvSceneSwitcher.networkTab.server.status.currentStatus</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="serverStatus">
<property name="text">
<string>AdvSceneSwitcher.networkTab.server.status.notRunning</string>
<string>AdvSceneSwitcher.networkTab.server.port</string>
</property>
</widget>
</item>
@ -3775,6 +3768,20 @@
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_19">
<property name="text">
<string>AdvSceneSwitcher.networkTab.server.status.currentStatus</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="sendPreview">
<property name="text">
<string>AdvSceneSwitcher.networkTab.server.sendPreview</string>
</property>
</widget>
</item>
</layout>
</item>
<item>

View File

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

View File

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

View File

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

View File

@ -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<std::mutex> lock(switcher->m);
switcher->networkConfig.SendPreview = state;
}
void AdvSceneSwitcher::on_clientReconnect_clicked()
{
if (loading) {