From 071c3309c2bfea0a173777e4f0c3a00a7a807201 Mon Sep 17 00:00:00 2001 From: WarmUpTill <19472752+WarmUpTill@users.noreply.github.com> Date: Sun, 13 Oct 2024 00:13:09 +0200 Subject: [PATCH] Add option to check current streaming service --- data/locale/de-DE.ini | 1 - data/locale/en-US.ini | 6 +- data/locale/es-ES.ini | 1 - data/locale/pt-BR.ini | 1 - data/locale/tr-TR.ini | 1 - data/locale/zh-CN.ini | 1 - plugins/base/macro-condition-streaming.cpp | 124 +++++++++++++++++---- plugins/base/macro-condition-streaming.hpp | 22 +++- 8 files changed, 124 insertions(+), 33 deletions(-) diff --git a/data/locale/de-DE.ini b/data/locale/de-DE.ini index 71c7e940..e67eb90b 100644 --- a/data/locale/de-DE.ini +++ b/data/locale/de-DE.ini @@ -212,7 +212,6 @@ AdvSceneSwitcher.condition.stream.state.start="Stream läuft" AdvSceneSwitcher.condition.stream.state.stop="Stream gestoppt" AdvSceneSwitcher.condition.stream.state.starting="Stream wird gestartet" AdvSceneSwitcher.condition.stream.state.stopping="Stream wird gestoppt" -AdvSceneSwitcher.condition.stream.entry="{{streamState}}{{keyFrameInterval}}" AdvSceneSwitcher.condition.record="Aufnahme" AdvSceneSwitcher.condition.record.state.start="Aufnahme läuft" AdvSceneSwitcher.condition.record.state.pause="Aufnahme pausiert" diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index 57626229..f25383a1 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -419,7 +419,9 @@ AdvSceneSwitcher.condition.stream.state.stop="Stream stopped" AdvSceneSwitcher.condition.stream.state.starting="Stream starting" AdvSceneSwitcher.condition.stream.state.stopping="Stream stopping" AdvSceneSwitcher.condition.stream.state.keyFrameInterval="Keyframe interval equals" -AdvSceneSwitcher.condition.stream.entry="{{streamState}}{{keyFrameInterval}}" +AdvSceneSwitcher.condition.stream.state.service="Service name matches" +AdvSceneSwitcher.condition.stream.service.tooltip="Current service name: %1" +AdvSceneSwitcher.condition.stream.entry="{{streamState}}{{keyFrameInterval}}{{serviceName}}{{regex}}{{currentService}}" AdvSceneSwitcher.condition.record="Recording" AdvSceneSwitcher.condition.record.state.start="Recording running" AdvSceneSwitcher.condition.record.state.pause="Recording paused" @@ -1882,6 +1884,8 @@ AdvSceneSwitcher.tempVar.streaming.keyframeInterval="Stream keyframe interval" AdvSceneSwitcher.tempVar.streaming.keyframeInterval.description="Stream keyframe interval configured in the OBS settings." AdvSceneSwitcher.tempVar.streaming.durationSeconds="Stream duration" AdvSceneSwitcher.tempVar.streaming.durationSeconds.description="Seconds passed since the stream was started.\nThis value will be zero if the stream is stopped." +AdvSceneSwitcher.tempVar.streaming.serviceName="Service" +AdvSceneSwitcher.tempVar.streaming.serviceName.description="The name of the streaming service being streamed to (e.g. Twitch)" AdvSceneSwitcher.tempVar.clipboard.text="Clipboard text" AdvSceneSwitcher.tempVar.clipboard.text.description="The text contained in the clipboard.\nWill be empty if the clipboard does not contain text." diff --git a/data/locale/es-ES.ini b/data/locale/es-ES.ini index 958deff9..9f466d46 100644 --- a/data/locale/es-ES.ini +++ b/data/locale/es-ES.ini @@ -172,7 +172,6 @@ AdvSceneSwitcher.condition.stream.state.start="Transmisión en ejecución" AdvSceneSwitcher.condition.stream.state.stop="Transmisión detenida" AdvSceneSwitcher.condition.stream.state.starting="Inicio de transmisión" AdvSceneSwitcher.condition.stream.state.stopping="Detener transmisión" -AdvSceneSwitcher.condition.stream.entry="{{streamState}}{{keyFrameInterval}}" AdvSceneSwitcher.condition.record="Grabación" AdvSceneSwitcher.condition.record.state.start="Grabación en ejecución" AdvSceneSwitcher.condition.record.state.pause="Grabación en pausa" diff --git a/data/locale/pt-BR.ini b/data/locale/pt-BR.ini index a5f7fcd5..c6cc3d28 100644 --- a/data/locale/pt-BR.ini +++ b/data/locale/pt-BR.ini @@ -395,7 +395,6 @@ AdvSceneSwitcher.condition.stream.state.stop="Streaming parado" AdvSceneSwitcher.condition.stream.state.starting="Iniciando o streaming" AdvSceneSwitcher.condition.stream.state.stopping="Parando o streaming" AdvSceneSwitcher.condition.stream.state.keyFrameInterval="Intervalo de keyframe igual a" -AdvSceneSwitcher.condition.stream.entry="{{streamState}}{{keyFrameInterval}}" AdvSceneSwitcher.condition.record="Gravação" AdvSceneSwitcher.condition.record.state.start="Gravação em execução" AdvSceneSwitcher.condition.record.state.pause="Gravação pausada" diff --git a/data/locale/tr-TR.ini b/data/locale/tr-TR.ini index 3d8af1a9..c3befce3 100644 --- a/data/locale/tr-TR.ini +++ b/data/locale/tr-TR.ini @@ -149,7 +149,6 @@ AdvSceneSwitcher.condition.stream.state.start="Yayın çalışıyor" AdvSceneSwitcher.condition.stream.state.stop="Yayın durdu" AdvSceneSwitcher.condition.stream.state.starting="Yayın başlıyor" AdvSceneSwitcher.condition.stream.state.stopping="Yayın duruyor" -AdvSceneSwitcher.condition.stream.entry="{{streamState}}{{keyFrameInterval}}" AdvSceneSwitcher.condition.record="Kayıt" AdvSceneSwitcher.condition.record.state.start="Kayıt Çalışıyor" AdvSceneSwitcher.condition.record.state.pause="Kayıt durakladı" diff --git a/data/locale/zh-CN.ini b/data/locale/zh-CN.ini index aa643f62..cf0607aa 100644 --- a/data/locale/zh-CN.ini +++ b/data/locale/zh-CN.ini @@ -257,7 +257,6 @@ AdvSceneSwitcher.condition.stream.state.stop="推流停止" AdvSceneSwitcher.condition.stream.state.starting="推流启动中" AdvSceneSwitcher.condition.stream.state.stopping="推流停止中" AdvSceneSwitcher.condition.stream.state.keyFrameInterval="关键帧间隔等于" -AdvSceneSwitcher.condition.stream.entry="{{streamState}}{{keyFrameInterval}}" AdvSceneSwitcher.condition.record="录制" AdvSceneSwitcher.condition.record.state.start="录制运行中" AdvSceneSwitcher.condition.record.state.pause="录制暂停" diff --git a/plugins/base/macro-condition-streaming.cpp b/plugins/base/macro-condition-streaming.cpp index bec42718..5afd4958 100644 --- a/plugins/base/macro-condition-streaming.cpp +++ b/plugins/base/macro-condition-streaming.cpp @@ -1,8 +1,10 @@ #include "macro-condition-streaming.hpp" #include "profile-helpers.hpp" #include "layout-helpers.hpp" +#include "ui-helpers.hpp" #include +#include namespace advss { @@ -25,6 +27,8 @@ const static std::map "AdvSceneSwitcher.condition.stream.state.stopping"}, {MacroConditionStream::Condition::KEYFRAME_INTERVAL, "AdvSceneSwitcher.condition.stream.state.keyFrameInterval"}, + {MacroConditionStream::Condition::SERVICE, + "AdvSceneSwitcher.condition.stream.state.service"}, }; static bool setupStreamingEventHandler(); @@ -32,7 +36,7 @@ static bool steamingEventHandlerIsSetup = setupStreamingEventHandler(); static std::chrono::high_resolution_clock::time_point streamStartTime{}; static std::chrono::high_resolution_clock::time_point streamStopTime{}; -bool setupStreamingEventHandler() +static bool setupStreamingEventHandler() { static auto handleStreamingEvents = [](enum obs_frontend_event event, void *) { @@ -56,16 +60,40 @@ bool setupStreamingEventHandler() int MacroConditionStream::GetKeyFrameInterval() const { const auto configPath = GetPathInProfileDir("streamEncoder.json"); - obs_data_t *settings = + OBSDataAutoRelease settings = obs_data_create_from_json_file_safe(configPath.c_str(), "bak"); if (!settings) { return -1; } int ret = obs_data_get_int(settings, "keyint_sec"); - obs_data_release(settings); return ret; } +static std::string getCurrentServiceName() +{ + auto service = obs_frontend_get_streaming_service(); + if (!service) { + return "None"; + } + + auto id = obs_service_get_id(service); + if (strcmp(id, "rtmp_common") != 0) { + return obs_service_get_display_name(id); + } + + const auto configPath = GetPathInProfileDir("service.json"); + OBSDataAutoRelease serviceSettings = + obs_data_create_from_json_file_safe(configPath.c_str(), "bak"); + OBSDataAutoRelease settings = + obs_data_get_obj(serviceSettings, "settings"); + auto serviceName = obs_data_get_string(settings, "service"); + + if (serviceName) { + return serviceName; + } + return "None"; +} + bool MacroConditionStream::CheckCondition() { bool match = false; @@ -73,6 +101,7 @@ bool MacroConditionStream::CheckCondition() bool streamStarting = streamStartTime != _lastStreamStartingTime; bool streamStopping = streamStopTime != _lastStreamStoppingTime; const int keyFrameInterval = GetKeyFrameInterval(); + auto serviceName = getCurrentServiceName(); switch (_condition) { case Condition::STOP: @@ -90,6 +119,13 @@ bool MacroConditionStream::CheckCondition() case Condition::KEYFRAME_INTERVAL: match = keyFrameInterval == _keyFrameInterval; break; + case Condition::SERVICE: + if (_regex.Enabled()) { + match = _regex.Matches(serviceName, _serviceName); + } else { + match = std::string(_serviceName) == serviceName; + } + break; default: break; } @@ -108,6 +144,7 @@ bool MacroConditionStream::CheckCondition() SetTempVarValue("durationSeconds", std::to_string(streamDurationSeconds)); SetTempVarValue("keyframeInterval", std::to_string(keyFrameInterval)); + SetTempVarValue("serviceName", serviceName); return match; } @@ -117,6 +154,8 @@ bool MacroConditionStream::Save(obs_data_t *obj) const MacroCondition::Save(obj); obs_data_set_int(obj, "state", static_cast(_condition)); _keyFrameInterval.Save(obj, "keyFrameInterval"); + _serviceName.Save(obj, "serviceName"); + _regex.Save(obj); return true; } @@ -125,6 +164,8 @@ bool MacroConditionStream::Load(obs_data_t *obj) MacroCondition::Load(obj); _condition = static_cast(obs_data_get_int(obj, "state")); _keyFrameInterval.Load(obj, "keyFrameInterval"); + _serviceName.Load(obj, "serviceName"); + _regex.Load(obj); return true; } @@ -143,6 +184,12 @@ void MacroConditionStream::SetupTempVars() "AdvSceneSwitcher.tempVar.streaming.durationSeconds"), obs_module_text( "AdvSceneSwitcher.tempVar.streaming.durationSeconds.description")); + AddTempvar( + "serviceName", + obs_module_text( + "AdvSceneSwitcher.tempVar.streaming.serviceName"), + obs_module_text( + "AdvSceneSwitcher.tempVar.streaming.serviceName.description")); } static inline void populateStateSelection(QComboBox *list) @@ -156,11 +203,28 @@ MacroConditionStreamEdit::MacroConditionStreamEdit( QWidget *parent, std::shared_ptr entryData) : QWidget(parent), _streamState(new QComboBox()), - _keyFrameInterval(new VariableSpinBox()) + _keyFrameInterval(new VariableSpinBox()), + _serviceName(new VariableLineEdit(this)), + _currentService(new AutoUpdateTooltipLabel( + this, + []() { + QString formatString = obs_module_text( + "AdvSceneSwitcher.condition.stream.service.tooltip"); + return formatString.arg(QString::fromStdString( + getCurrentServiceName())); + })), + _regex(new RegexConfigWidget(this)) { _keyFrameInterval->setMinimum(0); _keyFrameInterval->setMaximum(25); + QString path = GetThemeTypeName() == "Light" + ? ":/res/images/help.svg" + : ":/res/images/help_light.svg"; + QIcon icon(path); + QPixmap pixmap = icon.pixmap(QSize(16, 16)); + _currentService->setPixmap(pixmap); + populateStateSelection(_streamState); QWidget::connect(_streamState, SIGNAL(currentIndexChanged(int)), this, @@ -170,13 +234,21 @@ MacroConditionStreamEdit::MacroConditionStreamEdit( SIGNAL(NumberVariableChanged(const NumberVariable &)), this, SLOT(KeyFrameIntervalChanged(const NumberVariable &))); + QWidget::connect(_serviceName, SIGNAL(editingFinished()), this, + SLOT(ServiceNameChanged())); + QWidget::connect(_regex, + SIGNAL(RegexConfigChanged(const RegexConfig &)), this, + SLOT(RegexChanged(const RegexConfig &))); - QHBoxLayout *mainLayout = new QHBoxLayout; + auto layout = new QHBoxLayout; PlaceWidgets(obs_module_text("AdvSceneSwitcher.condition.stream.entry"), - mainLayout, + layout, {{"{{streamState}}", _streamState}, - {"{{keyFrameInterval}}", _keyFrameInterval}}); - setLayout(mainLayout); + {"{{keyFrameInterval}}", _keyFrameInterval}, + {"{{serviceName}}", _serviceName}, + {"{{regex}}", _regex}, + {"{{currentService}}", _currentService}}); + setLayout(layout); _entryData = entryData; UpdateEntryData(); @@ -185,27 +257,31 @@ MacroConditionStreamEdit::MacroConditionStreamEdit( void MacroConditionStreamEdit::StateChanged(int value) { - if (_loading || !_entryData) { - return; - } - - auto lock = LockContext(); + GUARD_LOADING_AND_LOCK(); _entryData->_condition = static_cast(value); - SetWidgetVisiblity(); + SetWidgetVisibility(); } void MacroConditionStreamEdit::KeyFrameIntervalChanged( const NumberVariable &value) { - if (_loading || !_entryData) { - return; - } - - auto lock = LockContext(); + GUARD_LOADING_AND_LOCK(); _entryData->_keyFrameInterval = value; } +void MacroConditionStreamEdit::ServiceNameChanged() +{ + GUARD_LOADING_AND_LOCK(); + _entryData->_serviceName = _serviceName->text().toStdString(); +} + +void MacroConditionStreamEdit::RegexChanged(const RegexConfig ®ex) +{ + GUARD_LOADING_AND_LOCK(); + _entryData->_regex = regex; +} + void MacroConditionStreamEdit::UpdateEntryData() { if (!_entryData) { @@ -214,10 +290,10 @@ void MacroConditionStreamEdit::UpdateEntryData() _streamState->setCurrentIndex(static_cast(_entryData->_condition)); _keyFrameInterval->SetValue(_entryData->_keyFrameInterval); - SetWidgetVisiblity(); + SetWidgetVisibility(); } -void MacroConditionStreamEdit::SetWidgetVisiblity() +void MacroConditionStreamEdit::SetWidgetVisibility() { if (!_entryData) { return; @@ -225,6 +301,12 @@ void MacroConditionStreamEdit::SetWidgetVisiblity() _keyFrameInterval->setVisible( _entryData->_condition == MacroConditionStream::Condition::KEYFRAME_INTERVAL); + const bool isCheckingStreamingService = + _entryData->_condition == + MacroConditionStream::Condition::SERVICE; + _serviceName->setVisible(isCheckingStreamingService); + _regex->setVisible(isCheckingStreamingService); + _currentService->setVisible(isCheckingStreamingService); } } // namespace advss diff --git a/plugins/base/macro-condition-streaming.hpp b/plugins/base/macro-condition-streaming.hpp index ad6adc34..ccc6d80b 100644 --- a/plugins/base/macro-condition-streaming.hpp +++ b/plugins/base/macro-condition-streaming.hpp @@ -1,6 +1,9 @@ #pragma once #include "macro-condition-edit.hpp" #include "variable-spinbox.hpp" +#include "regex-config.hpp" +#include "variable-string.hpp" +#include "variable-line-edit.hpp" #include #include @@ -25,9 +28,12 @@ public: STARTING, STOPPING, KEYFRAME_INTERVAL, + SERVICE, }; Condition _condition = Condition::STOP; NumberVariable _keyFrameInterval = 0; + StringVariable _serviceName = ""; + RegexConfig _regex; private: void SetupTempVars(); @@ -59,15 +65,19 @@ public: private slots: void StateChanged(int value); void KeyFrameIntervalChanged(const NumberVariable &); - -protected: - QComboBox *_streamState; - VariableSpinBox *_keyFrameInterval; - std::shared_ptr _entryData; + void ServiceNameChanged(); + void RegexChanged(const RegexConfig &); private: - void SetWidgetVisiblity(); + void SetWidgetVisibility(); + QComboBox *_streamState; + VariableSpinBox *_keyFrameInterval; + VariableLineEdit *_serviceName; + QLabel *_currentService; + RegexConfigWidget *_regex; + + std::shared_ptr _entryData; bool _loading = true; };