From: Brandon Lewis Date: Thu, 7 Oct 2010 12:49:15 +0000 (+0100) Subject: GESKeyFileFormatter: New GKeyFile GESFormatter X-Git-Tag: 1.19.3~493^2~2545 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9f1dc7709a8453122d127af18758aff398d76b77;p=platform%2Fupstream%2Fgstreamer.git GESKeyFileFormatter: New GKeyFile GESFormatter --- diff --git a/docs/libs/ges-docs.sgml b/docs/libs/ges-docs.sgml index 284d8ea..50e85cb 100644 --- a/docs/libs/ges-docs.sgml +++ b/docs/libs/ges-docs.sgml @@ -80,6 +80,7 @@ platform as well as Windows. It is released under the GNU Library General Public Serialization Classes + diff --git a/docs/libs/ges-sections.txt b/docs/libs/ges-sections.txt index 599c61a..ee9af24 100644 --- a/docs/libs/ges-sections.txt +++ b/docs/libs/ges-sections.txt @@ -536,7 +536,7 @@ GES_TYPE_TRACK_TEXT_OVERLAY GESFormatter GESFormatter GESFormatterClass -ges_formatter_new +ges_default_formatter_new ges_formatter_load_from_uri ges_formatter_save_to_uri ges_formatter_new_for_uri @@ -553,3 +553,19 @@ GES_IS_FORMATTER GES_IS_FORMATTER_CLASS GES_TYPE_FORMATTER + +
+ges-keyfile-formatter +GESFormatter +GESKeyfileFormatter +GESKeyfileFormatterClass +ges_keyfile_formatter_new + +GES_IS_KEYFILE_FORMATTER +GES_IS_KEYFILE_FORMATTER_CLASS +GES_KEYFILE_FORMATTER +GES_KEYFILE_FORMATTER_CLASS +GES_KEYFILE_FORMATTER_GET_CLASS +GES_TYPE_KEYFILE_FORMATTER +ges_keyfile_formatter_get_type +
diff --git a/docs/libs/ges.types b/docs/libs/ges.types index aa2a79b..cee331b 100644 --- a/docs/libs/ges.types +++ b/docs/libs/ges.types @@ -31,3 +31,4 @@ ges_text_halign_get_type ges_video_test_pattern_get_type ges_track_operation_get_type ges_formatter_get_type +ges_keyfile_formatter_get_type diff --git a/ges/Makefile.am b/ges/Makefile.am index 2dd6d6e..5efb4f3 100644 --- a/ges/Makefile.am +++ b/ges/Makefile.am @@ -39,6 +39,7 @@ libges_@GST_MAJORMINOR@_la_SOURCES = \ ges-track-text-overlay.c \ ges-screenshot.c \ ges-formatter.c \ + ges-keyfile-formatter.c \ ges-utils.c libges_@GST_MAJORMINOR@includedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/ges/ @@ -76,6 +77,7 @@ libges_@GST_MAJORMINOR@include_HEADERS = \ ges-track-text-overlay.h \ ges-screenshot.h \ ges-formatter.h \ + ges-keyfile-formatter.h \ ges-utils.h libges_@GST_MAJORMINOR@_la_CFLAGS = -I$(top_srcdir) $(GST_PROFILE_CFLAGS) $(GST_PBUTILS_CFLAGS) $(GST_VIDEO_CFLAGS) $(GST_CONTROLLER_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) diff --git a/ges/ges-formatter.c b/ges/ges-formatter.c index 48607af..8d36e1d 100644 --- a/ges/ges-formatter.c +++ b/ges/ges-formatter.c @@ -37,10 +37,6 @@ G_DEFINE_TYPE (GESFormatter, ges_formatter, G_TYPE_OBJECT); static void ges_formatter_dispose (GObject * object); static void ges_formatter_finalize (GObject * object); -/* for ini format */ -static gboolean save_ini (GESFormatter * formatter, GESTimeline * timeline); -static gboolean load_ini (GESFormatter * formatter, GESTimeline * timeline); - static void ges_formatter_class_init (GESFormatterClass * klass) { @@ -48,9 +44,6 @@ ges_formatter_class_init (GESFormatterClass * klass) object_class->dispose = ges_formatter_dispose; object_class->finalize = ges_formatter_finalize; - - klass->save = save_ini; - klass->load = load_ini; } static void @@ -74,12 +67,6 @@ ges_formatter_finalize (GObject * formatter) { } -GESFormatter * -ges_formatter_new (void) -{ - return g_object_new (GES_TYPE_FORMATTER, NULL); -} - /** * ges_formatter_new_for_uri: * @uri: a #gchar * pointing to the uri @@ -94,11 +81,26 @@ GESFormatter * ges_formatter_new_for_uri (gchar * uri) { if (ges_formatter_can_load_uri (uri)) - return ges_formatter_new (); + return GES_FORMATTER (ges_keyfile_formatter_new ()); return NULL; } /** + * ges_formatter_default_new: + * + * Creates a new instance of the default GESFormatter type on this system + * (currently #GESKeyFileFormatter). + * + * Returns: a #GESFormatter instance or NULL + */ + +GESFormatter * +ges_default_formatter_new (void) +{ + return GES_FORMATTER (ges_keyfile_formatter_new ()); +} + +/** * ges_formatter_can_load_uri: * @uri: a #gchar * pointing to the URI * @@ -187,6 +189,7 @@ ges_formatter_load (GESFormatter * formatter, GESTimeline * timeline) if (klass->load) return klass->load (formatter, timeline); + GST_ERROR ("not implemented!"); return FALSE; } @@ -213,6 +216,7 @@ ges_formatter_save (GESFormatter * formatter, GESTimeline * timeline) if (klass->save) return klass->save (formatter, timeline); + GST_ERROR ("not implemented!"); return FALSE; } @@ -315,392 +319,3 @@ ges_formatter_save_to_uri (GESFormatter * formatter, GESTimeline * timeline, return ret; } - -static gboolean -save_ini (GESFormatter * formatter, GESTimeline * timeline) -{ - GKeyFile *kf; - GList *tmp, *tracks; - int i = 0; - int n_objects = 0; - gchar buffer[255]; - - GST_DEBUG ("saving 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 (track->caps); - - 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); - - for (i = 0, tmp = timeline->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", layer->priority); - 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); - } - - if (formatter->data) { - g_free (formatter->data); - } - - formatter->data = g_key_file_to_data (kf, &formatter->length, NULL); - 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; - 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); - gst_value_deserialize (&v, type_field); - g_free (type_field); - - if (!caps) - 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", 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_ini (GESFormatter * formatter, GESTimeline * timeline) -{ - GKeyFile *kf; - GError *error = NULL; - gboolean ret = TRUE; - gchar **groups; - gsize n_groups, i; - GESTimelineLayer *cur_layer = NULL; - - kf = g_key_file_new (); - if (!g_key_file_load_from_data (kf, formatter->data, formatter->length, - G_KEY_FILE_NONE, &error)) { - ret = FALSE; - GST_ERROR (error->message); - GST_INFO (formatter->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; -} diff --git a/ges/ges-formatter.h b/ges/ges-formatter.h index 01beac5..d35f22b 100644 --- a/ges/ges-formatter.h +++ b/ges/ges-formatter.h @@ -79,8 +79,8 @@ struct _GESFormatterClass { GType ges_formatter_get_type (void); -GESFormatter *ges_formatter_new (void); GESFormatter *ges_formatter_new_for_uri (gchar *uri); +GESFormatter *ges_default_formatter_new (void); gboolean ges_formatter_can_load_uri (gchar * uri); gboolean ges_formatter_can_save_uri (gchar * uri); diff --git a/ges/ges-keyfile-formatter.c b/ges/ges-keyfile-formatter.c new file mode 100644 index 0000000..0dfdf0c --- /dev/null +++ b/ges/ges-keyfile-formatter.c @@ -0,0 +1,471 @@ +/* GStreamer Editing Services + * Copyright (C) 2010 Brandon Lewis + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:ges-keyfile-formatter + * @short_description: Base Class for loading and saving #GESTimeline data. + * + * Responsible for loading and/or saving the contents of a #GESTimeline to/from + * various formats. + **/ + +#include +#include +#include "ges.h" +#include "ges-internal.h" + +G_DEFINE_TYPE (GESKeyfileFormatter, ges_keyfile_formatter, GES_TYPE_FORMATTER); + +static void ges_keyfile_formatter_dispose (GObject * object); +static void ges_keyfile_formatter_finalize (GObject * object); + +/* 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; + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (klass); + formatter_klass = GES_FORMATTER_CLASS (klass); + + + object_class->dispose = ges_keyfile_formatter_dispose; + object_class->finalize = ges_keyfile_formatter_finalize; + + formatter_klass->save = save_keyfile; + formatter_klass->load = load_keyfile; +} + +static void +ges_keyfile_formatter_init (GESKeyfileFormatter * object) +{ +} + +static void +ges_keyfile_formatter_dispose (GObject * object) +{ +} + +static void +ges_keyfile_formatter_finalize (GObject * keyfile_formatter) +{ +} + +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; + int i = 0; + int n_objects = 0; + gchar buffer[255]; + + 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 (track->caps); + + 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); + + for (i = 0, tmp = timeline->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", layer->priority); + 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); + } + + if (keyfile_formatter->data) { + g_free (keyfile_formatter->data); + } + + keyfile_formatter->data = + g_key_file_to_data (kf, &keyfile_formatter->length, NULL); + 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; + 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); + gst_value_deserialize (&v, type_field); + g_free (type_field); + + if (!caps) + 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", 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; + + kf = g_key_file_new (); + if (!g_key_file_load_from_data (kf, keyfile_formatter->data, + keyfile_formatter->length, G_KEY_FILE_NONE, &error)) { + ret = FALSE; + GST_ERROR (error->message); + GST_INFO (keyfile_formatter->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; +} diff --git a/ges/ges-keyfile-formatter.h b/ges/ges-keyfile-formatter.h new file mode 100644 index 0000000..45c31d3 --- /dev/null +++ b/ges/ges-keyfile-formatter.h @@ -0,0 +1,72 @@ +/* GStreamer Editing Services + * Copyright (C) 2010 Brandon Lewis + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GES_KEYFILE_FORMATTER +#define _GES_KEYFILE_FORMATTER + +#include +#include + +#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: + * @parent: parent + * + * Serializes a #GESTimeline to a file using #GKeyFile + */ + +struct _GESKeyfileFormatter { + GESFormatter parent; + + /*< public >*/ +}; + +/** + * GESKeyfileFormatterClass: + * @parent_class: parent class + */ + +struct _GESKeyfileFormatterClass { + GESFormatterClass parent_class; + + /*< public >*/ +}; + +GType ges_keyfile_formatter_get_type (void); + +GESKeyfileFormatter *ges_keyfile_formatter_new (void); + +#endif /* _GES_KEYFILE_FORMATTER */ diff --git a/ges/ges-types.h b/ges/ges-types.h index 1351d2d..003eba8 100644 --- a/ges/ges-types.h +++ b/ges/ges-types.h @@ -108,4 +108,8 @@ typedef struct _GESTrackTextOverlayClass typedef struct _GESFormatter GESFormatter; typedef struct _GESFormatterClass GESFormatterClass; +typedef struct _GESKeyfileFormatter GESKeyfileFormatter; +typedef struct _GESKeyfileFormatterClass GESKeyfileFormatterClass; + + #endif /* __GES_TYPES_H__ */ diff --git a/ges/ges.h b/ges/ges.h index 4bcfe52..8be9a34 100644 --- a/ges/ges.h +++ b/ges/ges.h @@ -55,6 +55,7 @@ #include #include +#include #include