Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to check the current stream key #1248

Merged
merged 2 commits into from
Oct 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion data/locale/en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -419,9 +419,10 @@ 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.state.streamKey="Stream key is"
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.stream.entry="{{streamState}}{{keyFrameInterval}}{{streamKey}}{{serviceName}}{{regex}}{{currentService}}"
AdvSceneSwitcher.condition.record="Recording"
AdvSceneSwitcher.condition.record.state.start="Recording running"
AdvSceneSwitcher.condition.record.state.pause="Recording paused"
Expand Down Expand Up @@ -1882,6 +1883,7 @@ AdvSceneSwitcher.tempVar.display.height.description="The height of the display w

AdvSceneSwitcher.tempVar.streaming.keyframeInterval="Stream keyframe interval"
AdvSceneSwitcher.tempVar.streaming.keyframeInterval.description="Stream keyframe interval configured in the OBS settings."
AdvSceneSwitcher.tempVar.streaming.streamKey="Stream key"
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"
Expand Down
1 change: 1 addition & 0 deletions lib/macro/macro-condition-queue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ void MacroConditionQueueEdit::UpdateEntryData()
}
_conditions->setCurrentIndex(static_cast<int>(_entryData->_condition));
_queues->SetActionQueue(_entryData->_queue);
_size->SetValue(_entryData->_size);
SetWidgetVisibility();
}

Expand Down
87 changes: 70 additions & 17 deletions plugins/base/macro-condition-streaming.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ bool MacroConditionStream::_registered = MacroConditionFactory::Register(
{MacroConditionStream::Create, MacroConditionStreamEdit::Create,
"AdvSceneSwitcher.condition.stream"});

const static std::map<MacroConditionStream::Condition, std::string>
streamStates = {
const static std::map<MacroConditionStream::Condition, std::string> conditions =
{
{MacroConditionStream::Condition::STOP,
"AdvSceneSwitcher.condition.stream.state.stop"},
{MacroConditionStream::Condition::START,
Expand All @@ -27,6 +27,8 @@ const static std::map<MacroConditionStream::Condition, std::string>
"AdvSceneSwitcher.condition.stream.state.stopping"},
{MacroConditionStream::Condition::KEYFRAME_INTERVAL,
"AdvSceneSwitcher.condition.stream.state.keyFrameInterval"},
{MacroConditionStream::Condition::STREAM_KEY,
"AdvSceneSwitcher.condition.stream.state.streamKey"},
{MacroConditionStream::Condition::SERVICE,
"AdvSceneSwitcher.condition.stream.state.service"},
};
Expand Down Expand Up @@ -57,13 +59,28 @@ static bool setupStreamingEventHandler()
return true;
}

int MacroConditionStream::GetKeyFrameInterval() const
static std::optional<std::string> getStreamKey()
{
const auto configPath = GetPathInProfileDir("service.json");
OBSDataAutoRelease data =
obs_data_create_from_json_file_safe(configPath.c_str(), "bak");
if (!data) {
return {};
}
OBSDataAutoRelease settings = obs_data_get_obj(data, "settings");
if (!settings) {
return {};
}
return obs_data_get_string(settings, "key");
}

std::optional<int> getKeyFrameInterval()
{
const auto configPath = GetPathInProfileDir("streamEncoder.json");
OBSDataAutoRelease settings =
obs_data_create_from_json_file_safe(configPath.c_str(), "bak");
if (!settings) {
return -1;
return {};
}
int ret = obs_data_get_int(settings, "keyint_sec");
return ret;
Expand Down Expand Up @@ -100,7 +117,8 @@ bool MacroConditionStream::CheckCondition()

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

switch (_condition) {
Expand All @@ -117,7 +135,14 @@ bool MacroConditionStream::CheckCondition()
match = streamStopping;
break;
case Condition::KEYFRAME_INTERVAL:
match = keyFrameInterval == _keyFrameInterval;
if (keyFrameInterval) {
match = *keyFrameInterval == _keyFrameInterval;
}
break;
case Condition::STREAM_KEY:
if (streamKey) {
match = streamKey == std::string(_streamKey);
}
break;
case Condition::SERVICE:
if (_regex.Enabled()) {
Expand All @@ -143,8 +168,14 @@ bool MacroConditionStream::CheckCondition()
obs_frontend_streaming_active() ? seconds.count() : 0;
SetTempVarValue("durationSeconds",
std::to_string(streamDurationSeconds));
SetTempVarValue("keyframeInterval", std::to_string(keyFrameInterval));
SetTempVarValue("serviceName", serviceName);
if (keyFrameInterval) {
SetTempVarValue("keyframeInterval",
std::to_string(*keyFrameInterval));
}
if (streamKey) {
SetTempVarValue("streamKey", *streamKey);
}

return match;
}
Expand All @@ -154,6 +185,7 @@ 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");
_streamKey.Save(obj, "streamKey");
_serviceName.Save(obj, "serviceName");
_regex.Save(obj);
return true;
Expand All @@ -164,6 +196,7 @@ bool MacroConditionStream::Load(obs_data_t *obj)
MacroCondition::Load(obj);
_condition = static_cast<Condition>(obs_data_get_int(obj, "state"));
_keyFrameInterval.Load(obj, "keyFrameInterval");
_streamKey.Load(obj, "streamKey");
_serviceName.Load(obj, "serviceName");
_regex.Load(obj);
return true;
Expand All @@ -178,6 +211,9 @@ void MacroConditionStream::SetupTempVars()
"AdvSceneSwitcher.tempVar.streaming.keyframeInterval"),
obs_module_text(
"AdvSceneSwitcher.tempVar.streaming.keyframeInterval.description"));
AddTempvar("streamKey",
obs_module_text(
"AdvSceneSwitcher.tempVar.streaming.streamKey"));
AddTempvar(
"durationSeconds",
obs_module_text(
Expand All @@ -192,18 +228,19 @@ void MacroConditionStream::SetupTempVars()
"AdvSceneSwitcher.tempVar.streaming.serviceName.description"));
}

static inline void populateStateSelection(QComboBox *list)
static void populateConditionSelection(QComboBox *list)
{
for (auto entry : streamStates) {
list->addItem(obs_module_text(entry.second.c_str()));
for (const auto &[_, name] : conditions) {
list->addItem(obs_module_text(name.c_str()));
}
}

MacroConditionStreamEdit::MacroConditionStreamEdit(
QWidget *parent, std::shared_ptr<MacroConditionStream> entryData)
: QWidget(parent),
_streamState(new QComboBox()),
_conditions(new QComboBox()),
_keyFrameInterval(new VariableSpinBox()),
_streamKey(new VariableLineEdit(this)),
_serviceName(new VariableLineEdit(this)),
_currentService(new AutoUpdateTooltipLabel(
this,
Expand All @@ -225,10 +262,12 @@ MacroConditionStreamEdit::MacroConditionStreamEdit(
QPixmap pixmap = icon.pixmap(QSize(16, 16));
_currentService->setPixmap(pixmap);

populateStateSelection(_streamState);
_streamKey->setEchoMode(QLineEdit::PasswordEchoOnEdit);

populateConditionSelection(_conditions);

QWidget::connect(_streamState, SIGNAL(currentIndexChanged(int)), this,
SLOT(StateChanged(int)));
QWidget::connect(_conditions, SIGNAL(currentIndexChanged(int)), this,
SLOT(ConditionChanged(int)));
QWidget::connect(
_keyFrameInterval,
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
Expand All @@ -239,12 +278,15 @@ MacroConditionStreamEdit::MacroConditionStreamEdit(
QWidget::connect(_regex,
SIGNAL(RegexConfigChanged(const RegexConfig &)), this,
SLOT(RegexChanged(const RegexConfig &)));
QWidget::connect(_streamKey, SIGNAL(editingFinished()), this,
SLOT(StreamKeyChanged()));

auto layout = new QHBoxLayout;
PlaceWidgets(obs_module_text("AdvSceneSwitcher.condition.stream.entry"),
layout,
{{"{{streamState}}", _streamState},
{{"{{streamState}}", _conditions},
{"{{keyFrameInterval}}", _keyFrameInterval},
{"{{streamKey}}", _streamKey},
{"{{serviceName}}", _serviceName},
{"{{regex}}", _regex},
{"{{currentService}}", _currentService}});
Expand All @@ -255,7 +297,7 @@ MacroConditionStreamEdit::MacroConditionStreamEdit(
_loading = false;
}

void MacroConditionStreamEdit::StateChanged(int value)
void MacroConditionStreamEdit::ConditionChanged(int value)
{
GUARD_LOADING_AND_LOCK();
_entryData->_condition =
Expand All @@ -282,13 +324,22 @@ void MacroConditionStreamEdit::RegexChanged(const RegexConfig &regex)
_entryData->_regex = regex;
}

void MacroConditionStreamEdit::StreamKeyChanged()
{
GUARD_LOADING_AND_LOCK();
_entryData->_streamKey = _streamKey->text().toStdString();
}

void MacroConditionStreamEdit::UpdateEntryData()
{
if (!_entryData) {
return;
}

_streamState->setCurrentIndex(static_cast<int>(_entryData->_condition));
_conditions->setCurrentIndex(static_cast<int>(_entryData->_condition));
_streamKey->setText(_entryData->_streamKey);
_serviceName->setText(_entryData->_serviceName);
_regex->SetRegexConfig(_entryData->_regex);
_keyFrameInterval->SetValue(_entryData->_keyFrameInterval);
SetWidgetVisibility();
}
Expand All @@ -301,6 +352,8 @@ void MacroConditionStreamEdit::SetWidgetVisibility()
_keyFrameInterval->setVisible(
_entryData->_condition ==
MacroConditionStream::Condition::KEYFRAME_INTERVAL);
_streamKey->setVisible(_entryData->_condition ==
MacroConditionStream::Condition::STREAM_KEY);
const bool isCheckingStreamingService =
_entryData->_condition ==
MacroConditionStream::Condition::SERVICE;
Expand Down
9 changes: 6 additions & 3 deletions plugins/base/macro-condition-streaming.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,17 @@ class MacroConditionStream : public MacroCondition {
STARTING,
STOPPING,
KEYFRAME_INTERVAL,
STREAM_KEY,
SERVICE,
};
Condition _condition = Condition::STOP;
NumberVariable<int> _keyFrameInterval = 0;
StringVariable _streamKey;
StringVariable _serviceName = "";
RegexConfig _regex;

private:
void SetupTempVars();
int GetKeyFrameInterval() const;

std::chrono::high_resolution_clock::time_point _lastStreamStartingTime{};
std::chrono::high_resolution_clock::time_point _lastStreamStoppingTime{};
Expand All @@ -63,16 +64,18 @@ class MacroConditionStreamEdit : public QWidget {
}

private slots:
void StateChanged(int value);
void ConditionChanged(int value);
void KeyFrameIntervalChanged(const NumberVariable<int> &);
void StreamKeyChanged();
void ServiceNameChanged();
void RegexChanged(const RegexConfig &);

private:
void SetWidgetVisibility();

QComboBox *_streamState;
QComboBox *_conditions;
VariableSpinBox *_keyFrameInterval;
VariableLineEdit *_streamKey;
VariableLineEdit *_serviceName;
QLabel *_currentService;
RegexConfigWidget *_regex;
Expand Down
Loading