GList *lchild;
PendingGroup *pgroup = tmp->data;
+ timeline_add_group (self->timeline, pgroup->group);
+
for (lchild = ((PendingGroup *) tmp->data)->pending_children; lchild;
lchild = lchild->next) {
child = g_hash_table_lookup (priv->containers, lchild->data);
GST_DEBUG_OBJECT (tmp->data, "Adding %s child %" GST_PTR_FORMAT " %s",
(const gchar *) lchild->data, child,
GES_TIMELINE_ELEMENT_NAME (child));
- ges_timeline_element_set_timeline (GES_TIMELINE_ELEMENT (pgroup->group),
- self->timeline);
ges_container_add (GES_CONTAINER (pgroup->group), child);
}
}
if (!GES_TIMELINE_ELEMENT_TIMELINE (group)) {
timeline_add_group (GES_TIMELINE_ELEMENT_TIMELINE (child),
GES_GROUP (group));
+ timeline_emit_group_added (GES_TIMELINE_ELEMENT_TIMELINE (child),
+ GES_GROUP (group));
}
children = GES_CONTAINER_CHILDREN (group);
paste_position);
if (ngroup) {
- if (GES_CONTAINER_CHILDREN (ngroup))
+ if (GES_CONTAINER_CHILDREN (ngroup)) {
timeline_add_group (GES_TIMELINE_ELEMENT_TIMELINE (GES_CONTAINER_CHILDREN
(ngroup)->data), GES_GROUP (element));
+ timeline_emit_group_added (GES_TIMELINE_ELEMENT_TIMELINE
+ (GES_CONTAINER_CHILDREN (ngroup)->data), GES_GROUP (element));
+ }
}
return ngroup;
G_GNUC_INTERNAL void
timeline_add_group (GESTimeline *timeline,
GESGroup *group);
-G_GNUC_INTERNAL
-void
+G_GNUC_INTERNAL void
timeline_remove_group (GESTimeline *timeline,
GESGroup *group);
+G_GNUC_INTERNAL void
+timeline_emit_group_added (GESTimeline *timeline,
+ GESGroup *group);
+G_GNUC_INTERNAL void
+timeline_emit_group_removed (GESTimeline * timeline,
+ GESGroup * group, GPtrArray * array);
G_GNUC_INTERNAL
gboolean
void
timeline_fill_gaps (GESTimeline *timeline);
-G_GNUC_INTERNAL GList *
-timeline_get_groups (GESTimeline * timeline);
-
-G_GNUC_INTERNAL void
-timeline_emit_group_removed (GESTimeline * timeline,
- GESGroup * group, GPtrArray * array);
G_GNUC_INTERNAL
void
track_resort_and_fill_gaps (GESTrack *track);
* @timeline: the #GESTimeline
* @layer: the #GESLayer that was added to the timeline
*
- * Will be emitted after the layer was added to the timeline.
+ * Will be emitted after a new layer is added to the timeline.
*/
ges_timeline_signals[LAYER_ADDED] =
g_signal_new ("layer-added", G_TYPE_FROM_CLASS (klass),
* @timeline: the #GESTimeline
* @group: the #GESGroup
*
- * Will be emitted after a group has been added to to the timeline.
+ * Will be emitted after a new group is added to to the timeline.
*/
ges_timeline_signals[GROUP_ADDED] =
g_signal_new ("group-added", G_TYPE_FROM_CLASS (klass),
gst_object_ref_sink (group));
ges_timeline_element_set_timeline (GES_TIMELINE_ELEMENT (group), timeline);
+}
+/**
+ * timeline_emit_group_added:
+ * @timeline: a #GESTimeline
+ * @group: group that was added
+ *
+ * Emit group-added signal.
+ */
+void
+timeline_emit_group_added (GESTimeline * timeline, GESGroup * group)
+{
g_signal_emit (timeline, ges_timeline_signals[GROUP_ADDED], 0, group);
}
gst_object_unref (group);
}
-GList *
-timeline_get_groups (GESTimeline * timeline)
-{
- return timeline->priv->groups;
-}
-
static GPtrArray *
select_tracks_for_object_default (GESTimeline * timeline,
GESClip * clip, GESTrackElement * tr_object, gpointer user_data)
}
/**
+ * ges_timeline_get_groups:
+ * @timeline: a #GESTimeline
+ *
+ * Get the list of #GESGroup present in the Timeline.
+ *
+ * Returns: (transfer none) (element-type GESGroup): the list of
+ * #GESGroup that contain clips present in the timeline's layers.
+ * Must not be changed.
+ */
+GList *
+ges_timeline_get_groups (GESTimeline * timeline)
+{
+ return timeline->priv->groups;
+}
+
+/**
* ges_timeline_append_layer:
* @timeline: a #GESTimeline
*
GstPad * ges_timeline_get_pad_for_track (GESTimeline * timeline, GESTrack *track);
GList *ges_timeline_get_tracks (GESTimeline *timeline);
+GList* ges_timeline_get_groups (GESTimeline * timeline);
+
gboolean ges_timeline_commit (GESTimeline * timeline);
gboolean ges_timeline_commit_sync (GESTimeline * timeline);
GList *seen_groups = NULL;
g_string_append (str, " <groups>\n");
- for (tmp = timeline_get_groups (timeline); tmp; tmp = tmp->next) {
+ for (tmp = ges_timeline_get_groups (timeline); tmp; tmp = tmp->next) {
_save_group (self, str, &seen_groups, tmp->data);
}
g_string_append (str, " </groups>\n");
--- /dev/null
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2016 Alexandru Băluț <alexandru.balut@gmail.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+from gi.repository import GES
+from gi.repository import GLib
+import tempfile
+
+
+def create_main_loop():
+ """Creates a MainLoop with a timeout."""
+ mainloop = GLib.MainLoop()
+ timed_out = False
+
+ def quit_cb(unused):
+ nonlocal timed_out
+ timed_out = True
+ mainloop.quit()
+
+ def run(timeout_seconds=5):
+ source = GLib.timeout_source_new_seconds(timeout_seconds)
+ source.set_callback(quit_cb)
+ source.attach()
+ GLib.MainLoop.run(mainloop)
+ source.destroy()
+ if timed_out:
+ raise Exception("Timed out after %s seconds" % timeout_seconds)
+
+ mainloop.run = run
+ return mainloop
+
+def create_project(with_group=False, saved=False):
+ """Creates a project with two clips in a group."""
+ project = GES.Project()
+ timeline = project.extract()
+ layer = timeline.append_layer()
+
+ if with_group:
+ clip1 = GES.TitleClip()
+ clip1.set_start(0)
+ clip1.set_duration(10)
+ layer.add_clip(clip1)
+ clip2 = GES.TitleClip()
+ clip2.set_start(100)
+ clip2.set_duration(10)
+ layer.add_clip(clip2)
+ group = GES.Container.group([clip1, clip2])
+
+ if saved:
+ uri = "file://%s" % tempfile.NamedTemporaryFile(suffix=".xges").name
+ project.save(timeline, uri, None, overwrite=True)
+
+ return timeline
+
import unittest # noqa
from unittest import mock
+import common
+
Gst.init(None)
GES.init()
child_removed_cb.reset_mock()
group.ungroup(recursive=False)
child_removed_cb.assert_called_once_with(group, clip1)
+
+ def test_loaded_project_has_groups(self):
+ mainloop = common.create_main_loop()
+ timeline = common.create_project(with_group=True, saved=True)
+ layer, = timeline.get_layers()
+ group, = timeline.get_groups()
+ self.assertEqual(len(layer.get_clips()), 2)
+ for clip in layer.get_clips():
+ self.assertEqual(clip.get_parent(), group)
+
+ # Reload the project, check the group.
+ project = GES.Project.new(uri=timeline.get_asset().props.uri)
+
+ loaded_called = False
+ def loaded(unused_project, unused_timeline):
+ nonlocal loaded_called
+ loaded_called = True
+ mainloop.quit()
+ project.connect("loaded", loaded)
+
+ timeline = project.extract()
+
+ mainloop.run()
+ self.assertTrue(loaded_called)
+
+ layer, = timeline.get_layers()
+ group, = timeline.get_groups()
+ self.assertEqual(len(layer.get_clips()), 2)
+ for clip in layer.get_clips():
+ self.assertEqual(clip.get_parent(), group)
--- /dev/null
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2016 Alexandru Băluț <alexandru.balut@gmail.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+import gi
+
+gi.require_version("Gst", "1.0")
+gi.require_version("GES", "1.0")
+
+from gi.repository import Gst # noqa
+from gi.repository import GES # noqa
+import unittest # noqa
+from unittest import mock
+
+import common
+
+Gst.init(None)
+GES.init()
+
+
+class TestTimeline(unittest.TestCase):
+
+ def test_signals_not_emitted_when_loading(self):
+ mainloop = common.create_main_loop()
+ timeline = common.create_project(with_group=True, saved=True)
+
+ # Reload the project, check the group.
+ project = GES.Project.new(uri=timeline.get_asset().props.uri)
+
+ loaded_called = False
+ def loaded(unused_project, unused_timeline):
+ nonlocal loaded_called
+ loaded_called = True
+ mainloop.quit()
+ project.connect("loaded", loaded)
+
+ timeline = project.extract()
+
+ signals = ["layer-added", "group-added", "track-added"]
+ called = []
+ handle = mock.Mock()
+ for signal in signals:
+ timeline.connect(signal, handle)
+
+ mainloop.run()
+ self.assertTrue(loaded_called)
+ handle.assert_not_called()