ges: Avoid emitting 'child-added/removed' when signal emission stops addition

In the GESTimeline, TrackElement addition to a clip might get cancelled
(and thus the element gets removed), we need to make sure users do not
get wrong signals.

Also document the fact that user should connect to container::child-added
with g_signal_connect_after.
This commit is contained in:
Thibault Saunier 2015-09-24 13:21:15 +02:00
parent bd1d03202b
commit 822e0a7b09
2 changed files with 24 additions and 7 deletions

View file

@ -77,6 +77,10 @@ struct _GESContainerPrivate
*/ */
GHashTable *mappings; GHashTable *mappings;
guint nb_effects; guint nb_effects;
/* List of GESTimelineElement being in the "child-added" signal
* emission stage */
GList *adding_children;
}; };
enum enum
@ -380,6 +384,9 @@ ges_container_class_init (GESContainerClass * klass)
* @element: the #GESTimelineElement that was added. * @element: the #GESTimelineElement that was added.
* *
* Will be emitted after a child was added to @container. * Will be emitted after a child was added to @container.
* Usually you should connect with #g_signal_connect_after
* as in the first emission stage, the signal emission might
* get stopped internally.
*/ */
ges_container_signals[CHILD_ADDED_SIGNAL] = ges_container_signals[CHILD_ADDED_SIGNAL] =
g_signal_new ("child-added", G_TYPE_FROM_CLASS (klass), g_signal_new ("child-added", G_TYPE_FROM_CLASS (klass),
@ -687,8 +694,10 @@ ges_container_add (GESContainer * container, GESTimelineElement * child)
_ges_container_add_child_properties (container, child); _ges_container_add_child_properties (container, child);
priv->adding_children = g_list_prepend (priv->adding_children, child);
g_signal_emit (container, ges_container_signals[CHILD_ADDED_SIGNAL], 0, g_signal_emit (container, ges_container_signals[CHILD_ADDED_SIGNAL], 0,
child); child);
priv->adding_children = g_list_remove (priv->adding_children, child);
return TRUE; return TRUE;
} }
@ -733,8 +742,13 @@ ges_container_remove (GESContainer * container, GESTimelineElement * child)
_ges_container_remove_child_properties (container, child); _ges_container_remove_child_properties (container, child);
g_signal_emit (container, ges_container_signals[CHILD_REMOVED_SIGNAL], 0, if (!g_list_find (container->priv->adding_children, child)) {
child); g_signal_emit (container, ges_container_signals[CHILD_REMOVED_SIGNAL], 0,
child);
} else {
GST_INFO_OBJECT (container, "Not emitting 'child-removed' signal as child"
" removal happend during 'child-added' signal emission");
}
gst_object_unref (child); gst_object_unref (child);
return TRUE; return TRUE;

View file

@ -2276,13 +2276,14 @@ clip_track_element_added_cb (GESClip * clip,
if (!tracks || tracks->len == 0) { if (!tracks || tracks->len == 0) {
GST_WARNING_OBJECT (timeline, "Got no Track to add %p (type %s), removing" GST_WARNING_OBJECT (timeline, "Got no Track to add %p (type %s), removing"
" from clip", " from clip (stopping 'child-added' signal emission).",
track_element, ges_track_type_name (ges_track_element_get_track_type track_element, ges_track_type_name (ges_track_element_get_track_type
(track_element))); (track_element)));
if (tracks) if (tracks)
g_ptr_array_unref (tracks); g_ptr_array_unref (tracks);
g_signal_stop_emission_by_name (clip, "child-added");
ges_container_remove (GES_CONTAINER (clip), ges_container_remove (GES_CONTAINER (clip),
GES_TIMELINE_ELEMENT (track_element)); GES_TIMELINE_ELEMENT (track_element));
@ -2306,8 +2307,9 @@ clip_track_element_added_cb (GESClip * clip,
} }
} else { } else {
GST_INFO_OBJECT (clip, "Already had a Source Element in %" GST_PTR_FORMAT GST_INFO_OBJECT (clip, "Already had a Source Element in %" GST_PTR_FORMAT
" of type %s, removing new one.", track, " of type %s, removing new one. (stopping 'child-added' emission)",
G_OBJECT_TYPE_NAME (track_element)); track, G_OBJECT_TYPE_NAME (track_element));
g_signal_stop_emission_by_name (clip, "child-added");
ges_container_remove (GES_CONTAINER (clip), ges_container_remove (GES_CONTAINER (clip),
GES_TIMELINE_ELEMENT (track_element)); GES_TIMELINE_ELEMENT (track_element));
} }
@ -2331,8 +2333,9 @@ clip_track_element_added_cb (GESClip * clip,
continue; continue;
} else { } else {
GST_INFO_OBJECT (clip, "Already had a Source Element in %" GST_PTR_FORMAT GST_INFO_OBJECT (clip, "Already had a Source Element in %" GST_PTR_FORMAT
" of type %s, removing new one.", track, " of type %s, removing new one. (stopping 'child-added' emission)",
G_OBJECT_TYPE_NAME (track_element)); track, G_OBJECT_TYPE_NAME (track_element));
g_signal_stop_emission_by_name (clip, "child-added");
ges_container_remove (GES_CONTAINER (clip), ges_container_remove (GES_CONTAINER (clip),
GES_TIMELINE_ELEMENT (track_element)); GES_TIMELINE_ELEMENT (track_element));
} }