mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 00:36:51 +00:00
formatter: Serialize Transition border and invert properties
Marking them as children properties and properly allow serializing clips children properties. This doesn't handle several TrackElement of a same type with different property values but this require more worked already marked as fixme to allow specifying full path of elements in the children properties API. See https://gitlab.gnome.org/GNOME/pitivi/issues/1687
This commit is contained in:
parent
5f5cbd111c
commit
bfb943be1b
6 changed files with 102 additions and 20 deletions
|
@ -77,6 +77,7 @@ typedef struct PendingClip
|
||||||
GESLayer *layer;
|
GESLayer *layer;
|
||||||
|
|
||||||
GstStructure *properties;
|
GstStructure *properties;
|
||||||
|
GstStructure *children_properties;
|
||||||
gchar *metadatas;
|
gchar *metadatas;
|
||||||
|
|
||||||
GList *effects;
|
GList *effects;
|
||||||
|
@ -503,26 +504,26 @@ _loading_done_cb (GESFormatter * self)
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
_set_child_property (GQuark field_id, const GValue * value,
|
_set_child_property (GQuark field_id, const GValue * value,
|
||||||
GESTrackElement * effect)
|
GESTimelineElement * tlelement)
|
||||||
{
|
{
|
||||||
GParamSpec *pspec;
|
GParamSpec *pspec;
|
||||||
GstElement *element;
|
GObject *object;
|
||||||
|
|
||||||
/* FIXME: error handling? */
|
/* FIXME: error handling? */
|
||||||
if (!ges_track_element_lookup_child (effect,
|
if (!ges_timeline_element_lookup_child (tlelement,
|
||||||
g_quark_to_string (field_id), &element, &pspec)) {
|
g_quark_to_string (field_id), &object, &pspec)) {
|
||||||
#ifndef GST_DISABLE_GST_DEBUG
|
#ifndef GST_DISABLE_GST_DEBUG
|
||||||
gchar *tmp = gst_value_serialize (value);
|
gchar *tmp = gst_value_serialize (value);
|
||||||
GST_ERROR_OBJECT (effect, "Could not set %s=%s",
|
GST_ERROR_OBJECT (tlelement, "Could not set %s=%s",
|
||||||
g_quark_to_string (field_id), tmp);
|
g_quark_to_string (field_id), tmp);
|
||||||
g_free (tmp);
|
g_free (tmp);
|
||||||
#endif
|
#endif
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_object_set_property (G_OBJECT (element), pspec->name, value);
|
g_object_set_property (G_OBJECT (object), pspec->name, value);
|
||||||
g_param_spec_unref (pspec);
|
g_param_spec_unref (pspec);
|
||||||
gst_object_unref (element);
|
gst_object_unref (object);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -538,7 +539,7 @@ _add_object_to_layer (GESBaseXmlFormatterPrivate * priv, const gchar * id,
|
||||||
GESLayer * layer, GESAsset * asset, GstClockTime start,
|
GESLayer * layer, GESAsset * asset, GstClockTime start,
|
||||||
GstClockTime inpoint, GstClockTime duration,
|
GstClockTime inpoint, GstClockTime duration,
|
||||||
GESTrackType track_types, const gchar * metadatas,
|
GESTrackType track_types, const gchar * metadatas,
|
||||||
GstStructure * properties)
|
GstStructure * properties, GstStructure * children_properties)
|
||||||
{
|
{
|
||||||
GESClip *clip = ges_layer_add_asset (layer,
|
GESClip *clip = ges_layer_add_asset (layer,
|
||||||
asset, start, inpoint, duration, track_types);
|
asset, start, inpoint, duration, track_types);
|
||||||
|
@ -558,6 +559,10 @@ _add_object_to_layer (GESBaseXmlFormatterPrivate * priv, const gchar * id,
|
||||||
gst_structure_foreach (properties,
|
gst_structure_foreach (properties,
|
||||||
(GstStructureForeachFunc) set_property_foreach, clip);
|
(GstStructureForeachFunc) set_property_foreach, clip);
|
||||||
|
|
||||||
|
if (children_properties)
|
||||||
|
gst_structure_foreach (children_properties,
|
||||||
|
(GstStructureForeachFunc) _set_child_property, clip);
|
||||||
|
|
||||||
g_hash_table_insert (priv->containers, g_strdup (id), gst_object_ref (clip));
|
g_hash_table_insert (priv->containers, g_strdup (id), gst_object_ref (clip));
|
||||||
return clip;
|
return clip;
|
||||||
}
|
}
|
||||||
|
@ -758,7 +763,7 @@ new_asset_cb (GESAsset * source, GAsyncResult * res, PendingAsset * passet)
|
||||||
clip =
|
clip =
|
||||||
_add_object_to_layer (priv, pend->id, pend->layer, asset,
|
_add_object_to_layer (priv, pend->id, pend->layer, asset,
|
||||||
pend->start, pend->inpoint, pend->duration, pend->track_types,
|
pend->start, pend->inpoint, pend->duration, pend->track_types,
|
||||||
pend->metadatas, pend->properties);
|
pend->metadatas, pend->properties, pend->children_properties);
|
||||||
|
|
||||||
if (clip == NULL)
|
if (clip == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
@ -944,6 +949,7 @@ ges_base_xml_formatter_add_clip (GESBaseXmlFormatter * self,
|
||||||
const gchar * id, const char *asset_id, GType type, GstClockTime start,
|
const gchar * id, const char *asset_id, GType type, GstClockTime start,
|
||||||
GstClockTime inpoint, GstClockTime duration,
|
GstClockTime inpoint, GstClockTime duration,
|
||||||
guint layer_prio, GESTrackType track_types, GstStructure * properties,
|
guint layer_prio, GESTrackType track_types, GstStructure * properties,
|
||||||
|
GstStructure * children_properties,
|
||||||
const gchar * metadatas, GError ** error)
|
const gchar * metadatas, GError ** error)
|
||||||
{
|
{
|
||||||
GESAsset *asset;
|
GESAsset *asset;
|
||||||
|
@ -999,6 +1005,8 @@ ges_base_xml_formatter_add_clip (GESBaseXmlFormatter * self,
|
||||||
pclip->layer = gst_object_ref (entry->layer);
|
pclip->layer = gst_object_ref (entry->layer);
|
||||||
|
|
||||||
pclip->properties = properties ? gst_structure_copy (properties) : NULL;
|
pclip->properties = properties ? gst_structure_copy (properties) : NULL;
|
||||||
|
pclip->children_properties =
|
||||||
|
properties ? gst_structure_copy (children_properties) : NULL;
|
||||||
pclip->metadatas = g_strdup (metadatas);
|
pclip->metadatas = g_strdup (metadatas);
|
||||||
|
|
||||||
/* Add the new pending object to the hashtable */
|
/* Add the new pending object to the hashtable */
|
||||||
|
@ -1013,7 +1021,8 @@ ges_base_xml_formatter_add_clip (GESBaseXmlFormatter * self,
|
||||||
}
|
}
|
||||||
|
|
||||||
nclip = _add_object_to_layer (priv, id, entry->layer,
|
nclip = _add_object_to_layer (priv, id, entry->layer,
|
||||||
asset, start, inpoint, duration, track_types, metadatas, properties);
|
asset, start, inpoint, duration, track_types, metadatas, properties,
|
||||||
|
children_properties);
|
||||||
|
|
||||||
if (!nclip)
|
if (!nclip)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -281,9 +281,8 @@ _lookup_child (GESTimelineElement * self, const gchar * prop_name,
|
||||||
{
|
{
|
||||||
GList *tmp;
|
GList *tmp;
|
||||||
|
|
||||||
/* FIXME Implement a synthax to precisely get properties by path */
|
/* FIXME Implement a syntax to precisely get properties by path */
|
||||||
for (tmp = GES_CONTAINER_CHILDREN (self); tmp; tmp = tmp->next) {
|
for (tmp = GES_CONTAINER_CHILDREN (self); tmp; tmp = tmp->next) {
|
||||||
|
|
||||||
if (ges_timeline_element_lookup_child (tmp->data, prop_name, child, pspec))
|
if (ges_timeline_element_lookup_child (tmp->data, prop_name, child, pspec))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,6 +232,7 @@ G_GNUC_INTERNAL void ges_base_xml_formatter_add_clip (GESBaseXmlFormatter * self
|
||||||
guint layer_prio,
|
guint layer_prio,
|
||||||
GESTrackType track_types,
|
GESTrackType track_types,
|
||||||
GstStructure *properties,
|
GstStructure *properties,
|
||||||
|
GstStructure * children_properties,
|
||||||
const gchar *metadatas,
|
const gchar *metadatas,
|
||||||
GError **error);
|
GError **error);
|
||||||
G_GNUC_INTERNAL void ges_base_xml_formatter_add_asset (GESBaseXmlFormatter * self,
|
G_GNUC_INTERNAL void ges_base_xml_formatter_add_asset (GESBaseXmlFormatter * self,
|
||||||
|
|
|
@ -227,6 +227,22 @@ ges_transition_clip_set_property (GObject * object,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_lookup_child (GESTimelineElement * self, const gchar * prop_name,
|
||||||
|
GObject ** child, GParamSpec ** pspec)
|
||||||
|
{
|
||||||
|
GESTimelineElementClass *element_klass =
|
||||||
|
g_type_class_peek (GES_TYPE_TIMELINE_ELEMENT);
|
||||||
|
|
||||||
|
/* Bypass the container implementation as we handle children properties directly */
|
||||||
|
/* FIXME Implement a syntax to precisely get properties by path */
|
||||||
|
if (element_klass->lookup_child (self, prop_name, child, pspec))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ges_transition_clip_class_init (GESTransitionClipClass * klass)
|
ges_transition_clip_class_init (GESTransitionClipClass * klass)
|
||||||
{
|
{
|
||||||
|
@ -251,6 +267,7 @@ ges_transition_clip_class_init (GESTransitionClipClass * klass)
|
||||||
GES_VIDEO_STANDARD_TRANSITION_TYPE_CROSSFADE,
|
GES_VIDEO_STANDARD_TRANSITION_TYPE_CROSSFADE,
|
||||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||||
|
|
||||||
|
GES_TIMELINE_ELEMENT_CLASS (klass)->lookup_child = _lookup_child;
|
||||||
container_class->child_added = _child_added;
|
container_class->child_added = _child_added;
|
||||||
container_class->child_removed = _child_removed;
|
container_class->child_removed = _child_removed;
|
||||||
|
|
||||||
|
@ -287,9 +304,16 @@ _child_added (GESContainer * container, GESTimelineElement * element)
|
||||||
GESTransitionClipPrivate *priv = GES_TRANSITION_CLIP (container)->priv;
|
GESTransitionClipPrivate *priv = GES_TRANSITION_CLIP (container)->priv;
|
||||||
|
|
||||||
if (GES_IS_VIDEO_TRANSITION (element)) {
|
if (GES_IS_VIDEO_TRANSITION (element)) {
|
||||||
|
GObjectClass *eklass = G_OBJECT_GET_CLASS (element);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (container, "%" GST_PTR_FORMAT " added", element);
|
GST_DEBUG_OBJECT (container, "%" GST_PTR_FORMAT " added", element);
|
||||||
priv->video_transitions =
|
priv->video_transitions =
|
||||||
g_slist_prepend (priv->video_transitions, gst_object_ref (element));
|
g_slist_prepend (priv->video_transitions, gst_object_ref (element));
|
||||||
|
|
||||||
|
ges_timeline_element_add_child_property (GES_TIMELINE_ELEMENT (container),
|
||||||
|
g_object_class_find_property (eklass, "invert"), G_OBJECT (element));
|
||||||
|
ges_timeline_element_add_child_property (GES_TIMELINE_ELEMENT (container),
|
||||||
|
g_object_class_find_property (eklass, "border"), G_OBJECT (element));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -465,13 +465,13 @@ _parse_clip (GMarkupParseContext * context,
|
||||||
const gchar ** attribute_values, GESXmlFormatter * self, GError ** error)
|
const gchar ** attribute_values, GESXmlFormatter * self, GError ** error)
|
||||||
{
|
{
|
||||||
GType type;
|
GType type;
|
||||||
GstStructure *props = NULL;
|
GstStructure *props = NULL, *children_props = NULL;
|
||||||
GESTrackType track_types;
|
GESTrackType track_types;
|
||||||
GstClockTime start, inpoint = 0, duration, layer_prio;
|
GstClockTime start, inpoint = 0, duration, layer_prio;
|
||||||
|
|
||||||
const gchar *strid, *asset_id, *strstart, *strin, *strduration, *strrate,
|
const gchar *strid, *asset_id, *strstart, *strin, *strduration, *strrate,
|
||||||
*strtrack_types, *strtype, *metadatas = NULL, *properties =
|
*strtrack_types, *strtype, *metadatas = NULL, *properties =
|
||||||
NULL, *strlayer_prio;
|
NULL, *children_properties = NULL, *strlayer_prio;
|
||||||
|
|
||||||
if (!g_markup_collect_attributes (element_name, attribute_names,
|
if (!g_markup_collect_attributes (element_name, attribute_names,
|
||||||
attribute_values, error,
|
attribute_values, error,
|
||||||
|
@ -483,6 +483,7 @@ _parse_clip (GMarkupParseContext * context,
|
||||||
G_MARKUP_COLLECT_STRING, "track-types", &strtrack_types,
|
G_MARKUP_COLLECT_STRING, "track-types", &strtrack_types,
|
||||||
G_MARKUP_COLLECT_STRING, "layer-priority", &strlayer_prio,
|
G_MARKUP_COLLECT_STRING, "layer-priority", &strlayer_prio,
|
||||||
COLLECT_STR_OPT, "properties", &properties,
|
COLLECT_STR_OPT, "properties", &properties,
|
||||||
|
COLLECT_STR_OPT, "children-properties", &children_properties,
|
||||||
COLLECT_STR_OPT, "metadatas", &metadatas,
|
COLLECT_STR_OPT, "metadatas", &metadatas,
|
||||||
COLLECT_STR_OPT, "rate", &strrate,
|
COLLECT_STR_OPT, "rate", &strrate,
|
||||||
COLLECT_STR_OPT, "inpoint", &strin, G_MARKUP_COLLECT_INVALID)) {
|
COLLECT_STR_OPT, "inpoint", &strin, G_MARKUP_COLLECT_INVALID)) {
|
||||||
|
@ -521,9 +522,15 @@ _parse_clip (GMarkupParseContext * context,
|
||||||
goto wrong_properties;
|
goto wrong_properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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_clip (GES_BASE_XML_FORMATTER (self),
|
ges_base_xml_formatter_add_clip (GES_BASE_XML_FORMATTER (self),
|
||||||
strid, asset_id, type, start, inpoint, duration, layer_prio,
|
strid, asset_id, type, start, inpoint, duration, layer_prio,
|
||||||
track_types, props, metadatas, error);
|
track_types, props, children_props, metadatas, error);
|
||||||
if (props)
|
if (props)
|
||||||
gst_structure_free (props);
|
gst_structure_free (props);
|
||||||
|
|
||||||
|
@ -536,6 +543,13 @@ wrong_properties:
|
||||||
element_name, asset_id, properties);
|
element_name, asset_id, properties);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
wrong_children_properties:
|
||||||
|
g_set_error (error, G_MARKUP_ERROR,
|
||||||
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
||||||
|
"element '%s', Clip %s children properties '%s', could no be deserialized",
|
||||||
|
element_name, asset_id, children_properties);
|
||||||
|
return;
|
||||||
|
|
||||||
convertion_failed:
|
convertion_failed:
|
||||||
g_set_error (error, G_MARKUP_ERROR,
|
g_set_error (error, G_MARKUP_ERROR,
|
||||||
G_MARKUP_ERROR_INVALID_CONTENT,
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
||||||
|
@ -1001,14 +1015,14 @@ _save_tracks (GESXmlFormatter * self, GString * str, GESTimeline * timeline)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
_save_children_properties (GString * str, GESTrackElement * trackelement)
|
_save_children_properties (GString * str, GESTimelineElement * element)
|
||||||
{
|
{
|
||||||
GstStructure *structure;
|
GstStructure *structure;
|
||||||
GParamSpec **pspecs, *spec;
|
GParamSpec **pspecs, *spec;
|
||||||
guint i, n_props;
|
guint i, n_props;
|
||||||
gchar *struct_str;
|
gchar *struct_str;
|
||||||
|
|
||||||
pspecs = ges_track_element_list_children_properties (trackelement, &n_props);
|
pspecs = ges_timeline_element_list_children_properties (element, &n_props);
|
||||||
|
|
||||||
structure = gst_structure_new_empty ("properties");
|
structure = gst_structure_new_empty ("properties");
|
||||||
for (i = 0; i < n_props; i++) {
|
for (i = 0; i < n_props; i++) {
|
||||||
|
@ -1021,7 +1035,7 @@ _save_children_properties (GString * str, GESTrackElement * trackelement)
|
||||||
spec->name);
|
spec->name);
|
||||||
|
|
||||||
_init_value_from_spec_for_serialization (&val, spec);
|
_init_value_from_spec_for_serialization (&val, spec);
|
||||||
ges_track_element_get_child_property_by_pspec (trackelement, spec, &val);
|
ges_timeline_element_get_child_property_by_pspec (element, spec, &val);
|
||||||
gst_structure_set_value (structure, spec_name, &val);
|
gst_structure_set_value (structure, spec_name, &val);
|
||||||
|
|
||||||
g_free (spec_name);
|
g_free (spec_name);
|
||||||
|
@ -1146,7 +1160,7 @@ _save_effect (GString * str, guint clip_id, GESTrackElement * trackelement,
|
||||||
g_free (properties);
|
g_free (properties);
|
||||||
g_free (metas);
|
g_free (metas);
|
||||||
|
|
||||||
_save_children_properties (str, trackelement);
|
_save_children_properties (str, GES_TIMELINE_ELEMENT (trackelement));
|
||||||
append_escaped (str, g_markup_printf_escaped (">\n"));
|
append_escaped (str, g_markup_printf_escaped (">\n"));
|
||||||
|
|
||||||
_save_keyframes (str, trackelement, -1);
|
_save_keyframes (str, trackelement, -1);
|
||||||
|
@ -1203,17 +1217,23 @@ _save_layers (GESXmlFormatter * self, GString * str, GESTimeline * timeline)
|
||||||
g_markup_printf_escaped (" <clip id='%i' asset-id='%s'"
|
g_markup_printf_escaped (" <clip id='%i' asset-id='%s'"
|
||||||
" type-name='%s' layer-priority='%i' track-types='%i' start='%"
|
" type-name='%s' layer-priority='%i' track-types='%i' start='%"
|
||||||
G_GUINT64_FORMAT "' duration='%" G_GUINT64_FORMAT "' inpoint='%"
|
G_GUINT64_FORMAT "' duration='%" G_GUINT64_FORMAT "' inpoint='%"
|
||||||
G_GUINT64_FORMAT "' rate='%d' properties='%s' >\n",
|
G_GUINT64_FORMAT "' rate='%d' properties='%s' ",
|
||||||
priv->nbelements, extractable_id,
|
priv->nbelements, extractable_id,
|
||||||
g_type_name (G_OBJECT_TYPE (clip)), priority,
|
g_type_name (G_OBJECT_TYPE (clip)), priority,
|
||||||
ges_clip_get_supported_formats (clip), _START (clip),
|
ges_clip_get_supported_formats (clip), _START (clip),
|
||||||
_DURATION (clip), _INPOINT (clip), 0, properties));
|
_DURATION (clip), _INPOINT (clip), 0, properties));
|
||||||
|
|
||||||
|
if (GES_IS_TRANSITION_CLIP (clip))
|
||||||
|
_save_children_properties (str, GES_TIMELINE_ELEMENT (clip));
|
||||||
|
g_string_append (str, ">\n");
|
||||||
|
|
||||||
g_free (extractable_id);
|
g_free (extractable_id);
|
||||||
g_free (properties);
|
g_free (properties);
|
||||||
|
|
||||||
g_hash_table_insert (self->priv->element_id, clip,
|
g_hash_table_insert (self->priv->element_id, clip,
|
||||||
GINT_TO_POINTER (priv->nbelements));
|
GINT_TO_POINTER (priv->nbelements));
|
||||||
|
|
||||||
|
|
||||||
/* Effects must always be serialized in the right priority order.
|
/* Effects must always be serialized in the right priority order.
|
||||||
* List order is guaranteed by the fact that ges_clip_get_top_effects
|
* List order is guaranteed by the fact that ges_clip_get_top_effects
|
||||||
* sorts the effects. */
|
* sorts the effects. */
|
||||||
|
@ -1223,6 +1243,7 @@ _save_layers (GESXmlFormatter * self, GString * str, GESTimeline * timeline)
|
||||||
GES_TRACK_ELEMENT (tmpeffect->data), timeline);
|
GES_TRACK_ELEMENT (tmpeffect->data), timeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tracks = ges_timeline_get_tracks (timeline);
|
tracks = ges_timeline_get_tracks (timeline);
|
||||||
|
|
||||||
for (tmptrackelement = GES_CONTAINER_CHILDREN (clip); tmptrackelement;
|
for (tmptrackelement = GES_CONTAINER_CHILDREN (clip); tmptrackelement;
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
from . import overrides_hack
|
from . import overrides_hack
|
||||||
|
|
||||||
|
import tempfile
|
||||||
|
|
||||||
import gi
|
import gi
|
||||||
gi.require_version("Gst", "1.0")
|
gi.require_version("Gst", "1.0")
|
||||||
gi.require_version("GES", "1.0")
|
gi.require_version("GES", "1.0")
|
||||||
|
@ -68,6 +70,32 @@ class TestCopyPaste(unittest.TestCase):
|
||||||
self.assertEqual(len(self.layer.get_clips()), 2)
|
self.assertEqual(len(self.layer.get_clips()), 2)
|
||||||
|
|
||||||
|
|
||||||
|
class TestTransitionClip(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_serialize_invert(self):
|
||||||
|
timeline = GES.Timeline.new()
|
||||||
|
timeline.add_track(GES.VideoTrack.new())
|
||||||
|
layer = timeline.append_layer()
|
||||||
|
|
||||||
|
clip1 = GES.TransitionClip.new_for_nick("crossfade")
|
||||||
|
clip1.props.duration = Gst.SECOND
|
||||||
|
self.assertTrue(layer.add_clip(clip1))
|
||||||
|
|
||||||
|
vtransition, = clip1.children
|
||||||
|
vtransition.set_inverted(True)
|
||||||
|
self.assertEqual(vtransition.props.invert, True)
|
||||||
|
|
||||||
|
with tempfile.NamedTemporaryFile() as tmpxges:
|
||||||
|
uri = Gst.filename_to_uri(tmpxges.name)
|
||||||
|
timeline.save_to_uri(uri, None, True)
|
||||||
|
|
||||||
|
timeline = GES.Timeline.new_from_uri(uri)
|
||||||
|
self.assertIsNotNone(timeline)
|
||||||
|
layer, = timeline.get_layers()
|
||||||
|
clip, = layer.get_clips()
|
||||||
|
vtransition, = clip.children
|
||||||
|
self.assertEqual(vtransition.props.invert, True)
|
||||||
|
|
||||||
class TestTitleClip(unittest.TestCase):
|
class TestTitleClip(unittest.TestCase):
|
||||||
|
|
||||||
def testSetColor(self):
|
def testSetColor(self):
|
||||||
|
|
Loading…
Reference in a new issue