static void track_element_added_cb (GESClip * clip, GESTrackElement * track_element, GHashTable * props_table) { GESPitiviFormatter *formatter; formatter = GES_PITIVI_FORMATTER (g_hash_table_lookup (props_table, "current-formatter")); if (formatter) { GESPitiviFormatterPrivate *priv = formatter->priv; /* Make sure the hack to get a ref to the formatter * doesn't break everything */ g_hash_table_steal (props_table, "current-formatter"); priv->sources_to_load = g_list_remove (priv->sources_to_load, clip); if (!priv->sources_to_load && GES_FORMATTER (formatter)->project) ges_project_set_loaded (GES_FORMATTER (formatter)->project, GES_FORMATTER (formatter)); } /* Disconnect the signal */ g_signal_handlers_disconnect_by_func (clip, track_element_added_cb, props_table); }
static gboolean save_to_uri (GESFormatter * formatter, GESTimeline * timeline, const gchar * uri) { gchar *location; GError *e = NULL; gboolean ret = TRUE; GESFormatterPrivate *priv = GES_FORMATTER (formatter)->priv; if (!(location = g_filename_from_uri (uri, NULL, NULL))) { return FALSE; } if (!ges_formatter_save (formatter, timeline)) { GST_ERROR ("couldn't serialize formatter"); } else { if (!g_file_set_contents (location, priv->data, priv->length, &e)) { GST_ERROR ("couldn't write file '%s': %s", location, e->message); ret = FALSE; } } if (e) g_error_free (e); g_free (location); return ret; }
GESFormatter * ges_formatter_new_for_uri (const gchar * uri) { if (ges_formatter_can_load_uri (uri)) return GES_FORMATTER (ges_keyfile_formatter_new ()); return NULL; }
static gboolean load_from_uri (GESFormatter * formatter, GESTimeline * timeline, const gchar * uri) { gchar *location; GError *e = NULL; gboolean ret = TRUE; GESFormatterPrivate *priv = GES_FORMATTER (formatter)->priv; if (priv->data) { GST_ERROR ("formatter already has data! please set data to NULL"); } if (!(location = gst_uri_get_location (uri))) { return FALSE; } if (g_file_get_contents (location, &priv->data, &priv->length, &e)) { if (!ges_formatter_load (formatter, timeline)) { GST_ERROR ("couldn't deserialize formatter"); ret = FALSE; } } else { GST_ERROR ("couldn't read file '%s': %s", location, e->message); ret = FALSE; } if (e) g_error_free (e); g_free (location); return ret; }
void ges_formatter_clear_data (GESFormatter * formatter) { GESFormatterPrivate *priv = GES_FORMATTER (formatter)->priv; priv->data = NULL; priv->length = 0; }
/** * ges_formatter_get_data: * @formatter: a #GESFormatter * @length: location into which to store the size of the data in bytes. * * Lets you get the data @formatter used for loading. * * Returns: (transfer none): a pointer to the data. */ void * ges_formatter_get_data (GESFormatter * formatter, gsize * length) { GESFormatterPrivate *priv = GES_FORMATTER (formatter)->priv; *length = priv->length; return priv->data; }
void ges_formatter_set_data (GESFormatter * formatter, void *data, gsize length) { GESFormatterPrivate *priv = GES_FORMATTER (formatter)->priv; if (priv->data) g_free (priv->data); priv->data = data; priv->length = length; }
static void ges_formatter_dispose (GObject * object) { GESFormatterPrivate *priv = GES_FORMATTER (object)->priv; if (priv->data) { g_free (priv->data); } g_hash_table_destroy (priv->uri_newuri_table); g_hash_table_destroy (priv->parent_newparent_table); }
static gboolean _load_project (GESProject * project, GESTimeline * timeline, GError ** error) { GError *lerr = NULL; GESProjectPrivate *priv; GESFormatter *formatter; priv = GES_PROJECT (project)->priv; if (priv->uri == NULL) { EmitLoadedInIdle *data = g_slice_new (EmitLoadedInIdle); GST_LOG_OBJECT (project, "%s, Loading an empty timeline %s" " as no URI set yet", GST_OBJECT_NAME (timeline), ges_asset_get_id (GES_ASSET (project))); data->timeline = gst_object_ref (timeline); data->project = gst_object_ref (project); /* Make sure the signal is emitted after the functions ends */ g_idle_add ((GSourceFunc) _emit_loaded_in_idle, data); return TRUE; } if (priv->formatter_asset == NULL) priv->formatter_asset = _find_formatter_asset_for_uri (priv->uri); if (priv->formatter_asset == NULL) goto failed; formatter = GES_FORMATTER (ges_asset_extract (priv->formatter_asset, &lerr)); if (lerr) { GST_WARNING_OBJECT (project, "Could not create the formatter: %s", (*error)->message); goto failed; } ges_project_add_formatter (GES_PROJECT (project), formatter); ges_formatter_load_from_uri (formatter, timeline, priv->uri, &lerr); if (lerr) { GST_WARNING_OBJECT (project, "Could not load the timeline," " returning: %s", lerr->message); goto failed; } return TRUE; failed: if (lerr) g_propagate_error (error, lerr); return FALSE; }
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_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 load_project (gchar * uri) { GESFormatter *formatter; GESTimeline *timeline; GMainLoop *mainloop; GESTimelinePipeline *pipeline; GstBus *bus; formatter = GES_FORMATTER (ges_pitivi_formatter_new ()); timeline = ges_timeline_new (); pipeline = ges_timeline_pipeline_new (); bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); mainloop = g_main_loop_new (NULL, FALSE); ges_timeline_pipeline_add_timeline (pipeline, timeline); ges_formatter_load_from_uri (formatter, timeline, uri); ges_timeline_pipeline_set_mode (pipeline, TIMELINE_MODE_PREVIEW_VIDEO); gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING); gst_bus_add_signal_watch (bus); g_signal_connect (bus, "message", G_CALLBACK (bus_message_cb), mainloop); g_main_loop_run (mainloop); }
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); }
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); }
GESFormatter * ges_default_formatter_new (void) { return GES_FORMATTER (ges_keyfile_formatter_new ()); }
static gboolean load_pitivi_file_from_uri (GESFormatter * self, GESTimeline * timeline, const gchar * uri, GError ** error) { xmlDocPtr doc; GESLayer *layer; GESPitiviFormatterPrivate *priv = GES_PITIVI_FORMATTER (self)->priv; gboolean ret = TRUE; gint *prio = malloc (sizeof (gint)); *prio = 0; layer = ges_layer_new (); g_object_set (layer, "auto-transition", TRUE, NULL); g_hash_table_insert (priv->layers_table, prio, layer); g_object_set (layer, "priority", (gint32) 0, NULL); if (!ges_timeline_add_layer (timeline, layer)) { GST_ERROR ("Couldn't add layer"); return FALSE; } if (!(doc = xmlParseFile (uri))) { GST_ERROR ("The xptv file for uri %s was badly formed or did not exist", uri); return FALSE; } priv->xpathCtx = xmlXPathNewContext (doc); if (self->project) parse_metadatas (self); if (!create_tracks (self)) { GST_ERROR ("Couldn't create tracks"); return FALSE; } list_sources (self); if (!parse_clips (self)) { GST_ERROR ("Couldn't find clips markup in the xptv file"); return FALSE; } if (!parse_track_elements (self)) { GST_ERROR ("Couldn't find track objects markup in the xptv file"); return FALSE; } /* If there are no clips to load we should emit * 'project-loaded' signal. */ if (!g_hash_table_size (priv->clips_table) && GES_FORMATTER (self)->project) { ges_project_set_loaded (GES_FORMATTER (self)->project, GES_FORMATTER (self)); } else { if (!make_clips (self)) { GST_ERROR ("Couldn't deserialise the project properly"); return FALSE; } } xmlXPathFreeContext (priv->xpathCtx); xmlFreeDoc (doc); return ret; }
/** * ges_project_save: * @project: A #GESProject to save * @timeline: The #GESTimeline to save, it must have been extracted from @project * @uri: The uri where to save @project and @timeline * @formatter_asset: (allow-none): The formatter asset to use or %NULL. If %NULL, * will try to save in the same format as the one from which the timeline as been loaded * or default to the formatter with highest rank * @overwrite: %TRUE to overwrite file if it exists * @error: (out) (allow-none): An error to be set in case something wrong happens or %NULL * * Save the timeline of @project to @uri. You should make sure that @timeline * is one of the timelines that have been extracted from @project * (using ges_asset_extract (@project);) * * Returns: %TRUE if the project could be save, %FALSE otherwize */ gboolean ges_project_save (GESProject * project, GESTimeline * timeline, const gchar * uri, GESAsset * formatter_asset, gboolean overwrite, GError ** error) { GESAsset *tl_asset; gboolean ret = TRUE; GESFormatter *formatter = NULL; g_return_val_if_fail (GES_IS_PROJECT (project), FALSE); g_return_val_if_fail (formatter_asset == NULL || g_type_is_a (ges_asset_get_extractable_type (formatter_asset), GES_TYPE_FORMATTER), FALSE); g_return_val_if_fail ((error == NULL || *error == NULL), FALSE); tl_asset = ges_extractable_get_asset (GES_EXTRACTABLE (timeline)); if (tl_asset == NULL && project->priv->uri == NULL) { GESAsset *asset = ges_asset_cache_lookup (GES_TYPE_PROJECT, uri); if (asset) { GST_WARNING_OBJECT (project, "Trying to save project to %s but we already" "have %" GST_PTR_FORMAT " for that uri, can not save", uri, asset); goto out; } GST_DEBUG_OBJECT (project, "Timeline %" GST_PTR_FORMAT " has no asset" " we have no uri set, so setting ourself as asset", timeline); ges_extractable_set_asset (GES_EXTRACTABLE (timeline), GES_ASSET (project)); } else if (tl_asset != GES_ASSET (project)) { GST_WARNING_OBJECT (project, "Timeline %" GST_PTR_FORMAT " not created by this project can not save", timeline); ret = FALSE; goto out; } if (formatter_asset == NULL) formatter_asset = gst_object_ref (ges_formatter_get_default ()); formatter = GES_FORMATTER (ges_asset_extract (formatter_asset, error)); if (formatter == NULL) { GST_WARNING_OBJECT (project, "Could not create the formatter %p %s: %s", formatter_asset, ges_asset_get_id (formatter_asset), (error && *error) ? (*error)->message : "Unknown Error"); ret = FALSE; goto out; } ges_project_add_formatter (project, formatter); ret = ges_formatter_save_to_uri (formatter, timeline, uri, overwrite, error); if (ret && project->priv->uri == NULL) ges_project_set_uri (project, uri); out: if (formatter_asset) gst_object_unref (formatter_asset); ges_project_remove_formatter (project, formatter); return ret; }