formatter: save and load source's children properties

This commit is contained in:
Joris Valette 2013-09-14 01:35:55 +02:00 committed by Thibault Saunier
parent b89ffaea82
commit 84610050ae
3 changed files with 154 additions and 23 deletions

View file

@ -51,6 +51,12 @@ typedef struct PendingBinding
gchar *binding_type;
} PendingBinding;
typedef struct PendingChildProperties
{
gchar *track_id;
GstStructure *structure;
} PendingChildProperties;
typedef struct PendingClip
{
gchar *id;
@ -69,6 +75,8 @@ typedef struct PendingClip
GList *pending_bindings;
GList *children_props;
/* TODO Implement asset effect management
* PendingTrackElements *track_elements; */
} PendingClip;
@ -513,6 +521,14 @@ _add_track_element (GESFormatter * self, GESClip * clip,
(GstStructureForeachFunc) _set_child_property, trackelement);
}
static void
_free_pending_children_props (PendingChildProperties * pend)
{
g_free (pend->track_id);
if (pend->structure)
gst_structure_free (pend->structure);
}
static void
_free_pending_binding (PendingBinding * pend)
{
@ -543,6 +559,8 @@ _free_pending_clip (GESBaseXmlFormatterPrivate * priv, PendingClip * pend)
g_list_free_full (pend->effects, (GDestroyNotify) _free_pending_effect);
g_list_free_full (pend->pending_bindings,
(GDestroyNotify) _free_pending_binding);
g_list_free_full (pend->children_props,
(GDestroyNotify) _free_pending_children_props);
g_hash_table_remove (priv->clipid_pendings, pend->id);
g_free (pend->id);
g_slice_free (PendingClip, pend);
@ -560,6 +578,23 @@ _free_pending_asset (GESBaseXmlFormatterPrivate * priv, PendingAsset * passet)
g_slice_free (PendingAsset, passet);
}
static void
_add_children_properties (GESBaseXmlFormatterPrivate * priv, GList * childprops,
GESClip * clip)
{
GList *tmpchildprops;
for (tmpchildprops = childprops; tmpchildprops;
tmpchildprops = tmpchildprops->next) {
PendingChildProperties *pchildprops = tmpchildprops->data;
GESTrackElement *element =
_get_element_by_track_id (priv, pchildprops->track_id, clip);
if (element && pchildprops->structure)
gst_structure_foreach (pchildprops->structure,
(GstStructureForeachFunc) _set_child_property, element);
}
}
static void
_add_pending_bindings (GESBaseXmlFormatterPrivate * priv, GList * bindings,
GESClip * clip)
@ -650,6 +685,7 @@ new_asset_cb (GESAsset * source, GAsyncResult * res, PendingAsset * passet)
if (clip == NULL)
continue;
_add_children_properties (priv, pend->children_props, clip);
_add_pending_bindings (priv, pend->pending_bindings, clip);
GST_DEBUG_OBJECT (self, "Adding %i effect to new object",
@ -1009,6 +1045,41 @@ ges_base_xml_formatter_add_control_binding (GESBaseXmlFormatter * self,
GST_WARNING ("This interpolation type is not supported\n");
}
void
ges_base_xml_formatter_add_source (GESBaseXmlFormatter * self,
const gchar * track_id, GstStructure * children_properties)
{
GESBaseXmlFormatterPrivate *priv = _GET_PRIV (self);
GESTrackElement *element = NULL;
if (track_id[0] != '-' && priv->current_clip)
element = _get_element_by_track_id (priv, track_id, priv->current_clip);
else if (track_id[0] != '-' && priv->current_pending_clip) {
PendingChildProperties *pchildprops;
pchildprops = g_slice_new0 (PendingChildProperties);
pchildprops->track_id = g_strdup (track_id);
pchildprops->structure = children_properties ?
gst_structure_copy (children_properties) : NULL;
priv->current_pending_clip->children_props =
g_list_append (priv->current_pending_clip->children_props, pchildprops);
return;
}
else
element = priv->current_track_element;
if (element == NULL) {
GST_WARNING
("No current track element to which we can append children properties");
return;
}
gst_structure_foreach (children_properties,
(GstStructureForeachFunc) _set_child_property, element);
}
void
ges_base_xml_formatter_add_track_element (GESBaseXmlFormatter * self,
GType track_element_type, const gchar * asset_id, const gchar * track_id,

View file

@ -248,6 +248,10 @@ G_GNUC_INTERNAL void ges_base_xml_formatter_add_track_element (GESBaseXmlForma
const gchar *metadatas,
GError **error);
G_GNUC_INTERNAL void ges_base_xml_formatter_add_source (GESBaseXmlFormatter *self,
const gchar * track_id,
GstStructure *children_properties);
G_GNUC_INTERNAL void ges_base_xml_formatter_add_control_binding (GESBaseXmlFormatter * self,
const gchar * binding_type,
const gchar * source_type,

View file

@ -559,6 +559,43 @@ _parse_binding (GMarkupParseContext * context, const gchar * element_name,
property_name, (gint) g_ascii_strtoll (mode, NULL, 10), track_id, list);
}
static inline void
_parse_source (GMarkupParseContext * context, const gchar * element_name,
const gchar ** attribute_names, const gchar ** attribute_values,
GESXmlFormatter * self, GError ** error)
{
GstStructure *children_props = NULL;
const gchar *track_id = NULL, *children_properties = NULL;
if (!g_markup_collect_attributes (element_name, attribute_names,
attribute_values, error,
G_MARKUP_COLLECT_STRING, "track-id", &track_id,
COLLECT_STR_OPT, "children-properties", &children_properties,
G_MARKUP_COLLECT_INVALID)) {
return;
}
if (children_properties) {
children_props = gst_structure_from_string (children_properties, NULL);
if (children_props == NULL)
goto wrong_children_properties;
}
ges_base_xml_formatter_add_source (GES_BASE_XML_FORMATTER (self), track_id,
children_props);
if (children_props)
gst_structure_free (children_props);
return;
wrong_children_properties:
g_set_error (error, G_MARKUP_ERROR,
G_MARKUP_ERROR_INVALID_CONTENT,
"element '%s', children properties '%s', could no be deserialized",
element_name, children_properties);
}
static inline void
_parse_effect (GMarkupParseContext * context, const gchar * element_name,
const gchar ** attribute_names, const gchar ** attribute_values,
@ -668,6 +705,9 @@ _parse_element_start (GMarkupParseContext * context, const gchar * element_name,
else if (g_strcmp0 (element_name, "clip") == 0)
_parse_clip (context, element_name, attribute_names,
attribute_values, self, error);
else if (g_strcmp0 (element_name, "source") == 0)
_parse_source (context, element_name, attribute_names,
attribute_values, self, error);
else if (g_strcmp0 (element_name, "effect") == 0)
_parse_effect (context, element_name, attribute_names,
attribute_values, self, error);
@ -823,6 +863,37 @@ _save_tracks (GString * str, GESTimeline * timeline)
g_list_free_full (tracks, gst_object_unref);
}
static inline void
_save_children_properties (GString * str, GESTrackElement * trackelement)
{
GstStructure *structure;
GParamSpec **pspecs, *spec;
guint i, n_props;
pspecs = ges_track_element_list_children_properties (trackelement, &n_props);
structure = gst_structure_new_empty ("properties");
for (i = 0; i < n_props; i++) {
GValue val = { 0 };
spec = pspecs[i];
if (_can_serialize_spec (spec)) {
_init_value_from_spec_for_serialization (&val, spec);
ges_track_element_get_child_property_by_pspec (trackelement, spec, &val);
gst_structure_set_value (structure, spec->name, &val);
g_value_unset (&val);
}
g_param_spec_unref (spec);
}
g_free (pspecs);
append_escaped (str,
g_markup_printf_escaped (" children-properties='%s'",
gst_structure_to_string (structure)));
gst_structure_free (structure);
}
/* TODO : Use this function for every track element with controllable properties */
static inline void
_save_keyframes (GString * str, GESTrackElement * trackelement, gint index)
@ -883,10 +954,8 @@ _save_effect (GString * str, guint clip_id, GESTrackElement * trackelement,
{
GESTrack *tck;
GList *tmp, *tracks;
GstStructure *structure;
gchar *properties, *metas;
GParamSpec **pspecs, *spec;
guint j, n_props = 0, track_id = 0;
guint track_id = 0;
tck = ges_track_element_get_track (trackelement);
if (tck == NULL) {
@ -916,30 +985,12 @@ _save_effect (GString * str, guint clip_id, GESTrackElement * trackelement,
g_free (properties);
g_free (metas);
pspecs = ges_track_element_list_children_properties (trackelement, &n_props);
structure = gst_structure_new_empty ("properties");
for (j = 0; j < n_props; j++) {
GValue val = { 0 };
spec = pspecs[j];
if (_can_serialize_spec (spec)) {
_init_value_from_spec_for_serialization (&val, spec);
ges_track_element_get_child_property_by_pspec (trackelement, spec, &val);
gst_structure_set_value (structure, spec->name, &val);
g_value_unset (&val);
}
g_param_spec_unref (spec);
}
g_free (pspecs);
append_escaped (str,
g_markup_printf_escaped (" children-properties='%s'>\n",
gst_structure_to_string (structure)));
_save_children_properties (str, trackelement);
append_escaped (str, g_markup_printf_escaped (">\n"));
_save_keyframes (str, trackelement, -1);
append_escaped (str, g_markup_printf_escaped (" </effect>\n"));
gst_structure_free (structure);
}
static inline void
@ -1007,7 +1058,12 @@ _save_layers (GString * str, GESTimeline * timeline)
index =
g_list_index (tracks,
ges_track_element_get_track (tmptrackelement->data));
append_escaped (str,
g_markup_printf_escaped (" <source track-id='%i'", index));
_save_children_properties (str, tmptrackelement->data);
append_escaped (str, g_markup_printf_escaped (">\n"));
_save_keyframes (str, tmptrackelement->data, index);
append_escaped (str, g_markup_printf_escaped (" </source>\n"));
}
g_list_free_full (tracks, gst_object_unref);