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;
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)
{
@ -459,6 +484,14 @@ _add_track_element (GESFormatter * self, GESClip * clip,
(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
_free_pending_effect (PendingEffects * pend)
{
@ -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);
}
@ -496,6 +531,22 @@ _free_pending_asset (GESBaseXmlFormatterPrivate * priv, PendingAsset * 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
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)
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;

View 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,

View 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++;
}