diff --git a/docs/libs/ges-docs.sgml b/docs/libs/ges-docs.sgml index d3b7b89e4f..284d8ea99a 100644 --- a/docs/libs/ges-docs.sgml +++ b/docs/libs/ges-docs.sgml @@ -77,6 +77,11 @@ platform as well as Windows. It is released under the GNU Library General Public + + Serialization Classes + + + Object Hierarchy diff --git a/docs/libs/ges-sections.txt b/docs/libs/ges-sections.txt index c63dac71a7..b2d24e3826 100644 --- a/docs/libs/ges-sections.txt +++ b/docs/libs/ges-sections.txt @@ -529,3 +529,26 @@ GES_TRACK_TEXT_OVERLAY_CLASS GES_TRACK_TEXT_OVERLAY_GET_CLASS GES_TYPE_TRACK_TEXT_OVERLAY + +
+ges-formatter +GESFormatter +GESFormatter +GESFormatterClass +ges_formatter_new +ges_formatter_load_from_uri +ges_formatter_save_to_uri +ges_formatter_new_for_uri +ges_formatter_can_load_uri +ges_formatter_can_save_uri +ges_formatter_load +ges_formatter_save + +ges_formatter_get_type +GES_FORMATTER +GES_FORMATTER_CLASS +GES_FORMATTER_GET_CLASS +GES_IS_FORMATTER +GES_IS_FORMATTER_CLASS +GES_TYPE_FORMATTER +
diff --git a/docs/libs/ges.types b/docs/libs/ges.types index cf8a3e6b60..aa2a79b892 100644 --- a/docs/libs/ges.types +++ b/docs/libs/ges.types @@ -30,3 +30,4 @@ ges_text_valign_get_type ges_text_halign_get_type ges_video_test_pattern_get_type ges_track_operation_get_type +ges_formatter_get_type diff --git a/ges/Makefile.am b/ges/Makefile.am index c3da751def..2dd6d6e2fb 100644 --- a/ges/Makefile.am +++ b/ges/Makefile.am @@ -38,6 +38,7 @@ libges_@GST_MAJORMINOR@_la_SOURCES = \ ges-track-title-source.c \ ges-track-text-overlay.c \ ges-screenshot.c \ + ges-formatter.c \ ges-utils.c libges_@GST_MAJORMINOR@includedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/ges/ @@ -74,6 +75,7 @@ libges_@GST_MAJORMINOR@include_HEADERS = \ ges-track-title-source.h \ ges-track-text-overlay.h \ ges-screenshot.h \ + ges-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 new file mode 100644 index 0000000000..48607afcc0 --- /dev/null +++ b/ges/ges-formatter.c @@ -0,0 +1,706 @@ +/* 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-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-formatter.h" +#include "ges.h" +#include "ges-internal.h" + +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) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = ges_formatter_dispose; + object_class->finalize = ges_formatter_finalize; + + klass->save = save_ini; + klass->load = load_ini; +} + +static void +ges_formatter_init (GESFormatter * object) +{ +} + +static void +ges_formatter_dispose (GObject * object) +{ + GESFormatter *formatter; + formatter = GES_FORMATTER (object); + + if (formatter->data) { + g_free (formatter->data); + } +} + +static void +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 + * + * Creates a #GESFormatter that can handle the given URI. + * + * Returns: A GESFormatter or subclass that can load the given uri, or NULL if + * the uri is not supported. + */ + +GESFormatter * +ges_formatter_new_for_uri (gchar * uri) +{ + if (ges_formatter_can_load_uri (uri)) + return ges_formatter_new (); + return NULL; +} + +/** + * ges_formatter_can_load_uri: + * @uri: a #gchar * pointing to the URI + * + * Returns true if there is a #GESFormatterClass derivative registered with + * the system which can load data from the given URI. + * + * Returns: TRUE if the given uri is supported or FALSE if the uri is + * not supported. + */ + +gboolean +ges_formatter_can_load_uri (gchar * uri) +{ + if (!(gst_uri_is_valid (uri))) { + GST_ERROR ("Invalid uri!"); + return FALSE; + } + + if (!(gst_uri_has_protocol (uri, "file"))) { + gchar *proto = gst_uri_get_protocol (uri); + GST_ERROR ("Unspported protocol '%s'", proto); + g_free (proto); + return FALSE; + } + + /* TODO: implement file format registry */ + /* TODO: search through the registry and chose a GESFormatter class that can + * handle the URI.*/ + + return TRUE; +} + +/** + * ges_formatter_can_load_uri: + * @uri: a #gchar * pointing to a URI + * + * Returns TRUE if thereis a #GESFormatterClass derivative registered with the + * system which can save data to the given URI. + * + * Returns: TRUE if the given uri is supported or FALSE if the given URI is + * not suported. + */ + +gboolean +ges_formatter_can_save_uri (gchar * uri) +{ + if (!(gst_uri_is_valid (uri))) { + GST_ERROR ("Invalid uri!"); + return FALSE; + } + + if (!(gst_uri_has_protocol (uri, "file"))) { + gchar *proto = gst_uri_get_protocol (uri); + GST_ERROR ("Unspported protocol '%s'", proto); + g_free (proto); + return FALSE; + } + + /* TODO: implement file format registry */ + /* TODO: search through the registry and chose a GESFormatter class that can + * handle the URI.*/ + + return TRUE; + return FALSE; +} + +/** + * ges_formatter_load: + * @formatter: a pointer to a #GESFormatter instance or subclass. + * @timeline: a pointer to a #GESTimeline + * + * Loads data from formatter to into timeline. The data field of formatter + * must point to a block of data, and length must be correctly set to the + * length of the data. This method is only implemented in subclasses. + * + * Returns: TRUE if the data was successfully loaded into timeline + * or FALSE if an error occured during loading. + */ + +gboolean +ges_formatter_load (GESFormatter * formatter, GESTimeline * timeline) +{ + GESFormatterClass *klass; + + klass = GES_FORMATTER_GET_CLASS (formatter); + + if (klass->load) + return klass->load (formatter, timeline); + return FALSE; +} + +/** + * ges_formatter_save: + * @formatter: a pointer to a #GESFormatter instance or subclass. + * @timeline: a pointer to a #GESTimeline + * + * Save data from timeline into formatter. Upon success, The data field of the + * formatter will point to a newly-allocated block of data, and the length + * field of the formatter will contain the length of the block. This method is + * only implemented in subclasses. + * + * Returns: TRUE if the timeline data was successfully saved for FALSE if + * an error occured during saving. + */ + +gboolean +ges_formatter_save (GESFormatter * formatter, GESTimeline * timeline) +{ + GESFormatterClass *klass; + + klass = GES_FORMATTER_GET_CLASS (formatter); + + if (klass->save) + return klass->save (formatter, timeline); + return FALSE; +} + +/** + * ges_formatter_load_from_uri: + * @formatter: a pointer to a #GESFormatter instance or subclass + * @timeline: a pointer to a #GESTimeline + * @uri: a #gchar * pointing to a URI + * + * Load data from the given URI into timeline. The default implementation + * loads the entire contents of the uri with g_file_get_contents, then calls + * ges_formatter_load(). It works only on valid URIs pointing to local files. + * + * Subclasses should override the class method load_from_uri if they want to + * handle other types of URIs. They should also override the class method + * can_load_uri() to indicate that they can handle other types of URI. + * + * Returns: TRUE if the timeline data was successfully loaded from the URI or + * FALSE if an error occured during loading. + */ + +gboolean +ges_formatter_load_from_uri (GESFormatter * formatter, GESTimeline * timeline, + gchar * uri) +{ + gchar *location; + GError *e = NULL; + gboolean ret = TRUE; + + + if (formatter->data) { + GST_ERROR ("formatter already has data! please set data to NULL"); + } + + if (!(location = gst_uri_get_location (uri))) { + return FALSE; + } + + if (g_file_get_contents (location, &formatter->data, &formatter->length, &e)) { + if (!ges_formatter_load (formatter, timeline)) { + GST_ERROR ("couldn't deserialize formatter"); + ret = FALSE; + } + } else { + GST_ERROR ("couldn't read file '%s': %s", location, e->message); + ret = FALSE; + } + + if (e) + g_error_free (e); + g_free (location); + + return ret; +} + +/** + * ges_formatter_save_to_uri: + * @formatter: a pointer to a #GESFormatter instance or subclass + * @timeline: a pointer to a #GESTimeline + * @uri: a #gchar * pointing to a URI + * + * Save data from timeline to the given URI. The default implementation first + * calls ges_formatter_save () and then writes the entire contents of the data + * field to a local file using g_file_set_contents. It works only for local + * files. + * + * Subclasses should override the class method save_to_uri if they want to + * handle other types of URIs. They should also override the class method + * can_save_uri to return true for custom URIs. + * + * Returns: TRUE if the timeline data was successfully saved to the URI or + * FALSE if an error occured during saving. + */ + +gboolean +ges_formatter_save_to_uri (GESFormatter * formatter, GESTimeline * timeline, + gchar * uri) +{ + gchar *location; + GError *e = NULL; + gboolean ret = TRUE; + + + if (!(location = g_filename_from_uri (uri, NULL, NULL))) { + return FALSE; + } + + if (!ges_formatter_save (formatter, timeline)) { + GST_ERROR ("couldn't serialize formatter"); + } else { + if (!g_file_set_contents (location, formatter->data, formatter->length, &e)) { + GST_ERROR ("couldn't write file '%s': %s", location, e->message); + ret = FALSE; + } + } + + if (e) + g_error_free (e); + g_free (location); + + 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 new file mode 100644 index 0000000000..01beac5edb --- /dev/null +++ b/ges/ges-formatter.h @@ -0,0 +1,97 @@ +/* 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_FORMATTER +#define _GES_FORMATTER + +#include +#include + +#define GES_TYPE_FORMATTER ges_formatter_get_type() + +#define GES_FORMATTER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GES_TYPE_FORMATTER, GESFormatter)) + +#define GES_FORMATTER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GES_TYPE_FORMATTER, GESFormatterClass)) + +#define GES_IS_FORMATTER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GES_TYPE_FORMATTER)) + +#define GES_IS_FORMATTER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GES_TYPE_FORMATTER)) + +#define GES_FORMATTER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), GES_TYPE_FORMATTER, GESFormatterClass)) + +/** + * GESFormatter: + * @parent: parent + * + * Base class for timeline data serialization and deserialization. + */ + +struct _GESFormatter { + GObject parent; + + /*< private >*/ + gchar *data; + gsize length; +}; + +/** + * GESFormatterClass: + * @parent_class: parent class + * @can_load_uri: class method which returns true if a #GESFormatterClass can read + * from a given URI. + * @can_save_uri: class method which rturns true of a #GEFormatterClass can + * write to a given URI. + * @save: method to save timeline data + * @load: method to load timeline data + * + */ + +struct _GESFormatterClass { + GObjectClass parent_class; + + gboolean (*can_load_uri) (gchar * uri); + gboolean (*can_save_uri) (gchar * uri); + gboolean (*save) (GESFormatter * formatter, GESTimeline * timeline); + gboolean (*load) (GESFormatter * formatter, GESTimeline * timeline); +}; + +GType ges_formatter_get_type (void); + +GESFormatter *ges_formatter_new (void); +GESFormatter *ges_formatter_new_for_uri (gchar *uri); + +gboolean ges_formatter_can_load_uri (gchar * uri); +gboolean ges_formatter_can_save_uri (gchar * uri); + +gboolean ges_formatter_load_from_uri (GESFormatter * formatter, GESTimeline + *timeline, gchar *uri); + +gboolean ges_formatter_save_to_uri (GESFormatter * formatter, GESTimeline *timeline, + gchar *uri); + +gboolean ges_formatter_load (GESFormatter * formatter, GESTimeline * timeline); +gboolean ges_formatter_save (GESFormatter * formatter, GESTimeline * timeline); + +#endif /* _GES_FORMATTER */ diff --git a/ges/ges-types.h b/ges/ges-types.h index 5210b6163b..1351d2d7cc 100644 --- a/ges/ges-types.h +++ b/ges/ges-types.h @@ -105,5 +105,7 @@ typedef struct _GESTrackTextOverlay GESTrackTextOverlay; typedef struct _GESTrackTextOverlayClass GESTrackTextOverlayClass; +typedef struct _GESFormatter GESFormatter; +typedef struct _GESFormatterClass GESFormatterClass; #endif /* __GES_TYPES_H__ */ diff --git a/ges/ges.h b/ges/ges.h index a5c5ec79a6..4bcfe52d63 100644 --- a/ges/ges.h +++ b/ges/ges.h @@ -54,6 +54,8 @@ #include #include +#include + #include G_BEGIN_DECLS