mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 18:21:04 +00:00
GESKeyFileFormatter: New GKeyFile GESFormatter
This commit is contained in:
parent
f1b6e175cd
commit
9f1dc7709a
10 changed files with 588 additions and 405 deletions
|
@ -80,6 +80,7 @@ platform as well as Windows. It is released under the GNU Library General Public
|
||||||
<chapter>
|
<chapter>
|
||||||
<title>Serialization Classes</title>
|
<title>Serialization Classes</title>
|
||||||
<xi:include href="xml/ges-formatter.xml"/>
|
<xi:include href="xml/ges-formatter.xml"/>
|
||||||
|
<xi:include href="xml/ges-keyfile-formatter.xml"/>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
<chapter id="ges-hierarchy">
|
<chapter id="ges-hierarchy">
|
||||||
|
|
|
@ -536,7 +536,7 @@ GES_TYPE_TRACK_TEXT_OVERLAY
|
||||||
<TITLE>GESFormatter</TITLE>
|
<TITLE>GESFormatter</TITLE>
|
||||||
GESFormatter
|
GESFormatter
|
||||||
GESFormatterClass
|
GESFormatterClass
|
||||||
ges_formatter_new
|
ges_default_formatter_new
|
||||||
ges_formatter_load_from_uri
|
ges_formatter_load_from_uri
|
||||||
ges_formatter_save_to_uri
|
ges_formatter_save_to_uri
|
||||||
ges_formatter_new_for_uri
|
ges_formatter_new_for_uri
|
||||||
|
@ -553,3 +553,19 @@ GES_IS_FORMATTER
|
||||||
GES_IS_FORMATTER_CLASS
|
GES_IS_FORMATTER_CLASS
|
||||||
GES_TYPE_FORMATTER
|
GES_TYPE_FORMATTER
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<FILE>ges-keyfile-formatter</FILE>
|
||||||
|
<TITLE>GESFormatter</TITLE>
|
||||||
|
GESKeyfileFormatter
|
||||||
|
GESKeyfileFormatterClass
|
||||||
|
ges_keyfile_formatter_new
|
||||||
|
<SUBSECTION Standard>
|
||||||
|
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
|
||||||
|
</SECTION>
|
||||||
|
|
|
@ -31,3 +31,4 @@ ges_text_halign_get_type
|
||||||
ges_video_test_pattern_get_type
|
ges_video_test_pattern_get_type
|
||||||
ges_track_operation_get_type
|
ges_track_operation_get_type
|
||||||
ges_formatter_get_type
|
ges_formatter_get_type
|
||||||
|
ges_keyfile_formatter_get_type
|
||||||
|
|
|
@ -39,6 +39,7 @@ libges_@GST_MAJORMINOR@_la_SOURCES = \
|
||||||
ges-track-text-overlay.c \
|
ges-track-text-overlay.c \
|
||||||
ges-screenshot.c \
|
ges-screenshot.c \
|
||||||
ges-formatter.c \
|
ges-formatter.c \
|
||||||
|
ges-keyfile-formatter.c \
|
||||||
ges-utils.c
|
ges-utils.c
|
||||||
|
|
||||||
libges_@GST_MAJORMINOR@includedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/ges/
|
libges_@GST_MAJORMINOR@includedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/ges/
|
||||||
|
@ -76,6 +77,7 @@ libges_@GST_MAJORMINOR@include_HEADERS = \
|
||||||
ges-track-text-overlay.h \
|
ges-track-text-overlay.h \
|
||||||
ges-screenshot.h \
|
ges-screenshot.h \
|
||||||
ges-formatter.h \
|
ges-formatter.h \
|
||||||
|
ges-keyfile-formatter.h \
|
||||||
ges-utils.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)
|
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)
|
||||||
|
|
|
@ -37,10 +37,6 @@ G_DEFINE_TYPE (GESFormatter, ges_formatter, G_TYPE_OBJECT);
|
||||||
static void ges_formatter_dispose (GObject * object);
|
static void ges_formatter_dispose (GObject * object);
|
||||||
static void ges_formatter_finalize (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
|
static void
|
||||||
ges_formatter_class_init (GESFormatterClass * klass)
|
ges_formatter_class_init (GESFormatterClass * klass)
|
||||||
{
|
{
|
||||||
|
@ -48,9 +44,6 @@ ges_formatter_class_init (GESFormatterClass * klass)
|
||||||
|
|
||||||
object_class->dispose = ges_formatter_dispose;
|
object_class->dispose = ges_formatter_dispose;
|
||||||
object_class->finalize = ges_formatter_finalize;
|
object_class->finalize = ges_formatter_finalize;
|
||||||
|
|
||||||
klass->save = save_ini;
|
|
||||||
klass->load = load_ini;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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:
|
* ges_formatter_new_for_uri:
|
||||||
* @uri: a #gchar * pointing to the uri
|
* @uri: a #gchar * pointing to the uri
|
||||||
|
@ -94,10 +81,25 @@ GESFormatter *
|
||||||
ges_formatter_new_for_uri (gchar * uri)
|
ges_formatter_new_for_uri (gchar * uri)
|
||||||
{
|
{
|
||||||
if (ges_formatter_can_load_uri (uri))
|
if (ges_formatter_can_load_uri (uri))
|
||||||
return ges_formatter_new ();
|
return GES_FORMATTER (ges_keyfile_formatter_new ());
|
||||||
return NULL;
|
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:
|
* ges_formatter_can_load_uri:
|
||||||
* @uri: a #gchar * pointing to the URI
|
* @uri: a #gchar * pointing to the URI
|
||||||
|
@ -187,6 +189,7 @@ ges_formatter_load (GESFormatter * formatter, GESTimeline * timeline)
|
||||||
|
|
||||||
if (klass->load)
|
if (klass->load)
|
||||||
return klass->load (formatter, timeline);
|
return klass->load (formatter, timeline);
|
||||||
|
GST_ERROR ("not implemented!");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,6 +216,7 @@ ges_formatter_save (GESFormatter * formatter, GESTimeline * timeline)
|
||||||
|
|
||||||
if (klass->save)
|
if (klass->save)
|
||||||
return klass->save (formatter, timeline);
|
return klass->save (formatter, timeline);
|
||||||
|
GST_ERROR ("not implemented!");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,392 +319,3 @@ ges_formatter_save_to_uri (GESFormatter * formatter, GESTimeline * timeline,
|
||||||
|
|
||||||
return ret;
|
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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -79,8 +79,8 @@ struct _GESFormatterClass {
|
||||||
|
|
||||||
GType ges_formatter_get_type (void);
|
GType ges_formatter_get_type (void);
|
||||||
|
|
||||||
GESFormatter *ges_formatter_new (void);
|
|
||||||
GESFormatter *ges_formatter_new_for_uri (gchar *uri);
|
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_load_uri (gchar * uri);
|
||||||
gboolean ges_formatter_can_save_uri (gchar * uri);
|
gboolean ges_formatter_can_save_uri (gchar * uri);
|
||||||
|
|
471
ges/ges-keyfile-formatter.c
Normal file
471
ges/ges-keyfile-formatter.c
Normal file
|
@ -0,0 +1,471 @@
|
||||||
|
/* 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., 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 <gst/gst.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#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;
|
||||||
|
}
|
72
ges/ges-keyfile-formatter.h
Normal file
72
ges/ges-keyfile-formatter.h
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/* 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., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, 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:
|
||||||
|
* @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 */
|
|
@ -108,4 +108,8 @@ typedef struct _GESTrackTextOverlayClass
|
||||||
typedef struct _GESFormatter GESFormatter;
|
typedef struct _GESFormatter GESFormatter;
|
||||||
typedef struct _GESFormatterClass GESFormatterClass;
|
typedef struct _GESFormatterClass GESFormatterClass;
|
||||||
|
|
||||||
|
typedef struct _GESKeyfileFormatter GESKeyfileFormatter;
|
||||||
|
typedef struct _GESKeyfileFormatterClass GESKeyfileFormatterClass;
|
||||||
|
|
||||||
|
|
||||||
#endif /* __GES_TYPES_H__ */
|
#endif /* __GES_TYPES_H__ */
|
||||||
|
|
|
@ -55,6 +55,7 @@
|
||||||
#include <ges/ges-track-audio-transition.h>
|
#include <ges/ges-track-audio-transition.h>
|
||||||
|
|
||||||
#include <ges/ges-formatter.h>
|
#include <ges/ges-formatter.h>
|
||||||
|
#include <ges/ges-keyfile-formatter.h>
|
||||||
|
|
||||||
#include <ges/ges-utils.h>
|
#include <ges/ges-utils.h>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue