Skip to content

Commit

Permalink
Add option to check current streaming service
Browse files Browse the repository at this point in the history
  • Loading branch information
WarmUpTill committed Oct 12, 2024
1 parent c80edaa commit ca8e806
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 32 deletions.
1 change: 0 additions & 1 deletion data/locale/de-DE.ini
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
6 changes: 5 additions & 1 deletion data/locale/en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,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}}"
AdvSceneSwitcher.condition.record="Recording"
AdvSceneSwitcher.condition.record.state.start="Recording running"
AdvSceneSwitcher.condition.record.state.pause="Recording paused"
Expand Down Expand Up @@ -1879,6 +1881,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."
Expand Down
1 change: 0 additions & 1 deletion data/locale/es-ES.ini
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
1 change: 0 additions & 1 deletion data/locale/pt-BR.ini
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
1 change: 0 additions & 1 deletion data/locale/tr-TR.ini
Original file line number Diff line number Diff line change
Expand Up @@ -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ı"
Expand Down
1 change: 0 additions & 1 deletion data/locale/zh-CN.ini
Original file line number Diff line number Diff line change
Expand Up @@ -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="录制暂停"
Expand Down
110 changes: 89 additions & 21 deletions plugins/base/macro-condition-streaming.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "layout-helpers.hpp"

#include <obs-frontend-api.h>
#include <obs.hpp>

namespace advss {

Expand All @@ -25,14 +26,16 @@ const static std::map<MacroConditionStream::Condition, std::string>
"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();
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 *) {
Expand All @@ -56,23 +59,48 @@ 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;

bool streamStarting = streamStartTime != _lastStreamStartingTime;
bool streamStopping = streamStopTime != _lastStreamStoppingTime;
const int keyFrameInterval = GetKeyFrameInterval();
auto serviceName = getCurrentServiceName();

switch (_condition) {
case Condition::STOP:
Expand All @@ -90,6 +118,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;
}
Expand All @@ -108,6 +143,7 @@ bool MacroConditionStream::CheckCondition()
SetTempVarValue("durationSeconds",
std::to_string(streamDurationSeconds));
SetTempVarValue("keyframeInterval", std::to_string(keyFrameInterval));
SetTempVarValue("serviceName", serviceName);

return match;
}
Expand All @@ -117,6 +153,8 @@ bool MacroConditionStream::Save(obs_data_t *obj) const
MacroCondition::Save(obj);
obs_data_set_int(obj, "state", static_cast<int>(_condition));
_keyFrameInterval.Save(obj, "keyFrameInterval");
_serviceName.Save(obj, "serviceName");
_regex.Save(obj);
return true;
}

Expand All @@ -125,6 +163,8 @@ bool MacroConditionStream::Load(obs_data_t *obj)
MacroCondition::Load(obj);
_condition = static_cast<Condition>(obs_data_get_int(obj, "state"));
_keyFrameInterval.Load(obj, "keyFrameInterval");
_serviceName.Load(obj, "serviceName");
_regex.Load(obj);
return true;
}

Expand All @@ -143,6 +183,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)
Expand All @@ -156,11 +202,18 @@ MacroConditionStreamEdit::MacroConditionStreamEdit(
QWidget *parent, std::shared_ptr<MacroConditionStream> entryData)
: QWidget(parent),
_streamState(new QComboBox()),
_keyFrameInterval(new VariableSpinBox())
_keyFrameInterval(new VariableSpinBox()),
_serviceName(new VariableLineEdit(this)),
_regex(new RegexConfigWidget(this))
{
_keyFrameInterval->setMinimum(0);
_keyFrameInterval->setMaximum(25);

QString formatString = obs_module_text(
"AdvSceneSwitcher.condition.stream.service.tooltip");
_serviceName->setToolTip(formatString.arg(
QString::fromStdString(getCurrentServiceName())));

populateStateSelection(_streamState);

QWidget::connect(_streamState, SIGNAL(currentIndexChanged(int)), this,
Expand All @@ -170,13 +223,20 @@ MacroConditionStreamEdit::MacroConditionStreamEdit(
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
this,
SLOT(KeyFrameIntervalChanged(const NumberVariable<int> &)));
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}});
setLayout(layout);

_entryData = entryData;
UpdateEntryData();
Expand All @@ -185,27 +245,31 @@ MacroConditionStreamEdit::MacroConditionStreamEdit(

void MacroConditionStreamEdit::StateChanged(int value)
{
if (_loading || !_entryData) {
return;
}

auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_condition =
static_cast<MacroConditionStream::Condition>(value);
SetWidgetVisiblity();
SetWidgetVisibility();
}

void MacroConditionStreamEdit::KeyFrameIntervalChanged(
const NumberVariable<int> &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 &regex)
{
GUARD_LOADING_AND_LOCK();
_entryData->_regex = regex;
}

void MacroConditionStreamEdit::UpdateEntryData()
{
if (!_entryData) {
Expand All @@ -214,17 +278,21 @@ void MacroConditionStreamEdit::UpdateEntryData()

_streamState->setCurrentIndex(static_cast<int>(_entryData->_condition));
_keyFrameInterval->SetValue(_entryData->_keyFrameInterval);
SetWidgetVisiblity();
SetWidgetVisibility();
}

void MacroConditionStreamEdit::SetWidgetVisiblity()
void MacroConditionStreamEdit::SetWidgetVisibility()
{
if (!_entryData) {
return;
}
_keyFrameInterval->setVisible(
_entryData->_condition ==
MacroConditionStream::Condition::KEYFRAME_INTERVAL);
_serviceName->setVisible(_entryData->_condition ==
MacroConditionStream::Condition::SERVICE);
_regex->setVisible(_entryData->_condition ==
MacroConditionStream::Condition::SERVICE);
}

} // namespace advss
19 changes: 14 additions & 5 deletions plugins/base/macro-condition-streaming.hpp
Original file line number Diff line number Diff line change
@@ -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 <QWidget>
#include <QComboBox>
Expand All @@ -25,9 +28,12 @@ class MacroConditionStream : public MacroCondition {
STARTING,
STOPPING,
KEYFRAME_INTERVAL,
SERVICE,
};
Condition _condition = Condition::STOP;
NumberVariable<int> _keyFrameInterval = 0;
StringVariable _serviceName = "";
RegexConfig _regex;

private:
void SetupTempVars();
Expand Down Expand Up @@ -59,15 +65,18 @@ class MacroConditionStreamEdit : public QWidget {
private slots:
void StateChanged(int value);
void KeyFrameIntervalChanged(const NumberVariable<int> &);
void ServiceNameChanged();
void RegexChanged(const RegexConfig &);

private:
void SetWidgetVisibility();

protected:
QComboBox *_streamState;
VariableSpinBox *_keyFrameInterval;
std::shared_ptr<MacroConditionStream> _entryData;

private:
void SetWidgetVisiblity();
VariableLineEdit *_serviceName;
RegexConfigWidget *_regex;

std::shared_ptr<MacroConditionStream> _entryData;
bool _loading = true;
};

Expand Down

0 comments on commit ca8e806

Please sign in to comment.