mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +00:00
Remove the GESKeyFileFormatter
It was using deprecated URI, and can not be used in real life anymore. Also remove the ges_formatter_default_new method ges_formatter_new_for_uri that are useless now
This commit is contained in:
parent
35a3f72ad5
commit
97973f1eba
13 changed files with 10 additions and 1435 deletions
|
@ -87,7 +87,6 @@ platform as well as Windows. It is released under the GNU Library General Public
|
|||
<chapter>
|
||||
<title>Serialization Classes</title>
|
||||
<xi:include href="xml/ges-formatter.xml"/>
|
||||
<xi:include href="xml/ges-keyfile-formatter.xml"/>
|
||||
<xi:include href="xml/ges-pitivi-formatter.xml"/>
|
||||
</chapter>
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
ges_custom_timeline_source_get_type
|
||||
ges_formatter_get_type
|
||||
ges_keyfile_formatter_get_type
|
||||
ges_simple_timeline_layer_get_type
|
||||
%ges_text_halign_get_type
|
||||
%ges_text_valign_get_type
|
||||
|
|
|
@ -45,7 +45,6 @@ libges_@GST_API_VERSION@_la_SOURCES = \
|
|||
ges-track-parse-launch-effect.c \
|
||||
ges-screenshot.c \
|
||||
ges-formatter.c \
|
||||
ges-keyfile-formatter.c \
|
||||
ges-pitivi-formatter.c \
|
||||
ges-utils.c
|
||||
|
||||
|
@ -89,7 +88,6 @@ libges_@GST_API_VERSION@include_HEADERS = \
|
|||
ges-track-text-overlay.h \
|
||||
ges-screenshot.h \
|
||||
ges-formatter.h \
|
||||
ges-keyfile-formatter.h \
|
||||
ges-pitivi-formatter.h \
|
||||
ges-utils.h
|
||||
|
||||
|
|
|
@ -48,7 +48,6 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include "ges-formatter.h"
|
||||
#include "ges-keyfile-formatter.h"
|
||||
#include "ges-internal.h"
|
||||
#include "ges.h"
|
||||
|
||||
|
@ -168,39 +167,6 @@ ges_formatter_find_for_uri (const gchar * uri)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* ges_formatter_new_for_uri:
|
||||
* @uri: a #gchar * pointing to the uri
|
||||
*
|
||||
* Creates a #GESFormatter that can handle the given URI.
|
||||
*
|
||||
* Returns: A GESFormatter that can load the given uri, or NULL if
|
||||
* the uri is not supported.
|
||||
*/
|
||||
|
||||
GESFormatter *
|
||||
ges_formatter_new_for_uri (const gchar * uri)
|
||||
{
|
||||
if (ges_formatter_can_load_uri (uri, NULL))
|
||||
return GES_FORMATTER (ges_keyfile_formatter_new ());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* ges_default_formatter_new:
|
||||
*
|
||||
* Creates a new instance of the default GESFormatter type on this system
|
||||
* (currently #GESKeyfileFormatter).
|
||||
*
|
||||
* Returns: (transfer full): a #GESFormatter instance or %NULL
|
||||
*/
|
||||
|
||||
GESFormatter *
|
||||
ges_default_formatter_new (void)
|
||||
{
|
||||
return GES_FORMATTER (ges_keyfile_formatter_new ());
|
||||
}
|
||||
|
||||
static gboolean
|
||||
default_can_load_uri (const gchar * uri, GError ** error)
|
||||
{
|
||||
|
|
|
@ -169,9 +169,6 @@ struct _GESFormatterClass {
|
|||
GType ges_formatter_get_type (void);
|
||||
|
||||
/* Main Formatter methods */
|
||||
GESFormatter *ges_formatter_new_for_uri (const gchar *uri);
|
||||
GESFormatter *ges_default_formatter_new (void);
|
||||
|
||||
gboolean ges_formatter_can_load_uri (const gchar * uri, GError **error);
|
||||
gboolean ges_formatter_can_save_uri (const gchar * uri, GError **error);
|
||||
|
||||
|
|
|
@ -1,463 +0,0 @@
|
|||
/* GStreamer Editing Services
|
||||
* Copyright (C) 2010 Brandon Lewis <brandon.lewis@collabora.co.uk>
|
||||
* 2010 Nokia Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:ges-keyfile-formatter
|
||||
* @short_description: GKeyFile formatter
|
||||
**/
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <stdlib.h>
|
||||
#include "ges.h"
|
||||
#include "ges-internal.h"
|
||||
|
||||
G_DEFINE_TYPE (GESKeyfileFormatter, ges_keyfile_formatter, GES_TYPE_FORMATTER);
|
||||
|
||||
/* for ini format */
|
||||
static gboolean save_keyfile (GESFormatter * keyfile_formatter,
|
||||
GESTimeline * timeline);
|
||||
static gboolean load_keyfile (GESFormatter * keyfile_formatter,
|
||||
GESTimeline * timeline);
|
||||
|
||||
static void
|
||||
ges_keyfile_formatter_class_init (GESKeyfileFormatterClass * klass)
|
||||
{
|
||||
GESFormatterClass *formatter_klass;
|
||||
|
||||
formatter_klass = GES_FORMATTER_CLASS (klass);
|
||||
|
||||
formatter_klass->save = save_keyfile;
|
||||
formatter_klass->load = load_keyfile;
|
||||
}
|
||||
|
||||
static void
|
||||
ges_keyfile_formatter_init (GESKeyfileFormatter * object)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* ges_keyfile_formatter_new:
|
||||
*
|
||||
* Creates a new #GESKeyfileFormatter.
|
||||
*
|
||||
* Returns: The newly created #GESKeyfileFormatter.
|
||||
*/
|
||||
GESKeyfileFormatter *
|
||||
ges_keyfile_formatter_new (void)
|
||||
{
|
||||
return g_object_new (GES_TYPE_KEYFILE_FORMATTER, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
save_keyfile (GESFormatter * keyfile_formatter, GESTimeline * timeline)
|
||||
{
|
||||
GKeyFile *kf;
|
||||
GList *tmp, *tracks, *layers;
|
||||
int i = 0;
|
||||
int n_objects = 0;
|
||||
gchar buffer[255];
|
||||
gchar *data;
|
||||
gsize length;
|
||||
|
||||
GST_DEBUG ("saving keyfile_formatter");
|
||||
|
||||
kf = g_key_file_new ();
|
||||
|
||||
g_key_file_set_value (kf, "General", "version", "1");
|
||||
|
||||
tracks = ges_timeline_get_tracks (timeline);
|
||||
|
||||
for (i = 0, tmp = tracks; tmp; i++, tmp = tmp->next) {
|
||||
GESTrack *track;
|
||||
gchar *type;
|
||||
gchar *caps;
|
||||
GValue v = { 0 };
|
||||
|
||||
track = GES_TRACK (tmp->data);
|
||||
|
||||
g_snprintf (buffer, 255, "Track%d", i);
|
||||
g_value_init (&v, GES_TYPE_TRACK_TYPE);
|
||||
g_object_get_property (G_OBJECT (track), "track-type", &v);
|
||||
|
||||
type = gst_value_serialize (&v);
|
||||
caps = gst_caps_to_string (ges_track_get_caps (track));
|
||||
|
||||
g_key_file_set_value (kf, buffer, "type", type);
|
||||
g_key_file_set_string (kf, buffer, "caps", caps);
|
||||
|
||||
g_free (caps);
|
||||
g_free (type);
|
||||
gst_object_unref (track);
|
||||
tmp->data = NULL;
|
||||
}
|
||||
|
||||
g_list_free (tracks);
|
||||
|
||||
layers = ges_timeline_get_layers (timeline);
|
||||
|
||||
for (i = 0, tmp = layers; tmp; i++, tmp = tmp->next) {
|
||||
const gchar *type;
|
||||
GESTimelineLayer *layer;
|
||||
GList *objs, *cur;
|
||||
layer = tmp->data;
|
||||
|
||||
g_snprintf (buffer, 255, "Layer%d", i);
|
||||
|
||||
if (GES_IS_SIMPLE_TIMELINE_LAYER (tmp->data)) {
|
||||
type = "simple";
|
||||
} else {
|
||||
type = "default";
|
||||
}
|
||||
|
||||
g_key_file_set_integer (kf, buffer, "priority",
|
||||
ges_timeline_layer_get_priority (layer));
|
||||
g_key_file_set_value (kf, buffer, "type", type);
|
||||
|
||||
objs = ges_timeline_layer_get_objects (layer);
|
||||
|
||||
for (cur = objs; cur; cur = cur->next) {
|
||||
GESTimelineObject *obj;
|
||||
GParamSpec **properties;
|
||||
guint i, n;
|
||||
|
||||
obj = GES_TIMELINE_OBJECT (cur->data);
|
||||
properties =
|
||||
g_object_class_list_properties (G_OBJECT_GET_CLASS (obj), &n);
|
||||
|
||||
g_snprintf (buffer, 255, "Object%d", n_objects);
|
||||
n_objects++;
|
||||
|
||||
g_key_file_set_value (kf, buffer, "type",
|
||||
G_OBJECT_TYPE_NAME (G_OBJECT (obj)));
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
GValue v = { 0 };
|
||||
gchar *serialized;
|
||||
GParamSpec *p = properties[i];
|
||||
|
||||
g_value_init (&v, p->value_type);
|
||||
g_object_get_property (G_OBJECT (obj), p->name, &v);
|
||||
|
||||
/* FIXME: does this work for properties marked G_PARAM_CONSTRUCT_ONLY?
|
||||
* */
|
||||
|
||||
if ((p->flags & G_PARAM_READABLE) && (p->flags & G_PARAM_WRITABLE)) {
|
||||
if (!(serialized = gst_value_serialize (&v)))
|
||||
continue;
|
||||
|
||||
g_key_file_set_string (kf, buffer, p->name, serialized);
|
||||
g_free (serialized);
|
||||
}
|
||||
|
||||
g_value_unset (&v);
|
||||
}
|
||||
|
||||
g_free (properties);
|
||||
g_object_unref (obj);
|
||||
cur->data = NULL;
|
||||
}
|
||||
|
||||
g_list_free (objs);
|
||||
}
|
||||
|
||||
g_list_foreach (layers, (GFunc) g_object_unref, NULL);
|
||||
g_list_free (layers);
|
||||
|
||||
data = g_key_file_to_data (kf, &length, NULL);
|
||||
ges_formatter_set_data (keyfile_formatter, data, length);
|
||||
g_key_file_free (kf);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
create_track (GKeyFile * kf, gchar * group, GESTimeline * timeline)
|
||||
{
|
||||
GESTrack *track;
|
||||
GstCaps *caps;
|
||||
gchar *caps_field, *type_field;
|
||||
gboolean res;
|
||||
GValue v = { 0 };
|
||||
|
||||
if (!(caps_field = g_key_file_get_string (kf, group, "caps", NULL)))
|
||||
return FALSE;
|
||||
|
||||
caps = gst_caps_from_string (caps_field);
|
||||
g_free (caps_field);
|
||||
|
||||
if (!(type_field = g_key_file_get_value (kf, group, "type", NULL)))
|
||||
return FALSE;
|
||||
|
||||
g_value_init (&v, GES_TYPE_TRACK_TYPE);
|
||||
res = gst_value_deserialize (&v, type_field);
|
||||
g_free (type_field);
|
||||
|
||||
if (!caps || !res)
|
||||
return FALSE;
|
||||
|
||||
track = ges_track_new (g_value_get_flags (&v), caps);
|
||||
|
||||
if (!ges_timeline_add_track (timeline, track)) {
|
||||
g_object_unref (track);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GESTimelineLayer *
|
||||
create_layer (GKeyFile * kf, gchar * group, GESTimeline * timeline)
|
||||
{
|
||||
GESTimelineLayer *ret = NULL;
|
||||
gchar *type_field, *priority_field;
|
||||
gboolean is_simple;
|
||||
guint priority;
|
||||
|
||||
if (!(type_field = g_key_file_get_value (kf, group, "type", NULL)))
|
||||
return FALSE;
|
||||
|
||||
is_simple = g_str_equal (type_field, "simple");
|
||||
g_free (type_field);
|
||||
|
||||
if (!(priority_field = g_key_file_get_value (kf, group, "priority", NULL)))
|
||||
return FALSE;
|
||||
|
||||
priority = strtoul (priority_field, NULL, 10);
|
||||
g_free (priority_field);
|
||||
|
||||
if (is_simple) {
|
||||
GESSimpleTimelineLayer *simple;
|
||||
simple = ges_simple_timeline_layer_new ();
|
||||
ret = (GESTimelineLayer *) simple;
|
||||
} else {
|
||||
ret = ges_timeline_layer_new ();
|
||||
}
|
||||
|
||||
ges_timeline_layer_set_priority (ret, priority);
|
||||
if (!ges_timeline_add_layer (timeline, ret)) {
|
||||
g_object_unref (ret);
|
||||
ret = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
create_object (GKeyFile * kf, gchar * group, GESTimelineLayer * layer)
|
||||
{
|
||||
GType type;
|
||||
gchar *type_name;
|
||||
GObject *obj;
|
||||
GESTimelineObject *timeline_obj;
|
||||
gchar **keys;
|
||||
gsize n_keys, i;
|
||||
GParamSpec *pspec;
|
||||
GObjectClass *klass;
|
||||
GParameter *params, *p;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
GST_INFO ("processing '%s'", group);
|
||||
|
||||
/* get a reference to the object class */
|
||||
|
||||
if (!(type_name = g_key_file_get_value (kf, group, "type", NULL))) {
|
||||
GST_ERROR ("no type name for object '%s'", group);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!(type = g_type_from_name (type_name))) {
|
||||
GST_ERROR ("invalid type name '%s'", type_name);
|
||||
goto fail_free_type_name;
|
||||
}
|
||||
|
||||
if (!(klass = g_type_class_ref (type))) {
|
||||
GST_ERROR ("couldn't get class ref");
|
||||
goto fail_free_type_name;
|
||||
}
|
||||
|
||||
if (!(keys = g_key_file_get_keys (kf, group, &n_keys, NULL)))
|
||||
goto fail_unref_class;
|
||||
|
||||
/* create an array of parameters for the call to g_new0 */
|
||||
/* skip first field 'type' */
|
||||
|
||||
if (!(params = g_new0 (GParameter, (n_keys - 1)))) {
|
||||
GST_ERROR ("couldn't allocate parameter list");
|
||||
goto fail_free_keys;
|
||||
}
|
||||
|
||||
GST_DEBUG ("processing parameter list '%s'", group);
|
||||
|
||||
for (p = params, i = 1; i < n_keys; i++, p++) {
|
||||
gchar *value;
|
||||
gchar *key;
|
||||
|
||||
key = keys[i];
|
||||
|
||||
GST_DEBUG ("processing key '%s'", key);
|
||||
|
||||
/* find the param spec for this property */
|
||||
if (!(pspec = g_object_class_find_property (klass, key))) {
|
||||
GST_ERROR ("Object type %s has no property %s", type_name, key);
|
||||
goto fail_free_params;
|
||||
}
|
||||
|
||||
p->name = key;
|
||||
g_value_init (&p->value, pspec->value_type);
|
||||
|
||||
/* assume this is going to work */
|
||||
value = g_key_file_get_string (kf, group, key, NULL);
|
||||
|
||||
if (!gst_value_deserialize (&p->value, value)) {
|
||||
GST_ERROR ("Couldn't read property value '%s' for property '%s'",
|
||||
key, value);
|
||||
goto fail_free_params;
|
||||
}
|
||||
|
||||
g_free (value);
|
||||
}
|
||||
|
||||
/* create the object from the supplied type name */
|
||||
|
||||
if (!(obj = g_object_newv (type, (n_keys - 1), params))) {
|
||||
GST_ERROR ("couldn't create object");
|
||||
goto fail_free_type_name;
|
||||
}
|
||||
|
||||
/* check that we have a subclass of GESTimelineObject */
|
||||
|
||||
if (!GES_IS_TIMELINE_OBJECT (obj)) {
|
||||
GST_ERROR ("'%s' is not a subclass of GESTimelineObject!", type_name);
|
||||
goto fail_unref_obj;
|
||||
}
|
||||
timeline_obj = (GESTimelineObject *) obj;
|
||||
|
||||
/* add the object to the layer */
|
||||
|
||||
if (GES_IS_SIMPLE_TIMELINE_LAYER (layer)) {
|
||||
if (!ges_simple_timeline_layer_add_object ((GESSimpleTimelineLayer *)
|
||||
layer, timeline_obj, -1)) {
|
||||
goto fail_unref_obj;
|
||||
}
|
||||
} else {
|
||||
if (!ges_timeline_layer_add_object (layer, timeline_obj)) {
|
||||
goto fail_unref_obj;
|
||||
}
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
fail_unref_obj:
|
||||
if (!ret)
|
||||
g_object_unref (obj);
|
||||
|
||||
fail_free_params:
|
||||
for (p = params, i = 1; i < n_keys; i++, p++) {
|
||||
g_value_unset (&p->value);
|
||||
}
|
||||
g_free (params);
|
||||
|
||||
fail_free_keys:
|
||||
g_strfreev (keys);
|
||||
|
||||
fail_unref_class:
|
||||
g_type_class_unref (klass);
|
||||
|
||||
fail_free_type_name:
|
||||
g_free (type_name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
load_keyfile (GESFormatter * keyfile_formatter, GESTimeline * timeline)
|
||||
{
|
||||
GKeyFile *kf;
|
||||
GError *error = NULL;
|
||||
gboolean ret = TRUE;
|
||||
gchar **groups;
|
||||
gsize n_groups, i;
|
||||
GESTimelineLayer *cur_layer = NULL;
|
||||
gchar *data;
|
||||
gsize length;
|
||||
|
||||
kf = g_key_file_new ();
|
||||
data = ges_formatter_get_data (keyfile_formatter, &length);
|
||||
if (!g_key_file_load_from_data (kf, data, length, G_KEY_FILE_NONE, &error)) {
|
||||
ret = FALSE;
|
||||
GST_ERROR ("%s", error->message);
|
||||
GST_INFO ("%s", data);
|
||||
goto free_kf;
|
||||
}
|
||||
|
||||
if (!(groups = g_key_file_get_groups (kf, &n_groups))) {
|
||||
goto free_kf;
|
||||
}
|
||||
|
||||
for (i = 0; i < n_groups; i++) {
|
||||
gchar *group = groups[i];
|
||||
|
||||
if (g_str_has_prefix (group, "Track")) {
|
||||
if (!create_track (kf, group, timeline)) {
|
||||
GST_ERROR ("couldn't create object for %s", group);
|
||||
ret = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
else if (g_str_has_prefix (group, "Layer")) {
|
||||
if (!(cur_layer = create_layer (kf, group, timeline))) {
|
||||
GST_ERROR ("couldn't create object for %s", group);
|
||||
ret = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
else if (g_str_has_prefix (group, "Object")) {
|
||||
if (!cur_layer) {
|
||||
GST_ERROR ("Group %s occurs outside of Layer", group);
|
||||
ret = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!create_object (kf, group, cur_layer)) {
|
||||
GST_ERROR ("couldn't create object for %s", group);
|
||||
ret = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
else if (g_str_equal (group, "General")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
else {
|
||||
GST_ERROR ("Unrecognized group name %s", group);
|
||||
ret = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_strfreev (groups);
|
||||
|
||||
free_kf:
|
||||
g_key_file_free (kf);
|
||||
return ret;
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
/* GStreamer Editing Services
|
||||
* Copyright (C) 2010 Brandon Lewis <brandon.lewis@collabora.co.uk>
|
||||
* 2010 Nokia Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef _GES_KEYFILE_FORMATTER
|
||||
#define _GES_KEYFILE_FORMATTER
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <ges/ges-timeline.h>
|
||||
|
||||
#define GES_TYPE_KEYFILE_FORMATTER ges_keyfile_formatter_get_type()
|
||||
|
||||
#define GES_KEYFILE_FORMATTER(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GES_TYPE_KEYFILE_FORMATTER, GESKeyfileFormatter))
|
||||
|
||||
#define GES_KEYFILE_FORMATTER_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST ((klass), GES_TYPE_KEYFILE_FORMATTER, GESKeyfileFormatterClass))
|
||||
|
||||
#define GES_IS_KEYFILE_FORMATTER(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GES_TYPE_KEYFILE_FORMATTER))
|
||||
|
||||
#define GES_IS_KEYFILE_FORMATTER_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((klass), GES_TYPE_KEYFILE_FORMATTER))
|
||||
|
||||
#define GES_KEYFILE_FORMATTER_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), GES_TYPE_KEYFILE_FORMATTER, GESKeyfileFormatterClass))
|
||||
|
||||
/**
|
||||
* GESKeyfileFormatter:
|
||||
*
|
||||
* Serializes a #GESTimeline to a file using #GKeyFile
|
||||
*/
|
||||
|
||||
struct _GESKeyfileFormatter {
|
||||
/*< private >*/
|
||||
GESFormatter parent;
|
||||
|
||||
/* Padding for API extension */
|
||||
gpointer _ges_reserved[GES_PADDING];
|
||||
};
|
||||
|
||||
struct _GESKeyfileFormatterClass {
|
||||
/*< private >*/
|
||||
GESFormatterClass parent_class;
|
||||
|
||||
/* Padding for API extension */
|
||||
gpointer _ges_reserved[GES_PADDING];
|
||||
};
|
||||
|
||||
GType ges_keyfile_formatter_get_type (void);
|
||||
|
||||
GESKeyfileFormatter *ges_keyfile_formatter_new (void);
|
||||
|
||||
#endif /* _GES_KEYFILE_FORMATTER */
|
|
@ -1940,29 +1940,8 @@ gboolean
|
|||
ges_timeline_load_from_uri (GESTimeline * timeline, const gchar * uri,
|
||||
GError ** error)
|
||||
{
|
||||
GESFormatter *p = NULL;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
/* FIXME : we should have a GError** argument so the user can know why
|
||||
* it wasn't able to load the uri
|
||||
*/
|
||||
|
||||
if (!(p = ges_formatter_new_for_uri (uri))) {
|
||||
GST_ERROR ("unsupported uri '%s'", uri);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!ges_formatter_load_from_uri (p, timeline, uri, error)) {
|
||||
GST_ERROR ("error deserializing formatter");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
fail:
|
||||
if (p)
|
||||
g_object_unref (p);
|
||||
return ret;
|
||||
GST_FIXME ("This should be reimplemented");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1980,32 +1959,8 @@ gboolean
|
|||
ges_timeline_save_to_uri (GESTimeline * timeline, const gchar * uri,
|
||||
GError ** error)
|
||||
{
|
||||
GESFormatter *p = NULL;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
/* FIXME : How will the user be able to chose the format he
|
||||
* wishes to store to ? */
|
||||
|
||||
/* FIXME : How will we ensure a timeline loaded with a certain format
|
||||
* will be saved with the same one by default ? We need to make this
|
||||
* easy from an API perspective */
|
||||
|
||||
if (!(p = ges_formatter_new_for_uri (uri))) {
|
||||
GST_ERROR ("unsupported uri '%s'", uri);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!ges_formatter_save_to_uri (p, timeline, uri, error)) {
|
||||
GST_ERROR ("error serializing formatter");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
fail:
|
||||
if (p)
|
||||
g_object_unref (p);
|
||||
return ret;
|
||||
GST_FIXME ("This should be reimplemented");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -72,7 +72,6 @@ ges_init (void)
|
|||
|
||||
/* register formatter types with the system */
|
||||
GES_TYPE_PITIVI_FORMATTER;
|
||||
GES_TYPE_KEYFILE_FORMATTER;
|
||||
|
||||
/* check the gnonlin elements are available */
|
||||
if (!ges_check_gnonlin_availability ())
|
||||
|
|
|
@ -63,7 +63,6 @@
|
|||
#include <ges/ges-track-effect.h>
|
||||
#include <ges/ges-track-parse-launch-effect.h>
|
||||
#include <ges/ges-formatter.h>
|
||||
#include <ges/ges-keyfile-formatter.h>
|
||||
#include <ges/ges-pitivi-formatter.h>
|
||||
#include <ges/ges-utils.h>
|
||||
|
||||
|
|
|
@ -39,8 +39,7 @@ check_PROGRAMS = \
|
|||
ges/titles\
|
||||
ges/transition \
|
||||
ges/overlays\
|
||||
ges/text_properties\
|
||||
ges/save_and_load
|
||||
ges/text_properties
|
||||
|
||||
noinst_LTLIBRARIES=$(testutils_noisnt_libraries)
|
||||
noinst_HEADERS=$(testutils_noinst_headers)
|
||||
|
|
|
@ -1,808 +0,0 @@
|
|||
/* GStreamer Editing Services
|
||||
* Copyright (C) 2010 Brandon Lewis <brandon.lewis@collabora.co.uk>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "test-utils.h"
|
||||
#include <ges/ges.h>
|
||||
#include <gst/check/gstcheck.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#define GetCurrentDir getcwd
|
||||
|
||||
#include <gst/audio/audio.h>
|
||||
|
||||
#define KEY_FILE_START {\
|
||||
if (cmp) g_key_file_free (cmp);\
|
||||
cmp = g_key_file_new ();\
|
||||
}
|
||||
|
||||
#define KEY(group, key, value) \
|
||||
g_key_file_set_value (cmp, group, key, value)
|
||||
|
||||
#define COMPARE fail_unless(compare (cmp, formatter, timeline))
|
||||
|
||||
static gboolean
|
||||
compare (GKeyFile * cmp, GESFormatter * formatter, GESTimeline * timeline)
|
||||
{
|
||||
gchar *data, *fmt_data;
|
||||
gsize length;
|
||||
gboolean result = TRUE;
|
||||
|
||||
data = g_key_file_to_data (cmp, &length, NULL);
|
||||
ges_formatter_save (formatter, timeline);
|
||||
fmt_data = ges_formatter_get_data (formatter, &length);
|
||||
|
||||
if (!(g_strcmp0 (data, fmt_data) == 0)) {
|
||||
GST_ERROR ("difference between expected and output");
|
||||
GST_ERROR ("expected: \n%s", data);
|
||||
GST_ERROR ("actual: \n%s", fmt_data);
|
||||
result = FALSE;
|
||||
}
|
||||
g_free (data);
|
||||
return result;
|
||||
}
|
||||
|
||||
GST_START_TEST (test_simple)
|
||||
{
|
||||
gchar *uri = ges_test_file_uri ("test.xptv");
|
||||
|
||||
ges_init ();
|
||||
|
||||
fail_unless (ges_formatter_can_load_uri (uri, NULL));
|
||||
g_free (uri);
|
||||
|
||||
uri = ges_test_file_uri ("wrong_test.xptv");
|
||||
fail_if (ges_formatter_can_load_uri (uri, NULL));
|
||||
g_free (uri);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_keyfile_save)
|
||||
{
|
||||
GESTimeline *timeline;
|
||||
GESTimelineLayer *layer, *layer2;
|
||||
GESTrack *track;
|
||||
GESTimelineObject *source;
|
||||
GESFormatter *formatter;
|
||||
GKeyFile *cmp = NULL;
|
||||
|
||||
ges_init ();
|
||||
|
||||
/* setup timeline */
|
||||
|
||||
GST_DEBUG ("Create a timeline");
|
||||
timeline = ges_timeline_new ();
|
||||
fail_unless (timeline != NULL);
|
||||
|
||||
/* create serialization object */
|
||||
|
||||
GST_DEBUG ("creating a keyfile formatter");
|
||||
formatter = GES_FORMATTER (ges_keyfile_formatter_new ());
|
||||
|
||||
/* add a layer and make sure it's serialized */
|
||||
|
||||
GST_DEBUG ("Create a layer");
|
||||
layer = GES_TIMELINE_LAYER (ges_simple_timeline_layer_new ());
|
||||
fail_unless (layer != NULL);
|
||||
|
||||
GST_DEBUG ("Add the layer to the timeline");
|
||||
fail_unless (ges_timeline_add_layer (timeline, layer));
|
||||
|
||||
KEY_FILE_START;
|
||||
KEY ("General", "version", "1");
|
||||
KEY ("Layer0", "priority", "0");
|
||||
KEY ("Layer0", "type", "simple");
|
||||
COMPARE;
|
||||
|
||||
/* add a track and make sure it's serialized */
|
||||
|
||||
GST_DEBUG ("Create a Track");
|
||||
track = ges_track_audio_raw_new ();
|
||||
fail_unless (track != NULL);
|
||||
|
||||
GST_DEBUG ("Add the track to the timeline");
|
||||
fail_unless (ges_timeline_add_track (timeline, track));
|
||||
|
||||
KEY_FILE_START;
|
||||
KEY ("General", "version", "1");
|
||||
KEY ("Track0", "type", "GES_TRACK_TYPE_AUDIO");
|
||||
KEY ("Track0", "caps", "audio/x-raw");
|
||||
KEY ("Layer0", "priority", "0");
|
||||
KEY ("Layer0", "type", "simple");
|
||||
COMPARE;
|
||||
|
||||
/* add sources */
|
||||
|
||||
GST_DEBUG ("Adding first source");
|
||||
source = (GESTimelineObject *) ges_timeline_test_source_new ();
|
||||
ges_simple_timeline_layer_add_object (GES_SIMPLE_TIMELINE_LAYER (layer),
|
||||
source, -1);
|
||||
g_object_set (G_OBJECT (source), "duration", (guint64) 2 * GST_SECOND, NULL);
|
||||
|
||||
KEY ("Object0", "type", "GESTimelineTestSource");
|
||||
KEY ("Object0", "start", "0");
|
||||
KEY ("Object0", "in-point", "0");
|
||||
KEY ("Object0", "duration", "2000000000");
|
||||
KEY ("Object0", "priority", "2");
|
||||
KEY ("Object0", "supported-formats", "GES_TRACK_TYPE_UNKNOWN");
|
||||
KEY ("Object0", "max-duration", "18446744073709551615");
|
||||
KEY ("Object0", "mute", "false");
|
||||
KEY ("Object0", "vpattern", "100% Black");
|
||||
KEY ("Object0", "freq", "440");
|
||||
KEY ("Object0", "volume", "0");
|
||||
COMPARE;
|
||||
|
||||
GST_DEBUG ("Adding transition");
|
||||
source = (GESTimelineObject *)
|
||||
ges_timeline_standard_transition_new_for_nick ((gchar *) "bar-wipe-lr");
|
||||
|
||||
g_object_set (G_OBJECT (source), "duration", (guint64) GST_SECOND / 2, NULL);
|
||||
ges_simple_timeline_layer_add_object (GES_SIMPLE_TIMELINE_LAYER (layer),
|
||||
source, -1);
|
||||
|
||||
KEY ("Object1", "type", "GESTimelineStandardTransition");
|
||||
KEY ("Object1", "start", "1500000000");
|
||||
KEY ("Object1", "in-point", "0");
|
||||
KEY ("Object1", "duration", "500000000");
|
||||
KEY ("Object1", "priority", "1");
|
||||
KEY ("Object1", "supported-formats", "GES_TRACK_TYPE_UNKNOWN");
|
||||
KEY ("Object1", "max-duration", "18446744073709551615");
|
||||
KEY ("Object1", "vtype", "A bar moves from left to right");
|
||||
COMPARE;
|
||||
|
||||
GST_DEBUG ("Adding second source");
|
||||
source = (GESTimelineObject *) ges_timeline_test_source_new ();
|
||||
g_object_set (G_OBJECT (source), "duration", (guint64) 2 * GST_SECOND, NULL);
|
||||
ges_simple_timeline_layer_add_object (GES_SIMPLE_TIMELINE_LAYER (layer),
|
||||
source, -1);
|
||||
|
||||
KEY ("Object2", "type", "GESTimelineTestSource");
|
||||
KEY ("Object2", "start", "1500000000");
|
||||
KEY ("Object2", "in-point", "0");
|
||||
KEY ("Object2", "duration", "2000000000");
|
||||
KEY ("Object2", "priority", "3");
|
||||
KEY ("Object2", "supported-formats", "GES_TRACK_TYPE_UNKNOWN");
|
||||
KEY ("Object2", "max-duration", "18446744073709551615");
|
||||
KEY ("Object2", "mute", "false");
|
||||
KEY ("Object2", "vpattern", "100% Black");
|
||||
KEY ("Object2", "freq", "440");
|
||||
KEY ("Object2", "volume", "0");
|
||||
COMPARE;
|
||||
|
||||
/* add a second layer to the timeline */
|
||||
|
||||
GST_DEBUG ("Adding a second layer to the timeline");
|
||||
layer2 = ges_timeline_layer_new ();
|
||||
ges_timeline_layer_set_priority (layer2, 1);
|
||||
fail_unless (layer != NULL);
|
||||
fail_unless (ges_timeline_add_layer (timeline, layer2));
|
||||
|
||||
KEY ("Layer1", "priority", "1");
|
||||
KEY ("Layer1", "type", "default");
|
||||
COMPARE;
|
||||
|
||||
GST_DEBUG ("Adding a few more sources");
|
||||
source = (GESTimelineObject *) ges_timeline_title_source_new ();
|
||||
g_object_set (G_OBJECT (source),
|
||||
"duration", (guint64) GST_SECOND,
|
||||
"start", (guint64) 5 * GST_SECOND, "text", "the quick brown fox", NULL);
|
||||
fail_unless (ges_timeline_layer_add_object (layer2, source));
|
||||
|
||||
KEY ("Object3", "type", "GESTimelineTitleSource");
|
||||
KEY ("Object3", "start", "5000000000");
|
||||
KEY ("Object3", "in-point", "0");
|
||||
KEY ("Object3", "duration", "1000000000");
|
||||
KEY ("Object3", "priority", "0");
|
||||
KEY ("Object3", "supported-formats", "GES_TRACK_TYPE_UNKNOWN");
|
||||
KEY ("Object3", "max-duration", "18446744073709551615");
|
||||
KEY ("Object3", "mute", "false");
|
||||
KEY ("Object3", "text", "\"the\\\\ quick\\\\ brown\\\\ fox\"");
|
||||
KEY ("Object3", "font-desc", "\"Serif\\\\ 36\"");
|
||||
KEY ("Object3", "halignment", "center");
|
||||
KEY ("Object3", "valignment", "baseline");
|
||||
KEY ("Object3", "color", "4294967295");
|
||||
KEY ("Object3", "background", "4294967295");
|
||||
KEY ("Object3", "xpos", "0.5");
|
||||
KEY ("Object3", "ypos", "0.5");
|
||||
COMPARE;
|
||||
|
||||
/* tear-down */
|
||||
g_key_file_free (cmp);
|
||||
|
||||
|
||||
GST_DEBUG ("Removing layer from the timeline");
|
||||
fail_unless (ges_timeline_remove_layer (timeline, layer));
|
||||
fail_unless (ges_timeline_remove_layer (timeline, layer2));
|
||||
|
||||
GST_DEBUG ("Removing track from the timeline");
|
||||
g_object_ref (track);
|
||||
fail_unless (ges_timeline_remove_track (timeline, track));
|
||||
fail_unless (ges_track_get_timeline (track) == NULL);
|
||||
ASSERT_OBJECT_REFCOUNT (track, "track", 1);
|
||||
g_object_unref (track);
|
||||
|
||||
ASSERT_OBJECT_REFCOUNT (timeline, "timeline", 1);
|
||||
|
||||
g_object_unref (timeline);
|
||||
g_object_unref (formatter);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
/* do action for every item and then free the list */
|
||||
|
||||
#define g_list_free_all(list) \
|
||||
{ \
|
||||
g_list_foreach(list, (GFunc) g_object_unref, NULL); \
|
||||
g_list_free(list); \
|
||||
}
|
||||
|
||||
/* print out a helpful error message when a comparison fails. Works with the
|
||||
* TIMELINE_COMPARE_*, LAYER*, SIMPLE_LAYER*, abd TRACK, macros below to give
|
||||
* information about the source line where the failing object was created.
|
||||
*/
|
||||
|
||||
#define CMP_FAIL(a, ...) \
|
||||
fail_unless (FALSE, __VA_ARGS__);
|
||||
|
||||
/* compare two GObjects for equality. pointer identity and GType short-circuit
|
||||
* the comparison. If a and b are not identical pointers and of the same
|
||||
* GType, compares every readable property for equality using
|
||||
* g_param_values_cmp.
|
||||
*/
|
||||
|
||||
static gboolean
|
||||
ges_objs_equal (GObject * a, GObject * b)
|
||||
{
|
||||
GType at;
|
||||
GObjectClass *klass;
|
||||
GParamSpec **props = NULL, **iter = NULL;
|
||||
guint n_props, i;
|
||||
guint ret = FALSE;
|
||||
gchar *typename;
|
||||
|
||||
GST_DEBUG ("comparing %s (%p) and %s (%p)\n",
|
||||
G_OBJECT_TYPE_NAME (a), a, G_OBJECT_TYPE_NAME (b), b);
|
||||
|
||||
if (a == b)
|
||||
return TRUE;
|
||||
|
||||
at = G_TYPE_FROM_INSTANCE (a);
|
||||
|
||||
fail_unless (at == G_TYPE_FROM_INSTANCE (b));
|
||||
|
||||
typename = (gchar *) g_type_name (at);
|
||||
|
||||
/* compare every readable property */
|
||||
|
||||
klass = G_OBJECT_GET_CLASS (a);
|
||||
props = g_object_class_list_properties (klass, &n_props);
|
||||
|
||||
for (i = 0, iter = props; i < n_props; i++, iter++) {
|
||||
GValue av = { 0 }
|
||||
, bv = {
|
||||
0};
|
||||
|
||||
/* ignore name and layer properties */
|
||||
if (!g_strcmp0 ("name", (*iter)->name) ||
|
||||
!g_strcmp0 ("layer", (*iter)->name) ||
|
||||
!g_strcmp0 ("parent", (*iter)->name))
|
||||
continue;
|
||||
|
||||
/* special case caps property */
|
||||
if (!g_strcmp0 ("caps", (*iter)->name)) {
|
||||
GstCaps *acaps, *bcaps;
|
||||
|
||||
g_object_get (a, "caps", &acaps, NULL);
|
||||
g_object_get (b, "caps", &bcaps, NULL);
|
||||
if (gst_caps_is_equal (acaps, bcaps)) {
|
||||
gst_caps_unref (acaps);
|
||||
gst_caps_unref (bcaps);
|
||||
continue;
|
||||
} else {
|
||||
gst_caps_unref (acaps);
|
||||
gst_caps_unref (bcaps);
|
||||
CMP_FAIL (b, "%s's %p and %p differ by property caps", a, b);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
g_value_init (&av, (*iter)->value_type);
|
||||
g_value_init (&bv, (*iter)->value_type);
|
||||
|
||||
if (!((*iter)->flags & G_PARAM_READABLE))
|
||||
continue;
|
||||
|
||||
g_object_get_property (a, (*iter)->name, &av);
|
||||
g_object_get_property (b, (*iter)->name, &bv);
|
||||
|
||||
if (g_param_values_cmp (*iter, &av, &bv) != 0) {
|
||||
gchar *a_str, *b_str;
|
||||
|
||||
a_str = gst_value_serialize (&av);
|
||||
b_str = gst_value_serialize (&bv);
|
||||
|
||||
CMP_FAIL (b, "%s's %p and %p differ by property %s (%s != %s)",
|
||||
typename, a, b, (*iter)->name, a_str, b_str);
|
||||
|
||||
g_free (a_str);
|
||||
g_free (b_str);
|
||||
|
||||
goto fail;
|
||||
}
|
||||
|
||||
g_value_unset (&av);
|
||||
g_value_unset (&bv);
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
fail:
|
||||
if (props)
|
||||
g_free (props);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ges_tracks_equal (GESTrack * a, GESTrack * b)
|
||||
{
|
||||
return ges_objs_equal (G_OBJECT (a), G_OBJECT (b));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ges_layers_equal (GESTimelineLayer * a, GESTimelineLayer * b)
|
||||
{
|
||||
GList *a_objs = NULL, *b_objs = NULL, *a_iter, *b_iter;
|
||||
gboolean ret = FALSE;
|
||||
guint i;
|
||||
|
||||
if (!ges_objs_equal (G_OBJECT (a), G_OBJECT (b)))
|
||||
return FALSE;
|
||||
|
||||
a_objs = ges_timeline_layer_get_objects (a);
|
||||
b_objs = ges_timeline_layer_get_objects (b);
|
||||
|
||||
/* one shortcoming of this procedure is that the objects need to be stored
|
||||
* in the same order. Not sure if this is a problem in practice */
|
||||
|
||||
for (i = 0, a_iter = a_objs, b_iter = b_objs; a_iter && b_iter; a_iter =
|
||||
a_iter->next, b_iter = b_iter->next, i++) {
|
||||
if (!ges_objs_equal (a_iter->data, b_iter->data)) {
|
||||
CMP_FAIL (b, "layers %p and %p differ by obj at position %d", a, b, i);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (a_iter || b_iter) {
|
||||
CMP_FAIL (b, "layers %p and %p have differing number of objects", a, b);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
fail:
|
||||
|
||||
g_list_free_all (a_objs);
|
||||
g_list_free_all (b_objs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ges_timelines_equal (GESTimeline * a, GESTimeline * b)
|
||||
{
|
||||
GList *a_tracks, *b_tracks, *a_iter, *b_iter, *a_layers, *b_layers;
|
||||
|
||||
gboolean ret = FALSE;
|
||||
guint i;
|
||||
|
||||
if (!ges_objs_equal (G_OBJECT (a), G_OBJECT (b))) {
|
||||
CMP_FAIL (b, "%p and %p are not of the same type");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
a_tracks = ges_timeline_get_tracks (a);
|
||||
b_tracks = ges_timeline_get_tracks (b);
|
||||
a_layers = ges_timeline_get_layers (a);
|
||||
b_layers = ges_timeline_get_layers (b);
|
||||
|
||||
/* one shortcoming of this procedure is that the objects need to be stored
|
||||
* in the same order. Not sure if this is a problem in practice */
|
||||
|
||||
for (i = 0, a_iter = a_tracks, b_iter = b_tracks; a_iter && b_iter; a_iter =
|
||||
a_iter->next, b_iter = b_iter->next, i++) {
|
||||
if (!ges_tracks_equal (a_iter->data, b_iter->data)) {
|
||||
CMP_FAIL (b, "GESTimelines %p and %p differ by tracks at position %d", a,
|
||||
b, i);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (a_iter || b_iter) {
|
||||
CMP_FAIL (b, "GESTimelines %p and %p have differing number of tracks", a,
|
||||
b);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (i = 0, a_iter = a_layers, b_iter = b_layers; a_iter && b_iter; a_iter =
|
||||
a_iter->next, b_iter = b_iter->next, i++) {
|
||||
if (!ges_layers_equal (a_iter->data, b_iter->data)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (a_iter || b_iter) {
|
||||
CMP_FAIL (b, "GESTimelines %p and %p have differing numbre of layers", a,
|
||||
b);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
fail:
|
||||
|
||||
g_list_free_all (a_tracks);
|
||||
g_list_free_all (b_tracks);
|
||||
g_list_free_all (a_layers);
|
||||
g_list_free_all (b_layers);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define TIMELINE_BEGIN(location) \
|
||||
{\
|
||||
GESTimeline **a, *b;\
|
||||
a = &(location);\
|
||||
if (*a) g_object_unref (*a);\
|
||||
b = ges_timeline_new();\
|
||||
*a = b;\
|
||||
|
||||
#define TIMELINE_END }
|
||||
|
||||
#define TIMELINE_COMPARE(a, b)\
|
||||
{\
|
||||
fail_unless (ges_timelines_equal(a, b));\
|
||||
}
|
||||
|
||||
#define TRACK(type, caps) \
|
||||
{\
|
||||
GESTrack *trk;\
|
||||
GstCaps *c;\
|
||||
c = gst_caps_from_string(caps);\
|
||||
trk = ges_track_new (type, c);\
|
||||
ges_timeline_add_track (b, trk);\
|
||||
g_object_set_data(G_OBJECT(trk),"file", (void *) __FILE__);\
|
||||
g_object_set_data(G_OBJECT(trk),"line", (void *) __LINE__);\
|
||||
g_object_set_data(G_OBJECT(trk),"function", (void *) GST_FUNCTION);\
|
||||
}
|
||||
|
||||
#define LAYER_BEGIN(priority) \
|
||||
{\
|
||||
GESTimelineLayer *l;\
|
||||
l = ges_timeline_layer_new ();\
|
||||
ges_timeline_add_layer (b, l);\
|
||||
ges_timeline_layer_set_priority (l, priority);\
|
||||
g_object_set_data(G_OBJECT(l),"file", (void *) __FILE__);\
|
||||
g_object_set_data(G_OBJECT(l),"line", (void *) __LINE__);\
|
||||
g_object_set_data(G_OBJECT(l),"function", (void *) GST_FUNCTION);
|
||||
|
||||
#define LAYER_END \
|
||||
}
|
||||
|
||||
#define LAYER_OBJECT(type, ...) \
|
||||
{\
|
||||
GESTimelineObject *obj;\
|
||||
obj = GES_TIMELINE_OBJECT(\
|
||||
g_object_new ((type), __VA_ARGS__, NULL));\
|
||||
ges_timeline_layer_add_object (l, obj);\
|
||||
g_object_set_data(G_OBJECT(obj),"file", (void *) __FILE__);\
|
||||
g_object_set_data(G_OBJECT(obj),"line", (void *) __LINE__);\
|
||||
g_object_set_data(G_OBJECT(obj),"function", (void *) GST_FUNCTION);\
|
||||
}
|
||||
|
||||
#define SIMPLE_LAYER_BEGIN(priority) \
|
||||
{\
|
||||
GESSimpleTimelineLayer *l;\
|
||||
l = ges_simple_timeline_layer_new ();\
|
||||
ges_timeline_add_layer (b, GES_TIMELINE_LAYER(l));\
|
||||
ges_timeline_layer_set_priority(GES_TIMELINE_LAYER(l), priority);\
|
||||
g_object_set_data(G_OBJECT(l),"file", (void *) __FILE__);\
|
||||
g_object_set_data(G_OBJECT(l),"line", (void *) __LINE__);\
|
||||
g_object_set_data(G_OBJECT(l),"function", (void *) GST_FUNCTION);
|
||||
|
||||
#define SIMPLE_LAYER_OBJECT(type, position, ...) \
|
||||
{\
|
||||
GESTimelineObject *obj;\
|
||||
obj = GES_TIMELINE_OBJECT(\
|
||||
g_object_new ((type), __VA_ARGS__, NULL));\
|
||||
ges_simple_timeline_layer_add_object (l, obj, position);\
|
||||
g_object_set_data(G_OBJECT(obj),"file", (void *) __FILE__);\
|
||||
g_object_set_data(G_OBJECT(obj),"line", (void *) __LINE__);\
|
||||
g_object_set_data(G_OBJECT(obj),"function", (void *) GST_FUNCTION);\
|
||||
}
|
||||
|
||||
/* */
|
||||
static const gchar *data = "\n[General]\n"
|
||||
"[Track0]\n"
|
||||
"type=GES_TRACK_TYPE_AUDIO\n"
|
||||
"caps=audio/x-raw\n"
|
||||
"\n"
|
||||
"[Layer0]\n"
|
||||
"priority=0\n"
|
||||
"type=simple\n"
|
||||
"\n"
|
||||
"[Object0]\n"
|
||||
"type=GESTimelineTestSource\n"
|
||||
"start=0\n"
|
||||
"in-point=0\n"
|
||||
"duration=2000000000\n"
|
||||
"priority=2\n"
|
||||
"mute=false\n"
|
||||
"vpattern=100% Black\n"
|
||||
"freq=440\n"
|
||||
"volume=0\n"
|
||||
"\n"
|
||||
"[Object1]\n"
|
||||
"type=GESTimelineStandardTransition\n"
|
||||
"start=1500000000\n"
|
||||
"in-point=0\n"
|
||||
"duration=500000000\n"
|
||||
"priority=1\n"
|
||||
"vtype=A bar moves from left to right\n"
|
||||
"\n"
|
||||
"[Object2]\n"
|
||||
"type=GESTimelineTestSource\n"
|
||||
"start=1500000000\n"
|
||||
"in-point=0\n"
|
||||
"duration=2000000000\n"
|
||||
"priority=2\n"
|
||||
"mute=false\n"
|
||||
"vpattern=100% Black\n"
|
||||
"freq=440\n"
|
||||
"volume=0\n"
|
||||
"\n"
|
||||
"[Layer1]\n"
|
||||
"priority=1\n"
|
||||
"type=default\n"
|
||||
"\n"
|
||||
"[Object3]\n"
|
||||
"type=GESTimelineTitleSource\n"
|
||||
"start=5000000000\n"
|
||||
"in-point=0\n"
|
||||
"duration=1000000000\n"
|
||||
"priority=2\n"
|
||||
"mute=false\n"
|
||||
"text=\"the\\\\ quick\\\\ brown\\\\ fox\"\n"
|
||||
"font-desc=\"Serif\\\\ 36\"\n"
|
||||
"halignment=center\n" "valignment=baseline\n";
|
||||
|
||||
GST_START_TEST (test_keyfile_load)
|
||||
{
|
||||
GESTimeline *timeline = NULL, *expected = NULL;
|
||||
GESFormatter *formatter;
|
||||
|
||||
ges_init ();
|
||||
|
||||
/* setup timeline */
|
||||
|
||||
GST_DEBUG ("Create a timeline");
|
||||
timeline = ges_timeline_new ();
|
||||
fail_unless (timeline != NULL);
|
||||
|
||||
/* create serialization object */
|
||||
|
||||
GST_DEBUG ("creating a default formatter");
|
||||
formatter = GES_FORMATTER (ges_keyfile_formatter_new ());
|
||||
|
||||
ges_formatter_set_data (formatter, g_strdup (data), strlen (data));
|
||||
|
||||
fail_unless (ges_formatter_load (formatter, timeline));
|
||||
|
||||
TIMELINE_BEGIN (expected) {
|
||||
|
||||
TRACK (GES_TRACK_TYPE_AUDIO, "audio/x-raw");
|
||||
|
||||
SIMPLE_LAYER_BEGIN (0) {
|
||||
|
||||
SIMPLE_LAYER_OBJECT ((GES_TYPE_TIMELINE_TEST_SOURCE), -1,
|
||||
"duration", (guint64) 2 * GST_SECOND);
|
||||
|
||||
SIMPLE_LAYER_OBJECT ((GES_TYPE_TIMELINE_STANDARD_TRANSITION), -1,
|
||||
"duration", (guint64) GST_SECOND / 2,
|
||||
"vtype", GES_VIDEO_STANDARD_TRANSITION_TYPE_BAR_WIPE_LR);
|
||||
|
||||
SIMPLE_LAYER_OBJECT ((GES_TYPE_TIMELINE_TEST_SOURCE), -1,
|
||||
"duration", (guint64) 2 * GST_SECOND);
|
||||
|
||||
} LAYER_END;
|
||||
|
||||
LAYER_BEGIN (1) {
|
||||
|
||||
LAYER_OBJECT (GES_TYPE_TIMELINE_TITLE_SOURCE,
|
||||
"start", (guint64) 5 * GST_SECOND,
|
||||
"duration", (guint64) GST_SECOND, "priority", 2, "text",
|
||||
"the quick brown fox");
|
||||
|
||||
} LAYER_END;
|
||||
|
||||
} TIMELINE_END;
|
||||
|
||||
TIMELINE_COMPARE (timeline, expected);
|
||||
|
||||
/* tear-down */
|
||||
g_object_unref (formatter);
|
||||
g_object_unref (timeline);
|
||||
g_object_unref (expected);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_pitivi_file_load)
|
||||
{
|
||||
GESFormatter *formatter;
|
||||
GESTimeline *timeline, *expected;
|
||||
GMainLoop *mainloop;
|
||||
gchar *uri, *save_uri, *cur_dir;
|
||||
|
||||
/*create the expected timeline */
|
||||
timeline = ges_timeline_new ();
|
||||
mainloop = g_main_loop_new (NULL, FALSE);
|
||||
expected = ges_timeline_new ();
|
||||
|
||||
/* create the timeline from formatter */
|
||||
formatter = GES_FORMATTER (ges_pitivi_formatter_new ());
|
||||
cur_dir = g_get_current_dir ();
|
||||
uri = g_build_filename (cur_dir, "test.xptv", NULL);
|
||||
save_uri = g_build_filename (cur_dir, "testsave.xptv", NULL);
|
||||
g_free (cur_dir);
|
||||
|
||||
if (g_file_test (uri, G_FILE_TEST_EXISTS) == FALSE) {
|
||||
GST_ERROR ("Could not test GESPitiviFormatter as no project file found");
|
||||
return;
|
||||
}
|
||||
|
||||
ges_formatter_load_from_uri (formatter, timeline, uri, NULL);
|
||||
g_timeout_add (1000, (GSourceFunc) g_main_loop_quit, mainloop);
|
||||
g_main_loop_run (mainloop);
|
||||
|
||||
formatter = GES_FORMATTER (ges_pitivi_formatter_new ());
|
||||
ges_formatter_save_to_uri (formatter, timeline, save_uri, NULL);
|
||||
formatter = GES_FORMATTER (ges_pitivi_formatter_new ());
|
||||
ges_formatter_load_from_uri (formatter, expected, uri, NULL);
|
||||
g_timeout_add (1000, (GSourceFunc) g_main_loop_quit, mainloop);
|
||||
g_main_loop_run (mainloop);
|
||||
|
||||
/* compare the two timelines and fail test if they are different */
|
||||
TIMELINE_COMPARE (expected, timeline);
|
||||
g_free (uri);
|
||||
g_free (save_uri);
|
||||
g_main_loop_unref (mainloop);
|
||||
g_object_unref (formatter);
|
||||
g_object_unref (timeline);
|
||||
g_object_unref (expected);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_keyfile_identity)
|
||||
{
|
||||
|
||||
/* we will create several timelines. they will first be serialized, then
|
||||
* deseriailzed and compared against the original. */
|
||||
|
||||
GESTimeline *orig = NULL, *serialized = NULL;
|
||||
GESFormatter *formatter;
|
||||
|
||||
ges_init ();
|
||||
|
||||
formatter = GES_FORMATTER (ges_keyfile_formatter_new ());
|
||||
|
||||
TIMELINE_BEGIN (orig) {
|
||||
|
||||
TRACK (GES_TRACK_TYPE_AUDIO, "audio/x-raw,"
|
||||
"format=(string)" GST_AUDIO_NE (S32) ",rate=8000");
|
||||
TRACK (GES_TRACK_TYPE_VIDEO, "video/x-raw,format=(string)RGB24");
|
||||
|
||||
LAYER_BEGIN (5) {
|
||||
|
||||
LAYER_OBJECT (GES_TYPE_TIMELINE_TEXT_OVERLAY,
|
||||
"start", (guint64) GST_SECOND,
|
||||
"duration", (guint64) 2 * GST_SECOND,
|
||||
"priority", 1,
|
||||
"text", "Hello, world!",
|
||||
"font-desc", "Sans 9",
|
||||
"halignment", GES_TEXT_HALIGN_LEFT,
|
||||
"valignment", GES_TEXT_VALIGN_TOP);
|
||||
|
||||
LAYER_OBJECT (GES_TYPE_TIMELINE_TEST_SOURCE,
|
||||
"start", (guint64) 0,
|
||||
"duration", (guint64) 5 * GST_SECOND,
|
||||
"priority", 2,
|
||||
"freq", (gdouble) 500,
|
||||
"volume", 1.0, "vpattern", GES_VIDEO_TEST_PATTERN_WHITE);
|
||||
|
||||
LAYER_OBJECT (GES_TYPE_TIMELINE_TEXT_OVERLAY,
|
||||
"start", (guint64) 7 * GST_SECOND,
|
||||
"duration", (guint64) 2 * GST_SECOND,
|
||||
"priority", 2,
|
||||
"text", "Hello, world!",
|
||||
"font-desc", "Sans 9",
|
||||
"halignment", GES_TEXT_HALIGN_LEFT,
|
||||
"valignment", GES_TEXT_VALIGN_TOP);
|
||||
|
||||
LAYER_OBJECT (GES_TYPE_TIMELINE_TEST_SOURCE,
|
||||
"start", (guint64) 6 * GST_SECOND,
|
||||
"duration", (guint64) 5 * GST_SECOND,
|
||||
"priority", 3,
|
||||
"freq", (gdouble) 600,
|
||||
"volume", 1.0, "vpattern", GES_VIDEO_TEST_PATTERN_RED);
|
||||
|
||||
}
|
||||
LAYER_END;
|
||||
|
||||
}
|
||||
TIMELINE_END;
|
||||
|
||||
serialized = ges_timeline_new ();
|
||||
|
||||
ges_formatter_save (formatter, orig);
|
||||
ges_formatter_load (formatter, serialized);
|
||||
|
||||
TIMELINE_COMPARE (serialized, orig);
|
||||
|
||||
g_object_unref (formatter);
|
||||
g_object_unref (serialized);
|
||||
g_object_unref (orig);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
ges_suite (void)
|
||||
{
|
||||
Suite *s = suite_create ("ges-save-load");
|
||||
TCase *tc_chain = tcase_create ("basic");
|
||||
|
||||
suite_add_tcase (s, tc_chain);
|
||||
|
||||
tcase_add_test (tc_chain, test_simple);
|
||||
tcase_add_test (tc_chain, test_keyfile_save);
|
||||
tcase_add_test (tc_chain, test_keyfile_load);
|
||||
tcase_add_test (tc_chain, test_keyfile_identity);
|
||||
tcase_add_test (tc_chain, test_pitivi_file_load);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int nf;
|
||||
|
||||
Suite *s = ges_suite ();
|
||||
SRunner *sr = srunner_create (s);
|
||||
|
||||
gst_check_init (&argc, &argv);
|
||||
|
||||
srunner_run_all (sr, CK_NORMAL);
|
||||
nf = srunner_ntests_failed (sr);
|
||||
srunner_free (sr);
|
||||
|
||||
return nf;
|
||||
}
|
|
@ -1377,6 +1377,8 @@ fail:
|
|||
static gboolean
|
||||
load_file_async (App * app)
|
||||
{
|
||||
|
||||
#if 0
|
||||
GESFormatter *formatter;
|
||||
g_printf ("%s\n", app->pending_uri);
|
||||
|
||||
|
@ -1386,6 +1388,9 @@ load_file_async (App * app)
|
|||
|
||||
g_free (app->pending_uri);
|
||||
app->pending_uri = NULL;
|
||||
#endif
|
||||
|
||||
GST_FIXME ("This should be reimplemented");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue