mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-08-12 12:18:35 -05:00
Add option to set and check list source settings by name
This makes it easier to select the intended settings value as the underlying value often has no direct connection to the user facing name. It also makes it possible to select list entries whos underlying value changes frequently, but the user facing value does not. (E.g. device IDs based on the input port compared to the device name)
This commit is contained in:
@@ -9,12 +9,16 @@
|
||||
|
||||
Q_DECLARE_METATYPE(advss::SourceSetting);
|
||||
|
||||
using properties_delete_t = decltype(&obs_properties_destroy);
|
||||
using properties_t = std::unique_ptr<obs_properties_t, properties_delete_t>;
|
||||
|
||||
namespace advss {
|
||||
|
||||
SourceSetting::SourceSetting(const std::string &id,
|
||||
SourceSetting::SourceSetting(const std::string &id, obs_property_type type,
|
||||
const std::string &description,
|
||||
const std::string &longDescription)
|
||||
: _id(id),
|
||||
_type(type),
|
||||
_description(description),
|
||||
_longDescription(longDescription)
|
||||
{
|
||||
@@ -24,6 +28,7 @@ bool SourceSetting::Save(obs_data_t *obj) const
|
||||
{
|
||||
OBSDataAutoRelease data = obs_data_create();
|
||||
obs_data_set_string(data, "id", _id.c_str());
|
||||
obs_data_set_int(data, "type", _type);
|
||||
obs_data_set_string(data, "description", _description.c_str());
|
||||
obs_data_set_obj(obj, "sourceSetting", data);
|
||||
return true;
|
||||
@@ -33,10 +38,21 @@ bool SourceSetting::Load(obs_data_t *obj)
|
||||
{
|
||||
OBSDataAutoRelease data = obs_data_get_obj(obj, "sourceSetting");
|
||||
_id = obs_data_get_string(data, "id");
|
||||
_type = static_cast<obs_property_type>(obs_data_get_int(data, "type"));
|
||||
_description = obs_data_get_string(data, "description");
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool isListType(obs_property_type type)
|
||||
{
|
||||
return type == OBS_PROPERTY_LIST || type == OBS_PROPERTY_EDITABLE_LIST;
|
||||
}
|
||||
|
||||
bool SourceSetting::IsList() const
|
||||
{
|
||||
return isListType(_type);
|
||||
}
|
||||
|
||||
bool SourceSetting::operator==(const SourceSetting &other) const
|
||||
{
|
||||
return _id == other._id;
|
||||
@@ -85,7 +101,7 @@ static void addSettingsHelper(obs_property_t *property,
|
||||
if (!property) {
|
||||
continue;
|
||||
}
|
||||
auto type = obs_property_get_type(property);
|
||||
const auto type = obs_property_get_type(property);
|
||||
if (type == OBS_PROPERTY_GROUP) {
|
||||
auto group = obs_property_group_content(property);
|
||||
auto description = obs_property_description(property);
|
||||
@@ -110,7 +126,8 @@ static void addSettingsHelper(obs_property_t *property,
|
||||
prefix + description +
|
||||
obs_module_text(getPropertySuffix(type));
|
||||
auto longDescription = obs_property_long_description(property);
|
||||
SourceSetting setting(name, descriptionWithPrefixAndSuffix,
|
||||
SourceSetting setting(name, type,
|
||||
descriptionWithPrefixAndSuffix,
|
||||
longDescription ? longDescription : "");
|
||||
settings.emplace_back(setting);
|
||||
} while (obs_property_next(&property));
|
||||
@@ -118,19 +135,20 @@ static void addSettingsHelper(obs_property_t *property,
|
||||
|
||||
std::vector<SourceSetting> GetSoruceSettings(obs_source_t *source)
|
||||
{
|
||||
auto properties = obs_source_properties(source);
|
||||
properties_t properties(obs_source_properties(source),
|
||||
obs_properties_destroy);
|
||||
if (!properties) {
|
||||
return {};
|
||||
}
|
||||
std::vector<SourceSetting> settings;
|
||||
auto it = obs_properties_first(properties);
|
||||
|
||||
auto it = obs_properties_first(properties.get());
|
||||
addSettingsHelper(it, settings);
|
||||
obs_properties_destroy(properties);
|
||||
return settings;
|
||||
}
|
||||
|
||||
std::optional<std::string> GetSourceSettingValue(const OBSWeakSource &ws,
|
||||
const SourceSetting &setting)
|
||||
static std::optional<std::string>
|
||||
getDataJsonWithDefaults(const OBSWeakSource &ws)
|
||||
{
|
||||
OBSSourceAutoRelease source = obs_weak_source_get_source(ws);
|
||||
OBSDataAutoRelease data = obs_source_get_settings(source);
|
||||
@@ -143,10 +161,139 @@ std::optional<std::string> GetSourceSettingValue(const OBSWeakSource &ws,
|
||||
if (!json) {
|
||||
return {};
|
||||
}
|
||||
auto value = GetJsonField(json, setting.GetID());
|
||||
return json;
|
||||
}
|
||||
|
||||
std::optional<std::string> GetSourceSettingValue(const OBSWeakSource &source,
|
||||
const SourceSetting &setting)
|
||||
{
|
||||
const auto json = getDataJsonWithDefaults(source);
|
||||
if (!json) {
|
||||
return {};
|
||||
}
|
||||
auto value = GetJsonField(*json, setting.GetID());
|
||||
return value;
|
||||
}
|
||||
|
||||
static obs_property_t *findListPropertyByIdHelper(obs_property_t *property,
|
||||
const std::string &id)
|
||||
{
|
||||
do {
|
||||
if (!property) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto type = obs_property_get_type(property);
|
||||
if (type == OBS_PROPERTY_GROUP) {
|
||||
auto group = obs_property_group_content(property);
|
||||
findListPropertyByIdHelper(obs_properties_first(group),
|
||||
id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isListType(type)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto name = obs_property_name(property);
|
||||
if (name != id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return property;
|
||||
|
||||
} while (obs_property_next(&property));
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static std::pair<obs_property_t *, properties_t>
|
||||
findListPropertyById(const obs_source_t *source, const std::string &id)
|
||||
{
|
||||
// Note:
|
||||
// Using obs_source_properties() here might cause flickering for some
|
||||
// sources, as this will call obs_properties_apply_settings()
|
||||
// implicitly.
|
||||
// So, we use obs_get_source_properties() instead.
|
||||
//
|
||||
// 20250617: This might cause issues with the move plugin as it doesn't
|
||||
// handle obs_get_source_properties() properly in the move filter
|
||||
auto properties = obs_get_source_properties(obs_source_get_id(source));
|
||||
if (!properties) {
|
||||
return {nullptr, properties_t(nullptr, obs_properties_destroy)};
|
||||
}
|
||||
auto property = obs_properties_first(properties);
|
||||
return {findListPropertyByIdHelper(property, id),
|
||||
properties_t(nullptr, obs_properties_destroy)};
|
||||
}
|
||||
|
||||
static std::pair<obs_property_t *, properties_t>
|
||||
findListPropertyById(const OBSWeakSource &ws, const std::string &id)
|
||||
{
|
||||
OBSSourceAutoRelease source = obs_weak_source_get_source(ws);
|
||||
return findListPropertyById(source.Get(), id);
|
||||
}
|
||||
|
||||
std::optional<std::string>
|
||||
GetSourceSettingListEntryName(const OBSWeakSource &source,
|
||||
const SourceSetting &setting)
|
||||
{
|
||||
if (!setting.IsList()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto json = getDataJsonWithDefaults(source);
|
||||
if (!json) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto &[property, properties] =
|
||||
findListPropertyById(source, setting.GetID());
|
||||
if (!property) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto type = obs_property_list_format(property);
|
||||
if (type == OBS_COMBO_FORMAT_INVALID) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto currentValue = GetJsonField(*json, setting.GetID());
|
||||
if (!currentValue) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto count = obs_property_list_item_count(property);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
std::string value;
|
||||
switch (type) {
|
||||
case OBS_COMBO_FORMAT_INT:
|
||||
value = std::to_string(
|
||||
obs_property_list_item_int(property, i));
|
||||
break;
|
||||
case OBS_COMBO_FORMAT_FLOAT:
|
||||
value = std::to_string(
|
||||
obs_property_list_item_float(property, i));
|
||||
break;
|
||||
case OBS_COMBO_FORMAT_STRING:
|
||||
value = obs_property_list_item_string(property, i);
|
||||
break;
|
||||
case OBS_COMBO_FORMAT_BOOL:
|
||||
value = std::to_string(
|
||||
obs_property_list_item_bool(property, i));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (value == currentValue) {
|
||||
return obs_property_list_item_name(property, i);
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void SetSourceSetting(obs_source_t *source, const SourceSetting &setting,
|
||||
const std::string &value)
|
||||
{
|
||||
@@ -233,6 +380,63 @@ void SetSourceSetting(obs_source_t *source, const SourceSetting &setting,
|
||||
obs_source_update(source, data);
|
||||
}
|
||||
|
||||
void SetSourceSettingListEntryValueByName(obs_source_t *source,
|
||||
const SourceSetting &setting,
|
||||
const std::string &name)
|
||||
{
|
||||
if (!setting.IsList()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &[property, properties] =
|
||||
findListPropertyById(source, setting.GetID());
|
||||
if (!property) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto type = obs_property_list_format(property);
|
||||
if (type == OBS_COMBO_FORMAT_INVALID) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto count = obs_property_list_item_count(property);
|
||||
bool found = false;
|
||||
size_t idx = 0;
|
||||
for (; idx < count; idx++) {
|
||||
if (obs_property_list_item_name(property, idx) == name) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string value;
|
||||
switch (type) {
|
||||
case OBS_COMBO_FORMAT_INT:
|
||||
value = std::to_string(
|
||||
obs_property_list_item_int(property, idx));
|
||||
break;
|
||||
case OBS_COMBO_FORMAT_FLOAT:
|
||||
value = std::to_string(
|
||||
obs_property_list_item_float(property, idx));
|
||||
break;
|
||||
case OBS_COMBO_FORMAT_STRING:
|
||||
value = obs_property_list_item_string(property, idx);
|
||||
break;
|
||||
case OBS_COMBO_FORMAT_BOOL:
|
||||
value = std::to_string(
|
||||
obs_property_list_item_bool(property, idx));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
SetSourceSetting(source, setting, value);
|
||||
}
|
||||
|
||||
SourceSettingSelection::SourceSettingSelection(QWidget *parent)
|
||||
: QWidget(parent),
|
||||
_settings(new FilterComboBox(
|
||||
|
||||
Reference in New Issue
Block a user