mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 00:36:51 +00:00
validate: Add a deep-property-path
parameter to the wait
signal
Allowing wait actions to wait on any property of any element in the pipeline, even for elements that might be added later in the pipeline. This also works for pads which can be pretty useful Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7700>
This commit is contained in:
parent
2c88bbf07f
commit
302797a965
1 changed files with 115 additions and 19 deletions
|
@ -3257,14 +3257,22 @@ typedef struct
|
|||
guint sigid;
|
||||
gboolean check_done;
|
||||
gboolean check_property;
|
||||
|
||||
gchar *parent_name;
|
||||
gchar *object_name;
|
||||
gchar *property_name;
|
||||
GMutex lock;
|
||||
} WaitingSignalData;
|
||||
|
||||
static WaitingSignalData *
|
||||
waiting_signal_data_new (GstElement * target, GstValidateAction * action)
|
||||
waiting_signal_data_new (GstElement * target, GstValidateAction * action,
|
||||
gchar * parent_name, gchar * object_name, gchar * property_name)
|
||||
{
|
||||
WaitingSignalData *data = g_new0 (WaitingSignalData, 1);
|
||||
|
||||
data->parent_name = parent_name;
|
||||
data->object_name = object_name;
|
||||
data->property_name = property_name;
|
||||
data->target = gst_object_ref (target);
|
||||
data->action = gst_validate_action_ref (action);
|
||||
|
||||
|
@ -3279,6 +3287,9 @@ waiting_signal_data_free (WaitingSignalData * data)
|
|||
|
||||
g_assert (scenario);
|
||||
|
||||
g_free (data->object_name);
|
||||
g_free (data->parent_name);
|
||||
g_free (data->property_name);
|
||||
gst_object_unref (data->target);
|
||||
gst_validate_action_unref (data->action);
|
||||
g_free (data);
|
||||
|
@ -3302,11 +3313,15 @@ waiting_signal_data_disconnect (WaitingSignalData * data,
|
|||
}
|
||||
|
||||
static void
|
||||
stop_waiting_signal_cb (WaitingSignalData * data)
|
||||
stop_waiting_signal_cb (WaitingSignalData * data, GstObject * prop_object,
|
||||
GParamSpec * prop, GstObject * object)
|
||||
{
|
||||
GstStructure *check = NULL;
|
||||
GstValidateAction *action = gst_validate_action_ref (data->action);
|
||||
GstValidateScenario *scenario = NULL;
|
||||
const gchar *property_name = NULL;
|
||||
gboolean check_property = data->check_property;
|
||||
GstObject *property_check_target = GST_OBJECT_CAST (data->target);
|
||||
|
||||
g_mutex_lock (&data->lock);
|
||||
if (data->check_done) {
|
||||
|
@ -3315,10 +3330,40 @@ stop_waiting_signal_cb (WaitingSignalData * data)
|
|||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (data->object_name) {
|
||||
if (g_strcmp0 (data->object_name, GST_OBJECT_NAME (prop_object)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (g_strcmp0 (data->property_name, prop->name) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (data->parent_name) {
|
||||
GstObject *parent = gst_object_get_parent (prop_object);
|
||||
|
||||
if (parent && g_strcmp0 (data->parent_name, GST_OBJECT_NAME (parent))) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
gst_clear_object (&parent);
|
||||
}
|
||||
|
||||
property_check_target = prop_object;
|
||||
property_name = data->property_name;
|
||||
check_property =
|
||||
gst_structure_has_field (action->structure, "property-value");
|
||||
|
||||
} else {
|
||||
property_name =
|
||||
gst_structure_get_string (action->structure, "property-name");
|
||||
}
|
||||
|
||||
scenario = gst_validate_action_get_scenario (data->action);
|
||||
if (data->check_property &&
|
||||
_check_property (scenario, action, data->target,
|
||||
gst_structure_get_string (action->structure, "property-name"),
|
||||
if (check_property &&
|
||||
_check_property (scenario, action, property_check_target,
|
||||
property_name,
|
||||
gst_structure_get_value (action->structure, "property-value"),
|
||||
FALSE) != GST_VALIDATE_EXECUTE_ACTION_OK) {
|
||||
|
||||
|
@ -3326,6 +3371,7 @@ stop_waiting_signal_cb (WaitingSignalData * data)
|
|||
|
||||
goto cleanup;
|
||||
}
|
||||
data->check_done = TRUE;
|
||||
|
||||
waiting_signal_data_disconnect (data, scenario);
|
||||
if (gst_structure_get (action->structure, "check", GST_TYPE_STRUCTURE,
|
||||
|
@ -3349,6 +3395,7 @@ stop_waiting_signal_cb (WaitingSignalData * data)
|
|||
cleanup:
|
||||
gst_validate_action_unref (action);
|
||||
gst_clear_object (&scenario);
|
||||
g_mutex_unlock (&data->lock);
|
||||
}
|
||||
|
||||
static GstValidateExecuteActionReturn
|
||||
|
@ -3418,21 +3465,56 @@ _execute_wait_for_signal (GstValidateScenario * scenario,
|
|||
const GValue *property_value =
|
||||
gst_structure_get_value (action->structure, "property-value");
|
||||
DECLARE_AND_GET_PIPELINE (scenario, action);
|
||||
gboolean checking_property = signal_name == NULL;
|
||||
const gchar *deep_property_path =
|
||||
gst_structure_get_string (action->structure, "deep-property-path");
|
||||
gboolean checking_property = signal_name == NULL
|
||||
&& deep_property_path == NULL;
|
||||
gchar *parent_name = NULL, *object_name = NULL, *deep_property_name = NULL;
|
||||
|
||||
REPORT_UNLESS (signal_name || property_name, done,
|
||||
"No signal-name or property-name given for wait action");
|
||||
REPORT_UNLESS (!property_name || (property_name && property_value), done,
|
||||
"`property-name` specified without a `property-value`");
|
||||
targets = _find_elements_defined_in_action (scenario, action);
|
||||
REPORT_UNLESS ((g_list_length (targets) == 1), done,
|
||||
"Could not find target element.");
|
||||
if (deep_property_path && *deep_property_path) {
|
||||
gchar **elem_pad_name = g_strsplit (deep_property_path, ".", 2);
|
||||
gchar **object_prop_name =
|
||||
g_strsplit (elem_pad_name[1] ? elem_pad_name[1] : elem_pad_name[0],
|
||||
"::",
|
||||
-1);
|
||||
|
||||
gst_validate_printf (action, "Waiting for '%s'\n",
|
||||
signal_name ? signal_name : property_name);
|
||||
REPORT_UNLESS (object_prop_name[1], done,
|
||||
"Property specification %s is missing a `::propename` part",
|
||||
deep_property_path);
|
||||
|
||||
target = targets->data;
|
||||
data = waiting_signal_data_new (target, action);
|
||||
deep_property_name = g_strdup (object_prop_name[1]);
|
||||
object_name = g_strdup (object_prop_name[0]);
|
||||
if (elem_pad_name[1]) {
|
||||
parent_name = g_strdup (elem_pad_name[0]);
|
||||
}
|
||||
|
||||
g_strfreev (elem_pad_name);
|
||||
g_strfreev (object_prop_name);
|
||||
|
||||
target = gst_object_ref (pipeline);
|
||||
signal_name = g_strdup ("deep-notify");
|
||||
|
||||
gst_validate_printf (action, "Waiting for 'deep-notify::%s'\n",
|
||||
deep_property_name);
|
||||
} else {
|
||||
|
||||
REPORT_UNLESS (signal_name || property_name, done,
|
||||
"No signal-name or property-name given for wait action");
|
||||
REPORT_UNLESS (!property_name || (property_name && property_value), done,
|
||||
"`property-name` specified without a `property-value`");
|
||||
|
||||
targets = _find_elements_defined_in_action (scenario, action);
|
||||
REPORT_UNLESS ((g_list_length (targets) == 1), done,
|
||||
"Could not find target element.");
|
||||
target = targets->data;
|
||||
gst_validate_printf (action, "Waiting for '%s'\n",
|
||||
signal_name ? signal_name : property_name);
|
||||
}
|
||||
|
||||
|
||||
data =
|
||||
waiting_signal_data_new (target, action, parent_name, object_name,
|
||||
deep_property_name);
|
||||
|
||||
if (checking_property) {
|
||||
signal_name = g_strdup_printf ("notify::%s", property_name);
|
||||
|
@ -3461,8 +3543,7 @@ _execute_wait_for_signal (GstValidateScenario * scenario,
|
|||
non_blocking ? GST_VALIDATE_EXECUTE_ACTION_NON_BLOCKING :
|
||||
GST_VALIDATE_EXECUTE_ACTION_ASYNC;
|
||||
if (checking_property) {
|
||||
GST_ERROR ("Checking property value");
|
||||
if (_check_property (scenario, action, target, property_name,
|
||||
if (_check_property (scenario, action, data->target, property_name,
|
||||
property_value, FALSE) == GST_VALIDATE_EXECUTE_ACTION_OK) {
|
||||
data->check_done = TRUE;
|
||||
waiting_signal_data_disconnect (data, scenario);
|
||||
|
@ -3558,6 +3639,8 @@ _execute_wait (GstValidateScenario * scenario, GstValidateAction * action)
|
|||
gst_structure_get_boolean (action->structure, "on-clock", &on_clock);
|
||||
if (gst_structure_has_field (action->structure, "signal-name")) {
|
||||
return _execute_wait_for_signal (scenario, action);
|
||||
} else if (gst_structure_has_field (action->structure, "deep-property-path")) {
|
||||
return _execute_wait_for_signal (scenario, action);
|
||||
} else if (gst_structure_has_field (action->structure, "property-name")) {
|
||||
return _execute_wait_for_signal (scenario, action);
|
||||
} else if (gst_structure_has_field (action->structure, "message-type")) {
|
||||
|
@ -8146,6 +8229,19 @@ register_action_types (void)
|
|||
.types = "structure",
|
||||
NULL
|
||||
},
|
||||
{
|
||||
.name = "deep-property-path",
|
||||
.description = "The property to wait to be set on the object inside the pipeline that matches"
|
||||
" the path defined as:\n\n"
|
||||
"```\n"
|
||||
"element-name.padname::property-name=new-value\n"
|
||||
"```\n\n"
|
||||
"> NOTE: `.padname` is not needed if setting a property on an element\n\n",
|
||||
.mandatory = FALSE,
|
||||
.types = "string",
|
||||
NULL
|
||||
},
|
||||
|
||||
{NULL}
|
||||
}),
|
||||
"Waits for signal 'signal-name', message 'message-type', or during 'duration' seconds",
|
||||
|
|
Loading…
Reference in a new issue