container: Let full control of children priorities to subclasses

For that we make the children_control_mode a protected filed, directly usable by
subclasses, removing the method to set it.

And we let the subclass set and get the priority offsets to the container class.
This commit is contained in:
Thibault Saunier 2013-07-01 17:51:32 -04:00 committed by Mathieu Duponchelle
parent ed9dcddef4
commit 9e15e13983
3 changed files with 75 additions and 74 deletions

View file

@ -85,11 +85,9 @@ enum
static GParamSpec *properties[PROP_LAST];
/*****************************************************
* *
* GESTimelineElement virtual methods implementation *
* *
*****************************************************/
/****************************************************
* Listen to our children *
****************************************************/
static void
_get_priority_range (GESContainer * container, guint32 * min_priority,
@ -106,6 +104,31 @@ _get_priority_range (GESContainer * container, guint32 * min_priority,
}
}
static void
_child_priority_changed_cb (GESTimelineElement * child,
GParamSpec * arg G_GNUC_UNUSED, GESContainer * container)
{
guint32 min_prio, max_prio;
GST_DEBUG_OBJECT (container, "TimelineElement %p priority changed to %i",
child, _PRIORITY (child));
if (container->children_control_mode == GES_CHILDREN_IGNORE_NOTIFIES)
return;
/* Update mapping */
_get_priority_range (container, &min_prio, &max_prio);
_ges_container_set_priority_offset (container, child,
min_prio + _PRIORITY (container) - _PRIORITY (child));
}
/*****************************************************
* *
* GESTimelineElement virtual methods implementation *
* *
*****************************************************/
static gboolean
_set_start (GESTimelineElement * element, GstClockTime start)
{
@ -116,8 +139,7 @@ _set_start (GESTimelineElement * element, GstClockTime start)
GST_DEBUG_OBJECT (element, "Setting children start, (initiated_move: %"
GST_PTR_FORMAT ")", container->initiated_move);
_ges_container_set_children_control_mode (container,
GES_CHILDREN_IGNORE_NOTIFIES);
container->children_control_mode = GES_CHILDREN_IGNORE_NOTIFIES;
for (tmp = container->children; tmp; tmp = g_list_next (tmp)) {
GESTimelineElement *child = (GESTimelineElement *) tmp->data;
@ -130,7 +152,7 @@ _set_start (GESTimelineElement * element, GstClockTime start)
}
}
_ges_container_set_children_control_mode (container, GES_CHILDREN_UPDATE);
container->children_control_mode = GES_CHILDREN_UPDATE;
return TRUE;
}
@ -141,8 +163,7 @@ _set_inpoint (GESTimelineElement * element, GstClockTime inpoint)
GList *tmp;
GESContainer *container = GES_CONTAINER (element);
_ges_container_set_children_control_mode (container,
GES_CHILDREN_IGNORE_NOTIFIES);
container->children_control_mode = GES_CHILDREN_IGNORE_NOTIFIES;
for (tmp = container->children; tmp; tmp = g_list_next (tmp)) {
GESTimelineElement *child = (GESTimelineElement *) tmp->data;
@ -150,7 +171,7 @@ _set_inpoint (GESTimelineElement * element, GstClockTime inpoint)
_set_inpoint0 (child, inpoint);
}
}
_ges_container_set_children_control_mode (container, GES_CHILDREN_UPDATE);
container->children_control_mode = GES_CHILDREN_UPDATE;
return TRUE;
}
@ -163,8 +184,7 @@ _set_duration (GESTimelineElement * element, GstClockTime duration)
GESContainer *container = GES_CONTAINER (element);
_ges_container_set_children_control_mode (container,
GES_CHILDREN_IGNORE_NOTIFIES);
container->children_control_mode = GES_CHILDREN_IGNORE_NOTIFIES;
for (tmp = container->children; tmp; tmp = g_list_next (tmp)) {
GESTimelineElement *child = (GESTimelineElement *) tmp->data;
@ -176,7 +196,7 @@ _set_duration (GESTimelineElement * element, GstClockTime duration)
_set_duration0 (GES_TIMELINE_ELEMENT (child), duration);
}
}
_ges_container_set_children_control_mode (container, GES_CHILDREN_UPDATE);
container->children_control_mode = GES_CHILDREN_UPDATE;
return TRUE;
}
@ -203,6 +223,7 @@ _set_priority (GESTimelineElement * element, guint32 priority)
_get_priority_range (container, &min_prio, &max_prio);
container->children_control_mode = GES_CHILDREN_UPDATE_OFFSETS;
for (tmp = container->children; tmp; tmp = g_list_next (tmp)) {
guint32 real_tck_prio;
GESTimelineElement *child = (GESTimelineElement *) tmp->data;
@ -222,7 +243,7 @@ _set_priority (GESTimelineElement * element, guint32 priority)
}
_set_priority0 (child, real_tck_prio);
}
_ges_container_set_children_control_mode (container, GES_CHILDREN_UPDATE);
container->children_control_mode = GES_CHILDREN_UPDATE;
_compute_height (container);
return TRUE;
@ -301,12 +322,11 @@ _add_child (GESContainer * container, GESTimelineElement * element)
/* We set the timing value of the child to ours, we avoid infinite loop
* making sure the container ignore notifies from the child */
_ges_container_set_children_control_mode (container,
GES_CHILDREN_IGNORE_NOTIFIES);
container->children_control_mode = GES_CHILDREN_IGNORE_NOTIFIES;
_set_start0 (element, GES_TIMELINE_ELEMENT_START (container));
_set_inpoint0 (element, GES_TIMELINE_ELEMENT_INPOINT (container));
_set_duration0 (element, GES_TIMELINE_ELEMENT_DURATION (container));
_ges_container_set_children_control_mode (container, GES_CHILDREN_UPDATE);
container->children_control_mode = GES_CHILDREN_UPDATE;
return TRUE;
}
@ -325,6 +345,8 @@ _remove_child (GESContainer * container, GESTimelineElement * element)
static void
_child_added (GESContainer * container, GESTimelineElement * element)
{
g_signal_connect (G_OBJECT (element), "notify::priority",
G_CALLBACK (_child_priority_changed_cb), container);
_compute_height (container);
}

View file

@ -55,7 +55,6 @@ typedef struct
guint start_notifyid;
guint duration_notifyid;
guint inpoint_notifyid;
guint priority_notifyid;
} ChildMapping;
enum
@ -76,7 +75,6 @@ struct _GESContainerPrivate
/* Set to TRUE when the container is doing updates of track object
* properties so we don't end up in infinite property update loops
*/
GESChildrenControlMode children_control_mode;
GHashTable *mappings;
guint nb_effects;
};
@ -102,7 +100,6 @@ _free_mapping (ChildMapping * mapping)
g_signal_handler_disconnect (child, mapping->start_notifyid);
g_signal_handler_disconnect (child, mapping->duration_notifyid);
g_signal_handler_disconnect (child, mapping->inpoint_notifyid);
g_signal_handler_disconnect (child, mapping->priority_notifyid);
ges_timeline_element_set_parent (child, NULL);
g_slice_free (ChildMapping, mapping);
@ -150,17 +147,11 @@ _set_start (GESTimelineElement * element, GstClockTime start)
map = g_hash_table_lookup (priv->mappings, child);
map->start_offset = start - _START (child);
}
priv->children_control_mode = GES_CHILDREN_UPDATE;
container->children_control_mode = GES_CHILDREN_UPDATE;
return TRUE;
}
static gboolean
_set_priority (GESTimelineElement * element, guint32 priority)
{
return TRUE;
}
static gboolean
_set_inpoint (GESTimelineElement * element, GstClockTime inpoint)
{
@ -288,7 +279,6 @@ ges_container_class_init (GESContainerClass * klass)
element_class->set_start = _set_start;
element_class->set_duration = _set_duration;
element_class->set_inpoint = _set_inpoint;
element_class->set_priority = _set_priority;
/* No default implementations */
klass->remove_child = NULL;
@ -329,7 +319,7 @@ _child_start_changed_cb (GESTimelineElement * child,
GESContainerPrivate *priv = container->priv;
GESTimelineElement *element = GES_TIMELINE_ELEMENT (container);
if (priv->children_control_mode == GES_CHILDREN_IGNORE_NOTIFIES)
if (container->children_control_mode == GES_CHILDREN_IGNORE_NOTIFIES)
return;
map = g_hash_table_lookup (priv->mappings, child);
@ -353,7 +343,7 @@ _child_inpoint_changed_cb (GESTimelineElement * child,
GESContainerPrivate *priv = container->priv;
GESTimelineElement *element = GES_TIMELINE_ELEMENT (container);
if (priv->children_control_mode == GES_CHILDREN_IGNORE_NOTIFIES)
if (container->children_control_mode == GES_CHILDREN_IGNORE_NOTIFIES)
return;
map = g_hash_table_lookup (priv->mappings, child);
@ -374,7 +364,7 @@ _child_duration_changed_cb (GESTimelineElement * child,
GESContainerPrivate *priv = container->priv;
GESTimelineElement *element = GES_TIMELINE_ELEMENT (container);
if (priv->children_control_mode == GES_CHILDREN_IGNORE_NOTIFIES)
if (container->children_control_mode == GES_CHILDREN_IGNORE_NOTIFIES)
return;
map = g_hash_table_lookup (priv->mappings, child);
@ -386,30 +376,6 @@ _child_duration_changed_cb (GESTimelineElement * child,
container->initiated_move = NULL;
}
static void
_child_priority_changed_cb (GESTimelineElement * child,
GParamSpec * arg G_GNUC_UNUSED, GESContainer * container)
{
ChildMapping *map;
guint32 min_prio, max_prio;
GESContainerPrivate *priv = container->priv;
GST_DEBUG_OBJECT (container, "TimelineElement %p priority changed to %i",
child, _PRIORITY (child));
if (priv->children_control_mode == GES_CHILDREN_IGNORE_NOTIFIES)
return;
/* Update mapping */
map = g_hash_table_lookup (priv->mappings, child);
g_assert (map);
GES_CONTAINER_GET_CLASS (container)->get_priority_range (container, &min_prio,
&max_prio);
map->priority_offset = min_prio + _PRIORITY (container) - _PRIORITY (child);
}
/****************************************************
* *
* Internal methods implementation *
@ -430,13 +396,6 @@ _ges_container_sort_children_by_end (GESContainer * container)
(GCompareFunc) element_end_compare);
}
void
_ges_container_set_children_control_mode (GESContainer * container,
GESChildrenControlMode children_control_mode)
{
container->priv->children_control_mode = children_control_mode;
}
void
_ges_container_set_height (GESContainer * container, guint32 height)
{
@ -447,6 +406,28 @@ _ges_container_set_height (GESContainer * container, guint32 height)
}
}
gint
_ges_container_get_priority_offset (GESContainer * container,
GESTimelineElement * elem)
{
ChildMapping *map = g_hash_table_lookup (container->priv->mappings, elem);
g_return_val_if_fail (map, 0);
return map->priority_offset;
}
void
_ges_container_set_priority_offset (GESContainer * container,
GESTimelineElement * elem, gint32 priority_offset)
{
ChildMapping *map = g_hash_table_lookup (container->priv->mappings, elem);
g_return_if_fail (map);
map->priority_offset = priority_offset;
}
/**********************************************
* *
* API implementation *
@ -480,15 +461,15 @@ ges_container_add (GESContainer * container, GESTimelineElement * child)
GST_DEBUG_OBJECT (container, "adding timeline element %" GST_PTR_FORMAT,
child);
priv->children_control_mode = GES_CHILDREN_IGNORE_NOTIFIES;
container->children_control_mode = GES_CHILDREN_IGNORE_NOTIFIES;
if (class->add_child) {
if (class->add_child (container, child) == FALSE) {
priv->children_control_mode = GES_CHILDREN_UPDATE;
container->children_control_mode = GES_CHILDREN_UPDATE;
GST_WARNING_OBJECT (container, "Erreur adding child %p", child);
return FALSE;
}
}
priv->children_control_mode = GES_CHILDREN_UPDATE;
container->children_control_mode = GES_CHILDREN_UPDATE;
mapping = g_slice_new0 (ChildMapping);
mapping->child = gst_object_ref (child);
@ -497,8 +478,6 @@ ges_container_add (GESContainer * container, GESTimelineElement * child)
mapping->inpoint_offset = _INPOINT (container) - _INPOINT (child);
GES_CONTAINER_GET_CLASS (container)->get_priority_range (container,
&min_prio, &max_prio);
mapping->priority_offset =
min_prio + _PRIORITY (container) - _PRIORITY (child);
g_hash_table_insert (priv->mappings, child, mapping);
@ -514,10 +493,6 @@ ges_container_add (GESContainer * container, GESTimelineElement * child)
mapping->inpoint_notifyid =
g_signal_connect (G_OBJECT (child), "notify::in-point",
G_CALLBACK (_child_inpoint_changed_cb), container);
mapping->priority_notifyid =
g_signal_connect (G_OBJECT (child), "notify::priority",
G_CALLBACK (_child_priority_changed_cb), container);
if (ges_timeline_element_set_parent (child, GES_TIMELINE_ELEMENT (container))
== FALSE) {

View file

@ -84,6 +84,7 @@ struct _GESContainer
guint32 height; /* the span of priorities this object needs */
/* <protected> */
GESChildrenControlMode children_control_mode;
/*< readonly >*/
GESTimelineElement *initiated_move;
@ -144,8 +145,6 @@ GList * ges_container_ungroup (GESContainer * container, gboolean recursive)
GESContainer *ges_container_group (GList *containers);
/* To be used by subclasses only */
void _ges_container_set_children_control_mode (GESContainer * container,
GESChildrenControlMode children_control_mode);
void _ges_container_set_height (GESContainer * container,
guint32 height);
gboolean ges_container_edit (GESContainer * container,
@ -153,6 +152,11 @@ gboolean ges_container_edit (GESContainer * container,
GESEditMode mode,
GESEdge edge,
guint64 position);
gint _ges_container_get_priority_offset (GESContainer * container,
GESTimelineElement *elem);
void _ges_container_set_priority_offset (GESContainer * container,
GESTimelineElement *elem,
gint32 priority_offset);
G_END_DECLS