formatters: Save and load bindings applied to sources.

This commit is contained in:
Mathieu Duponchelle 2013-07-09 00:31:30 +02:00 committed by Thibault Saunier
parent 6a187e09dd
commit f1a3d65ef6
3 changed files with 119 additions and 14 deletions

View file

@ -40,6 +40,14 @@ typedef struct PendingEffects
} PendingEffects; } PendingEffects;
typedef struct PendingBinding
{
gchar *track_id;
GstControlSource *source;
gchar *propname;
gchar *binding_type;
} PendingBinding;
typedef struct PendingClip typedef struct PendingClip
{ {
gchar *id; gchar *id;
@ -56,6 +64,8 @@ typedef struct PendingClip
GList *effects; GList *effects;
GList *pending_bindings;
/* TODO Implement asset effect management /* TODO Implement asset effect management
* PendingTrackElements *track_elements; */ * PendingTrackElements *track_elements; */
} PendingClip; } PendingClip;
@ -98,6 +108,9 @@ struct _GESBaseXmlFormatterPrivate
/* current track element */ /* current track element */
GESTrackElement *current_track_element; GESTrackElement *current_track_element;
GESClip *current_clip;
PendingClip *current_pending_clip;
}; };
static void static void
@ -341,6 +354,8 @@ ges_base_xml_formatter_init (GESBaseXmlFormatter * self)
priv->layers = g_hash_table_new_full (g_direct_hash, priv->layers = g_hash_table_new_full (g_direct_hash,
g_direct_equal, NULL, (GDestroyNotify) _free_layer_entry); g_direct_equal, NULL, (GDestroyNotify) _free_layer_entry);
priv->current_track_element = NULL; priv->current_track_element = NULL;
priv->current_clip = NULL;
priv->current_pending_clip = NULL;
} }
static void 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 static void
_set_auto_transition (gpointer prio, LayerEntry * entry, gpointer udata) _set_auto_transition (gpointer prio, LayerEntry * entry, gpointer udata)
{ {
@ -459,6 +484,14 @@ _add_track_element (GESFormatter * self, GESClip * clip,
(GstStructureForeachFunc) _set_child_property, trackelement); (GstStructureForeachFunc) _set_child_property, trackelement);
} }
static void
_free_pending_binding (PendingBinding * pend)
{
g_free (pend->propname);
g_free (pend->binding_type);
g_free (pend->track_id);
}
static void static void
_free_pending_effect (PendingEffects * pend) _free_pending_effect (PendingEffects * pend)
{ {
@ -480,6 +513,8 @@ _free_pending_clip (GESBaseXmlFormatterPrivate * priv, PendingClip * pend)
if (pend->properties) if (pend->properties)
gst_structure_free (pend->properties); gst_structure_free (pend->properties);
g_list_free_full (pend->effects, (GDestroyNotify) _free_pending_effect); 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_hash_table_remove (priv->clipid_pendings, pend->id);
g_slice_free (PendingClip, pend); g_slice_free (PendingClip, pend);
} }
@ -496,6 +531,22 @@ _free_pending_asset (GESBaseXmlFormatterPrivate * priv, PendingAsset * passet)
priv->pending_assets = g_list_remove (priv->pending_assets, passet); priv->pending_assets = g_list_remove (priv->pending_assets, 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 static void
new_asset_cb (GESAsset * source, GAsyncResult * res, PendingAsset * passet) new_asset_cb (GESAsset * source, GAsyncResult * res, PendingAsset * passet)
{ {
@ -570,6 +621,8 @@ new_asset_cb (GESAsset * source, GAsyncResult * res, PendingAsset * passet)
if (clip == NULL) if (clip == NULL)
continue; continue;
_add_pending_bindings (priv, pend->pending_bindings, clip);
GST_DEBUG_OBJECT (self, "Adding %i effect to new object", GST_DEBUG_OBJECT (self, "Adding %i effect to new object",
g_list_length (pend->effects)); g_list_length (pend->effects));
for (tmpeffect = pend->effects; tmpeffect; tmpeffect = tmpeffect->next) { 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_list_append (pendings, pclip));
g_hash_table_insert (priv->clipid_pendings, g_strdup (id), pclip); g_hash_table_insert (priv->clipid_pendings, g_strdup (id), pclip);
priv->current_clip = NULL;
priv->current_pending_clip = pclip;
return; return;
} }
@ -747,6 +803,8 @@ ges_base_xml_formatter_add_clip (GESBaseXmlFormatter * self,
if (!nclip) if (!nclip)
return; return;
priv->current_clip = nclip;
} }
void void
@ -831,12 +889,35 @@ ges_base_xml_formatter_add_track (GESBaseXmlFormatter * self,
void void
ges_base_xml_formatter_add_control_binding (GESBaseXmlFormatter * self, ges_base_xml_formatter_add_control_binding (GESBaseXmlFormatter * self,
const gchar * binding_type, const gchar * source_type, 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); 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) { if (element == NULL) {
GST_WARNING ("No current track element to which we can append a binding"); GST_WARNING ("No current track element to which we can append a binding");
return; return;

View file

@ -212,7 +212,7 @@ void ges_base_xml_formatter_add_encoding_profile (GESBaseXmlFormat
gboolean variableframerate, gboolean variableframerate,
GstStructure * properties, GstStructure * properties,
GError ** error); 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, GType effect_type,
const gchar *asset_id, const gchar *asset_id,
const gchar * track_id, const gchar * track_id,
@ -222,12 +222,13 @@ G_GNUC_INTERNAL void ges_base_xml_formatter_add_track_element (GESBaseXmlForm
const gchar *metadatas, const gchar *metadatas,
GError **error); GError **error);
G_GNUC_INTERNAL void ges_base_xml_formatter_add_control_binding(GESBaseXmlFormatter * self, G_GNUC_INTERNAL void ges_base_xml_formatter_add_control_bindingi (GESBaseXmlFormatter * self,
const gchar * binding_type, const gchar * binding_type,
const gchar * source_type, const gchar * source_type,
const gchar * property_name, const gchar * property_name,
gint mode, gint mode,
GSList * timed_values); const gchar *track_id,
GSList * timed_values);
G_GNUC_INTERNAL void set_property_foreach (GQuark field_id, G_GNUC_INTERNAL void set_property_foreach (GQuark field_id,
const GValue * value, const GValue * value,

View file

@ -513,7 +513,7 @@ _parse_binding (GMarkupParseContext * context, const gchar * element_name,
GESXmlFormatter * self, GError ** error) GESXmlFormatter * self, GError ** error)
{ {
const gchar *type = NULL, *source_type = NULL, *timed_values = 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 **pairs, **tmp;
gchar *pair; gchar *pair;
GSList *list = NULL; 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, "source_type", &source_type,
G_MARKUP_COLLECT_STRING, "property", &property_name, G_MARKUP_COLLECT_STRING, "property", &property_name,
G_MARKUP_COLLECT_STRING, "mode", &mode, G_MARKUP_COLLECT_STRING, "mode", &mode,
G_MARKUP_COLLECT_STRING, "track_id", &track_id,
G_MARKUP_COLLECT_STRING, "values", &timed_values, G_MARKUP_COLLECT_STRING, "values", &timed_values,
G_MARKUP_COLLECT_INVALID)) { G_MARKUP_COLLECT_INVALID)) {
return; return;
@ -549,10 +550,11 @@ _parse_binding (GMarkupParseContext * context, const gchar * element_name,
} }
g_strfreev (pairs); g_strfreev (pairs);
ges_base_xml_formatter_add_control_binding (GES_BASE_XML_FORMATTER (self), ges_base_xml_formatter_add_control_binding (GES_BASE_XML_FORMATTER (self),
type, type,
source_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 static inline void
@ -809,7 +811,7 @@ _save_tracks (GString * str, GESTimeline * timeline)
/* TODO : Use this function for every track element with controllable properties */ /* TODO : Use this function for every track element with controllable properties */
static inline void static inline void
_save_keyframes (GString * str, GESTrackElement * trackelement) _save_keyframes (GString * str, GESTrackElement * trackelement, gint index)
{ {
GHashTable *bindings_hashtable; GHashTable *bindings_hashtable;
GHashTableIter iter; GHashTableIter iter;
@ -839,6 +841,7 @@ _save_keyframes (GString * str, GESTrackElement * trackelement)
(gchar *) key)); (gchar *) key));
g_object_get (source, "mode", &mode, NULL); g_object_get (source, "mode", &mode, NULL);
append_escaped (str, g_markup_printf_escaped (" mode='%d'", mode)); 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 ='")); append_escaped (str, g_markup_printf_escaped (" values ='"));
timed_values = timed_values =
gst_timed_value_control_source_get_all 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", g_markup_printf_escaped (" children-properties='%s'>\n",
gst_structure_to_string (structure))); gst_structure_to_string (structure)));
_save_keyframes (str, trackelement); _save_keyframes (str, trackelement, -1);
append_escaped (str, g_markup_printf_escaped ("</effect>\n")); append_escaped (str, g_markup_printf_escaped ("</effect>\n"));
gst_structure_free (structure); gst_structure_free (structure);
@ -950,6 +953,8 @@ _save_layers (GString * str, GESTimeline * timeline)
clips = ges_layer_get_clips (layer); clips = ges_layer_get_clips (layer);
for (tmpclip = clips; tmpclip; tmpclip = tmpclip->next) { for (tmpclip = clips; tmpclip; tmpclip = tmpclip->next) {
GList *effects, *tmpeffect; GList *effects, *tmpeffect;
GList *tmptrackelement;
GList *tracks;
clip = GES_CLIP (tmpclip->data); clip = GES_CLIP (tmpclip->data);
effects = ges_clip_get_top_effects (clip); effects = ges_clip_get_top_effects (clip);
@ -973,6 +978,24 @@ _save_layers (GString * str, GESTimeline * timeline)
for (tmpeffect = effects; tmpeffect; tmpeffect = tmpeffect->next) for (tmpeffect = effects; tmpeffect; tmpeffect = tmpeffect->next)
_save_effect (str, nbclips, GES_TRACK_ELEMENT (tmpeffect->data), _save_effect (str, nbclips, GES_TRACK_ELEMENT (tmpeffect->data),
timeline); 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"); g_string_append (str, "</clip>\n");
nbclips++; nbclips++;
} }