formatters: Save and load bindings applied to sources.
authorMathieu Duponchelle <mathieu.duponchelle@epitech.eu>
Mon, 8 Jul 2013 22:31:30 +0000 (00:31 +0200)
committerThibault Saunier <thibault.saunier@collabora.com>
Mon, 8 Jul 2013 23:32:09 +0000 (19:32 -0400)
ges/ges-base-xml-formatter.c
ges/ges-internal.h
ges/ges-xml-formatter.c

index 12d2ff0..f8f5443 100644 (file)
@@ -40,6 +40,14 @@ typedef struct PendingEffects
 
 } PendingEffects;
 
+typedef struct PendingBinding
+{
+  gchar *track_id;
+  GstControlSource *source;
+  gchar *propname;
+  gchar *binding_type;
+} PendingBinding;
+
 typedef struct PendingClip
 {
   gchar *id;
@@ -56,6 +64,8 @@ typedef struct PendingClip
 
   GList *effects;
 
+  GList *pending_bindings;
+
   /* TODO Implement asset effect management
    * PendingTrackElements *track_elements; */
 } PendingClip;
@@ -98,6 +108,9 @@ struct _GESBaseXmlFormatterPrivate
 
   /* current track element */
   GESTrackElement *current_track_element;
+
+  GESClip *current_clip;
+  PendingClip *current_pending_clip;
 };
 
 static void
@@ -341,6 +354,8 @@ ges_base_xml_formatter_init (GESBaseXmlFormatter * self)
   priv->layers = g_hash_table_new_full (g_direct_hash,
       g_direct_equal, NULL, (GDestroyNotify) _free_layer_entry);
   priv->current_track_element = NULL;
+  priv->current_clip = NULL;
+  priv->current_pending_clip = NULL;
 }
 
 static void
@@ -366,6 +381,16 @@ ges_base_xml_formatter_class_init (GESBaseXmlFormatterClass * self_class)
  *                                             *
  ***********************************************/
 
+
+static GESTrackElement *
+_get_element_by_track_id (GESBaseXmlFormatterPrivate * priv,
+    const gchar * track_id, GESClip * clip)
+{
+  GESTrack *track = g_hash_table_lookup (priv->tracks, track_id);
+
+  return ges_clip_find_track_element (clip, track, GES_TYPE_SOURCE);
+}
+
 static void
 _set_auto_transition (gpointer prio, LayerEntry * entry, gpointer udata)
 {
@@ -460,6 +485,14 @@ _add_track_element (GESFormatter * self, GESClip * clip,
 }
 
 static void
+_free_pending_binding (PendingBinding * pend)
+{
+  g_free (pend->propname);
+  g_free (pend->binding_type);
+  g_free (pend->track_id);
+}
+
+static void
 _free_pending_effect (PendingEffects * pend)
 {
   g_free (pend->track_id);
@@ -480,6 +513,8 @@ _free_pending_clip (GESBaseXmlFormatterPrivate * priv, PendingClip * pend)
   if (pend->properties)
     gst_structure_free (pend->properties);
   g_list_free_full (pend->effects, (GDestroyNotify) _free_pending_effect);
+  g_list_free_full (pend->pending_bindings,
+      (GDestroyNotify) _free_pending_binding);
   g_hash_table_remove (priv->clipid_pendings, pend->id);
   g_slice_free (PendingClip, pend);
 }
@@ -497,6 +532,22 @@ _free_pending_asset (GESBaseXmlFormatterPrivate * priv, PendingAsset * passet)
 }
 
 static void
+_add_pending_bindings (GESBaseXmlFormatterPrivate * priv, GList * bindings,
+    GESClip * clip)
+{
+  GList *tmpbinding;
+
+  for (tmpbinding = bindings; tmpbinding; tmpbinding = tmpbinding->next) {
+    PendingBinding *pbinding = tmpbinding->data;
+    GESTrackElement *element =
+        _get_element_by_track_id (priv, pbinding->track_id, clip);
+    if (element)
+      ges_track_element_set_control_source (element,
+          pbinding->source, pbinding->propname, pbinding->binding_type);
+  }
+}
+
+static void
 new_asset_cb (GESAsset * source, GAsyncResult * res, PendingAsset * passet)
 {
   GError *error = NULL;
@@ -570,6 +621,8 @@ new_asset_cb (GESAsset * source, GAsyncResult * res, PendingAsset * passet)
     if (clip == NULL)
       continue;
 
+    _add_pending_bindings (priv, pend->pending_bindings, clip);
+
     GST_DEBUG_OBJECT (self, "Adding %i effect to new object",
         g_list_length (pend->effects));
     for (tmpeffect = pend->effects; tmpeffect; tmpeffect = tmpeffect->next) {
@@ -739,6 +792,9 @@ ges_base_xml_formatter_add_clip (GESBaseXmlFormatter * self,
         g_list_append (pendings, pclip));
     g_hash_table_insert (priv->clipid_pendings, g_strdup (id), pclip);
 
+    priv->current_clip = NULL;
+    priv->current_pending_clip = pclip;
+
     return;
   }
 
@@ -747,6 +803,8 @@ ges_base_xml_formatter_add_clip (GESBaseXmlFormatter * self,
 
   if (!nclip)
     return;
+
+  priv->current_clip = nclip;
 }
 
 void
@@ -831,12 +889,35 @@ ges_base_xml_formatter_add_track (GESBaseXmlFormatter * self,
 void
 ges_base_xml_formatter_add_control_binding (GESBaseXmlFormatter * self,
     const gchar * binding_type, const gchar * source_type,
-    const gchar * property_name, gint mode, GSList * timed_values)
+    const gchar * property_name, gint mode, const gchar * track_id,
+    GSList * timed_values)
 {
   GESBaseXmlFormatterPrivate *priv = _GET_PRIV (self);
-  GESTrackElement *element;
+  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) {
+    PendingBinding *pbinding;
+
+    pbinding = g_slice_new0 (PendingBinding);
+    pbinding->source = gst_interpolation_control_source_new ();
+    g_object_set (pbinding->source, "mode", mode, NULL);
+    gst_timed_value_control_source_set_from_list (GST_TIMED_VALUE_CONTROL_SOURCE
+        (pbinding->source), timed_values);
+    pbinding->propname = g_strdup (property_name);
+    pbinding->binding_type = g_strdup (binding_type);
+    pbinding->track_id = g_strdup (track_id);
+    priv->current_pending_clip->pending_bindings =
+        g_list_append (priv->current_pending_clip->pending_bindings, pbinding);
+    return;
+  }
+
+  else {
+    element = priv->current_track_element;
+  }
 
-  element = priv->current_track_element;
   if (element == NULL) {
     GST_WARNING ("No current track element to which we can append a binding");
     return;
index 0d3a60b..1ea661f 100644 (file)
@@ -212,7 +212,7 @@ void ges_base_xml_formatter_add_encoding_profile               (GESBaseXmlFormat
                                                                  gboolean variableframerate,
                                                                  GstStructure * properties,
                                                                  GError ** error);
-G_GNUC_INTERNAL void ges_base_xml_formatter_add_track_element    (GESBaseXmlFormatter *self,
+G_GNUC_INTERNAL void ges_base_xml_formatter_add_track_element   (GESBaseXmlFormatter *self,
                                                                  GType effect_type,
                                                                  const gchar *asset_id,
                                                                  const gchar * track_id,
@@ -222,12 +222,13 @@ G_GNUC_INTERNAL void ges_base_xml_formatter_add_track_element    (GESBaseXmlForm
                                                                  const gchar *metadatas,
                                                                  GError **error);
 
-G_GNUC_INTERNAL void ges_base_xml_formatter_add_control_binding(GESBaseXmlFormatter * self,
-                const gchar * binding_type,
-                const gchar * source_type,
-                const gchar * property_name,
-                gint mode,
-                GSList * timed_values);
+G_GNUC_INTERNAL void ges_base_xml_formatter_add_control_bindingi (GESBaseXmlFormatter * self,
+                                                                  const gchar * binding_type,
+                                                                  const gchar * source_type,
+                                                                  const gchar * property_name,
+                                                                  gint mode,
+                                                                  const gchar *track_id,
+                                                                  GSList * timed_values);
 
 G_GNUC_INTERNAL void set_property_foreach                       (GQuark field_id,
                                                                  const GValue * value,
index fa595ca..c42457f 100644 (file)
@@ -513,7 +513,7 @@ _parse_binding (GMarkupParseContext * context, const gchar * element_name,
     GESXmlFormatter * self, GError ** error)
 {
   const gchar *type = NULL, *source_type = NULL, *timed_values =
-      NULL, *property_name = NULL, *mode = NULL;
+      NULL, *property_name = NULL, *mode = NULL, *track_id = NULL;
   gchar **pairs, **tmp;
   gchar *pair;
   GSList *list = NULL;
@@ -524,6 +524,7 @@ _parse_binding (GMarkupParseContext * context, const gchar * element_name,
           G_MARKUP_COLLECT_STRING, "source_type", &source_type,
           G_MARKUP_COLLECT_STRING, "property", &property_name,
           G_MARKUP_COLLECT_STRING, "mode", &mode,
+          G_MARKUP_COLLECT_STRING, "track_id", &track_id,
           G_MARKUP_COLLECT_STRING, "values", &timed_values,
           G_MARKUP_COLLECT_INVALID)) {
     return;
@@ -549,10 +550,11 @@ _parse_binding (GMarkupParseContext * context, const gchar * element_name,
   }
 
   g_strfreev (pairs);
+
   ges_base_xml_formatter_add_control_binding (GES_BASE_XML_FORMATTER (self),
       type,
       source_type,
-      property_name, (gint) g_ascii_strtoll (mode, NULL, 10), list);
+      property_name, (gint) g_ascii_strtoll (mode, NULL, 10), track_id, list);
 }
 
 static inline void
@@ -809,7 +811,7 @@ _save_tracks (GString * str, GESTimeline * timeline)
 
 /* TODO : Use this function for every track element with controllable properties */
 static inline void
-_save_keyframes (GString * str, GESTrackElement * trackelement)
+_save_keyframes (GString * str, GESTrackElement * trackelement, gint index)
 {
   GHashTable *bindings_hashtable;
   GHashTableIter iter;
@@ -839,6 +841,7 @@ _save_keyframes (GString * str, GESTrackElement * trackelement)
                 (gchar *) key));
         g_object_get (source, "mode", &mode, NULL);
         append_escaped (str, g_markup_printf_escaped (" mode='%d'", mode));
+        append_escaped (str, g_markup_printf_escaped (" track_id='%d'", index));
         append_escaped (str, g_markup_printf_escaped (" values ='"));
         timed_values =
             gst_timed_value_control_source_get_all
@@ -917,7 +920,7 @@ _save_effect (GString * str, guint clip_id, GESTrackElement * trackelement,
       g_markup_printf_escaped (" children-properties='%s'>\n",
           gst_structure_to_string (structure)));
 
-  _save_keyframes (str, trackelement);
+  _save_keyframes (str, trackelement, -1);
 
   append_escaped (str, g_markup_printf_escaped ("</effect>\n"));
   gst_structure_free (structure);
@@ -950,6 +953,8 @@ _save_layers (GString * str, GESTimeline * timeline)
     clips = ges_layer_get_clips (layer);
     for (tmpclip = clips; tmpclip; tmpclip = tmpclip->next) {
       GList *effects, *tmpeffect;
+      GList *tmptrackelement;
+      GList *tracks;
 
       clip = GES_CLIP (tmpclip->data);
       effects = ges_clip_get_top_effects (clip);
@@ -973,6 +978,24 @@ _save_layers (GString * str, GESTimeline * timeline)
       for (tmpeffect = effects; tmpeffect; tmpeffect = tmpeffect->next)
         _save_effect (str, nbclips, GES_TRACK_ELEMENT (tmpeffect->data),
             timeline);
+
+      tracks = ges_timeline_get_tracks (timeline);
+
+      for (tmptrackelement = GES_CONTAINER_CHILDREN (clip); tmptrackelement;
+          tmptrackelement = tmptrackelement->next) {
+        gint index;
+
+        if (!GES_IS_SOURCE (tmptrackelement->data))
+          continue;
+
+        index =
+            g_list_index (tracks,
+            ges_track_element_get_track (tmptrackelement->data));
+        _save_keyframes (str, tmptrackelement->data, index);
+      }
+
+      g_list_free_full (tracks, gst_object_unref);
+
       g_string_append (str, "</clip>\n");
       nbclips++;
     }