Merge branch '0.10'
[platform/upstream/gstreamer.git] / tests / check / ges / save_and_load.c
1 /* GStreamer Editing Services
2  * Copyright (C) 2010 Brandon Lewis <brandon.lewis@collabora.co.uk>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include <ges/ges.h>
21 #include <gst/check/gstcheck.h>
22 #include <string.h>
23 #include <unistd.h>
24 #define GetCurrentDir getcwd
25
26 #include <gst/audio/audio.h>
27
28 #define KEY_FILE_START {\
29   if (cmp) g_key_file_free (cmp);\
30   cmp = g_key_file_new ();\
31 }
32
33 #define KEY(group, key, value) \
34   g_key_file_set_value (cmp, group, key, value)
35
36 #define COMPARE fail_unless(compare (cmp, formatter, timeline))
37
38 static gboolean
39 compare (GKeyFile * cmp, GESFormatter * formatter, GESTimeline * timeline)
40 {
41   gchar *data, *fmt_data;
42   gsize length;
43   gboolean result = TRUE;
44
45   data = g_key_file_to_data (cmp, &length, NULL);
46   ges_formatter_save (formatter, timeline);
47   fmt_data = ges_formatter_get_data (formatter, &length);
48
49   if (!(g_strcmp0 (data, fmt_data) == 0)) {
50     GST_ERROR ("difference between expected and output");
51     GST_ERROR ("expected: \n%s", data);
52     GST_ERROR ("actual: \n%s", fmt_data);
53     result = FALSE;
54   }
55   g_free (data);
56   return result;
57 }
58
59 GST_START_TEST (test_keyfile_save)
60 {
61   GESTimeline *timeline;
62   GESTimelineLayer *layer, *layer2;
63   GESTrack *track;
64   GESTimelineObject *source;
65   GESFormatter *formatter;
66   GKeyFile *cmp = NULL;
67
68   ges_init ();
69
70   /* setup timeline */
71
72   GST_DEBUG ("Create a timeline");
73   timeline = ges_timeline_new ();
74   fail_unless (timeline != NULL);
75
76   /* create serialization object */
77
78   GST_DEBUG ("creating a keyfile formatter");
79   formatter = GES_FORMATTER (ges_keyfile_formatter_new ());
80
81   /* add a layer and make sure it's serialized */
82
83   GST_DEBUG ("Create a layer");
84   layer = GES_TIMELINE_LAYER (ges_simple_timeline_layer_new ());
85   fail_unless (layer != NULL);
86
87   GST_DEBUG ("Add the layer to the timeline");
88   fail_unless (ges_timeline_add_layer (timeline, layer));
89
90   KEY_FILE_START;
91   KEY ("General", "version", "1");
92   KEY ("Layer0", "priority", "0");
93   KEY ("Layer0", "type", "simple");
94   COMPARE;
95
96   /* add a track and make sure it's serialized */
97
98   GST_DEBUG ("Create a Track");
99   track = ges_track_audio_raw_new ();
100   fail_unless (track != NULL);
101
102   GST_DEBUG ("Add the track to the timeline");
103   fail_unless (ges_timeline_add_track (timeline, track));
104
105   KEY_FILE_START;
106   KEY ("General", "version", "1");
107   KEY ("Track0", "type", "GES_TRACK_TYPE_AUDIO");
108   KEY ("Track0", "caps", "audio/x-raw");
109   KEY ("Layer0", "priority", "0");
110   KEY ("Layer0", "type", "simple");
111   COMPARE;
112
113   /* add sources */
114
115   GST_DEBUG ("Adding first source");
116   source = (GESTimelineObject *) ges_timeline_test_source_new ();
117   ges_simple_timeline_layer_add_object (GES_SIMPLE_TIMELINE_LAYER (layer),
118       source, -1);
119   g_object_set (G_OBJECT (source), "duration", (guint64) 2 * GST_SECOND, NULL);
120
121   KEY ("Object0", "type", "GESTimelineTestSource");
122   KEY ("Object0", "start", "0");
123   KEY ("Object0", "in-point", "0");
124   KEY ("Object0", "duration", "2000000000");
125   KEY ("Object0", "priority", "2");
126   KEY ("Object0", "supported-formats", "GES_TRACK_TYPE_UNKNOWN");
127   KEY ("Object0", "max-duration", "18446744073709551615");
128   KEY ("Object0", "mute", "false");
129   KEY ("Object0", "vpattern", "100% Black");
130   KEY ("Object0", "freq", "440");
131   KEY ("Object0", "volume", "0");
132   COMPARE;
133
134   GST_DEBUG ("Adding transition");
135   source = (GESTimelineObject *)
136       ges_timeline_standard_transition_new_for_nick ((gchar *) "bar-wipe-lr");
137
138   g_object_set (G_OBJECT (source), "duration", (guint64) GST_SECOND / 2, NULL);
139   ges_simple_timeline_layer_add_object (GES_SIMPLE_TIMELINE_LAYER (layer),
140       source, -1);
141
142   KEY ("Object1", "type", "GESTimelineStandardTransition");
143   KEY ("Object1", "start", "1500000000");
144   KEY ("Object1", "in-point", "0");
145   KEY ("Object1", "duration", "500000000");
146   KEY ("Object1", "priority", "1");
147   KEY ("Object1", "supported-formats", "GES_TRACK_TYPE_UNKNOWN");
148   KEY ("Object1", "max-duration", "18446744073709551615");
149   KEY ("Object1", "vtype", "A bar moves from left to right");
150   COMPARE;
151
152   GST_DEBUG ("Adding second source");
153   source = (GESTimelineObject *) ges_timeline_test_source_new ();
154   g_object_set (G_OBJECT (source), "duration", (guint64) 2 * GST_SECOND, NULL);
155   ges_simple_timeline_layer_add_object (GES_SIMPLE_TIMELINE_LAYER (layer),
156       source, -1);
157
158   KEY ("Object2", "type", "GESTimelineTestSource");
159   KEY ("Object2", "start", "1500000000");
160   KEY ("Object2", "in-point", "0");
161   KEY ("Object2", "duration", "2000000000");
162   KEY ("Object2", "priority", "3");
163   KEY ("Object2", "supported-formats", "GES_TRACK_TYPE_UNKNOWN");
164   KEY ("Object2", "max-duration", "18446744073709551615");
165   KEY ("Object2", "mute", "false");
166   KEY ("Object2", "vpattern", "100% Black");
167   KEY ("Object2", "freq", "440");
168   KEY ("Object2", "volume", "0");
169   COMPARE;
170
171   /* add a second layer to the timeline */
172
173   GST_DEBUG ("Adding a second layer to the timeline");
174   layer2 = ges_timeline_layer_new ();
175   ges_timeline_layer_set_priority (layer2, 1);
176   fail_unless (layer != NULL);
177   fail_unless (ges_timeline_add_layer (timeline, layer2));
178
179   KEY ("Layer1", "priority", "1");
180   KEY ("Layer1", "type", "default");
181   COMPARE;
182
183   GST_DEBUG ("Adding a few more sources");
184   source = (GESTimelineObject *) ges_timeline_title_source_new ();
185   g_object_set (G_OBJECT (source),
186       "duration", (guint64) GST_SECOND,
187       "start", (guint64) 5 * GST_SECOND, "text", "the quick brown fox", NULL);
188   fail_unless (ges_timeline_layer_add_object (layer2, source));
189
190   KEY ("Object3", "type", "GESTimelineTitleSource");
191   KEY ("Object3", "start", "5000000000");
192   KEY ("Object3", "in-point", "0");
193   KEY ("Object3", "duration", "1000000000");
194   KEY ("Object3", "priority", "0");
195   KEY ("Object3", "supported-formats", "GES_TRACK_TYPE_UNKNOWN");
196   KEY ("Object3", "max-duration", "18446744073709551615");
197   KEY ("Object3", "mute", "false");
198   KEY ("Object3", "text", "\"the\\\\ quick\\\\ brown\\\\ fox\"");
199   KEY ("Object3", "font-desc", "\"Serif\\\\ 36\"");
200   KEY ("Object3", "halignment", "center");
201   KEY ("Object3", "valignment", "baseline");
202   KEY ("Object3", "color", "4294967295");
203   KEY ("Object3", "xpos", "0.5");
204   KEY ("Object3", "ypos", "0.5");
205   COMPARE;
206
207   /* tear-down */
208   g_key_file_free (cmp);
209
210
211   GST_DEBUG ("Removing layer from the timeline");
212   fail_unless (ges_timeline_remove_layer (timeline, layer));
213   fail_unless (ges_timeline_remove_layer (timeline, layer2));
214
215   GST_DEBUG ("Removing track from the timeline");
216   g_object_ref (track);
217   fail_unless (ges_timeline_remove_track (timeline, track));
218   fail_unless (ges_track_get_timeline (track) == NULL);
219   ASSERT_OBJECT_REFCOUNT (track, "track", 1);
220   g_object_unref (track);
221
222   ASSERT_OBJECT_REFCOUNT (timeline, "timeline", 1);
223
224   g_object_unref (timeline);
225   g_object_unref (formatter);
226 }
227
228 GST_END_TEST;
229
230 /* do action for every item and then free the list */
231
232 #define g_list_free_all(list)                           \
233   {                                                     \
234     g_list_foreach(list, (GFunc) g_object_unref, NULL); \
235     g_list_free(list);                                  \
236   }
237
238 /* print out a helpful error message when a comparison fails. Works with the
239  * TIMELINE_COMPARE_*, LAYER*, SIMPLE_LAYER*, abd TRACK, macros below to give
240  * information about the source line where the failing object was created.
241  */
242
243 #define CMP_FAIL(a, ...)        \
244   fail_unless (FALSE, __VA_ARGS__);
245
246 /* compare two GObjects for equality. pointer identity and GType short-circuit
247  * the comparison. If a and b are not identical pointers and of the same
248  * GType, compares every readable property for equality using
249  * g_param_values_cmp.
250  */
251
252 static gboolean
253 ges_objs_equal (GObject * a, GObject * b)
254 {
255   GType at;
256   GObjectClass *klass;
257   GParamSpec **props = NULL, **iter = NULL;
258   guint n_props, i;
259   guint ret = FALSE;
260   gchar *typename;
261
262   GST_DEBUG ("comparing %s (%p) and %s (%p)\n",
263       G_OBJECT_TYPE_NAME (a), a, G_OBJECT_TYPE_NAME (b), b);
264
265   if (a == b)
266     return TRUE;
267
268   at = G_TYPE_FROM_INSTANCE (a);
269
270   fail_unless (at == G_TYPE_FROM_INSTANCE (b));
271
272   typename = (gchar *) g_type_name (at);
273
274   /* compare every readable property */
275
276   klass = G_OBJECT_GET_CLASS (a);
277   props = g_object_class_list_properties (klass, &n_props);
278
279   for (i = 0, iter = props; i < n_props; i++, iter++) {
280     GValue av = { 0 }
281     , bv = {
282     0};
283
284     /* ignore name and layer properties */
285     if (!g_strcmp0 ("name", (*iter)->name) ||
286         !g_strcmp0 ("layer", (*iter)->name) ||
287         !g_strcmp0 ("parent", (*iter)->name))
288       continue;
289
290     /* special case caps property */
291     if (!g_strcmp0 ("caps", (*iter)->name)) {
292       GstCaps *acaps, *bcaps;
293
294       g_object_get (a, "caps", &acaps, NULL);
295       g_object_get (b, "caps", &bcaps, NULL);
296       if (gst_caps_is_equal (acaps, bcaps)) {
297         gst_caps_unref (acaps);
298         gst_caps_unref (bcaps);
299         continue;
300       } else {
301         gst_caps_unref (acaps);
302         gst_caps_unref (bcaps);
303         CMP_FAIL (b, "%s's %p and %p differ by property caps", a, b);
304         goto fail;
305       }
306     }
307
308     g_value_init (&av, (*iter)->value_type);
309     g_value_init (&bv, (*iter)->value_type);
310
311     if (!((*iter)->flags & G_PARAM_READABLE))
312       continue;
313
314     g_object_get_property (a, (*iter)->name, &av);
315     g_object_get_property (b, (*iter)->name, &bv);
316
317     if (g_param_values_cmp (*iter, &av, &bv) != 0) {
318       gchar *a_str, *b_str;
319
320       a_str = gst_value_serialize (&av);
321       b_str = gst_value_serialize (&bv);
322
323       CMP_FAIL (b, "%s's %p and %p differ by property %s (%s != %s)",
324           typename, a, b, (*iter)->name, a_str, b_str);
325
326       g_free (a_str);
327       g_free (b_str);
328
329       goto fail;
330     }
331
332     g_value_unset (&av);
333     g_value_unset (&bv);
334   }
335
336   ret = TRUE;
337
338 fail:
339   if (props)
340     g_free (props);
341   return ret;
342 }
343
344 static gboolean
345 ges_tracks_equal (GESTrack * a, GESTrack * b)
346 {
347   return ges_objs_equal (G_OBJECT (a), G_OBJECT (b));
348 }
349
350 static gboolean
351 ges_layers_equal (GESTimelineLayer * a, GESTimelineLayer * b)
352 {
353   GList *a_objs = NULL, *b_objs = NULL, *a_iter, *b_iter;
354   gboolean ret = FALSE;
355   guint i;
356
357   if (!ges_objs_equal (G_OBJECT (a), G_OBJECT (b)))
358     return FALSE;
359
360   a_objs = ges_timeline_layer_get_objects (a);
361   b_objs = ges_timeline_layer_get_objects (b);
362
363   /* one shortcoming of this procedure is that the objects need to be stored
364    * in the same order. Not sure if this is a problem in practice */
365
366   for (i = 0, a_iter = a_objs, b_iter = b_objs; a_iter && b_iter; a_iter =
367       a_iter->next, b_iter = b_iter->next, i++) {
368     if (!ges_objs_equal (a_iter->data, b_iter->data)) {
369       CMP_FAIL (b, "layers %p and %p differ by obj at position %d", a, b, i);
370       goto fail;
371     }
372   }
373
374   if (a_iter || b_iter) {
375     CMP_FAIL (b, "layers %p and %p have differing number of objects", a, b);
376     goto fail;
377   }
378
379   ret = TRUE;
380
381 fail:
382
383   g_list_free_all (a_objs);
384   g_list_free_all (b_objs);
385
386   return ret;
387 }
388
389 static gboolean
390 ges_timelines_equal (GESTimeline * a, GESTimeline * b)
391 {
392   GList *a_tracks, *b_tracks, *a_iter, *b_iter, *a_layers, *b_layers;
393
394   gboolean ret = FALSE;
395   guint i;
396
397   if (!ges_objs_equal (G_OBJECT (a), G_OBJECT (b))) {
398     CMP_FAIL (b, "%p and %p are not of the same type");
399     return FALSE;
400   }
401
402   a_tracks = ges_timeline_get_tracks (a);
403   b_tracks = ges_timeline_get_tracks (b);
404   a_layers = ges_timeline_get_layers (a);
405   b_layers = ges_timeline_get_layers (b);
406
407   /* one shortcoming of this procedure is that the objects need to be stored
408    * in the same order. Not sure if this is a problem in practice */
409
410   for (i = 0, a_iter = a_tracks, b_iter = b_tracks; a_iter && b_iter; a_iter =
411       a_iter->next, b_iter = b_iter->next, i++) {
412     if (!ges_tracks_equal (a_iter->data, b_iter->data)) {
413       CMP_FAIL (b, "GESTimelines %p and %p differ by tracks at position %d", a,
414           b, i);
415       goto fail;
416     }
417   }
418
419   if (a_iter || b_iter) {
420     CMP_FAIL (b, "GESTimelines %p and %p have differing number of tracks", a,
421         b);
422     goto fail;
423   }
424
425   for (i = 0, a_iter = a_layers, b_iter = b_layers; a_iter && b_iter; a_iter =
426       a_iter->next, b_iter = b_iter->next, i++) {
427     if (!ges_layers_equal (a_iter->data, b_iter->data)) {
428       goto fail;
429     }
430   }
431
432   if (a_iter || b_iter) {
433     CMP_FAIL (b, "GESTimelines %p and %p have differing numbre of layers", a,
434         b);
435     goto fail;
436   }
437
438   ret = TRUE;
439
440 fail:
441
442   g_list_free_all (a_tracks);
443   g_list_free_all (b_tracks);
444   g_list_free_all (a_layers);
445   g_list_free_all (b_layers);
446
447   return ret;
448 }
449
450 #define TIMELINE_BEGIN(location) \
451 {\
452   GESTimeline **a, *b;\
453   a = &(location);\
454   if (*a) g_object_unref (*a);\
455   b = ges_timeline_new();\
456   *a = b;\
457
458 #define TIMELINE_END }
459
460 #define TIMELINE_COMPARE(a, b)\
461 {\
462   fail_unless (ges_timelines_equal(a, b));\
463 }
464
465 #define TRACK(type, caps) \
466 {\
467   GESTrack *trk;\
468   GstCaps *c;\
469   c = gst_caps_from_string(caps);\
470   trk = ges_track_new (type, c);\
471   ges_timeline_add_track (b, trk);\
472   g_object_set_data(G_OBJECT(trk),"file", (void *) __FILE__);\
473   g_object_set_data(G_OBJECT(trk),"line", (void *) __LINE__);\
474   g_object_set_data(G_OBJECT(trk),"function", (void *) GST_FUNCTION);\
475 }
476
477 #define LAYER_BEGIN(priority) \
478 {\
479   GESTimelineLayer *l;\
480   l = ges_timeline_layer_new ();\
481   ges_timeline_add_layer (b, l);\
482   ges_timeline_layer_set_priority (l, priority);\
483   g_object_set_data(G_OBJECT(l),"file", (void *) __FILE__);\
484   g_object_set_data(G_OBJECT(l),"line", (void *) __LINE__);\
485   g_object_set_data(G_OBJECT(l),"function", (void *) GST_FUNCTION);
486
487 #define LAYER_END \
488 }
489
490 #define LAYER_OBJECT(type, ...) \
491 {\
492   GESTimelineObject *obj;\
493   obj = GES_TIMELINE_OBJECT(\
494         g_object_new ((type), __VA_ARGS__, NULL));\
495   ges_timeline_layer_add_object (l, obj);\
496   g_object_set_data(G_OBJECT(obj),"file", (void *) __FILE__);\
497   g_object_set_data(G_OBJECT(obj),"line", (void *) __LINE__);\
498   g_object_set_data(G_OBJECT(obj),"function", (void *) GST_FUNCTION);\
499 }
500
501 #define SIMPLE_LAYER_BEGIN(priority) \
502 {\
503   GESSimpleTimelineLayer *l;\
504   l = ges_simple_timeline_layer_new ();\
505   ges_timeline_add_layer (b, GES_TIMELINE_LAYER(l));\
506   ges_timeline_layer_set_priority(GES_TIMELINE_LAYER(l), priority);\
507   g_object_set_data(G_OBJECT(l),"file", (void *) __FILE__);\
508   g_object_set_data(G_OBJECT(l),"line", (void *) __LINE__);\
509   g_object_set_data(G_OBJECT(l),"function", (void *) GST_FUNCTION);
510
511 #define SIMPLE_LAYER_OBJECT(type, position, ...) \
512 {\
513   GESTimelineObject *obj;\
514   obj = GES_TIMELINE_OBJECT(\
515         g_object_new ((type), __VA_ARGS__, NULL));\
516   ges_simple_timeline_layer_add_object (l, obj, position);\
517   g_object_set_data(G_OBJECT(obj),"file", (void *) __FILE__);\
518   g_object_set_data(G_OBJECT(obj),"line", (void *) __LINE__);\
519   g_object_set_data(G_OBJECT(obj),"function", (void *) GST_FUNCTION);\
520 }
521
522 /* */
523 static const gchar *data = "\n[General]\n"
524     "[Track0]\n"
525     "type=GES_TRACK_TYPE_AUDIO\n"
526     "caps=audio/x-raw\n"
527     "\n"
528     "[Layer0]\n"
529     "priority=0\n"
530     "type=simple\n"
531     "\n"
532     "[Object0]\n"
533     "type=GESTimelineTestSource\n"
534     "start=0\n"
535     "in-point=0\n"
536     "duration=2000000000\n"
537     "priority=2\n"
538     "mute=false\n"
539     "vpattern=100% Black\n"
540     "freq=440\n"
541     "volume=0\n"
542     "\n"
543     "[Object1]\n"
544     "type=GESTimelineStandardTransition\n"
545     "start=1500000000\n"
546     "in-point=0\n"
547     "duration=500000000\n"
548     "priority=1\n"
549     "vtype=A bar moves from left to right\n"
550     "\n"
551     "[Object2]\n"
552     "type=GESTimelineTestSource\n"
553     "start=1500000000\n"
554     "in-point=0\n"
555     "duration=2000000000\n"
556     "priority=2\n"
557     "mute=false\n"
558     "vpattern=100% Black\n"
559     "freq=440\n"
560     "volume=0\n"
561     "\n"
562     "[Layer1]\n"
563     "priority=1\n"
564     "type=default\n"
565     "\n"
566     "[Object3]\n"
567     "type=GESTimelineTitleSource\n"
568     "start=5000000000\n"
569     "in-point=0\n"
570     "duration=1000000000\n"
571     "priority=2\n"
572     "mute=false\n"
573     "text=\"the\\\\ quick\\\\ brown\\\\ fox\"\n"
574     "font-desc=\"Serif\\\\ 36\"\n"
575     "halignment=center\n" "valignment=baseline\n";
576
577 GST_START_TEST (test_keyfile_load)
578 {
579   GESTimeline *timeline = NULL, *expected = NULL;
580   GESFormatter *formatter;
581
582   ges_init ();
583
584   /* setup timeline */
585
586   GST_DEBUG ("Create a timeline");
587   timeline = ges_timeline_new ();
588   fail_unless (timeline != NULL);
589
590   /* create serialization object */
591
592   GST_DEBUG ("creating a default formatter");
593   formatter = GES_FORMATTER (ges_keyfile_formatter_new ());
594
595   ges_formatter_set_data (formatter, g_strdup (data), strlen (data));
596
597   fail_unless (ges_formatter_load (formatter, timeline));
598
599   TIMELINE_BEGIN (expected) {
600
601     TRACK (GES_TRACK_TYPE_AUDIO, "audio/x-raw");
602
603     SIMPLE_LAYER_BEGIN (0) {
604
605       SIMPLE_LAYER_OBJECT ((GES_TYPE_TIMELINE_TEST_SOURCE), -1,
606           "duration", (guint64) 2 * GST_SECOND);
607
608       SIMPLE_LAYER_OBJECT ((GES_TYPE_TIMELINE_STANDARD_TRANSITION), -1,
609           "duration", (guint64) GST_SECOND / 2,
610           "vtype", GES_VIDEO_STANDARD_TRANSITION_TYPE_BAR_WIPE_LR);
611
612       SIMPLE_LAYER_OBJECT ((GES_TYPE_TIMELINE_TEST_SOURCE), -1,
613           "duration", (guint64) 2 * GST_SECOND);
614
615     } LAYER_END;
616
617     LAYER_BEGIN (1) {
618
619       LAYER_OBJECT (GES_TYPE_TIMELINE_TITLE_SOURCE,
620           "start", (guint64) 5 * GST_SECOND,
621           "duration", (guint64) GST_SECOND, "priority", 2, "text",
622           "the quick brown fox");
623
624     } LAYER_END;
625
626   } TIMELINE_END;
627
628   TIMELINE_COMPARE (timeline, expected);
629
630   /* tear-down */
631   g_object_unref (formatter);
632   g_object_unref (timeline);
633   g_object_unref (expected);
634 }
635
636 GST_END_TEST;
637
638 GST_START_TEST (test_pitivi_file_load)
639 {
640   GESFormatter *formatter;
641   GESTimeline *timeline, *expected;
642   GMainLoop *mainloop;
643   gchar *uri, *save_uri, *cur_dir;
644
645   /*create the expected timeline */
646   timeline = ges_timeline_new ();
647   mainloop = g_main_loop_new (NULL, FALSE);
648   expected = ges_timeline_new ();
649
650   /* create the timeline from formatter */
651   formatter = GES_FORMATTER (ges_pitivi_formatter_new ());
652   cur_dir = g_get_current_dir ();
653   uri = g_build_filename (cur_dir, "test.xptv", NULL);
654   save_uri = g_build_filename (cur_dir, "testsave.xptv", NULL);
655   g_free (cur_dir);
656
657   if (g_file_test (uri, G_FILE_TEST_EXISTS) == FALSE) {
658     GST_ERROR ("Could not test GESPitiviFormatter as no project file found");
659     return;
660   }
661
662   ges_formatter_load_from_uri (formatter, timeline, uri);
663   g_timeout_add (1000, (GSourceFunc) g_main_loop_quit, mainloop);
664   g_main_loop_run (mainloop);
665
666   formatter = GES_FORMATTER (ges_pitivi_formatter_new ());
667   ges_formatter_save_to_uri (formatter, timeline, save_uri);
668   formatter = GES_FORMATTER (ges_pitivi_formatter_new ());
669   ges_formatter_load_from_uri (formatter, expected, uri);
670   g_timeout_add (1000, (GSourceFunc) g_main_loop_quit, mainloop);
671   g_main_loop_run (mainloop);
672
673   /* compare the two timelines and fail test if they are different */
674   TIMELINE_COMPARE (expected, timeline);
675   g_free (uri);
676   g_free (save_uri);
677   g_main_loop_unref (mainloop);
678   g_object_unref (formatter);
679   g_object_unref (timeline);
680   g_object_unref (expected);
681 }
682
683 GST_END_TEST;
684
685 GST_START_TEST (test_keyfile_identity)
686 {
687
688   /* we will create several timelines. they will first be serialized, then
689    * deseriailzed and compared against the original. */
690
691   GESTimeline *orig = NULL, *serialized = NULL;
692   GESFormatter *formatter;
693
694   ges_init ();
695
696   formatter = GES_FORMATTER (ges_keyfile_formatter_new ());
697
698   TIMELINE_BEGIN (orig) {
699
700     TRACK (GES_TRACK_TYPE_AUDIO, "audio/x-raw,"
701         "format=(string)" GST_AUDIO_NE (S32) ",rate=8000");
702     TRACK (GES_TRACK_TYPE_VIDEO, "video/x-raw,format=(string)RGB24");
703
704     LAYER_BEGIN (5) {
705
706       LAYER_OBJECT (GES_TYPE_TIMELINE_TEXT_OVERLAY,
707           "start", (guint64) GST_SECOND,
708           "duration", (guint64) 2 * GST_SECOND,
709           "priority", 1,
710           "text", "Hello, world!",
711           "font-desc", "Sans 9",
712           "halignment", GES_TEXT_HALIGN_LEFT,
713           "valignment", GES_TEXT_VALIGN_TOP);
714
715       LAYER_OBJECT (GES_TYPE_TIMELINE_TEST_SOURCE,
716           "start", (guint64) 0,
717           "duration", (guint64) 5 * GST_SECOND,
718           "priority", 2,
719           "freq", (gdouble) 500,
720           "volume", 1.0, "vpattern", GES_VIDEO_TEST_PATTERN_WHITE);
721
722       LAYER_OBJECT (GES_TYPE_TIMELINE_TEXT_OVERLAY,
723           "start", (guint64) 7 * GST_SECOND,
724           "duration", (guint64) 2 * GST_SECOND,
725           "priority", 2,
726           "text", "Hello, world!",
727           "font-desc", "Sans 9",
728           "halignment", GES_TEXT_HALIGN_LEFT,
729           "valignment", GES_TEXT_VALIGN_TOP);
730
731       LAYER_OBJECT (GES_TYPE_TIMELINE_TEST_SOURCE,
732           "start", (guint64) 6 * GST_SECOND,
733           "duration", (guint64) 5 * GST_SECOND,
734           "priority", 3,
735           "freq", (gdouble) 600,
736           "volume", 1.0, "vpattern", GES_VIDEO_TEST_PATTERN_RED);
737
738     }
739     LAYER_END;
740
741   }
742   TIMELINE_END;
743
744   serialized = ges_timeline_new ();
745
746   ges_formatter_save (formatter, orig);
747   ges_formatter_load (formatter, serialized);
748
749   TIMELINE_COMPARE (serialized, orig);
750
751   g_object_unref (formatter);
752   g_object_unref (serialized);
753   g_object_unref (orig);
754 }
755
756 GST_END_TEST;
757
758 static Suite *
759 ges_suite (void)
760 {
761   Suite *s = suite_create ("ges-save-load");
762   TCase *tc_chain = tcase_create ("basic");
763
764   suite_add_tcase (s, tc_chain);
765
766   tcase_add_test (tc_chain, test_keyfile_save);
767   tcase_add_test (tc_chain, test_keyfile_load);
768   tcase_add_test (tc_chain, test_keyfile_identity);
769   tcase_add_test (tc_chain, test_pitivi_file_load);
770
771   return s;
772 }
773
774 int
775 main (int argc, char **argv)
776 {
777   int nf;
778
779   Suite *s = ges_suite ();
780   SRunner *sr = srunner_create (s);
781
782   gst_check_init (&argc, &argv);
783
784   srunner_run_all (sr, CK_NORMAL);
785   nf = srunner_ntests_failed (sr);
786   srunner_free (sr);
787
788   return nf;
789 }