static void _add_track_element (GESFormatter * self, GESClip * clip, GESTrackElement * trackelement, const gchar * track_id, GstStructure * children_properties, GstStructure * properties) { GESBaseXmlFormatterPrivate *priv = _GET_PRIV (self); GESTrack *track = g_hash_table_lookup (priv->tracks, track_id); if (track == NULL) { GST_WARNING_OBJECT (self, "No track with id %s, can not add trackelement", track_id); gst_object_unref (trackelement); return; } GST_DEBUG_OBJECT (self, "Adding track_element: %" GST_PTR_FORMAT " To : %" GST_PTR_FORMAT, trackelement, clip); ges_container_add (GES_CONTAINER (clip), GES_TIMELINE_ELEMENT (trackelement)); gst_structure_foreach (children_properties, (GstStructureForeachFunc) _set_child_property, trackelement); if (properties) gst_structure_foreach (properties, (GstStructureForeachFunc) set_property_foreach, trackelement); }
void ges_base_xml_formatter_set_timeline_properties (GESBaseXmlFormatter * self, GESTimeline * timeline, const gchar * properties, const gchar * metadatas) { GESBaseXmlFormatterPrivate *priv = _GET_PRIV (self); gboolean auto_transition = FALSE; if (properties) { GstStructure *props = gst_structure_from_string (properties, NULL); if (props) { if (gst_structure_get_boolean (props, "auto-transition", &auto_transition)) gst_structure_remove_field (props, "auto-transition"); gst_structure_foreach (props, (GstStructureForeachFunc) set_property_foreach, timeline); gst_structure_free (props); } } if (metadatas) { ges_meta_container_add_metas_from_string (GES_META_CONTAINER (timeline), metadatas); }; priv->timeline_auto_transition = auto_transition; }
void ges_base_xml_formatter_add_source (GESBaseXmlFormatter * self, const gchar * track_id, GstStructure * children_properties) { GESBaseXmlFormatterPrivate *priv = _GET_PRIV (self); 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) { PendingChildProperties *pchildprops; pchildprops = g_slice_new0 (PendingChildProperties); pchildprops->track_id = g_strdup (track_id); pchildprops->structure = children_properties ? gst_structure_copy (children_properties) : NULL; priv->current_pending_clip->children_props = g_list_append (priv->current_pending_clip->children_props, pchildprops); return; } else { element = priv->current_track_element; } if (element == NULL) { GST_WARNING ("No current track element to which we can append children properties"); return; } gst_structure_foreach (children_properties, (GstStructureForeachFunc) _set_child_property, element); }
static void _finalize (GObject * object) { GESBaseXmlFormatterPrivate *priv = _GET_PRIV (object); if (priv->parsecontext != NULL) g_markup_parse_context_free (priv->parsecontext); G_OBJECT_CLASS (parent_class)->finalize (object); }
void ges_base_xml_formatter_add_layer (GESBaseXmlFormatter * self, GType extractable_type, guint priority, GstStructure * properties, const gchar * metadatas, GError ** error) { LayerEntry *entry; GESAsset *asset; GESLayer *layer; gboolean auto_transition = FALSE; GESBaseXmlFormatterPrivate *priv = _GET_PRIV (self); if (priv->check_only) return; if (extractable_type == G_TYPE_NONE) layer = ges_layer_new (); else { asset = ges_asset_request (extractable_type, NULL, error); if (asset == NULL) { if (error && *error == NULL) { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Layer type %s could not be created'", g_type_name (extractable_type)); return; } } layer = GES_LAYER (ges_asset_extract (asset, error)); } ges_layer_set_priority (layer, priority); ges_timeline_add_layer (GES_FORMATTER (self)->timeline, layer); if (properties) { if (gst_structure_get_boolean (properties, "auto-transition", &auto_transition)) gst_structure_remove_field (properties, "auto-transition"); gst_structure_foreach (properties, (GstStructureForeachFunc) set_property_foreach, layer); } if (metadatas) ges_meta_container_add_metas_from_string (GES_META_CONTAINER (layer), metadatas); entry = g_slice_new0 (LayerEntry); entry->layer = gst_object_ref (layer); entry->auto_trans = auto_transition; g_hash_table_insert (priv->layers, GINT_TO_POINTER (priority), entry); }
void ges_base_xml_formatter_add_control_binding (GESBaseXmlFormatter * self, const gchar * binding_type, const gchar * source_type, const gchar * property_name, gint mode, const gchar * track_id, GSList * timed_values) { GESBaseXmlFormatterPrivate *priv = _GET_PRIV (self); 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; } if (element == NULL) { GST_WARNING ("No current track element to which we can append a binding"); return; } if (!g_strcmp0 (source_type, "interpolation")) { GstControlSource *source; source = gst_interpolation_control_source_new (); ges_track_element_set_control_source (element, source, property_name, binding_type); g_object_set (source, "mode", mode, NULL); gst_timed_value_control_source_set_from_list (GST_TIMED_VALUE_CONTROL_SOURCE (source), timed_values); } else GST_WARNING ("This interpolation type is not supported\n"); }
static void _dispose (GObject * object) { GESBaseXmlFormatterPrivate *priv = _GET_PRIV (object); g_clear_pointer (&priv->assetid_pendingclips, (GDestroyNotify) g_hash_table_unref); g_clear_pointer (&priv->containers, (GDestroyNotify) g_hash_table_unref); g_clear_pointer (&priv->clipid_pendings, (GDestroyNotify) g_hash_table_unref); g_clear_pointer (&priv->tracks, (GDestroyNotify) g_hash_table_unref); g_clear_pointer (&priv->layers, (GDestroyNotify) g_hash_table_unref); G_OBJECT_CLASS (parent_class)->dispose (object); }
static void ges_container_init (GESContainer * self) { self->priv = _GET_PRIV (self); /* FIXME, check why default was GST_SECOND? (before the existend of * ges-container) * * _DURATION (self) = GST_SECOND; */ self->height = 1; /* FIXME Why 1 and not 0? */ self->children = NULL; self->priv->mappings = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) _free_mapping); }
static gboolean _can_load_uri (GESFormatter * dummy_formatter, const gchar * uri, GError ** error) { GMarkupParseContext *ctx; GESBaseXmlFormatter *self = GES_BASE_XML_FORMATTER (dummy_formatter); /* we create a temporary object so we can use it as a context */ _GET_PRIV (self)->check_only = TRUE; ctx = create_parser_context (self, uri, error); if (!ctx) return FALSE; g_markup_parse_context_free (ctx); return TRUE; }
void ges_base_xml_formatter_add_group (GESBaseXmlFormatter * self, const gchar * id, const gchar * properties) { PendingGroup *pgroup; GESBaseXmlFormatterPrivate *priv = _GET_PRIV (self); if (priv->check_only) return; pgroup = g_slice_new0 (PendingGroup); pgroup->group = ges_group_new (); g_hash_table_insert (priv->containers, g_strdup (id), gst_object_ref (pgroup->group)); priv->groups = g_list_prepend (priv->groups, pgroup); return; }
void ges_base_xml_formatter_last_group_add_child (GESBaseXmlFormatter * self, const gchar * child_id, const gchar * name) { PendingGroup *pgroup; GESBaseXmlFormatterPrivate *priv = _GET_PRIV (self); if (priv->check_only) return; g_return_if_fail (priv->groups); pgroup = priv->groups->data; pgroup->pending_children = g_list_prepend (pgroup->pending_children, g_strdup (child_id)); GST_DEBUG_OBJECT (self, "Adding %s to %s", child_id, GES_TIMELINE_ELEMENT_NAME (((PendingGroup *) priv->groups->data)->group)); }
static gboolean _load_from_uri (GESFormatter * self, GESTimeline * timeline, const gchar * uri, GError ** error) { GESBaseXmlFormatterPrivate *priv = _GET_PRIV (self); ges_timeline_set_auto_transition (timeline, FALSE); priv->parsecontext = create_parser_context (GES_BASE_XML_FORMATTER (self), uri, error); if (!priv->parsecontext) return FALSE; if (g_hash_table_size (priv->assetid_pendingclips) == 0 && priv->pending_assets == NULL) g_idle_add ((GSourceFunc) _loading_done_cb, g_object_ref (self)); return TRUE; }
void ges_base_xml_formatter_add_track (GESBaseXmlFormatter * self, GESTrackType track_type, GstCaps * caps, const gchar * id, GstStructure * properties, const gchar * metadatas, GError ** error) { GESTrack *track; GESBaseXmlFormatterPrivate *priv = _GET_PRIV (self); if (priv->check_only) { if (caps) gst_caps_unref (caps); return; } track = ges_track_new (track_type, caps); ges_timeline_add_track (GES_FORMATTER (self)->timeline, track); if (properties) { gchar *restriction; GstCaps *caps; gst_structure_get (properties, "restriction-caps", G_TYPE_STRING, &restriction, NULL); gst_structure_remove_fields (properties, "restriction-caps", "caps", "message-forward", NULL); if (g_strcmp0 (restriction, "NULL")) { caps = gst_caps_from_string (restriction); ges_track_set_restriction_caps (track, caps); } gst_structure_foreach (properties, (GstStructureForeachFunc) set_property_foreach, track); } g_hash_table_insert (priv->tracks, g_strdup (id), gst_object_ref (track)); if (metadatas) ges_meta_container_add_metas_from_string (GES_META_CONTAINER (track), metadatas); }
void ges_base_xml_formatter_add_asset (GESBaseXmlFormatter * self, const gchar * id, GType extractable_type, GstStructure * properties, const gchar * metadatas, GError ** error) { PendingAsset *passet; GESBaseXmlFormatterPrivate *priv = _GET_PRIV (self); if (priv->check_only) return; passet = g_slice_new0 (PendingAsset); passet->metadatas = g_strdup (metadatas); passet->formatter = gst_object_ref (self); if (properties) passet->properties = gst_structure_copy (properties); ges_asset_request_async (extractable_type, id, NULL, (GAsyncReadyCallback) new_asset_cb, passet); ges_project_add_loading_asset (GES_FORMATTER (self)->project, extractable_type, id); priv->pending_assets = g_list_prepend (priv->pending_assets, passet); }
void ges_base_xml_formatter_add_track_element (GESBaseXmlFormatter * self, GType track_element_type, const gchar * asset_id, const gchar * track_id, const gchar * timeline_obj_id, GstStructure * children_properties, GstStructure * properties, const gchar * metadatas, GError ** error) { GESTrackElement *trackelement; GError *err = NULL; GESAsset *asset = NULL; GESBaseXmlFormatterPrivate *priv = _GET_PRIV (self); if (priv->check_only) return; if (g_type_is_a (track_element_type, GES_TYPE_TRACK_ELEMENT) == FALSE) { GST_DEBUG_OBJECT (self, "%s is not a TrackElement, can not create it", g_type_name (track_element_type)); goto out; } if (g_type_is_a (track_element_type, GES_TYPE_BASE_EFFECT) == FALSE) { GST_FIXME_OBJECT (self, "%s currently not supported", g_type_name (track_element_type)); goto out; } asset = ges_asset_request (track_element_type, asset_id, &err); if (asset == NULL) { GST_DEBUG_OBJECT (self, "Can not create trackelement %s", asset_id); GST_FIXME_OBJECT (self, "Check if missing plugins etc %s", err ? err->message : ""); goto out; } trackelement = GES_TRACK_ELEMENT (ges_asset_extract (asset, NULL)); if (trackelement) { GESClip *clip; if (metadatas) ges_meta_container_add_metas_from_string (GES_META_CONTAINER (trackelement), metadatas); clip = g_hash_table_lookup (priv->containers, timeline_obj_id); if (clip) { _add_track_element (GES_FORMATTER (self), clip, trackelement, track_id, children_properties, properties); } else { PendingEffects *peffect; PendingClip *pend = g_hash_table_lookup (priv->clipid_pendings, timeline_obj_id); if (pend == NULL) { GST_WARNING_OBJECT (self, "No Clip with id: %s can not " "add TrackElement", timeline_obj_id); goto out; } peffect = g_slice_new0 (PendingEffects); peffect->trackelement = trackelement; peffect->track_id = g_strdup (track_id); peffect->properties = properties ? gst_structure_copy (properties) : NULL; peffect->children_properties = children_properties ? gst_structure_copy (children_properties) : NULL; pend->effects = g_list_append (pend->effects, peffect); } priv->current_track_element = trackelement; } ges_project_add_asset (GES_FORMATTER (self)->project, asset); out: if (asset) gst_object_unref (asset); if (err) g_error_free (err); return; }
void ges_base_xml_formatter_add_encoding_profile (GESBaseXmlFormatter * self, const gchar * type, const gchar * parent, const gchar * name, const gchar * description, GstCaps * format, const gchar * preset, const gchar * preset_name, guint id, guint presence, GstCaps * restriction, guint pass, gboolean variableframerate, GstStructure * properties, GError ** error) { const GList *tmp; GstEncodingProfile *profile; GstEncodingContainerProfile *parent_profile = NULL; GESBaseXmlFormatterPrivate *priv = _GET_PRIV (self); if (priv->check_only) goto done; if (parent == NULL) { profile = _create_profile (self, type, parent, name, description, format, preset, preset_name, id, presence, restriction, pass, variableframerate); ges_project_add_encoding_profile (GES_FORMATTER (self)->project, profile); gst_object_unref (profile); goto done; } for (tmp = ges_project_list_encoding_profiles (GES_FORMATTER (self)->project); tmp; tmp = tmp->next) { GstEncodingProfile *tmpprofile = GST_ENCODING_PROFILE (tmp->data); if (g_strcmp0 (gst_encoding_profile_get_name (tmpprofile), gst_encoding_profile_get_name (tmpprofile)) == 0) { if (!GST_IS_ENCODING_CONTAINER_PROFILE (tmpprofile)) { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Profile '%s' parent %s is not a container...'", name, parent); goto done; } parent_profile = GST_ENCODING_CONTAINER_PROFILE (tmpprofile); break; } } if (parent_profile == NULL) { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Profile '%s' parent %s does not exist'", name, parent); goto done; } profile = _create_profile (self, type, parent, name, description, format, preset, preset_name, id, presence, restriction, pass, variableframerate); if (profile == NULL) goto done; gst_encoding_container_profile_add_profile (parent_profile, profile); done: if (format) gst_caps_unref (format); if (restriction) gst_caps_unref (restriction); }
void ges_base_xml_formatter_add_clip (GESBaseXmlFormatter * self, const gchar * id, const char *asset_id, GType type, GstClockTime start, GstClockTime inpoint, GstClockTime duration, guint layer_prio, GESTrackType track_types, GstStructure * properties, const gchar * metadatas, GError ** error) { GESAsset *asset; GESClip *nclip; LayerEntry *entry; GESBaseXmlFormatterPrivate *priv = _GET_PRIV (self); if (priv->check_only) return; entry = g_hash_table_lookup (priv->layers, GINT_TO_POINTER (layer_prio)); if (entry == NULL) { g_set_error (error, GES_ERROR, GES_ERROR_FORMATTER_MALFORMED_INPUT_FILE, "We got a Clip in a layer" " that does not exist, something is wrong either in the project file or" " in %s", g_type_name (G_OBJECT_TYPE (self))); return; } /* We do not want the properties that are passed to layer-add_asset to be reset */ if (properties) gst_structure_remove_fields (properties, "supported-formats", "inpoint", "start", "duration", NULL); asset = ges_asset_request (type, asset_id, NULL); if (asset == NULL) { gchar *real_id; PendingClip *pclip; GList *pendings; real_id = ges_extractable_type_check_id (type, asset_id, error); if (real_id == NULL) { if (*error == NULL) g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Object type '%s' with Asset id: %s not be created'", g_type_name (type), asset_id); return; } pendings = g_hash_table_lookup (priv->assetid_pendingclips, asset_id); pclip = g_slice_new0 (PendingClip); GST_DEBUG_OBJECT (self, "Adding pending %p for %s, currently: %i", pclip, asset_id, g_list_length (pendings)); pclip->id = g_strdup (id); pclip->track_types = track_types; pclip->duration = duration; pclip->inpoint = inpoint; pclip->start = start; pclip->layer = gst_object_ref (entry->layer); pclip->properties = properties ? gst_structure_copy (properties) : NULL; pclip->metadatas = g_strdup (metadatas); /* Add the new pending object to the hashtable */ g_hash_table_insert (priv->assetid_pendingclips, real_id, 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; } nclip = _add_object_to_layer (priv, id, entry->layer, asset, start, inpoint, duration, track_types, metadatas, properties); if (!nclip) return; priv->current_clip = nclip; }
static void new_asset_cb (GESAsset * source, GAsyncResult * res, PendingAsset * passet) { GError *error = NULL; gchar *possible_id = NULL; GList *tmp, *pendings = NULL; GESFormatter *self = passet->formatter; const gchar *id = ges_asset_get_id (source); GESBaseXmlFormatterPrivate *priv = _GET_PRIV (self); GESAsset *asset = ges_asset_request_finish (res, &error); if (error) { GST_LOG_OBJECT (self, "Error %s creating asset id: %s", error->message, id); /* We set the metas on the Asset to give hints to the user */ if (passet->metadatas) ges_meta_container_add_metas_from_string (GES_META_CONTAINER (source), passet->metadatas); if (passet->properties) gst_structure_foreach (passet->properties, (GstStructureForeachFunc) set_property_foreach, source); possible_id = ges_project_try_updating_id (GES_FORMATTER (self)->project, source, error); if (possible_id == NULL) { GST_WARNING_OBJECT (self, "Abandoning creation of asset %s with ID %s" "- Error: %s", g_type_name (G_OBJECT_TYPE (source)), id, error->message); pendings = g_hash_table_lookup (priv->assetid_pendingclips, id); for (tmp = pendings; tmp; tmp = tmp->next) _free_pending_clip (priv, (PendingClip *) tmp->data); _free_pending_asset (priv, passet); goto done; } /* We got a possible ID replacement for that asset, create it, and * make sure the assetid_pendingclips will use it */ ges_asset_request_async (ges_asset_get_extractable_type (source), possible_id, NULL, (GAsyncReadyCallback) new_asset_cb, passet); ges_project_add_loading_asset (GES_FORMATTER (self)->project, ges_asset_get_extractable_type (source), possible_id); pendings = g_hash_table_lookup (priv->assetid_pendingclips, id); if (pendings) { g_hash_table_remove (priv->assetid_pendingclips, id); g_hash_table_insert (priv->assetid_pendingclips, g_strdup (possible_id), pendings); /* pendings should no be freed */ pendings = NULL; } goto done; } /* now that we have the GESAsset, we create the GESClips */ pendings = g_hash_table_lookup (priv->assetid_pendingclips, id); GST_DEBUG_OBJECT (self, "Asset created with ID %s, now creating pending " " Clips, nb pendings: %i", id, g_list_length (pendings)); for (tmp = pendings; tmp; tmp = tmp->next) { GList *tmpeffect; GESClip *clip; PendingClip *pend = (PendingClip *) tmp->data; clip = _add_object_to_layer (priv, pend->id, pend->layer, asset, pend->start, pend->inpoint, pend->duration, pend->track_types, pend->metadatas, pend->properties); if (clip == NULL) continue; _add_children_properties (priv, pend->children_props, clip); _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) { PendingEffects *peffect = (PendingEffects *) tmpeffect->data; /* We keep a ref as _free_pending_effect unrefs it */ _add_track_element (self, clip, gst_object_ref (peffect->trackelement), peffect->track_id, peffect->children_properties, peffect->properties); } _free_pending_clip (priv, pend); } /* And now add to the project */ ges_project_add_asset (self->project, asset); gst_object_unref (self); _free_pending_asset (priv, passet); done: if (asset) gst_object_unref (asset); if (possible_id) g_free (possible_id); if (pendings) { g_hash_table_remove (priv->assetid_pendingclips, id); g_list_free (pendings); } if (g_hash_table_size (priv->assetid_pendingclips) == 0 && priv->pending_assets == NULL) _loading_done (self); }