libobs: Fix source type versioning system
(This also modifies image-source, obs-text, text-freetype2, and UI) This improves source definition versioning. To do this, it now stores two identifier names. One "unversioned" which is the original name, and one "versioned" with the version number appended. This fixes both backward compatibility with older OBS versions, and fixes the inability to use "add existing" in OBS itself on sources created from older version definitions.
This commit is contained in:
parent
ef0f21b273
commit
b2302902a3
@ -111,8 +111,8 @@ function script_properties()
|
||||
local sources = obs.obs_enum_sources()
|
||||
if sources ~= nil then
|
||||
for _, source in ipairs(sources) do
|
||||
source_id = obs.obs_source_get_id(source)
|
||||
if source_id == "text_gdiplus" or source_id == "text_ft2_source" or source_id == "text_gdiplus_v2" or source_id == "text_ft2_source_v2" then
|
||||
source_id = obs.obs_source_get_unversioned_id(source)
|
||||
if source_id == "text_gdiplus" or source_id == "text_ft2_source" then
|
||||
local name = obs.obs_source_get_name(source)
|
||||
obs.obs_property_list_add_string(p, name, name)
|
||||
end
|
||||
|
@ -66,8 +66,8 @@ def script_properties():
|
||||
sources = obs.obs_enum_sources()
|
||||
if sources is not None:
|
||||
for source in sources:
|
||||
source_id = obs.obs_source_get_id(source)
|
||||
if source_id == "text_gdiplus" or source_id == "text_ft2_source" or source_id == "text_gdiplus_v2" or source_id == "text_ft2_source_v2":
|
||||
source_id = obs.obs_source_get_unversioned_id(source)
|
||||
if source_id == "text_gdiplus" or source_id == "text_ft2_source":
|
||||
name = obs.obs_source_get_name(source)
|
||||
obs.obs_property_list_add_string(p, name, name)
|
||||
|
||||
|
@ -4719,6 +4719,7 @@ void OBSBasic::AddSource(const char *id)
|
||||
|
||||
QMenu *OBSBasic::CreateAddSourcePopupMenu()
|
||||
{
|
||||
const char *unversioned_type;
|
||||
const char *type;
|
||||
bool foundValues = false;
|
||||
bool foundDeprecated = false;
|
||||
@ -4759,7 +4760,7 @@ QMenu *OBSBasic::CreateAddSourcePopupMenu()
|
||||
popup->insertAction(after, popupItem);
|
||||
};
|
||||
|
||||
while (obs_enum_input_types(idx++, &type)) {
|
||||
while (obs_enum_input_types2(idx++, &type, &unversioned_type)) {
|
||||
const char *name = obs_source_get_display_name(type);
|
||||
uint32_t caps = obs_get_source_output_flags(type);
|
||||
|
||||
@ -4767,9 +4768,9 @@ QMenu *OBSBasic::CreateAddSourcePopupMenu()
|
||||
continue;
|
||||
|
||||
if ((caps & OBS_SOURCE_DEPRECATED) == 0) {
|
||||
addSource(popup, type, name);
|
||||
addSource(popup, unversioned_type, name);
|
||||
} else {
|
||||
addSource(deprecated, type, name);
|
||||
addSource(deprecated, unversioned_type, name);
|
||||
foundDeprecated = true;
|
||||
}
|
||||
foundValues = true;
|
||||
|
@ -31,7 +31,7 @@ bool OBSBasicSourceSelect::EnumSources(void *data, obs_source_t *source)
|
||||
OBSBasicSourceSelect *window =
|
||||
static_cast<OBSBasicSourceSelect *>(data);
|
||||
const char *name = obs_source_get_name(source);
|
||||
const char *id = obs_source_get_id(source);
|
||||
const char *id = obs_source_get_unversioned_id(source);
|
||||
|
||||
if (strcmp(id, window->id) == 0)
|
||||
window->ui->sourceList->addItem(QT_UTF8(name));
|
||||
@ -44,7 +44,7 @@ bool OBSBasicSourceSelect::EnumGroups(void *data, obs_source_t *source)
|
||||
OBSBasicSourceSelect *window =
|
||||
static_cast<OBSBasicSourceSelect *>(data);
|
||||
const char *name = obs_source_get_name(source);
|
||||
const char *id = obs_source_get_id(source);
|
||||
const char *id = obs_source_get_unversioned_id(source);
|
||||
|
||||
if (strcmp(id, window->id) == 0) {
|
||||
OBSBasic *main =
|
||||
@ -82,7 +82,7 @@ void OBSBasicSourceSelect::OBSSourceRemoved(void *data, calldata_t *calldata)
|
||||
void OBSBasicSourceSelect::SourceAdded(OBSSource source)
|
||||
{
|
||||
const char *name = obs_source_get_name(source);
|
||||
const char *sourceId = obs_source_get_id(source);
|
||||
const char *sourceId = obs_source_get_unversioned_id(source);
|
||||
|
||||
if (strcmp(sourceId, id) != 0)
|
||||
return;
|
||||
@ -93,7 +93,7 @@ void OBSBasicSourceSelect::SourceAdded(OBSSource source)
|
||||
void OBSBasicSourceSelect::SourceRemoved(OBSSource source)
|
||||
{
|
||||
const char *name = obs_source_get_name(source);
|
||||
const char *sourceId = obs_source_get_id(source);
|
||||
const char *sourceId = obs_source_get_unversioned_id(source);
|
||||
|
||||
if (strcmp(sourceId, id) != 0)
|
||||
return;
|
||||
@ -184,7 +184,8 @@ bool AddNew(QWidget *parent, const char *id, const char *name,
|
||||
QTStr("NameExists.Text"));
|
||||
|
||||
} else {
|
||||
source = obs_source_create(id, name, NULL, nullptr);
|
||||
const char *v_id = obs_get_latest_input_type_id(id);
|
||||
source = obs_source_create(v_id, name, NULL, nullptr);
|
||||
|
||||
if (source) {
|
||||
AddSourceData data;
|
||||
@ -249,7 +250,8 @@ static inline const char *GetSourceDisplayName(const char *id)
|
||||
{
|
||||
if (strcmp(id, "scene") == 0)
|
||||
return Str("Basic.Scene");
|
||||
return obs_source_get_display_name(id);
|
||||
const char *v_id = obs_get_latest_input_type_id(id);
|
||||
return obs_source_get_display_name(v_id);
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(OBSScene);
|
||||
|
@ -726,6 +726,8 @@ struct obs_source {
|
||||
};
|
||||
|
||||
extern struct obs_source_info *get_source_info(const char *id);
|
||||
extern struct obs_source_info *get_source_info2(const char *unversioned_id,
|
||||
uint32_t ver);
|
||||
extern bool obs_source_init_context(struct obs_source *source,
|
||||
obs_data_t *settings, const char *name,
|
||||
obs_data_t *hotkey_data, bool private);
|
||||
|
@ -581,7 +581,7 @@ void obs_register_source_s(const struct obs_source_info *info, size_t size)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (get_source_info(info->id)) {
|
||||
if (get_source_info2(info->id, info->version)) {
|
||||
source_warn("Source '%s' already exists! "
|
||||
"Duplicate library?",
|
||||
info->id);
|
||||
@ -650,6 +650,17 @@ void obs_register_source_s(const struct obs_source_info *info, size_t size)
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* version-related stuff */
|
||||
data.unversioned_id = data.id;
|
||||
if (data.version) {
|
||||
struct dstr versioned_id = {0};
|
||||
dstr_printf(&versioned_id, "%s_v%d", data.id,
|
||||
(int)data.version);
|
||||
data.id = versioned_id.array;
|
||||
} else {
|
||||
data.id = bstrdup(data.id);
|
||||
}
|
||||
|
||||
if (array)
|
||||
darray_push_back(sizeof(struct obs_source_info), array, &data);
|
||||
da_push_back(obs->source_types, &data);
|
||||
|
@ -51,6 +51,19 @@ struct obs_source_info *get_source_info(const char *id)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct obs_source_info *get_source_info2(const char *unversioned_id,
|
||||
uint32_t ver)
|
||||
{
|
||||
for (size_t i = 0; i < obs->source_types.num; i++) {
|
||||
struct obs_source_info *info = &obs->source_types.array[i];
|
||||
if (strcmp(info->unversioned_id, unversioned_id) == 0 &&
|
||||
info->version == ver)
|
||||
return info;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *source_signals[] = {
|
||||
"void destroy(ptr source)",
|
||||
"void remove(ptr source)",
|
||||
@ -3381,6 +3394,13 @@ const char *obs_source_get_id(const obs_source_t *source)
|
||||
: NULL;
|
||||
}
|
||||
|
||||
const char *obs_source_get_unversioned_id(const obs_source_t *source)
|
||||
{
|
||||
return obs_source_valid(source, "obs_source_get_unversioned_id")
|
||||
? source->info.unversioned_id
|
||||
: NULL;
|
||||
}
|
||||
|
||||
static inline void render_filter_bypass(obs_source_t *target,
|
||||
gs_effect_t *effect,
|
||||
const char *tech_name)
|
||||
|
@ -523,6 +523,10 @@ struct obs_source_info {
|
||||
int64_t (*media_get_time)(void *data);
|
||||
void (*media_set_time)(void *data, int64_t miliseconds);
|
||||
enum obs_media_state (*media_get_state)(void *data);
|
||||
|
||||
/* version-related stuff */
|
||||
uint32_t version; /* increment if needed to specify a new version */
|
||||
const char *unversioned_id; /* set internally, don't set manually */
|
||||
};
|
||||
|
||||
EXPORT void obs_register_source_s(const struct obs_source_info *info,
|
||||
|
61
libobs/obs.c
61
libobs/obs.c
@ -989,6 +989,15 @@ void obs_shutdown(void)
|
||||
if (!obs)
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < obs->source_types.num; i++) {
|
||||
struct obs_source_info *item = &obs->source_types.array[i];
|
||||
if (item->type_data && item->free_type_data)
|
||||
item->free_type_data(item->type_data);
|
||||
if (item->id)
|
||||
bfree((void *)item->id);
|
||||
}
|
||||
da_free(obs->source_types);
|
||||
|
||||
#define FREE_REGISTERED_TYPES(structure, list) \
|
||||
do { \
|
||||
for (size_t i = 0; i < list.num; i++) { \
|
||||
@ -999,7 +1008,6 @@ void obs_shutdown(void)
|
||||
da_free(list); \
|
||||
} while (false)
|
||||
|
||||
FREE_REGISTERED_TYPES(obs_source_info, obs->source_types);
|
||||
FREE_REGISTERED_TYPES(obs_output_info, obs->output_types);
|
||||
FREE_REGISTERED_TYPES(obs_encoder_info, obs->encoder_types);
|
||||
FREE_REGISTERED_TYPES(obs_service_info, obs->service_types);
|
||||
@ -1255,6 +1263,47 @@ bool obs_enum_input_types(size_t idx, const char **id)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool obs_enum_input_types2(size_t idx, const char **id,
|
||||
const char **unversioned_id)
|
||||
{
|
||||
if (!obs)
|
||||
return false;
|
||||
|
||||
if (idx >= obs->input_types.num)
|
||||
return false;
|
||||
if (id)
|
||||
*id = obs->input_types.array[idx].id;
|
||||
if (unversioned_id)
|
||||
*unversioned_id = obs->input_types.array[idx].unversioned_id;
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *obs_get_latest_input_type_id(const char *unversioned_id)
|
||||
{
|
||||
struct obs_source_info *latest = NULL;
|
||||
int version = -1;
|
||||
|
||||
if (!obs)
|
||||
return false;
|
||||
if (!unversioned_id)
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < obs->input_types.num; i++) {
|
||||
struct obs_source_info *info = &obs->input_types.array[i];
|
||||
if (strcmp(info->unversioned_id, unversioned_id) == 0 &&
|
||||
(int)info->version > version) {
|
||||
latest = info;
|
||||
version = info->version;
|
||||
}
|
||||
}
|
||||
|
||||
assert(!!latest);
|
||||
if (!latest)
|
||||
return NULL;
|
||||
|
||||
return latest->id;
|
||||
}
|
||||
|
||||
bool obs_enum_filter_types(size_t idx, const char **id)
|
||||
{
|
||||
if (!obs)
|
||||
@ -1769,6 +1818,7 @@ static obs_source_t *obs_load_source_type(obs_data_t *source_data)
|
||||
obs_source_t *source;
|
||||
const char *name = obs_data_get_string(source_data, "name");
|
||||
const char *id = obs_data_get_string(source_data, "id");
|
||||
const char *v_id = obs_data_get_string(source_data, "versioned_id");
|
||||
obs_data_t *settings = obs_data_get_obj(source_data, "settings");
|
||||
obs_data_t *hotkeys = obs_data_get_obj(source_data, "hotkeys");
|
||||
double volume;
|
||||
@ -1784,7 +1834,10 @@ static obs_source_t *obs_load_source_type(obs_data_t *source_data)
|
||||
|
||||
prev_ver = (uint32_t)obs_data_get_int(source_data, "prev_ver");
|
||||
|
||||
source = obs_source_create_set_last_ver(id, name, settings, hotkeys,
|
||||
if (!*v_id)
|
||||
v_id = id;
|
||||
|
||||
source = obs_source_create_set_last_ver(v_id, name, settings, hotkeys,
|
||||
prev_ver);
|
||||
|
||||
obs_data_release(hotkeys);
|
||||
@ -1958,7 +2011,8 @@ obs_data_t *obs_save_source(obs_source_t *source)
|
||||
int64_t sync = obs_source_get_sync_offset(source);
|
||||
uint32_t flags = obs_source_get_flags(source);
|
||||
const char *name = obs_source_get_name(source);
|
||||
const char *id = obs_source_get_id(source);
|
||||
const char *id = source->info.unversioned_id;
|
||||
const char *v_id = source->info.id;
|
||||
bool enabled = obs_source_enabled(source);
|
||||
bool muted = obs_source_muted(source);
|
||||
bool push_to_mute = obs_source_push_to_mute_enabled(source);
|
||||
@ -1982,6 +2036,7 @@ obs_data_t *obs_save_source(obs_source_t *source)
|
||||
|
||||
obs_data_set_string(source_data, "name", name);
|
||||
obs_data_set_string(source_data, "id", id);
|
||||
obs_data_set_string(source_data, "versioned_id", v_id);
|
||||
obs_data_set_obj(source_data, "settings", settings);
|
||||
obs_data_set_int(source_data, "mixers", mixers);
|
||||
obs_data_set_int(source_data, "sync", sync);
|
||||
|
@ -517,6 +517,10 @@ EXPORT bool obs_enum_source_types(size_t idx, const char **id);
|
||||
* etc).
|
||||
*/
|
||||
EXPORT bool obs_enum_input_types(size_t idx, const char **id);
|
||||
EXPORT bool obs_enum_input_types2(size_t idx, const char **id,
|
||||
const char **unversioned_id);
|
||||
|
||||
EXPORT const char *obs_get_latest_input_type_id(const char *unversioned_id);
|
||||
|
||||
/**
|
||||
* Enumerates all available filter source types.
|
||||
@ -938,6 +942,7 @@ EXPORT enum obs_source_type obs_source_get_type(const obs_source_t *source);
|
||||
|
||||
/** Gets the source identifier */
|
||||
EXPORT const char *obs_source_get_id(const obs_source_t *source);
|
||||
EXPORT const char *obs_source_get_unversioned_id(const obs_source_t *source);
|
||||
|
||||
/** Returns the signal handler for a source */
|
||||
EXPORT signal_handler_t *
|
||||
|
@ -131,7 +131,8 @@ struct obs_source_info color_source_info_v1 = {
|
||||
};
|
||||
|
||||
struct obs_source_info color_source_info_v2 = {
|
||||
.id = "color_source_v2",
|
||||
.id = "color_source",
|
||||
.version = 2,
|
||||
.type = OBS_SOURCE_TYPE_INPUT,
|
||||
.output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW,
|
||||
.create = color_source_create,
|
||||
|
@ -1098,7 +1098,7 @@ bool obs_module_load(void)
|
||||
};
|
||||
|
||||
obs_source_info si_v2 = si;
|
||||
si_v2.id = "text_gdiplus_v2";
|
||||
si_v2.version = 2;
|
||||
si_v2.output_flags &= ~OBS_SOURCE_CAP_OBSOLETE;
|
||||
si_v2.get_defaults = [](obs_data_t *settings) {
|
||||
defaults(settings, 2);
|
||||
|
@ -53,7 +53,8 @@ static struct obs_source_info freetype2_source_info_v1 = {
|
||||
};
|
||||
|
||||
static struct obs_source_info freetype2_source_info_v2 = {
|
||||
.id = "text_ft2_source_v2",
|
||||
.id = "text_ft2_source",
|
||||
.version = 2,
|
||||
.type = OBS_SOURCE_TYPE_INPUT,
|
||||
.output_flags = OBS_SOURCE_VIDEO |
|
||||
#ifdef _WIN32
|
||||
|
Loading…
x
Reference in New Issue
Block a user