提交 b2302902 编写于 作者: J jp9000

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.
上级 ef0f21b2
......@@ -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,
......
......@@ -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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册