Add option to change various OBS video settings

This commit is contained in:
WarmUpTill 2025-05-25 15:58:35 +02:00 committed by WarmUpTill
parent 9a86ecac42
commit c05dd40c4c
4 changed files with 499 additions and 4 deletions

View File

@ -1238,6 +1238,18 @@ AdvSceneSwitcher.action.mqtt.topic="Topic:"
AdvSceneSwitcher.action.mqtt.qos="QoS:"
AdvSceneSwitcher.action.mqtt.retain="Retained message:"
AdvSceneSwitcher.action.mqtt.layout="Send message to{{connection}}"
AdvSceneSwitcher.action.obsSetting="OBS setting"
AdvSceneSwitcher.action.obsSetting.action.setFPSType="Set FPS selection type to"
AdvSceneSwitcher.action.obsSetting.action.setFPSCommonValue="Set FPS common selection to"
AdvSceneSwitcher.action.obsSetting.action.setFPSIntegerValue="Set FPS integer selection to"
AdvSceneSwitcher.action.obsSetting.action.setFPSFractionNumeratorValue="Set fractional FPS numerator selection to"
AdvSceneSwitcher.action.obsSetting.action.setFPSFractionDenominatorValue="Set fractional FPS denominator selection to"
AdvSceneSwitcher.action.obsSetting.action.setBaseCanvasX="Set base resolution X value"
AdvSceneSwitcher.action.obsSetting.action.setBaseCanvasY="Set base resolution Y value"
AdvSceneSwitcher.action.obsSetting.action.setOutputCanvasX="Set output resolution X value"
AdvSceneSwitcher.action.obsSetting.action.setOutputCanvasY="Set output resolution Y value"
AdvSceneSwitcher.action.obsSetting.getCurrentValue="Get current value"
AdvSceneSwitcher.action.obsSettings.layout="{{actions}}{{fpsType}}{{fpsIntValue}}{{fpsStringValue}}{{canvasSizeValue}}{{getCurrentValue}}"
# Hotkey
AdvSceneSwitcher.hotkey.startSwitcherHotkey="Start the Advanced Scene Switcher"
@ -2250,13 +2262,12 @@ AdvSceneSwitcher.script.timeout="Script timeout:{{timeout}}"
# This secion is copied from the OBS locale files
# commonly shared locale
# OBS commonly shared locale
Browse="Browse"
Show="Show"
Hide="Hide"
# properties window
# OBS properties window
Basic.PropertiesWindow="Properties for '%1'"
Basic.PropertiesWindow.AutoSelectFormat="%1 (autoselect: %2)"
Basic.PropertiesWindow.SelectColor="Select color"
@ -2273,7 +2284,7 @@ Basic.PropertiesWindow.AddEditableListFiles="Add files to '%1'"
Basic.PropertiesWindow.AddEditableListEntry="Add entry to '%1'"
Basic.PropertiesWindow.EditEditableListEntry="Edit entry from '%1'"
# properties view
# OBS properties view
Basic.PropertiesView.FPS.Simple="Simple FPS Values"
Basic.PropertiesView.FPS.Rational="Rational FPS Values"
Basic.PropertiesView.FPS.ValidFPSRanges="Valid FPS Ranges:"
@ -2281,6 +2292,11 @@ Basic.PropertiesView.UrlButton.Text="Open this link in your default web browser?
Basic.PropertiesView.UrlButton.Text.Url="URL: %1"
Basic.PropertiesView.UrlButton.OpenUrl="Open URL"
# OBS settings
Basic.Settings.Video.FPSCommon="Common FPS Values"
Basic.Settings.Video.FPSInteger="Integer FPS Value"
Basic.Settings.Video.FPSFraction="Fractional FPS Value"
# Legacy tabs below - please don't waste your time adding translations for these :)
# Transition Tab
AdvSceneSwitcher.transitionTab.title="Transition"

View File

@ -21,6 +21,8 @@ target_sources(
macro-action-log.hpp
macro-action-media.cpp
macro-action-media.hpp
macro-action-obs-settings.cpp
macro-action-obs-settings.hpp
macro-action-osc.cpp
macro-action-osc.hpp
macro-action-plugin-state.cpp

View File

@ -0,0 +1,387 @@
#include "macro-action-obs-settings.hpp"
#include "layout-helpers.hpp"
#include "profile-helpers.hpp"
#include "ui-helpers.hpp"
#include <obs-frontend-api.h>
#include <util/config-file.h>
namespace advss {
const std::string MacroActionOBSSettings::id = "obs_settings";
bool MacroActionOBSSettings::_registered = MacroActionFactory::Register(
MacroActionOBSSettings::id,
{MacroActionOBSSettings::Create, MacroActionOBSSettingsEdit::Create,
"AdvSceneSwitcher.action.obsSetting"});
const static std::map<MacroActionOBSSettings::Action, std::string> actionTypes = {
{MacroActionOBSSettings::Action::FPS_TYPE,
"AdvSceneSwitcher.action.obsSetting.action.setFPSType"},
{MacroActionOBSSettings::Action::FPS_COMMON_VALUE,
"AdvSceneSwitcher.action.obsSetting.action.setFPSCommonValue"},
{MacroActionOBSSettings::Action::FPS_INT_VALUE,
"AdvSceneSwitcher.action.obsSetting.action.setFPSIntegerValue"},
{MacroActionOBSSettings::Action::FPS_NUM_VALUE,
"AdvSceneSwitcher.action.obsSetting.action.setFPSFractionNumeratorValue"},
{MacroActionOBSSettings::Action::FPS_DEN_VALUE,
"AdvSceneSwitcher.action.obsSetting.action.setFPSFractionDenominatorValue"},
{MacroActionOBSSettings::Action::BASE_CANVAS_X_VALUE,
"AdvSceneSwitcher.action.obsSetting.action.setBaseCanvasX"},
{MacroActionOBSSettings::Action::BASE_CANVAS_Y_VALUE,
"AdvSceneSwitcher.action.obsSetting.action.setBaseCanvasY"},
{MacroActionOBSSettings::Action::OUTPUT_X_VALUE,
"AdvSceneSwitcher.action.obsSetting.action.setOutputCanvasX"},
{MacroActionOBSSettings::Action::OUTPUT_Y_VALUE,
"AdvSceneSwitcher.action.obsSetting.action.setOutputCanvasY"},
};
template<typename Func, typename... Args>
static void setConfigValueHelper(Func func, Args... args)
{
auto config = obs_frontend_get_profile_config();
func(config, args...);
if (config_save(config) != CONFIG_SUCCESS) {
blog(LOG_WARNING, "failed to save config!");
}
}
template<typename Func, typename... Args>
static auto getConfigValueHelper(Func func, Func defaultFunc, Args... args)
-> std::optional<std::invoke_result_t<Func, config_t *, Args...>>
{
using Ret = std::invoke_result_t<Func, config_t *, Args...>;
auto config = obs_frontend_get_profile_config();
if (config_has_user_value(config, args...)) {
return func(config, args...);
}
if (config_has_default_value(config, args...)) {
return defaultFunc(config, args...);
}
return std::optional<Ret>{};
}
bool MacroActionOBSSettings::PerformAction()
{
switch (_action) {
case Action::FPS_TYPE:
setConfigValueHelper(config_set_uint, "Video", "FPSType",
static_cast<int>(_fpsType));
obs_frontend_reset_video();
break;
case Action::FPS_COMMON_VALUE:
setConfigValueHelper(config_set_string, "Video", "FPSCommon",
_fpsStringValue.c_str());
obs_frontend_reset_video();
break;
case Action::FPS_INT_VALUE:
setConfigValueHelper(config_set_uint, "Video", "FPSInt",
static_cast<int>(_fpsIntValue));
obs_frontend_reset_video();
break;
case Action::FPS_NUM_VALUE:
setConfigValueHelper(config_set_uint, "Video", "FPSNum",
static_cast<int>(_fpsIntValue));
obs_frontend_reset_video();
break;
case Action::FPS_DEN_VALUE:
setConfigValueHelper(config_set_uint, "Video", "FPSDen",
static_cast<int>(_fpsIntValue));
obs_frontend_reset_video();
break;
case Action::BASE_CANVAS_X_VALUE:
setConfigValueHelper(config_set_uint, "Video", "BaseCX",
static_cast<int>(_canvasSizeValue));
obs_frontend_reset_video();
break;
case Action::BASE_CANVAS_Y_VALUE:
setConfigValueHelper(config_set_uint, "Video", "BaseCY",
static_cast<int>(_canvasSizeValue));
obs_frontend_reset_video();
break;
case Action::OUTPUT_X_VALUE:
setConfigValueHelper(config_set_uint, "Video", "OutputCX",
static_cast<int>(_canvasSizeValue));
obs_frontend_reset_video();
break;
case Action::OUTPUT_Y_VALUE:
setConfigValueHelper(config_set_uint, "Video", "OutputCY",
static_cast<int>(_canvasSizeValue));
obs_frontend_reset_video();
break;
default:
break;
}
return true;
}
void MacroActionOBSSettings::LogAction() const
{
auto it = actionTypes.find(_action);
if (it != actionTypes.end()) {
ablog(LOG_INFO, "performed action \"%s\"", it->second.c_str());
} else {
blog(LOG_WARNING, "ignored unknown obs setting action %d",
static_cast<int>(_action));
}
}
bool MacroActionOBSSettings::Save(obs_data_t *obj) const
{
MacroAction::Save(obj);
obs_data_set_int(obj, "action", static_cast<int>(_action));
_fpsIntValue.Save(obj, "fpsIntValue");
_fpsStringValue.Save(obj, "fpsStringValue");
_canvasSizeValue.Save(obj, "canvasSizeValue");
return true;
}
bool MacroActionOBSSettings::Load(obs_data_t *obj)
{
MacroAction::Load(obj);
_action = static_cast<Action>(obs_data_get_int(obj, "action"));
_fpsIntValue.Load(obj, "fpsIntValue");
_fpsStringValue.Load(obj, "fpsStringValue");
_canvasSizeValue.Load(obj, "canvasSizeValue");
return true;
}
std::shared_ptr<MacroAction> MacroActionOBSSettings::Create(Macro *m)
{
return std::make_shared<MacroActionOBSSettings>(m);
}
std::shared_ptr<MacroAction> MacroActionOBSSettings::Copy() const
{
return std::make_shared<MacroActionOBSSettings>(*this);
}
void MacroActionOBSSettings::ResolveVariablesToFixedValues()
{
_fpsIntValue.ResolveVariables();
_canvasSizeValue.ResolveVariables();
}
static void populateActionSelection(QComboBox *list)
{
for (const auto &[value, name] : actionTypes) {
list->addItem(obs_module_text(name.c_str()),
static_cast<int>(value));
}
}
static void populateFPSTypeSelection(QComboBox *list)
{
static const std::map<MacroActionOBSSettings::FPSType, std::string>
types = {
{MacroActionOBSSettings::FPSType::COMMON,
"Basic.Settings.Video.FPSCommon"},
{MacroActionOBSSettings::FPSType::INTEGER,
"Basic.Settings.Video.FPSInteger"},
{MacroActionOBSSettings::FPSType::FRACTION,
"Basic.Settings.Video.FPSFraction"},
};
for (const auto &[value, name] : types) {
list->addItem(obs_module_text(name.c_str()),
static_cast<int>(value));
}
}
MacroActionOBSSettingsEdit::MacroActionOBSSettingsEdit(
QWidget *parent, std::shared_ptr<MacroActionOBSSettings> entryData)
: QWidget(parent),
_actions(new QComboBox(this)),
_fpsType(new QComboBox(this)),
_fpsIntValue(new VariableSpinBox(this)),
_fpsStringValue(new VariableLineEdit(this)),
_canvasSizeValue(new VariableSpinBox(this)),
_getCurrentValue(new QPushButton(obs_module_text(
"AdvSceneSwitcher.action.obsSetting.getCurrentValue")))
{
populateActionSelection(_actions);
populateFPSTypeSelection(_fpsType);
_fpsIntValue->setMaximum(1000);
_canvasSizeValue->setMaximum(100000);
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
SLOT(ActionChanged(int)));
QWidget::connect(_fpsType, SIGNAL(currentIndexChanged(int)), this,
SLOT(FPSTypeChanged(int)));
QWidget::connect(
_fpsIntValue,
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
this, SLOT(FPSIntValueChanged(const NumberVariable<int> &)));
QWidget::connect(_fpsStringValue, SIGNAL(editingFinished()), this,
SLOT(FPSStringValueChanged()));
QWidget::connect(
_canvasSizeValue,
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
this,
SLOT(CanvasSizeValueChanged(const NumberVariable<int> &)));
QWidget::connect(_getCurrentValue, SIGNAL(clicked()), this,
SLOT(GetCurrentValueClicked()));
auto layout = new QHBoxLayout();
PlaceWidgets(
obs_module_text("AdvSceneSwitcher.action.obsSettings.layout"),
layout,
{{"{{actions}}", _actions},
{"{{fpsType}}", _fpsType},
{"{{fpsIntValue}}", _fpsIntValue},
{"{{fpsStringValue}}", _fpsStringValue},
{"{{canvasSizeValue}}", _canvasSizeValue},
{"{{getCurrentValue}}", _getCurrentValue}});
setLayout(layout);
_entryData = entryData;
UpdateEntryData();
_loading = false;
}
void MacroActionOBSSettingsEdit::UpdateEntryData()
{
if (!_entryData) {
return;
}
_actions->setCurrentIndex(
_actions->findData(static_cast<int>(_entryData->_action)));
_fpsType->setCurrentIndex(
_actions->findData(static_cast<int>(_entryData->_fpsType)));
_fpsIntValue->SetValue(_entryData->_fpsIntValue);
_fpsStringValue->setText(_entryData->_fpsStringValue);
_canvasSizeValue->SetValue(_entryData->_canvasSizeValue);
SetWidgetVisibility();
}
void MacroActionOBSSettingsEdit::FPSTypeChanged(int idx)
{
GUARD_LOADING_AND_LOCK();
_entryData->_fpsType = static_cast<MacroActionOBSSettings::FPSType>(
_fpsType->itemData(idx).toInt());
SetWidgetVisibility();
}
void MacroActionOBSSettingsEdit::FPSIntValueChanged(
const NumberVariable<int> &value)
{
GUARD_LOADING_AND_LOCK();
_entryData->_fpsIntValue = value;
}
void MacroActionOBSSettingsEdit::FPSStringValueChanged()
{
GUARD_LOADING_AND_LOCK();
_entryData->_fpsStringValue = _fpsStringValue->text().toStdString();
}
void MacroActionOBSSettingsEdit::CanvasSizeValueChanged(
const NumberVariable<int> &value)
{
GUARD_LOADING_AND_LOCK();
_entryData->_canvasSizeValue = value;
}
void MacroActionOBSSettingsEdit::GetCurrentValueClicked()
{
const auto setSpinVideoValue = [this](VariableSpinBox *spin,
const char *name) {
auto value = getConfigValueHelper(config_get_uint,
config_get_default_uint,
"Video", name);
if (!value) {
return;
}
spin->SetFixedValue(static_cast<int>(*value));
};
const auto setFpsValue = [&](const char *name) {
setSpinVideoValue(_fpsIntValue, name);
};
const auto setCanvasValue = [&](const char *name) {
setSpinVideoValue(_canvasSizeValue, name);
};
switch (_entryData->_action) {
case MacroActionOBSSettings::Action::FPS_COMMON_VALUE: {
auto value = getConfigValueHelper(config_get_string,
config_get_default_string,
"Video", "FPSCommon");
if (!value) {
break;
}
_fpsStringValue->setText(QString(*value));
break;
}
case MacroActionOBSSettings::Action::FPS_INT_VALUE:
setFpsValue("FPSInt");
break;
case MacroActionOBSSettings::Action::FPS_NUM_VALUE:
setFpsValue("FPSNum");
break;
case MacroActionOBSSettings::Action::FPS_DEN_VALUE:
setFpsValue("FPSDen");
break;
case MacroActionOBSSettings::Action::BASE_CANVAS_X_VALUE:
setCanvasValue("BaseCX");
break;
case MacroActionOBSSettings::Action::BASE_CANVAS_Y_VALUE:
setCanvasValue("BaseCY");
break;
case MacroActionOBSSettings::Action::OUTPUT_X_VALUE:
setCanvasValue("OutputCX");
break;
case MacroActionOBSSettings::Action::OUTPUT_Y_VALUE:
setCanvasValue("OutputCY");
break;
default:
break;
}
}
void MacroActionOBSSettingsEdit::SetWidgetVisibility()
{
if (!_entryData) {
return;
}
const bool isFPSSelection =
_entryData->_action ==
MacroActionOBSSettings::Action::FPS_TYPE ||
_entryData->_action ==
MacroActionOBSSettings::Action::FPS_COMMON_VALUE ||
_entryData->_action ==
MacroActionOBSSettings::Action::FPS_INT_VALUE ||
_entryData->_action ==
MacroActionOBSSettings::Action::FPS_DEN_VALUE ||
_entryData->_action ==
MacroActionOBSSettings::Action::FPS_NUM_VALUE;
_fpsType->setVisible(_entryData->_action ==
MacroActionOBSSettings::Action::FPS_TYPE);
_fpsIntValue->setVisible(
_entryData->_action ==
MacroActionOBSSettings::Action::FPS_INT_VALUE ||
_entryData->_action ==
MacroActionOBSSettings::Action::FPS_NUM_VALUE ||
_entryData->_action ==
MacroActionOBSSettings::Action::FPS_DEN_VALUE);
_fpsStringValue->setVisible(
_entryData->_action ==
MacroActionOBSSettings::Action::FPS_COMMON_VALUE);
_canvasSizeValue->setVisible(!isFPSSelection);
_getCurrentValue->setVisible(_entryData->_action !=
MacroActionOBSSettings::Action::FPS_TYPE);
}
void MacroActionOBSSettingsEdit::ActionChanged(int idx)
{
GUARD_LOADING_AND_LOCK();
_entryData->_action = static_cast<MacroActionOBSSettings::Action>(
_actions->itemData(idx).toInt());
SetWidgetVisibility();
}
} // namespace advss

View File

@ -0,0 +1,90 @@
#pragma once
#include "macro-action-edit.hpp"
#include "variable-spinbox.hpp"
#include "variable-line-edit.hpp"
#include <QComboBox>
#include <QHBoxLayout>
#include <chrono>
namespace advss {
class MacroActionOBSSettings : public MacroAction {
public:
MacroActionOBSSettings(Macro *m) : MacroAction(m) {}
bool PerformAction();
void LogAction() const;
bool Save(obs_data_t *obj) const;
bool Load(obs_data_t *obj);
std::string GetId() const { return id; };
static std::shared_ptr<MacroAction> Create(Macro *m);
std::shared_ptr<MacroAction> Copy() const;
void ResolveVariablesToFixedValues();
enum class Action {
FPS_TYPE,
FPS_COMMON_VALUE,
FPS_INT_VALUE,
FPS_NUM_VALUE,
FPS_DEN_VALUE,
BASE_CANVAS_X_VALUE,
BASE_CANVAS_Y_VALUE,
OUTPUT_X_VALUE,
OUTPUT_Y_VALUE,
};
Action _action = Action::FPS_COMMON_VALUE;
enum class FPSType {
COMMON,
INTEGER,
FRACTION,
};
FPSType _fpsType = FPSType::INTEGER;
IntVariable _fpsIntValue = 30;
StringVariable _fpsStringValue = "24 NTSC";
IntVariable _canvasSizeValue = 1920;
private:
static bool _registered;
static const std::string id;
};
class MacroActionOBSSettingsEdit : public QWidget {
Q_OBJECT
public:
MacroActionOBSSettingsEdit(
QWidget *parent,
std::shared_ptr<MacroActionOBSSettings> entryData = nullptr);
void UpdateEntryData();
static QWidget *Create(QWidget *parent,
std::shared_ptr<MacroAction> action)
{
return new MacroActionOBSSettingsEdit(
parent,
std::dynamic_pointer_cast<MacroActionOBSSettings>(
action));
}
private slots:
void ActionChanged(int);
void FPSTypeChanged(int);
void FPSIntValueChanged(const NumberVariable<int> &);
void FPSStringValueChanged();
void CanvasSizeValueChanged(const NumberVariable<int> &);
void GetCurrentValueClicked();
private:
void SetWidgetVisibility();
QComboBox *_actions;
QComboBox *_fpsType;
VariableSpinBox *_fpsIntValue;
VariableLineEdit *_fpsStringValue;
VariableSpinBox *_canvasSizeValue;
QPushButton *_getCurrentValue;
std::shared_ptr<MacroActionOBSSettings> _entryData;
bool _loading = true;
};
} // namespace advss