1 /* GStreamer Editing Services
3 * Copyright (C) <2015> Thibault Saunier <tsaunier@gnome.org>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
24 #include "ges-structured-interface.h"
25 #include "ges-internal.h"
30 #define LAST_CONTAINER_QDATA g_quark_from_string("ges-structured-last-container")
31 #define LAST_CHILD_QDATA g_quark_from_string("ges-structured-last-child")
33 #ifdef G_HAVE_ISO_VARARGS
34 #define REPORT_UNLESS(condition, errpoint, ...) \
37 gchar *tmp = gst_info_strdup_printf(__VA_ARGS__); \
38 *error = g_error_new_literal (GES_ERROR, 0, tmp); \
44 #else /* G_HAVE_GNUC_VARARGS */
45 #ifdef G_HAVE_GNUC_VARARGS
46 #define REPORT_UNLESS(condition, errpoint, args...) \
49 gchar *tmp = gst_info_strdup_printf(##args); \
50 *error = g_error_new_literal (GES_ERROR, 0, tmp); \
56 #endif /* G_HAVE_ISO_VARARGS */
57 #endif /* G_HAVE_GNUC_VARARGS */
59 #define GET_AND_CHECK(name,type,var,label) G_STMT_START {\
60 gboolean found = FALSE; \
62 if (type == GST_TYPE_CLOCK_TIME) {\
63 found = ges_util_structure_get_clocktime (structure,name, (GstClockTime*)var,NULL);\
66 found = gst_structure_get (structure, name, type, var, NULL); \
69 gchar *struct_str = gst_structure_to_string (structure); \
70 *error = g_error_new (GES_ERROR, 0, \
71 "Could not get the mandatory field '%s'" \
72 " of type %s - fields in %s", name, g_type_name (type), struct_str); \
73 g_free (struct_str); \
78 #define TRY_GET_STRING(name,var,def) G_STMT_START {\
79 *var = gst_structure_get_string (structure, name); \
84 #define TRY_GET_TIME(name, var, var_frames, def) G_STMT_START { \
85 if (!ges_util_structure_get_clocktime (structure, name, var, var_frames)) { \
87 *var_frames = GES_FRAME_NUMBER_NONE; \
92 _get_structure_value (GstStructure * structure, const gchar * field, GType type,
96 const gchar *value_str;
98 GValue nvalue = G_VALUE_INIT;
100 if (gst_structure_get (structure, field, type, v, NULL))
103 g_value_init (&nvalue, type);
104 value = gst_structure_get_value (structure, field);
108 if (g_value_transform (value, &nvalue))
109 goto set_and_get_value;
111 if (!G_VALUE_HOLDS_STRING (value))
114 value_str = g_value_get_string (value);
115 if (!gst_value_deserialize (&nvalue, value_str))
119 gst_structure_set_value (structure, field, &nvalue);
120 gst_structure_get (structure, field, type, v, NULL);
123 g_value_reset (&nvalue);
131 #define TRY_GET(name, type, var, def) G_STMT_START {\
132 g_assert (type != GST_TYPE_CLOCK_TIME); \
133 if (!_get_structure_value (structure, name, type, var))\
139 const gchar **fields;
140 GList *invalid_fields;
144 enum_from_str (GType type, const gchar * str_enum, guint * enum_value)
146 GValue value = G_VALUE_INIT;
147 g_value_init (&value, type);
149 if (!gst_value_deserialize (&value, str_enum))
152 *enum_value = g_value_get_enum (&value);
153 g_value_unset (&value);
159 _check_field (GQuark field_id, const GValue * value, FieldsError * fields_error)
162 const gchar *field = g_quark_to_string (field_id);
164 for (i = 0; fields_error->fields[i]; i++) {
165 if (g_strcmp0 (fields_error->fields[i], field) == 0) {
171 fields_error->invalid_fields =
172 g_list_append (fields_error->invalid_fields, (gpointer) field);
178 _check_fields (GstStructure * structure, FieldsError fields_error,
181 gst_structure_foreach (structure,
182 (GstStructureForeachFunc) _check_field, &fields_error);
184 if (fields_error.invalid_fields) {
186 const gchar *struct_name = gst_structure_get_name (structure);
187 GString *msg = g_string_new (NULL);
189 g_string_append_printf (msg, "Unknown propert%s in %s%s:",
190 g_list_length (fields_error.invalid_fields) > 1 ? "ies" : "y",
191 strlen (struct_name) > 1 ? "--" : "-",
192 gst_structure_get_name (structure));
194 for (tmp = fields_error.invalid_fields; tmp; tmp = tmp->next)
195 g_string_append_printf (msg, " %s", (gchar *) tmp->data);
198 *error = g_error_new_literal (GES_ERROR, 0, msg->str);
200 g_string_free (msg, TRUE);
208 static GESTimelineElement *
209 find_element_for_property (GESTimeline * timeline, GstStructure * structure,
210 gchar ** property_name, gboolean require_track_element, GError ** error)
213 const gchar *element_name;
214 GESTimelineElement *element;
216 element_name = gst_structure_get_string (structure, "element-name");
217 if (element_name == NULL) {
218 element = g_object_get_qdata (G_OBJECT (timeline), LAST_CHILD_QDATA);
220 gst_object_ref (element);
222 element = ges_timeline_get_element (timeline, element_name);
225 if (*property_name == NULL) {
226 gchar *tmpstr = *property_name;
227 const gchar *name = gst_structure_get_name (structure);
229 REPORT_UNLESS (g_str_has_prefix (name, "set-"), err,
230 "Could not find any property name in %" GST_PTR_FORMAT, structure);
232 *property_name = g_strdup (&tmpstr[4]);
238 if (!ges_timeline_element_lookup_child (element,
239 *property_name, NULL, NULL)) {
240 gst_clear_object (&element);
245 element = g_object_get_qdata (G_OBJECT (timeline), LAST_CONTAINER_QDATA);
247 gst_object_ref (element);
250 REPORT_UNLESS (GES_IS_TIMELINE_ELEMENT (element), err,
251 "Could not find child %s from %" GST_PTR_FORMAT, element_name, structure);
253 if (!require_track_element || GES_IS_TRACK_ELEMENT (element))
257 REPORT_UNLESS (GES_IS_CONTAINER (element), err,
258 "Could not find child %s from %" GST_PTR_FORMAT, element_name, structure);
260 for (tmp = GES_CONTAINER_CHILDREN (element); tmp; tmp = tmp->next) {
261 if (ges_timeline_element_lookup_child (tmp->data, *property_name, NULL,
263 gst_object_replace ((GstObject **) & element, tmp->data);
269 REPORT_UNLESS (GES_IS_TRACK_ELEMENT (element), err,
270 "Could not find TrackElement from %" GST_PTR_FORMAT, structure);
275 g_clear_object (&element);
280 _ges_save_timeline_if_needed (GESTimeline * timeline, GstStructure * structure,
284 const gchar *nested_timeline_id =
285 gst_structure_get_string (structure, "project-uri");
287 if (nested_timeline_id) {
288 res = ges_timeline_save_to_uri (timeline, nested_timeline_id, NULL, TRUE,
297 GstTimedValueControlSource *source;
298 GstStructure *structure;
300 const gchar *property_name;
305 un_set_keyframes_foreach (GQuark field_id, const GValue * value,
306 SetKeyframesData * d)
308 GValue v = G_VALUE_INIT;
309 GError **error = &d->error;
312 const gchar *valid_fields[] = {
313 "element-name", "property-name", "value", "timestamp", "project-uri",
314 "binding-type", "source-type", "interpolation-mode", "interpolation-mode",
317 const gchar *field = g_quark_to_string (field_id);
320 for (i = 0; valid_fields[i]; i++) {
321 if (g_quark_from_string (valid_fields[i]) == field_id)
326 ts = g_strtod (field, &tmp);
328 REPORT_UNLESS (errno == 0 && field != tmp, err,
329 "Could not convert `%s` to GstClockTime (%s)", field, g_strerror (errno));
331 if (gst_structure_has_name (d->structure, "remove-keyframe")) {
332 REPORT_UNLESS (gst_timed_value_control_source_unset (d->source,
333 ts * GST_SECOND), err, "Could not unset keyframe at %f", ts);
338 g_value_init (&v, G_TYPE_DOUBLE);
339 REPORT_UNLESS (g_value_transform (value, &v), err,
340 "Could not convert keyframe %f value %s to double", ts,
341 gst_value_serialize (value));
343 REPORT_UNLESS (gst_timed_value_control_source_set (d->source, ts * GST_SECOND,
344 g_value_get_double (&v)), err, "Could not set keyframe %f=%f", ts,
345 g_value_get_double (&v));
359 _ges_add_remove_keyframe_from_struct (GESTimeline * timeline,
360 GstStructure * structure, GError ** error)
362 GESTimelineElement *element = NULL;
366 GstClockTime timestamp;
367 GstControlBinding *binding = NULL;
368 GstTimedValueControlSource *source = NULL;
369 gchar *property_name = NULL;
371 gboolean ret = FALSE;
372 gboolean setting_value;
374 const gchar *valid_fields[] =
375 { "element-name", "property-name", "value", "timestamp", "project-uri",
379 FieldsError fields_error = { valid_fields, NULL };
381 if (gst_structure_has_field (structure, "value")) {
382 if (!_check_fields (structure, fields_error, error))
384 GET_AND_CHECK ("timestamp", GST_TYPE_CLOCK_TIME, ×tamp, done);
386 REPORT_UNLESS (!gst_structure_has_field (structure, "timestamp"), done,
387 "Doesn't have a `value` field in %" GST_PTR_FORMAT
388 " but has a `timestamp`" " that can't work!", structure);
391 GET_AND_CHECK ("property-name", G_TYPE_STRING, &property_name, done);
393 find_element_for_property (timeline, structure, &property_name, TRUE,
397 REPORT_UNLESS (binding =
398 ges_track_element_get_control_binding (GES_TRACK_ELEMENT (element),
400 done, "No control binding found for %" GST_PTR_FORMAT, structure);
402 g_object_get (binding, "control-source", &source, NULL);
403 REPORT_UNLESS (source, done,
404 "No control source found for '%" GST_PTR_FORMAT
405 "' you should first set-control-binding on it", structure);
406 REPORT_UNLESS (GST_IS_TIMED_VALUE_CONTROL_SOURCE (source), done,
407 "You can use add-keyframe"
408 " only on GstTimedValueControlSource not %s",
409 G_OBJECT_TYPE_NAME (source));
411 if (!gst_structure_has_field (structure, "value")) {
412 SetKeyframesData d = {
413 source, structure, NULL, property_name, TRUE,
415 gst_structure_foreach (structure,
416 (GstStructureForeachFunc) un_set_keyframes_foreach, &d);
418 g_propagate_error (error, d.error);
423 g_object_get (binding, "absolute", &absolute, NULL);
427 GValue v2 = G_VALUE_INIT;
429 if (!ges_timeline_element_lookup_child (element, property_name, NULL,
432 g_error_new (GES_ERROR, 0, "Could not get property %s for %s",
433 property_name, GES_TIMELINE_ELEMENT_NAME (element));
437 v = gst_structure_get_value (structure, "value");
439 gchar *struct_str = gst_structure_to_string (structure);
441 *error = g_error_new (GES_ERROR, 0,
442 "Could not get the mandatory field 'value'"
443 " of type %s - fields in %s", g_type_name (pspec->value_type),
449 g_value_init (&v2, G_TYPE_DOUBLE);
450 if (!g_value_transform (v, &v2)) {
451 gchar *struct_str = gst_structure_to_string (structure);
453 *error = g_error_new (GES_ERROR, 0,
454 "Could not get the mandatory field 'value'"
455 " of type %s - fields in %s", g_type_name (pspec->value_type),
460 value = g_value_get_double (&v2);
463 GET_AND_CHECK ("value", G_TYPE_DOUBLE, &value, done);
466 !g_strcmp0 (gst_structure_get_name (structure), "add-keyframe");
468 ret = gst_timed_value_control_source_set (source, timestamp, value);
470 ret = gst_timed_value_control_source_unset (source, timestamp);
474 g_error_new (GES_ERROR, 0,
475 "Could not %sset value for timestamp: %" GST_TIME_FORMAT,
476 setting_value ? "" : "un", GST_TIME_ARGS (timestamp));
478 ret = _ges_save_timeline_if_needed (timeline, structure, error);
481 gst_clear_object (&source);
482 gst_clear_object (&element);
483 g_free (property_name);
490 _ges_get_asset_from_timeline (GESTimeline * timeline, GType type,
491 const gchar * id, GError ** error)
494 GESProject *project = ges_timeline_get_project (timeline);
497 asset = ges_project_create_asset_sync (project, id, type, &err);
500 g_propagate_error (error, err);
501 if (!asset || (error && *error)) {
503 if (error && !*error) {
504 *error = g_error_new (GES_ERROR, 0,
505 "There was an error requesting the asset with id %s and type %s (%s)",
506 id, g_type_name (type), "unknown");
510 ("There was an error requesting the asset with id %s and type %s (%s)",
511 id, g_type_name (type), error ? (*error)->message : "unknown");
519 /* Unref after usage */
521 _ges_get_layer_by_priority (GESTimeline * timeline, gint priority)
525 GESLayer *layer = NULL;
527 priority = MAX (priority, 0);
528 layers = ges_timeline_get_layers (timeline);
529 nlayers = (gint) g_list_length (layers);
530 if (priority >= nlayers) {
533 while (i <= priority) {
534 layer = ges_timeline_append_layer (timeline);
539 layer = gst_object_ref (layer);
544 layer = ges_timeline_get_layer (timeline, priority);
547 g_list_free_full (layers, gst_object_unref);
553 ensure_uri (gchar * location)
555 if (gst_uri_is_valid (location))
556 return g_strdup (location);
558 return gst_filename_to_uri (location, NULL);
562 get_flags_from_string (GType type, const gchar * str_flags, guint * flags)
564 GValue value = G_VALUE_INIT;
565 g_value_init (&value, type);
567 if (!gst_value_deserialize (&value, str_flags)) {
568 g_value_unset (&value);
573 *flags = g_value_get_flags (&value);
574 g_value_unset (&value);
580 _ges_add_clip_from_struct (GESTimeline * timeline, GstStructure * structure,
583 GESAsset *asset = NULL;
584 GESLayer *layer = NULL;
589 const gchar *pattern;
590 const gchar *track_types_str;
591 const gchar *nested_timeline_id;
592 gchar *asset_id = NULL;
593 gchar *check_asset_id = NULL;
594 const gchar *type_string;
596 gboolean res = FALSE;
597 GESTrackType track_types = GES_TRACK_TYPE_UNKNOWN;
599 GESFrameNumber start_frame = GES_FRAME_NUMBER_NONE, inpoint_frame =
600 GES_FRAME_NUMBER_NONE, duration_frame = GES_FRAME_NUMBER_NONE;
601 GstClockTime duration = 1 * GST_SECOND, inpoint = 0, start =
604 const gchar *valid_fields[] =
605 { "asset-id", "pattern", "name", "layer-priority", "layer", "type",
606 "start", "inpoint", "duration", "text", "track-types", "project-uri",
610 FieldsError fields_error = { valid_fields, NULL };
612 if (!_check_fields (structure, fields_error, error))
615 GET_AND_CHECK ("asset-id", G_TYPE_STRING, &check_asset_id, beach);
617 TRY_GET_STRING ("pattern", &pattern, NULL);
618 TRY_GET_STRING ("text", &text, NULL);
619 TRY_GET_STRING ("name", &name, NULL);
620 TRY_GET ("layer-priority", G_TYPE_INT, &layer_priority, -1);
621 if (layer_priority == -1)
622 TRY_GET ("layer", G_TYPE_INT, &layer_priority, -1);
623 TRY_GET_STRING ("type", &type_string, "GESUriClip");
624 TRY_GET_TIME ("start", &start, &start_frame, GST_CLOCK_TIME_NONE);
625 TRY_GET_TIME ("inpoint", &inpoint, &inpoint_frame, 0);
626 TRY_GET_TIME ("duration", &duration, &duration_frame, GST_CLOCK_TIME_NONE);
627 TRY_GET_STRING ("track-types", &track_types_str, NULL);
628 TRY_GET_STRING ("project-uri", &nested_timeline_id, NULL);
630 if (track_types_str) {
631 if (!get_flags_from_string (GES_TYPE_TRACK_TYPE, track_types_str,
634 g_error_new (GES_ERROR, 0, "Invalid track types: %s",
640 if (!(type = g_type_from_name (type_string))) {
641 *error = g_error_new (GES_ERROR, 0, "This type doesn't exist : %s",
647 if (type == GES_TYPE_URI_CLIP) {
648 asset_id = ensure_uri (check_asset_id);
650 asset_id = g_strdup (check_asset_id);
653 gst_structure_set (structure, "asset-id", G_TYPE_STRING, asset_id, NULL);
654 asset = _ges_get_asset_from_timeline (timeline, type, asset_id, error);
661 if (layer_priority == -1) {
662 GESContainer *container;
664 container = g_object_get_qdata (G_OBJECT (timeline), LAST_CONTAINER_QDATA);
665 if (!container || !GES_IS_CLIP (container))
666 layer = _ges_get_layer_by_priority (timeline, 0);
668 layer = ges_clip_get_layer (GES_CLIP (container));
671 layer = _ges_get_layer_by_priority (timeline, 0);
673 layer = _ges_get_layer_by_priority (timeline, layer_priority);
678 g_error_new (GES_ERROR, 0, "No layer with priority %d", layer_priority);
682 if (GES_FRAME_NUMBER_IS_VALID (start_frame))
683 start = ges_timeline_get_frame_time (timeline, start_frame);
685 if (GES_FRAME_NUMBER_IS_VALID (inpoint_frame)) {
687 ges_clip_asset_get_frame_time (GES_CLIP_ASSET (asset), inpoint_frame);
688 if (!GST_CLOCK_TIME_IS_VALID (inpoint)) {
690 g_error_new (GES_ERROR, 0, "Could not get inpoint from frame %"
691 G_GINT64_FORMAT, inpoint_frame);
696 if (GES_FRAME_NUMBER_IS_VALID (duration_frame)) {
697 duration = ges_timeline_get_frame_time (timeline, duration_frame);
700 if (GES_IS_URI_CLIP_ASSET (asset) && !GST_CLOCK_TIME_IS_VALID (duration)) {
701 duration = GST_CLOCK_DIFF (inpoint,
702 ges_uri_clip_asset_get_duration (GES_URI_CLIP_ASSET (asset)));
705 clip = ges_layer_add_asset (layer, asset, start, inpoint, duration,
711 if (GES_TIMELINE_ELEMENT_DURATION (clip) == 0) {
712 *error = g_error_new (GES_ERROR, 0,
713 "Clip %s has 0 as duration, please provide a proper duration",
720 if (GES_IS_TEST_CLIP (clip)) {
724 REPORT_UNLESS (enum_from_str (GES_VIDEO_TEST_PATTERN_TYPE, pattern, &v),
725 beach, "Invalid pattern: %s", pattern);
726 ges_test_clip_set_vpattern (GES_TEST_CLIP (clip), v);
730 if (GES_IS_TITLE_CLIP (clip) && text)
731 ges_timeline_element_set_child_properties (GES_TIMELINE_ELEMENT (clip),
735 && !ges_timeline_element_set_name (GES_TIMELINE_ELEMENT (clip), name)) {
738 g_error_new (GES_ERROR, 0, "couldn't set name %s on clip with id %s",
743 g_error_new (GES_ERROR, 0,
744 "Couldn't add clip with id %s to layer with priority %d", asset_id,
751 g_object_set_qdata (G_OBJECT (timeline), LAST_CONTAINER_QDATA, clip);
752 g_object_set_qdata (G_OBJECT (timeline), LAST_CHILD_QDATA, NULL);
755 res = _ges_save_timeline_if_needed (timeline, structure, error);
758 gst_clear_object (&layer);
759 gst_clear_object (&asset);
761 g_free (check_asset_id);
766 _ges_add_track_from_struct (GESTimeline * timeline,
767 GstStructure * structure, GError ** error)
773 const gchar *valid_fields[] = { "type", "restrictions", NULL };
775 FieldsError fields_error = { valid_fields, NULL };
777 if (!_check_fields (structure, fields_error, error))
780 ttype = gst_structure_get_string (structure, "type");
781 if (!g_strcmp0 (ttype, "video")) {
782 track = GES_TRACK (ges_video_track_new ());
783 } else if (!g_strcmp0 (ttype, "audio")) {
784 track = GES_TRACK (ges_audio_track_new ());
786 g_set_error (error, GES_ERROR, 0, "Unhandled track type: `%s`", ttype);
791 if (gst_structure_has_field (structure, "restrictions")) {
792 GstStructure *restriction_struct;
793 gchar *restriction_str;
795 if (gst_structure_get (structure, "restrictions", GST_TYPE_STRUCTURE,
796 &restriction_struct, NULL)) {
797 caps = gst_caps_new_full (restriction_struct, NULL);
798 } else if (gst_structure_get (structure, "restrictions", G_TYPE_STRING,
799 &restriction_str, NULL)) {
800 caps = gst_caps_from_string (restriction_str);
803 g_set_error (error, GES_ERROR, 0, "Invalid restrictions caps: %s",
806 g_free (restriction_str);
809 g_free (restriction_str);
810 } else if (!gst_structure_get (structure, "restrictions", GST_TYPE_CAPS,
812 gchar *tmp = gst_structure_to_string (structure);
814 g_set_error (error, GES_ERROR, 0, "Can't use restrictions caps from %s",
817 g_object_unref (track);
821 ges_track_set_restriction_caps (track, caps);
822 gst_caps_unref (caps);
825 return ges_timeline_add_track (timeline, track);
829 _ges_container_add_child_from_struct (GESTimeline * timeline,
830 GstStructure * structure, GError ** error)
832 GESAsset *asset = NULL;
833 GESContainer *container;
834 GESTimelineElement *child = NULL;
835 const gchar *container_name, *child_name, *child_type, *id;
838 const gchar *valid_fields[] = { "container-name", "asset-id", "inpoint",
839 "child-type", "child-name", "project-uri", NULL
842 FieldsError fields_error = { valid_fields, NULL };
844 if (!_check_fields (structure, fields_error, error))
847 container_name = gst_structure_get_string (structure, "container-name");
849 if (container_name == NULL) {
850 container = g_object_get_qdata (G_OBJECT (timeline), LAST_CONTAINER_QDATA);
853 GES_CONTAINER (ges_timeline_get_element (timeline, container_name));
856 if (!GES_IS_CONTAINER (container)) {
858 g_error_new (GES_ERROR, 0, "Could not find container: %s (%p)",
859 container_name, container);
865 id = gst_structure_get_string (structure, "asset-id");
866 child_type = gst_structure_get_string (structure, "child-type");
868 if (id && child_type) {
870 _ges_get_asset_from_timeline (timeline, g_type_from_name (child_type),
878 child = GES_TIMELINE_ELEMENT (ges_asset_extract (asset, NULL));
879 if (!GES_IS_TIMELINE_ELEMENT (child)) {
880 *error = g_error_new (GES_ERROR, 0, "Could not extract child element");
886 child_name = gst_structure_get_string (structure, "child-name");
887 if (!child && child_name) {
888 child = ges_timeline_get_element (timeline, child_name);
889 if (!GES_IS_TIMELINE_ELEMENT (child)) {
890 *error = g_error_new (GES_ERROR, 0, "Could not find child element");
898 g_error_new (GES_ERROR, 0, "Wrong parameters, could not get a child");
904 ges_timeline_element_set_name (child, child_name);
906 child_name = GES_TIMELINE_ELEMENT_NAME (child);
908 if (gst_structure_has_field (structure, "inpoint")) {
909 GstClockTime inpoint;
910 GESFrameNumber finpoint;
912 if (!GES_IS_TRACK_ELEMENT (child)) {
913 *error = g_error_new (GES_ERROR, 0, "Child %s is not a trackelement"
914 ", can't set inpoint.", child_name);
916 gst_object_unref (child);
921 if (!ges_util_structure_get_clocktime (structure, "inpoint", &inpoint,
923 *error = g_error_new (GES_ERROR, 0, "Could not use inpoint.");
924 gst_object_unref (child);
929 if (!ges_track_element_set_has_internal_source (GES_TRACK_ELEMENT (child),
932 g_error_new (GES_ERROR, 0,
933 "Could not set inpoint as %s can't have an internal source",
935 gst_object_unref (child);
940 if (GES_FRAME_NUMBER_IS_VALID (finpoint))
941 inpoint = ges_timeline_get_frame_time (timeline, finpoint);
943 ges_timeline_element_set_inpoint (child, inpoint);
947 res = ges_container_add (container, child);
949 g_error_new (GES_ERROR, 0, "Could not add child to container");
951 g_object_set_qdata (G_OBJECT (timeline), LAST_CHILD_QDATA, child);
953 res = _ges_save_timeline_if_needed (timeline, structure, error);
956 gst_clear_object (&asset);
961 _ges_set_child_property_from_struct (GESTimeline * timeline,
962 GstStructure * structure, GError ** error)
965 GValue prop_value = G_VALUE_INIT;
966 gboolean prop_value_set = FALSE;
967 gchar *property_name;
968 GESTimelineElement *element;
972 const gchar *valid_fields[] =
973 { "element-name", "property", "value", "project-uri", NULL };
975 FieldsError fields_error = { valid_fields, NULL };
977 if (!_check_fields (structure, fields_error, error))
980 GET_AND_CHECK ("property", G_TYPE_STRING, &property_name, err);
983 find_element_for_property (timeline, structure, &property_name, FALSE,
987 value = gst_structure_get_value (structure, "value");
989 if (G_VALUE_TYPE (value) == G_TYPE_STRING) {
991 if (ges_timeline_element_lookup_child (element, property_name, NULL,
993 GType p_type = pspec->value_type;
994 g_param_spec_unref (pspec);
995 if (p_type != G_TYPE_STRING) {
996 const gchar *val_string = g_value_get_string (value);
997 g_value_init (&prop_value, p_type);
998 if (!gst_value_deserialize (&prop_value, val_string)) {
999 *error = g_error_new (GES_ERROR, 0, "Could not set the property %s "
1000 "because the value %s could not be deserialized to the %s type",
1001 property_name, val_string, g_type_name (p_type));
1004 prop_value_set = TRUE;
1007 /* else, let the setter fail below */
1010 if (!prop_value_set) {
1011 g_value_init (&prop_value, G_VALUE_TYPE (value));
1012 g_value_copy (value, &prop_value);
1015 serialized = gst_value_serialize (&prop_value);
1016 GST_INFO_OBJECT (element, "Setting property %s to %s\n", property_name,
1018 g_free (serialized);
1020 res = ges_timeline_element_set_child_property (element, property_name,
1022 g_value_unset (&prop_value);
1025 GParamSpec **specs =
1026 ges_timeline_element_list_children_properties (element, &n_specs);
1027 GString *errstr = g_string_new (NULL);
1029 g_string_append_printf (errstr,
1030 "\n Could not set property `%s` on `%s`, valid properties:\n",
1031 property_name, GES_TIMELINE_ELEMENT_NAME (element));
1033 for (i = 0; i < n_specs; i++)
1034 g_string_append_printf (errstr, " - %s\n", specs[i]->name);
1037 *error = g_error_new_literal (GES_ERROR, 0, errstr->str);
1038 g_string_free (errstr, TRUE);
1042 g_free (property_name);
1043 return _ges_save_timeline_if_needed (timeline, structure, error);
1046 g_free (property_name);
1051 _ges_set_control_source_from_struct (GESTimeline * timeline,
1052 GstStructure * structure, GError ** error)
1055 gboolean res = FALSE;
1056 GESTimelineElement *element = NULL;
1058 GstControlSource *source = NULL;
1059 gchar *property_name, *binding_type = NULL,
1060 *source_type = NULL, *interpolation_mode = NULL;
1062 GET_AND_CHECK ("property-name", G_TYPE_STRING, &property_name, beach);
1065 find_element_for_property (timeline, structure, &property_name, TRUE,
1069 if (GES_IS_CLIP (element)) {
1071 for (tmp = GES_CONTAINER_CHILDREN (element); tmp; tmp = tmp->next) {
1072 if (ges_timeline_element_lookup_child (tmp->data, property_name, NULL,
1074 gst_object_replace ((GstObject **) & element, tmp->data);
1081 REPORT_UNLESS (GES_IS_TRACK_ELEMENT (element), beach,
1082 "Could not find TrackElement from %" GST_PTR_FORMAT, structure);
1084 TRY_GET ("binding-type", G_TYPE_STRING, &binding_type, NULL);
1085 TRY_GET ("source-type", G_TYPE_STRING, &source_type, NULL);
1086 TRY_GET ("interpolation-mode", G_TYPE_STRING, &interpolation_mode, NULL);
1089 binding_type = g_strdup ("direct");
1091 REPORT_UNLESS (source_type == NULL
1092 || !g_strcmp0 (source_type, "interpolation"), beach,
1093 "Interpolation type %s not supported", source_type);
1094 source = gst_interpolation_control_source_new ();
1096 if (interpolation_mode)
1097 REPORT_UNLESS (enum_from_str (GST_TYPE_INTERPOLATION_MODE,
1098 interpolation_mode, &mode), beach,
1099 "Wrong interpolation mode: %s", interpolation_mode);
1101 mode = GST_INTERPOLATION_MODE_LINEAR;
1103 g_object_set (source, "mode", mode, NULL);
1105 res = ges_track_element_set_control_source (GES_TRACK_ELEMENT (element),
1106 source, property_name, binding_type);
1109 gst_clear_object (&element);
1110 gst_clear_object (&source);
1111 g_free (property_name);
1112 g_free (binding_type);
1113 g_free (source_type);
1114 g_free (interpolation_mode);
1119 #undef GET_AND_CHECK