utils: expose GstPluginAPIFlags

These can be passed to gst_type_mark_as_plugin_api, to inform
plugin cache generation.

For now a single flag is specified, "IGNORE_ENUM_MEMBERS", it
can be used for dynamically generated enums to avoid documenting
environment-specific enumeration members. An example is
GstX265EncTune.
This commit is contained in:
Mathieu Duponchelle 2020-06-05 21:10:29 +02:00
parent d46e902273
commit 0c1ce6e8c4
15 changed files with 98 additions and 42 deletions

View file

@ -183,7 +183,7 @@ _serialize_enum_default (GString * json, GType gtype, GValue * value)
} }
static void static void
_serialize_enum (GString * json, GType gtype) _serialize_enum (GString * json, GType gtype, GstPluginAPIFlags api_flags)
{ {
GEnumValue *values; GEnumValue *values;
guint j = 0; guint j = 0;
@ -191,25 +191,30 @@ _serialize_enum (GString * json, GType gtype)
values = G_ENUM_CLASS (g_type_class_ref (gtype))->values; values = G_ENUM_CLASS (g_type_class_ref (gtype))->values;
g_string_append_printf (json, "%s\"%s\": { " g_string_append_printf (json, "%s\"%s\": { "
"\"kind\": \"enum\"," "\"values\": [", json->len ? "," : "", "\"kind\": \"enum\"", json->len ? "," : "", g_type_name (gtype));
g_type_name (gtype));
while (values[j].value_name) { if (api_flags & GST_PLUGIN_API_FLAG_IGNORE_ENUM_MEMBERS) {
gchar *value_name = json_strescape (values[j].value_name); g_string_append (json, ",\"ignore-enum-members\": true}");
gchar *value_nick = json_strescape (values[j].value_nick); } else {
g_string_append (json, ",\"values\": [");
g_string_append_printf (json, "{\"name\": \"%s\"," while (values[j].value_name) {
"\"value\": \"%d\"," gchar *value_name = json_strescape (values[j].value_name);
"\"desc\": \"%s\"}", value_nick, values[j].value, value_name); gchar *value_nick = json_strescape (values[j].value_nick);
j++;
if (values[j].value_name)
g_string_append_c (json, ',');
g_free (value_name); g_string_append_printf (json, "{\"name\": \"%s\","
g_free (value_nick); "\"value\": \"%d\","
"\"desc\": \"%s\"}", value_nick, values[j].value, value_name);
j++;
if (values[j].value_name)
g_string_append_c (json, ',');
g_free (value_name);
g_free (value_nick);
}
g_string_append (json, "]}");
} }
g_string_append (json, "]}");
} }
static void static void
@ -250,6 +255,7 @@ _add_signals (GString * json, GString * other_types,
gint i = 0, j, k; gint i = 0, j, k;
GSignalQuery *query = NULL; GSignalQuery *query = NULL;
GType type; GType type;
GstPluginAPIFlags api_flags;
GSList *found_signals, *l; GSList *found_signals, *l;
for (k = 0; k < 2; k++) { for (k = 0; k < 2; k++) {
@ -323,12 +329,12 @@ _add_signals (GString * json, GString * other_types,
if (!g_hash_table_contains (seen_other_types, if (!g_hash_table_contains (seen_other_types,
g_type_name (query->param_types[j])) g_type_name (query->param_types[j]))
&& gst_type_is_plugin_api (query->param_types[j])) { && gst_type_is_plugin_api (query->param_types[j], &api_flags)) {
g_hash_table_insert (seen_other_types, g_hash_table_insert (seen_other_types,
(gpointer) g_type_name (query->param_types[j]), NULL); (gpointer) g_type_name (query->param_types[j]), NULL);
if (g_type_is_a (query->param_types[j], G_TYPE_ENUM)) { if (g_type_is_a (query->param_types[j], G_TYPE_ENUM)) {
_serialize_enum (other_types, query->param_types[j]); _serialize_enum (other_types, query->param_types[j], api_flags);
} else if (g_type_is_a (query->param_types[j], G_TYPE_FLAGS)) { } else if (g_type_is_a (query->param_types[j], G_TYPE_FLAGS)) {
_serialize_flags (other_types, query->param_types[j]); _serialize_flags (other_types, query->param_types[j]);
} else if (g_type_is_a (query->param_types[j], G_TYPE_OBJECT)) { } else if (g_type_is_a (query->param_types[j], G_TYPE_OBJECT)) {
@ -341,11 +347,11 @@ _add_signals (GString * json, GString * other_types,
if (!g_hash_table_contains (seen_other_types, if (!g_hash_table_contains (seen_other_types,
g_type_name (query->return_type)) g_type_name (query->return_type))
&& gst_type_is_plugin_api (query->return_type)) { && gst_type_is_plugin_api (query->return_type, &api_flags)) {
g_hash_table_insert (seen_other_types, g_hash_table_insert (seen_other_types,
(gpointer) g_type_name (query->return_type), NULL); (gpointer) g_type_name (query->return_type), NULL);
if (g_type_is_a (query->return_type, G_TYPE_ENUM)) { if (g_type_is_a (query->return_type, G_TYPE_ENUM)) {
_serialize_enum (other_types, query->return_type); _serialize_enum (other_types, query->return_type, api_flags);
} else if (g_type_is_a (query->return_type, G_TYPE_FLAGS)) { } else if (g_type_is_a (query->return_type, G_TYPE_FLAGS)) {
_serialize_flags (other_types, query->return_type); _serialize_flags (other_types, query->return_type);
} else if (g_type_is_a (query->return_type, G_TYPE_OBJECT)) { } else if (g_type_is_a (query->return_type, G_TYPE_OBJECT)) {
@ -395,6 +401,7 @@ _add_properties (GString * json, GString * other_types,
guint i, n_props; guint i, n_props;
gboolean opened = FALSE; gboolean opened = FALSE;
GParamSpec **specs, *spec; GParamSpec **specs, *spec;
GstPluginAPIFlags api_flags;
specs = g_object_class_list_properties (klass, &n_props); specs = g_object_class_list_properties (klass, &n_props);
@ -440,11 +447,11 @@ _add_properties (GString * json, GString * other_types,
if (!g_hash_table_contains (seen_other_types, if (!g_hash_table_contains (seen_other_types,
g_type_name (spec->value_type)) g_type_name (spec->value_type))
&& gst_type_is_plugin_api (spec->value_type)) { && gst_type_is_plugin_api (spec->value_type, &api_flags)) {
g_hash_table_insert (seen_other_types, g_hash_table_insert (seen_other_types,
(gpointer) g_type_name (spec->value_type), NULL); (gpointer) g_type_name (spec->value_type), NULL);
if (G_IS_PARAM_SPEC_ENUM (spec)) { if (G_IS_PARAM_SPEC_ENUM (spec)) {
_serialize_enum (other_types, spec->value_type); _serialize_enum (other_types, spec->value_type, api_flags);
} else if (G_IS_PARAM_SPEC_FLAGS (spec)) { } else if (G_IS_PARAM_SPEC_FLAGS (spec)) {
_serialize_flags (other_types, spec->value_type); _serialize_flags (other_types, spec->value_type);
} else if (G_IS_PARAM_SPEC_OBJECT (spec)) { } else if (G_IS_PARAM_SPEC_OBJECT (spec)) {
@ -698,6 +705,7 @@ _add_element_pad_templates (GString * json, GString * other_types,
const GList *pads; const GList *pads;
GstStaticPadTemplate *padtemplate; GstStaticPadTemplate *padtemplate;
GRegex *re = g_regex_new ("%", 0, 0, NULL); GRegex *re = g_regex_new ("%", 0, 0, NULL);
GstPluginAPIFlags api_flags;
pads = gst_element_factory_get_static_pad_templates (factory); pads = gst_element_factory_get_static_pad_templates (factory);
while (pads) { while (pads) {
@ -735,7 +743,7 @@ _add_element_pad_templates (GString * json, GString * other_types,
g_type_name (pad_type)); g_type_name (pad_type));
if (!g_hash_table_contains (seen_other_types, g_type_name (pad_type)) if (!g_hash_table_contains (seen_other_types, g_type_name (pad_type))
&& gst_type_is_plugin_api (pad_type)) { && gst_type_is_plugin_api (pad_type, &api_flags)) {
g_hash_table_insert (seen_other_types, g_hash_table_insert (seen_other_types,
(gpointer) g_type_name (pad_type), NULL); (gpointer) g_type_name (pad_type), NULL);
_serialize_object (other_types, seen_other_types, pad_type); _serialize_object (other_types, seen_other_types, pad_type);

View file

@ -79,7 +79,7 @@ static const gchar *_quark_strings[] = {
"GstMessageDeviceChanged", "device-changed", "trickmode-interval", "GstMessageDeviceChanged", "device-changed", "trickmode-interval",
"GstEventInstantRateChange", "GstEventInstantRateChange",
"GstEventInstantRateSyncTime", "GstMessageInstantRateRequest", "GstEventInstantRateSyncTime", "GstMessageInstantRateRequest",
"upstream-running-time", "base", "offset", "plugin-api" "upstream-running-time", "base", "offset", "plugin-api", "plugin-api-flags",
}; };
GQuark _priv_gst_quark_table[GST_QUARK_MAX]; GQuark _priv_gst_quark_table[GST_QUARK_MAX];

View file

@ -229,7 +229,8 @@ typedef enum _GstQuarkId
GST_QUARK_BASE = 198, GST_QUARK_BASE = 198,
GST_QUARK_OFFSET = 199, GST_QUARK_OFFSET = 199,
GST_QUARK_PLUGIN_API = 200, GST_QUARK_PLUGIN_API = 200,
GST_QUARK_MAX = 201 GST_QUARK_PLUGIN_API_FLAGS = 201,
GST_QUARK_MAX = 202
} GstQuarkId; } GstQuarkId;
extern GQuark _priv_gst_quark_table[GST_QUARK_MAX]; extern GQuark _priv_gst_quark_table[GST_QUARK_MAX];

View file

@ -4521,6 +4521,7 @@ invalid:
/** /**
* gst_type_mark_as_plugin_api: * gst_type_mark_as_plugin_api:
* @type: a GType * @type: a GType
* @flags: a set of #GstPluginApiFlags to further inform cache generation.
* *
* Marks @type as plugin API. This should be called in `class_init` of * Marks @type as plugin API. This should be called in `class_init` of
* elements that expose new types (i.e. enums, flags or internal GObjects) via * elements that expose new types (i.e. enums, flags or internal GObjects) via
@ -4536,14 +4537,17 @@ invalid:
* Since: 1.18 * Since: 1.18
*/ */
void void
gst_type_mark_as_plugin_api (GType type) gst_type_mark_as_plugin_api (GType type, GstPluginAPIFlags flags)
{ {
g_type_set_qdata (type, GST_QUARK (PLUGIN_API), GINT_TO_POINTER (TRUE)); g_type_set_qdata (type, GST_QUARK (PLUGIN_API), GINT_TO_POINTER (TRUE));
g_type_set_qdata (type, GST_QUARK (PLUGIN_API_FLAGS),
GINT_TO_POINTER (flags));
} }
/** /**
* gst_type_is_plugin_api: * gst_type_is_plugin_api:
* @type: a GType * @type: a GType
* @flags: (out) (nullable): What #GstPluginApiFlags the plugin was marked with
* *
* Checks if @type is plugin API. See gst_type_mark_as_plugin_api() for * Checks if @type is plugin API. See gst_type_mark_as_plugin_api() for
* details. * details.
@ -4553,7 +4557,15 @@ gst_type_mark_as_plugin_api (GType type)
* Since: 1.18 * Since: 1.18
*/ */
gboolean gboolean
gst_type_is_plugin_api (GType type) gst_type_is_plugin_api (GType type, GstPluginAPIFlags * flags)
{ {
return ! !GPOINTER_TO_INT (g_type_get_qdata (type, GST_QUARK (PLUGIN_API))); gboolean ret =
! !GPOINTER_TO_INT (g_type_get_qdata (type, GST_QUARK (PLUGIN_API)));
if (ret && flags) {
*flags =
GPOINTER_TO_INT (g_type_get_qdata (type, GST_QUARK (PLUGIN_API_FLAGS)));
}
return ret;
} }

View file

@ -1168,6 +1168,18 @@ typedef enum {
GST_SEARCH_MODE_AFTER GST_SEARCH_MODE_AFTER
} GstSearchMode; } GstSearchMode;
/**
* GstPluginAPIFlags:
* @GST_PLUGIN_API_FLAG_IGNORE_ENUM_MEMBERS: Ignore enum members when generating
* the plugins cache. This is useful if the members of the enum are generated
* dynamically, in order not to expose incorrect documentation to the end user.
*
* Since: 1.18
*/
typedef enum {
GST_PLUGIN_API_FLAG_IGNORE_ENUM_MEMBERS = (1 << 0),
} GstPluginAPIFlags;
GST_API GST_API
gpointer gst_util_array_binary_search (gpointer array, guint num_elements, gpointer gst_util_array_binary_search (gpointer array, guint num_elements,
gsize element_size, GCompareDataFunc search_func, gsize element_size, GCompareDataFunc search_func,
@ -1205,10 +1217,10 @@ gboolean gst_calculate_linear_regression (const GstClockTime * xy,
gdouble * r_squared); gdouble * r_squared);
GST_API GST_API
void gst_type_mark_as_plugin_api (GType type); void gst_type_mark_as_plugin_api (GType type, GstPluginAPIFlags flags);
GST_API GST_API
gboolean gst_type_is_plugin_api (GType type); gboolean gst_type_is_plugin_api (GType type, GstPluginAPIFlags *flags);
G_END_DECLS G_END_DECLS

View file

@ -158,7 +158,7 @@ gst_capsfilter_class_init (GstCapsFilterClass * klass)
trans_class->sink_event = GST_DEBUG_FUNCPTR (gst_capsfilter_sink_event); trans_class->sink_event = GST_DEBUG_FUNCPTR (gst_capsfilter_sink_event);
trans_class->stop = GST_DEBUG_FUNCPTR (gst_capsfilter_stop); trans_class->stop = GST_DEBUG_FUNCPTR (gst_capsfilter_stop);
gst_type_mark_as_plugin_api (GST_TYPE_CAPS_FILTER_CAPS_CHANGE_MODE); gst_type_mark_as_plugin_api (GST_TYPE_CAPS_FILTER_CAPS_CHANGE_MODE, 0);
} }
static void static void

View file

@ -242,7 +242,7 @@ gst_fake_sink_class_init (GstFakeSinkClass * klass)
gstbase_sink_class->render = GST_DEBUG_FUNCPTR (gst_fake_sink_render); gstbase_sink_class->render = GST_DEBUG_FUNCPTR (gst_fake_sink_render);
gstbase_sink_class->query = GST_DEBUG_FUNCPTR (gst_fake_sink_query); gstbase_sink_class->query = GST_DEBUG_FUNCPTR (gst_fake_sink_query);
gst_type_mark_as_plugin_api (GST_TYPE_FAKE_SINK_STATE_ERROR); gst_type_mark_as_plugin_api (GST_TYPE_FAKE_SINK_STATE_ERROR, 0);
} }
static void static void

View file

@ -349,9 +349,9 @@ gst_fake_src_class_init (GstFakeSrcClass * klass)
gstbase_src_class->get_times = GST_DEBUG_FUNCPTR (gst_fake_src_get_times); gstbase_src_class->get_times = GST_DEBUG_FUNCPTR (gst_fake_src_get_times);
gstbase_src_class->create = GST_DEBUG_FUNCPTR (gst_fake_src_create); gstbase_src_class->create = GST_DEBUG_FUNCPTR (gst_fake_src_create);
gst_type_mark_as_plugin_api (GST_TYPE_FAKE_SRC_DATA); gst_type_mark_as_plugin_api (GST_TYPE_FAKE_SRC_DATA, 0);
gst_type_mark_as_plugin_api (GST_TYPE_FAKE_SRC_SIZETYPE); gst_type_mark_as_plugin_api (GST_TYPE_FAKE_SRC_SIZETYPE, 0);
gst_type_mark_as_plugin_api (GST_TYPE_FAKE_SRC_FILLTYPE); gst_type_mark_as_plugin_api (GST_TYPE_FAKE_SRC_FILLTYPE, 0);
} }
static void static void

View file

@ -288,7 +288,7 @@ gst_file_sink_class_init (GstFileSinkClass * klass)
sizeof (off_t)); sizeof (off_t));
} }
gst_type_mark_as_plugin_api (GST_TYPE_FILE_SINK_BUFFER_MODE); gst_type_mark_as_plugin_api (GST_TYPE_FILE_SINK_BUFFER_MODE, 0);
} }
static void static void

View file

@ -1305,8 +1305,8 @@ gst_input_selector_class_init (GstInputSelectorClass * klass)
gstelement_class->release_pad = gst_input_selector_release_pad; gstelement_class->release_pad = gst_input_selector_release_pad;
gstelement_class->change_state = gst_input_selector_change_state; gstelement_class->change_state = gst_input_selector_change_state;
gst_type_mark_as_plugin_api (GST_TYPE_SELECTOR_PAD); gst_type_mark_as_plugin_api (GST_TYPE_SELECTOR_PAD, 0);
gst_type_mark_as_plugin_api (GST_TYPE_INPUT_SELECTOR_SYNC_MODE); gst_type_mark_as_plugin_api (GST_TYPE_INPUT_SELECTOR_SYNC_MODE, 0);
} }
static void static void

View file

@ -841,7 +841,7 @@ gst_multi_queue_class_init (GstMultiQueueClass * klass)
gstelement_class->change_state = gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_multi_queue_change_state); GST_DEBUG_FUNCPTR (gst_multi_queue_change_state);
gst_type_mark_as_plugin_api (GST_TYPE_MULTIQUEUE_PAD); gst_type_mark_as_plugin_api (GST_TYPE_MULTIQUEUE_PAD, 0);
} }
static void static void

View file

@ -148,7 +148,8 @@ gst_output_selector_class_init (GstOutputSelectorClass * klass)
gstelement_class->change_state = gst_output_selector_change_state; gstelement_class->change_state = gst_output_selector_change_state;
gst_type_mark_as_plugin_api (GST_TYPE_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE); gst_type_mark_as_plugin_api (GST_TYPE_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE,
0);
} }
static void static void

View file

@ -420,7 +420,7 @@ gst_queue_class_init (GstQueueClass * klass)
GST_DEBUG_REGISTER_FUNCPTR (gst_queue_chain); GST_DEBUG_REGISTER_FUNCPTR (gst_queue_chain);
GST_DEBUG_REGISTER_FUNCPTR (gst_queue_chain_list); GST_DEBUG_REGISTER_FUNCPTR (gst_queue_chain_list);
gst_type_mark_as_plugin_api (GST_TYPE_QUEUE_LEAKY); gst_type_mark_as_plugin_api (GST_TYPE_QUEUE_LEAKY, 0);
} }
static void static void

View file

@ -298,7 +298,7 @@ gst_tee_class_init (GstTeeClass * klass)
GST_DEBUG_FUNCPTR (gst_tee_request_new_pad); GST_DEBUG_FUNCPTR (gst_tee_request_new_pad);
gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_tee_release_pad); gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_tee_release_pad);
gst_type_mark_as_plugin_api (GST_TYPE_TEE_PULL_MODE); gst_type_mark_as_plugin_api (GST_TYPE_TEE_PULL_MODE, 0);
} }
static void static void

View file

@ -1953,6 +1953,26 @@ GST_START_TEST (test_regression)
GST_END_TEST; GST_END_TEST;
GST_START_TEST (test_mark_as_plugin_api)
{
GstPluginAPIFlags api_flags;
fail_unless (!gst_type_is_plugin_api (GST_TYPE_ELEMENT, NULL));
gst_type_mark_as_plugin_api (GST_TYPE_ELEMENT, 0);
fail_unless (gst_type_is_plugin_api (GST_TYPE_ELEMENT, &api_flags));
fail_unless_equals_int (api_flags, 0);
gst_type_mark_as_plugin_api (GST_TYPE_ELEMENT,
GST_PLUGIN_API_FLAG_IGNORE_ENUM_MEMBERS);
fail_unless (gst_type_is_plugin_api (GST_TYPE_ELEMENT, &api_flags));
fail_unless_equals_int (api_flags, GST_PLUGIN_API_FLAG_IGNORE_ENUM_MEMBERS);
}
GST_END_TEST;
static Suite * static Suite *
gst_utils_suite (void) gst_utils_suite (void)
{ {
@ -1994,6 +2014,8 @@ gst_utils_suite (void)
tcase_add_test (tc_chain, test_write_macros); tcase_add_test (tc_chain, test_write_macros);
tcase_add_test (tc_chain, test_regression); tcase_add_test (tc_chain, test_regression);
tcase_add_test (tc_chain, test_mark_as_plugin_api);
return s; return s;
} }