1 /* GStreamer Editing Services
2  *
3  * Copyright (C) <2012> Thibault Saunier <thibault.saunier@collabora.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20 
21 #include "test-utils.h"
22 #include <ges/ges.h>
23 #include <gst/check/gstcheck.h>
24 #include <gst/controller/gstdirectcontrolbinding.h>
25 #include <gst/controller/gstinterpolationcontrolsource.h>
26 
27 GMainLoop *mainloop;
28 
29 static void
project_loaded_cb(GESProject * project,GESTimeline * timeline,GMainLoop * mainloop)30 project_loaded_cb (GESProject * project, GESTimeline * timeline,
31     GMainLoop * mainloop)
32 {
33   g_main_loop_quit (mainloop);
34 }
35 
GST_START_TEST(test_project_simple)36 GST_START_TEST (test_project_simple)
37 {
38   gchar *id;
39   GESProject *project;
40   GESTimeline *timeline;
41 
42   ges_init ();
43 
44   mainloop = g_main_loop_new (NULL, FALSE);
45   project = GES_PROJECT (ges_asset_request (GES_TYPE_TIMELINE, NULL, NULL));
46   fail_unless (GES_IS_PROJECT (project));
47   assert_equals_string (ges_asset_get_id (GES_ASSET (project)), "project-0");
48   g_signal_connect (project, "loaded", (GCallback) project_loaded_cb, mainloop);
49 
50   timeline = GES_TIMELINE (ges_asset_extract (GES_ASSET (project), NULL));
51   g_main_loop_run (mainloop);
52 
53   fail_unless (GES_IS_TIMELINE (timeline));
54   id = ges_extractable_get_id (GES_EXTRACTABLE (timeline));
55   assert_equals_string (id, "project-0");
56   ASSERT_OBJECT_REFCOUNT (timeline, "We own the only ref", 1);
57 
58   g_free (id);
59   gst_object_unref (project);
60   gst_object_unref (timeline);
61   g_main_loop_unref (mainloop);
62   g_signal_handlers_disconnect_by_func (project, (GCallback) project_loaded_cb,
63       mainloop);
64 
65   ges_deinit ();
66 }
67 
68 GST_END_TEST;
69 
70 static void
asset_removed_add_cb(GESProject * project,GESAsset * asset,gboolean * called)71 asset_removed_add_cb (GESProject * project, GESAsset * asset, gboolean * called)
72 {
73   *called = TRUE;
74 }
75 
76 static void
asset_created_cb(GObject * source,GAsyncResult * res,GESAsset ** asset)77 asset_created_cb (GObject * source, GAsyncResult * res, GESAsset ** asset)
78 {
79   GError *error = NULL;
80   *asset = ges_asset_request_finish (res, &error);
81 
82   fail_unless (error == NULL);
83   g_main_loop_quit (mainloop);
84 }
85 
GST_START_TEST(test_project_add_assets)86 GST_START_TEST (test_project_add_assets)
87 {
88   GESProject *project;
89   GESAsset *asset;
90   gboolean added_cb_called = FALSE;
91   gboolean removed_cb_called = FALSE;
92 
93   ges_init ();
94 
95   mainloop = g_main_loop_new (NULL, FALSE);
96   project = GES_PROJECT (ges_asset_request (GES_TYPE_TIMELINE, NULL, NULL));
97   fail_unless (GES_IS_PROJECT (project));
98 
99   g_signal_connect (project, "asset-added",
100       (GCallback) asset_removed_add_cb, &added_cb_called);
101   g_signal_connect (project, "asset-removed",
102       (GCallback) asset_removed_add_cb, &removed_cb_called);
103 
104   ges_asset_request_async (GES_TYPE_TEST_CLIP, NULL, NULL,
105       (GAsyncReadyCallback) asset_created_cb, &asset);
106   g_main_loop_run (mainloop);
107   g_main_loop_unref (mainloop);
108 
109   fail_unless (GES_IS_ASSET (asset));
110 
111   fail_unless (ges_project_add_asset (project, asset));
112   fail_unless (added_cb_called);
113   ASSERT_OBJECT_REFCOUNT (project, "The project", 2);
114   ASSERT_OBJECT_REFCOUNT (asset, "The asset (1 for project and one for "
115       "us + 1 cache)", 3);
116 
117   fail_unless (ges_project_remove_asset (project, asset));
118   fail_unless (removed_cb_called);
119 
120   g_signal_handlers_disconnect_by_func (project,
121       (GCallback) asset_removed_add_cb, &added_cb_called);
122   g_signal_handlers_disconnect_by_func (project,
123       (GCallback) asset_removed_add_cb, &removed_cb_called);
124 
125   gst_object_unref (asset);
126   gst_object_unref (project);
127   ASSERT_OBJECT_REFCOUNT (asset, "The asset (1 ref in cache)", 1);
128   ASSERT_OBJECT_REFCOUNT (project, "The project (1 ref in cache)", 1);
129 
130   ges_deinit ();
131 }
132 
133 GST_END_TEST;
134 
135 static void
error_loading_asset_cb(GESProject * project,GError * error,gchar * id,GType extractable_type,GMainLoop * mainloop)136 error_loading_asset_cb (GESProject * project, GError * error, gchar * id,
137     GType extractable_type, GMainLoop * mainloop)
138 {
139   fail_unless (g_error_matches (error, GST_PARSE_ERROR,
140           GST_PARSE_ERROR_NO_SUCH_ELEMENT));
141   g_main_loop_quit (mainloop);
142 }
143 
GST_START_TEST(test_project_unexistant_effect)144 GST_START_TEST (test_project_unexistant_effect)
145 {
146   GESProject *project;
147   gboolean added_cb_called = FALSE;
148   gboolean removed_cb_called = FALSE;
149 
150   ges_init ();
151 
152   project = GES_PROJECT (ges_asset_request (GES_TYPE_TIMELINE, NULL, NULL));
153   fail_unless (GES_IS_PROJECT (project));
154 
155   mainloop = g_main_loop_new (NULL, FALSE);
156   g_signal_connect (project, "asset-added",
157       (GCallback) asset_removed_add_cb, &added_cb_called);
158   g_signal_connect (project, "asset-removed",
159       (GCallback) asset_removed_add_cb, &removed_cb_called);
160   g_signal_connect (project, "error-loading-asset",
161       (GCallback) error_loading_asset_cb, mainloop);
162 
163   fail_unless (ges_project_create_asset (project, "nowaythiselementexists",
164           GES_TYPE_EFFECT));
165   g_main_loop_run (mainloop);
166 
167   /* And.... try again! */
168   fail_if (ges_project_create_asset (project, "nowaythiselementexists",
169           GES_TYPE_EFFECT));
170 
171   fail_if (added_cb_called);
172   fail_if (removed_cb_called);
173 
174   ASSERT_OBJECT_REFCOUNT (project, "The project", 2);
175   gst_object_unref (project);
176   g_main_loop_unref (mainloop);
177 
178   ASSERT_OBJECT_REFCOUNT (project, "The project (1 ref in cache)", 1);
179 
180   ges_deinit ();
181 }
182 
183 GST_END_TEST;
184 
185 static void
asset_added_cb(GESProject * project,GESAsset * asset)186 asset_added_cb (GESProject * project, GESAsset * asset)
187 {
188   gchar *uri = ges_test_file_uri ("audio_video.ogg");
189   GstDiscovererInfo *info;
190 
191   if (ges_asset_get_extractable_type (asset) == GES_TYPE_EFFECT) {
192     assert_equals_string (ges_asset_get_id (asset), "video agingtv");
193   } else {
194     info = ges_uri_clip_asset_get_info (GES_URI_CLIP_ASSET (asset));
195     fail_unless (GST_IS_DISCOVERER_INFO (info));
196     assert_equals_string (ges_asset_get_id (asset), uri);
197   }
198 
199   g_free (uri);
200 }
201 
202 static gchar *
_set_new_uri(GESProject * project,GError * error,GESAsset * wrong_asset)203 _set_new_uri (GESProject * project, GError * error, GESAsset * wrong_asset)
204 {
205   fail_unless (!g_strcmp0 (ges_asset_get_id (wrong_asset),
206           "file:///test/not/exisiting"));
207 
208   return ges_test_file_uri ("audio_video.ogg");
209 }
210 
211 static void
_test_project(GESProject * project,GESTimeline * timeline)212 _test_project (GESProject * project, GESTimeline * timeline)
213 {
214   guint a_meta;
215   gchar *media_uri;
216   GESTrack *track;
217   const GList *profiles;
218   GstEncodingContainerProfile *profile;
219   GList *tracks, *tmp, *tmptrackelement, *clips;
220 
221   fail_unless (GES_IS_TIMELINE (timeline));
222   assert_equals_int (g_list_length (timeline->layers), 2);
223 
224   assert_equals_string (ges_meta_container_get_string (GES_META_CONTAINER
225           (project), "name"), "Example project");
226   clips = ges_layer_get_clips (GES_LAYER (timeline->layers->data));
227   fail_unless (ges_meta_container_get_uint (GES_META_CONTAINER
228           (timeline->layers->data), "a", &a_meta));
229   assert_equals_int (a_meta, 3);
230   assert_equals_int (g_list_length (clips), 1);
231   media_uri = ges_test_file_uri ("audio_video.ogg");
232   assert_equals_string (ges_asset_get_id (ges_extractable_get_asset
233           (GES_EXTRACTABLE (clips->data))), media_uri);
234   g_free (media_uri);
235   g_list_free_full (clips, gst_object_unref);
236 
237   /* Check tracks and the objects  they contain */
238   tracks = ges_timeline_get_tracks (timeline);
239   assert_equals_int (g_list_length (tracks), 2);
240   for (tmp = tracks; tmp; tmp = tmp->next) {
241     GList *trackelements;
242     track = GES_TRACK (tmp->data);
243 
244     trackelements = ges_track_get_elements (track);
245     GST_DEBUG_OBJECT (track, "Testing track");
246     switch (track->type) {
247       case GES_TRACK_TYPE_VIDEO:
248         assert_equals_int (g_list_length (trackelements), 2);
249         for (tmptrackelement = trackelements; tmptrackelement;
250             tmptrackelement = tmptrackelement->next) {
251           GESTrackElement *trackelement =
252               GES_TRACK_ELEMENT (tmptrackelement->data);
253 
254           if (GES_IS_BASE_EFFECT (trackelement)) {
255             guint nb_scratch_lines;
256 
257             ges_timeline_element_get_child_properties (tmptrackelement->data,
258                 "scratch-lines", &nb_scratch_lines, NULL);
259             assert_equals_int (nb_scratch_lines, 12);
260 
261             nle_object_check (ges_track_element_get_nleobject (trackelement),
262                 0, 1000000000, 0, 1000000000, MIN_NLE_PRIO + TRANSITIONS_HEIGHT,
263                 TRUE);
264           } else {
265             nle_object_check (ges_track_element_get_nleobject (trackelement),
266                 0, 1000000000, 0, 1000000000,
267                 MIN_NLE_PRIO + TRANSITIONS_HEIGHT + 1, TRUE);
268           }
269         }
270         break;
271       case GES_TRACK_TYPE_AUDIO:
272         assert_equals_int (g_list_length (trackelements), 2);
273         break;
274       default:
275         g_assert (1);
276     }
277 
278     g_list_free_full (trackelements, gst_object_unref);
279 
280   }
281   g_list_free_full (tracks, gst_object_unref);
282 
283   /* Now test the encoding profile */
284   profiles = ges_project_list_encoding_profiles (project);
285   assert_equals_int (g_list_length ((GList *) profiles), 1);
286   profile = profiles->data;
287   fail_unless (GST_IS_ENCODING_CONTAINER_PROFILE (profile));
288   profiles = gst_encoding_container_profile_get_profiles (profile);
289   assert_equals_int (g_list_length ((GList *) profiles), 2);
290 }
291 
292 static void
_add_properties(GESTimeline * timeline)293 _add_properties (GESTimeline * timeline)
294 {
295   GList *tracks;
296   GList *tmp;
297 
298   tracks = ges_timeline_get_tracks (timeline);
299   for (tmp = tracks; tmp; tmp = tmp->next) {
300     GESTrack *track;
301     GList *track_elements;
302     GList *tmp_tck;
303 
304     track = GES_TRACK (tmp->data);
305     switch (track->type) {
306       case GES_TRACK_TYPE_VIDEO:
307         track_elements = ges_track_get_elements (track);
308 
309         for (tmp_tck = track_elements; tmp_tck; tmp_tck = tmp_tck->next) {
310           GESTrackElement *element = GES_TRACK_ELEMENT (tmp_tck->data);
311 
312           /* Adding keyframes */
313           if (GES_IS_EFFECT (element)) {
314             GstControlSource *source;
315             GstControlBinding *tmp_binding, *binding;
316 
317             source = gst_interpolation_control_source_new ();
318 
319             /* Check binding creation and replacement */
320             binding =
321                 ges_track_element_get_control_binding (element,
322                 "scratch-lines");
323             fail_unless (binding == NULL);
324             ges_track_element_set_control_source (element,
325                 source, "scratch-lines", "direct");
326             tmp_binding =
327                 ges_track_element_get_control_binding (element,
328                 "scratch-lines");
329             fail_unless (tmp_binding != NULL);
330             ges_track_element_set_control_source (element,
331                 source, "scratch-lines", "direct");
332             binding =
333                 ges_track_element_get_control_binding (element,
334                 "scratch-lines");
335             fail_unless (binding != tmp_binding);
336 
337 
338             g_object_set (source, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);
339             gst_timed_value_control_source_set (GST_TIMED_VALUE_CONTROL_SOURCE
340                 (source), 0 * GST_SECOND, 0.);
341             gst_timed_value_control_source_set (GST_TIMED_VALUE_CONTROL_SOURCE
342                 (source), 5 * GST_SECOND, 0.);
343             gst_timed_value_control_source_set (GST_TIMED_VALUE_CONTROL_SOURCE
344                 (source), 10 * GST_SECOND, 1.);
345           } else if (GES_IS_VIDEO_SOURCE (element)) {
346             /* Adding children properties */
347             gint64 posx = 42;
348             ges_timeline_element_set_child_properties (GES_TIMELINE_ELEMENT
349                 (element), "posx", posx, NULL);
350             ges_timeline_element_get_child_properties (GES_TIMELINE_ELEMENT
351                 (element), "posx", &posx, NULL);
352             fail_unless_equals_int64 (posx, 42);
353           }
354 
355         }
356         g_list_free_full (track_elements, g_object_unref);
357         break;
358       default:
359         break;
360     }
361   }
362 
363   g_list_free_full (tracks, g_object_unref);
364 }
365 
366 static void
_check_properties(GESTimeline * timeline)367 _check_properties (GESTimeline * timeline)
368 {
369   GList *tracks;
370   GList *tmp;
371 
372   tracks = ges_timeline_get_tracks (timeline);
373   for (tmp = tracks; tmp; tmp = tmp->next) {
374     GESTrack *track;
375     GList *track_elements;
376     GList *tmp_tck;
377 
378     track = GES_TRACK (tmp->data);
379     switch (track->type) {
380       case GES_TRACK_TYPE_VIDEO:
381         track_elements = ges_track_get_elements (track);
382 
383         for (tmp_tck = track_elements; tmp_tck; tmp_tck = tmp_tck->next) {
384           GESTrackElement *element = GES_TRACK_ELEMENT (tmp_tck->data);
385           /* Checking keyframes */
386           if (GES_IS_EFFECT (element)) {
387             GstControlBinding *binding;
388             GstControlSource *source;
389             GList *timed_values;
390             GstTimedValue *value;
391 
392             binding =
393                 ges_track_element_get_control_binding (element,
394                 "scratch-lines");
395             fail_unless (binding != NULL);
396             g_object_get (binding, "control-source", &source, NULL);
397             fail_unless (source != NULL);
398 
399             /* Now check keyframe position */
400             timed_values =
401                 gst_timed_value_control_source_get_all
402                 (GST_TIMED_VALUE_CONTROL_SOURCE (source));
403             value = timed_values->data;
404             fail_unless (value->value == 0.);
405             fail_unless (value->timestamp == 0 * GST_SECOND);
406             timed_values = timed_values->next;
407             value = timed_values->data;
408             fail_unless (value->value == 0.);
409             fail_unless (value->timestamp == 5 * GST_SECOND);
410             timed_values = timed_values->next;
411             value = timed_values->data;
412             fail_unless (value->value == 1.);
413             fail_unless (value->timestamp == 10 * GST_SECOND);
414           }
415           /* Checking children properties */
416           else if (GES_IS_VIDEO_SOURCE (element)) {
417             /* Init 'posx' with a wrong value */
418             gint64 posx = 27;
419             ges_timeline_element_get_child_properties (GES_TIMELINE_ELEMENT
420                 (element), "posx", &posx, NULL);
421             fail_unless_equals_int64 (posx, 42);
422           }
423         }
424         g_list_free_full (track_elements, g_object_unref);
425         break;
426       default:
427         break;
428     }
429   }
430 
431   g_list_free_full (tracks, g_object_unref);
432 }
433 
GST_START_TEST(test_project_add_properties)434 GST_START_TEST (test_project_add_properties)
435 {
436   GESProject *project;
437   GESTimeline *timeline;
438   gchar *uri;
439 
440   ges_init ();
441 
442   uri = ges_test_file_uri ("test-properties.xges");
443   project = ges_project_new (uri);
444   g_free (uri);
445   mainloop = g_main_loop_new (NULL, FALSE);
446 
447   /* Connect the signals */
448   g_signal_connect (project, "loaded", (GCallback) project_loaded_cb, mainloop);
449   g_signal_connect (project, "missing-uri", (GCallback) _set_new_uri, NULL);
450 
451   /* Now extract a timeline from it */
452   GST_LOG ("Loading project");
453   timeline = GES_TIMELINE (ges_asset_extract (GES_ASSET (project), NULL));
454 
455   g_main_loop_run (mainloop);
456 
457   GST_LOG ("Test first loading");
458 
459 
460   _add_properties (timeline);
461 
462   uri = ges_test_get_tmp_uri ("test-properties-save.xges");
463   fail_unless (ges_project_save (project, timeline, uri, NULL, TRUE, NULL));
464   gst_object_unref (timeline);
465   gst_object_unref (project);
466 
467   project = ges_project_new (uri);
468   g_free (uri);
469 
470   ASSERT_OBJECT_REFCOUNT (project, "Our + cache", 2);
471 
472   g_signal_connect (project, "loaded", (GCallback) project_loaded_cb, mainloop);
473 
474   GST_LOG ("Loading saved project");
475   timeline = GES_TIMELINE (ges_asset_extract (GES_ASSET (project), NULL));
476   fail_unless (GES_IS_TIMELINE (timeline));
477 
478   g_main_loop_run (mainloop);
479 
480   _check_properties (timeline);
481 
482   gst_object_unref (timeline);
483   gst_object_unref (project);
484 
485   g_main_loop_unref (mainloop);
486   g_signal_handlers_disconnect_by_func (project, (GCallback) project_loaded_cb,
487       mainloop);
488   g_signal_handlers_disconnect_by_func (project, (GCallback) asset_added_cb,
489       NULL);
490 
491   ges_deinit ();
492 }
493 
494 GST_END_TEST;
495 
GST_START_TEST(test_project_load_xges)496 GST_START_TEST (test_project_load_xges)
497 {
498   gboolean saved;
499   GESProject *loaded_project, *saved_project;
500   GESTimeline *timeline;
501   GESAsset *formatter_asset;
502   gchar *uri;
503   GList *tmp;
504 
505   ges_init ();
506 
507   uri = ges_test_file_uri ("test-project.xges");
508   loaded_project = ges_project_new (uri);
509   mainloop = g_main_loop_new (NULL, FALSE);
510   fail_unless (GES_IS_PROJECT (loaded_project));
511 
512   /* Connect the signals */
513   g_signal_connect (loaded_project, "asset-added", (GCallback) asset_added_cb,
514       NULL);
515   g_signal_connect (loaded_project, "loaded", (GCallback) project_loaded_cb,
516       mainloop);
517 
518   /* Make sure we update the project's dummy URL to some actual URL */
519   g_signal_connect (loaded_project, "missing-uri", (GCallback) _set_new_uri,
520       NULL);
521 
522   /* Now extract a timeline from it */
523   GST_LOG ("Loading project");
524   timeline =
525       GES_TIMELINE (ges_asset_extract (GES_ASSET (loaded_project), NULL));
526   fail_unless (GES_IS_TIMELINE (timeline));
527   tmp = ges_project_get_loading_assets (loaded_project);
528   assert_equals_int (g_list_length (tmp), 1);
529   g_list_free_full (tmp, g_object_unref);
530 
531   g_main_loop_run (mainloop);
532   GST_LOG ("Test first loading");
533   _test_project (loaded_project, timeline);
534   g_free (uri);
535 
536   uri = ges_test_get_tmp_uri ("test-project_TMP.xges");
537   formatter_asset = ges_asset_request (GES_TYPE_FORMATTER, "ges", NULL);
538   saved =
539       ges_project_save (loaded_project, timeline, uri, formatter_asset, TRUE,
540       NULL);
541   fail_unless (saved);
542   gst_object_unref (timeline);
543 
544   saved_project = ges_project_new (uri);
545   ASSERT_OBJECT_REFCOUNT (saved_project, "Our + cache", 2);
546   g_signal_connect (saved_project, "asset-added", (GCallback) asset_added_cb,
547       NULL);
548   g_signal_connect (saved_project, "loaded", (GCallback) project_loaded_cb,
549       mainloop);
550 
551   GST_LOG ("Loading saved project");
552   timeline = GES_TIMELINE (ges_asset_extract (GES_ASSET (saved_project), NULL));
553   fail_unless (GES_IS_TIMELINE (timeline));
554   g_main_loop_run (mainloop);
555   _test_project (saved_project, timeline);
556 
557   fail_unless (ges_meta_container_get_string (GES_META_CONTAINER
558           (loaded_project), GES_META_FORMAT_VERSION));
559   fail_unless_equals_string (ges_meta_container_get_string (GES_META_CONTAINER
560           (loaded_project), GES_META_FORMAT_VERSION),
561       ges_meta_container_get_string (GES_META_CONTAINER (loaded_project),
562           GES_META_FORMAT_VERSION));
563   gst_object_unref (timeline);
564   gst_object_unref (saved_project);
565   gst_object_unref (loaded_project);
566   g_free (uri);
567 
568   ASSERT_OBJECT_REFCOUNT (saved_project, "Still 1 ref for asset cache", 1);
569 
570   g_main_loop_unref (mainloop);
571   g_signal_handlers_disconnect_by_func (saved_project,
572       (GCallback) project_loaded_cb, mainloop);
573   g_signal_handlers_disconnect_by_func (saved_project,
574       (GCallback) asset_added_cb, NULL);
575 
576   ges_deinit ();
577 }
578 
579 GST_END_TEST;
580 
GST_START_TEST(test_project_auto_transition)581 GST_START_TEST (test_project_auto_transition)
582 {
583   GList *layers, *tmp;
584   GESProject *project;
585   GESTimeline *timeline;
586   GESLayer *layer = NULL;
587   GESAsset *formatter_asset;
588   gboolean saved;
589   gchar *tmpuri, *uri;
590 
591   ges_init ();
592 
593   uri = ges_test_file_uri ("test-auto-transition.xges");
594   project = ges_project_new (uri);
595   mainloop = g_main_loop_new (NULL, FALSE);
596   fail_unless (GES_IS_PROJECT (project));
597 
598   /* Connect the signals */
599   g_signal_connect (project, "loaded", (GCallback) project_loaded_cb, mainloop);
600   g_signal_connect (project, "missing-uri", (GCallback) _set_new_uri, NULL);
601 
602   /* Now extract a timeline from it */
603   GST_LOG ("Loading project");
604   timeline = GES_TIMELINE (ges_asset_extract (GES_ASSET (project), NULL));
605 
606   g_main_loop_run (mainloop);
607 
608   /* Check timeline and layers auto-transition, must be FALSE */
609   fail_if (ges_timeline_get_auto_transition (timeline));
610   layers = ges_timeline_get_layers (timeline);
611   for (tmp = layers; tmp; tmp = tmp->next) {
612     layer = tmp->data;
613     fail_if (ges_layer_get_auto_transition (layer));
614   }
615 
616   g_list_free_full (layers, gst_object_unref);
617   g_free (uri);
618 
619   /* Set timeline and layers auto-transition to TRUE */
620   ges_timeline_set_auto_transition (timeline, TRUE);
621 
622   tmpuri = ges_test_get_tmp_uri ("test-auto-transition-save.xges");
623   formatter_asset = ges_asset_request (GES_TYPE_FORMATTER, "ges", NULL);
624   saved =
625       ges_project_save (project, timeline, tmpuri, formatter_asset, TRUE, NULL);
626   fail_unless (saved);
627 
628   gst_object_unref (timeline);
629   gst_object_unref (project);
630 
631   project = ges_project_new (tmpuri);
632 
633   ASSERT_OBJECT_REFCOUNT (project, "Our + cache", 2);
634 
635   g_signal_connect (project, "loaded", (GCallback) project_loaded_cb, mainloop);
636 
637   GST_LOG ("Loading saved project");
638   timeline = GES_TIMELINE (ges_asset_extract (GES_ASSET (project), NULL));
639   fail_unless (GES_IS_TIMELINE (timeline));
640 
641   g_main_loop_run (mainloop);
642 
643   /* Check timeline and layers auto-transition, must be TRUE  */
644   fail_unless (ges_timeline_get_auto_transition (timeline));
645   layers = ges_timeline_get_layers (timeline);
646   for (tmp = layers; tmp; tmp = tmp->next) {
647     layer = tmp->data;
648     fail_unless (ges_layer_get_auto_transition (layer));
649   }
650 
651   g_list_free_full (layers, gst_object_unref);
652   gst_object_unref (timeline);
653   gst_object_unref (project);
654   g_free (tmpuri);
655 
656   g_main_loop_unref (mainloop);
657   g_signal_handlers_disconnect_by_func (project, (GCallback) project_loaded_cb,
658       mainloop);
659   g_signal_handlers_disconnect_by_func (project, (GCallback) asset_added_cb,
660       NULL);
661 
662   ges_deinit ();
663 }
664 
665 GST_END_TEST;
666 
667 /*  FIXME This test does not pass for some bad reason */
668 #if 0
669 static void
670 project_loaded_now_play_cb (GESProject * project, GESTimeline * timeline)
671 {
672   GstBus *bus;
673   GstMessage *message;
674   gboolean carry_on = TRUE;
675 
676   GESPipeline *pipeline = ges_pipeline_new ();
677 
678   fail_unless (ges_pipeline_set_timeline (pipeline, timeline));
679 
680   bus = gst_element_get_bus (GST_ELEMENT (pipeline));
681   fail_if (gst_element_set_state (GST_ELEMENT (pipeline),
682           GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE);
683 
684   GST_DEBUG ("Let's poll the bus");
685 
686   while (carry_on) {
687     message = gst_bus_poll (bus, GST_MESSAGE_ANY, GST_SECOND / 10);
688     if (message) {
689       GST_ERROR ("GOT MESSAGE: %" GST_PTR_FORMAT, message);
690       switch (GST_MESSAGE_TYPE (message)) {
691         case GST_MESSAGE_EOS:
692           /* we should check if we really finished here */
693           GST_WARNING ("Got an EOS, we did not even start!");
694           carry_on = FALSE;
695           fail_if (TRUE);
696           break;
697         case GST_MESSAGE_SEGMENT_START:
698         case GST_MESSAGE_SEGMENT_DONE:
699           /* We shouldn't see any segement messages, since we didn't do a segment seek */
700           GST_WARNING ("Saw a Segment start/stop");
701           fail_if (TRUE);
702           break;
703         case GST_MESSAGE_ERROR:
704           fail_error_message (message);
705           break;
706         case GST_MESSAGE_ASYNC_DONE:
707           GST_DEBUG ("prerolling done");
708           carry_on = FALSE;
709           break;
710         default:
711           break;
712       }
713       gst_mini_object_unref (GST_MINI_OBJECT (message));
714     }
715   }
716 
717   fail_if (gst_element_set_state (GST_ELEMENT (pipeline),
718           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
719   gst_object_unref (pipeline);
720   g_main_loop_quit (mainloop);
721 }
722 
723 
724 GST_START_TEST (test_load_xges_and_play)
725 {
726   GESProject *project;
727   GESTimeline *timeline;
728   gchar *uri = ges_test_file_uri ("test-project_TMP.xges");
729 
730   project = ges_project_new (uri);
731   fail_unless (GES_IS_PROJECT (project));
732 
733   mainloop = g_main_loop_new (NULL, FALSE);
734   /* Connect the signals */
735   g_signal_connect (project, "loaded", (GCallback) project_loaded_now_play_cb,
736       NULL);
737 
738   /* Now extract a timeline from it */
739   timeline = GES_TIMELINE (ges_asset_extract (GES_ASSET (project), NULL));
740   fail_unless (GES_IS_TIMELINE (timeline));
741 
742   g_main_loop_run (mainloop);
743 
744   g_free (uri);
745   gst_object_unref (project);
746   gst_object_unref (timeline);
747   g_main_loop_unref (mainloop);
748 }
749 
750 GST_END_TEST;
751 #endif
752 
753 static Suite *
ges_suite(void)754 ges_suite (void)
755 {
756   Suite *s = suite_create ("ges-project");
757   TCase *tc_chain = tcase_create ("project");
758 
759   suite_add_tcase (s, tc_chain);
760 
761   tcase_add_test (tc_chain, test_project_simple);
762   tcase_add_test (tc_chain, test_project_add_assets);
763   tcase_add_test (tc_chain, test_project_load_xges);
764   tcase_add_test (tc_chain, test_project_add_properties);
765   tcase_add_test (tc_chain, test_project_auto_transition);
766   /*tcase_add_test (tc_chain, test_load_xges_and_play); */
767   tcase_add_test (tc_chain, test_project_unexistant_effect);
768 
769   return s;
770 }
771 
772 GST_CHECK_MAIN (ges);
773