/** * ges_text_overlay_clip_new: * * Creates a new #GESTextOverlayClip * * Returns: (transfer floating) (nullable): The newly created * #GESTextOverlayClip, or %NULL if there was an error. */ GESTextOverlayClip * ges_text_overlay_clip_new (void) { GESTextOverlayClip *new_clip; GESAsset *asset = ges_asset_request (GES_TYPE_OVERLAY_TEXT_CLIP, NULL, NULL); new_clip = GES_OVERLAY_TEXT_CLIP (ges_asset_extract (asset, NULL)); gst_object_unref (asset); return new_clip; }
/** * ges_test_clip_new: * * Creates a new #GESTestClip. * * Returns: The newly created #GESTestClip, or NULL if there was an * error. */ GESTestClip * ges_test_clip_new (void) { GESTestClip *new_clip; GESAsset *asset = ges_asset_request (GES_TYPE_TEST_CLIP, NULL, NULL); new_clip = GES_TEST_CLIP (ges_asset_extract (asset, NULL)); gst_object_unref (asset); return new_clip; }
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); }
/** * ges_asset_custom_source_clip_new: * @func: (scope notified): The #GESFillTrackElementUserFunc that will be used to fill the track * objects. * @user_data: (closure): a gpointer that will be used when @func is called. * * Helper constructor to instanciate a new #GESAsset from which you can * extract #GESCustomSourceClip-s * * Returns: The new #GESAsset */ GESAsset * ges_asset_custom_source_clip_new (GESFillTrackElementUserFunc func, gpointer user_data) { GESAsset *asset; gchar *id = g_strdup_printf ("%i!%i", GPOINTER_TO_INT (func), GPOINTER_TO_INT (user_data)); asset = ges_asset_request (GES_TYPE_CUSTOM_SOURCE_CLIP, id, NULL); g_free (id); return asset; }
GESTransitionClip * ges_transition_clip_new_for_nick (gchar * nick) { GESTransitionClip *ret = NULL; GESAsset *asset = ges_asset_request (GES_TYPE_TRANSITION_CLIP, nick, NULL); if (asset != NULL) { ret = GES_TRANSITION_CLIP (ges_asset_extract (asset, NULL)); gst_object_unref (asset); } else GST_WARNING ("No asset found for nick: %s", nick); return ret; }
/** * ges_effect_new: * @bin_description: The gst-launch like bin description of the effect * * Creates a new #GESEffect from the description of the bin. * * Returns: a newly created #GESEffect, or %NULL if something went * wrong. */ GESEffect * ges_effect_new (const gchar * bin_description) { GESEffect *effect; GESAsset *asset = ges_asset_request (GES_TYPE_EFFECT, bin_description, NULL); g_return_val_if_fail (asset, NULL); effect = GES_EFFECT (ges_asset_extract (asset, NULL)); gst_object_unref (asset); return effect; }
void _init_standard_transition_assets (void) { guint i; for (i = 1; i < G_N_ELEMENTS (transition_types) - 1; i++) { GESAsset *asset = ges_asset_request (GES_TYPE_TRANSITION_CLIP, transition_types[i].value_nick, NULL); ges_meta_container_register_meta_string (GES_META_CONTAINER (asset), GES_META_READABLE, GES_META_DESCRIPTION, transition_types[i].value_name); } }
/** * ges_project_new: * @uri: (allow-none): The uri to be set after creating the project. * * Creates a new #GESProject and sets its uri to @uri if provided. Note that * if @uri is not valid or %NULL, the uri of the project will then be set * the first time you save the project. If you then save the project to * other locations, it will never be updated again and the first valid URI is * the URI it will keep refering to. * * Returns: A newly created #GESProject */ GESProject * ges_project_new (const gchar * uri) { gchar *id = (gchar *) uri; GESProject *project; if (uri == NULL) id = g_strdup_printf ("project-%i", nb_projects++); project = GES_PROJECT (ges_asset_request (GES_TYPE_TIMELINE, id, NULL)); if (project && uri) ges_project_set_uri (project, uri); return project; }
static gboolean _add_asset (GstValidateScenario *scenario, GstValidateAction *action) { const gchar *id = NULL; const gchar *type_string = NULL; GType type; GESTimeline *timeline = get_timeline(scenario); GESProject *project = ges_timeline_get_project(timeline); GESAsset *asset; GError *error = NULL; gboolean res = FALSE; id = gst_structure_get_string (action->structure, "id"); type_string = gst_structure_get_string (action->structure, "type"); if (!type_string || !id) { GST_ERROR("Missing parameters, we got type %s and id %s", type_string, id); goto beach; } if (!(type = g_type_from_name(type_string))) { GST_ERROR("This type doesn't exist : %s", type_string); goto beach; } if (type == GES_TYPE_URI_CLIP) asset = (GESAsset *) ges_uri_clip_asset_request_sync(id, &error); else asset = ges_asset_request(type, id, &error); if (!asset || error) { GST_ERROR("There was an error requesting the asset with id %s and type %s", id, type_string); goto beach; } res = ges_project_add_asset(project, asset); beach: g_object_unref(timeline); return res; }
/* Internal methods */ static void ges_transition_clip_update_vtype_internal (GESClip * self, GESVideoStandardTransitionType value, gboolean set_asset) { GSList *tmp; guint index; GEnumClass *enum_class; const gchar *asset_id = NULL; GESTransitionClip *trself = GES_TRANSITION_CLIP (self); enum_class = g_type_class_peek (GES_VIDEO_STANDARD_TRANSITION_TYPE_TYPE); for (index = 0; index < enum_class->n_values; index++) { if (enum_class->values[index].value == value) { asset_id = enum_class->values[index].value_nick; break; } } if (asset_id == NULL) { GST_WARNING_OBJECT (self, "Wrong transition type value: %i can not set it", value); return; } for (tmp = trself->priv->video_transitions; tmp; tmp = tmp->next) { if (!ges_video_transition_set_transition_type (GES_VIDEO_TRANSITION (tmp->data), value)) return; } trself->vtype = value; trself->priv->vtype_name = asset_id; if (set_asset) { /* We already checked the value, so we can be sure no error will accured */ ges_extractable_set_asset (GES_EXTRACTABLE (self), ges_asset_request (GES_TYPE_TRANSITION_CLIP, asset_id, NULL)); } }
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; }
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; }
/** * ges_layer_add_clip: * @layer: a #GESLayer * @clip: (transfer full): the #GESClip to add. * * Adds the given clip to the layer. Sets the clip's parent, and thus * takes ownership of the clip. * * An clip can only be added to one layer. * * Calling this method will construct and properly set all the media related * elements on @clip. If you need to know when those objects (actually #GESTrackElement) * are constructed, you should connect to the container::child-added signal which * is emited right after those elements are ready to be used. * * Returns: TRUE if the clip was properly added to the layer, or FALSE * if the @layer refuses to add the clip. */ gboolean ges_layer_add_clip (GESLayer * layer, GESClip * clip) { GESAsset *asset; GESLayerPrivate *priv; GESLayer *current_layer; g_return_val_if_fail (GES_IS_LAYER (layer), FALSE); g_return_val_if_fail (GES_IS_CLIP (clip), FALSE); GST_DEBUG_OBJECT (layer, "adding clip:%p", clip); priv = layer->priv; current_layer = ges_clip_get_layer (clip); if (G_UNLIKELY (current_layer)) { GST_WARNING ("Clip %p already belongs to another layer", clip); gst_object_unref (current_layer); return FALSE; } asset = ges_extractable_get_asset (GES_EXTRACTABLE (clip)); if (asset == NULL) { gchar *id; NewAssetUData *mudata = g_slice_new (NewAssetUData); mudata->clip = clip; mudata->layer = layer; GST_DEBUG_OBJECT (layer, "%" GST_PTR_FORMAT " as no reference to any " "assets creating a asset... trying sync", clip); id = ges_extractable_get_id (GES_EXTRACTABLE (clip)); asset = ges_asset_request (G_OBJECT_TYPE (clip), id, NULL); if (asset == NULL) { GESProject *project = layer->timeline ? GES_PROJECT (ges_extractable_get_asset (GES_EXTRACTABLE (layer->timeline))) : NULL; ges_asset_request_async (G_OBJECT_TYPE (clip), id, NULL, (GAsyncReadyCallback) new_asset_cb, mudata); if (project) ges_project_add_loading_asset (project, G_OBJECT_TYPE (clip), id); g_free (id); GST_LOG_OBJECT (layer, "Object added async"); return TRUE; } g_free (id); ges_extractable_set_asset (GES_EXTRACTABLE (clip), asset); g_slice_free (NewAssetUData, mudata); } gst_object_ref_sink (clip); /* Take a reference to the clip and store it stored by start/priority */ priv->clips_start = g_list_insert_sorted (priv->clips_start, clip, (GCompareFunc) element_start_compare); /* Inform the clip it's now in this layer */ ges_clip_set_layer (clip, layer); GST_DEBUG ("current clip priority : %d, Height: %d", _PRIORITY (clip), LAYER_HEIGHT); /* Set the priority. */ if (_PRIORITY (clip) > LAYER_HEIGHT) { GST_WARNING_OBJECT (layer, "%p is out of the layer space, setting its priority to " "%d, setting it to the maximum priority of the layer: %d", clip, _PRIORITY (clip), LAYER_HEIGHT - 1); _set_priority0 (GES_TIMELINE_ELEMENT (clip), LAYER_HEIGHT - 1); } /* If the clip has an acceptable priority, we just let it with its current * priority */ ges_layer_resync_priorities (layer); ges_timeline_element_set_timeline (GES_TIMELINE_ELEMENT (clip), layer->timeline); /* emit 'clip-added' */ g_signal_emit (layer, ges_layer_signals[OBJECT_ADDED], 0, clip); return TRUE; }
static gboolean _add_clip(GstValidateScenario *scenario, GstValidateAction * action) { GESTimeline *timeline = get_timeline(scenario); GESAsset *asset; GESLayer *layer; GESClip *clip; GError *error = NULL; gint layer_priority; const gchar *name; const gchar *asset_id; const gchar *type_string; GType type; gboolean res = FALSE; GstClockTime duration = 1 * GST_SECOND; gst_structure_get_int(action->structure, "layer-priority", &layer_priority); name = gst_structure_get_string(action->structure, "name"); asset_id = gst_structure_get_string(action->structure, "asset-id"); type_string = gst_structure_get_string(action->structure, "type"); if (!(type = g_type_from_name(type_string))) { GST_ERROR("This type doesn't exist : %s", type_string); goto beach; } asset = ges_asset_request(type, asset_id, &error); if (!asset || error) { GST_ERROR("There was an error requesting the asset with id %s and type %s (%s)", asset_id, type_string, error->message); goto beach; } layer = _get_layer_by_priority(timeline, layer_priority); if (!layer) { GST_ERROR("No layer with priority %d", layer_priority); goto beach; } if (type == GES_TYPE_URI_CLIP) { duration = GST_CLOCK_TIME_NONE; } clip = ges_layer_add_asset(layer, asset, GST_CLOCK_TIME_NONE, 0, duration, GES_TRACK_TYPE_UNKNOWN); if (clip) { res = TRUE; if (!ges_timeline_element_set_name(GES_TIMELINE_ELEMENT(clip), name)) { res = FALSE; GST_ERROR("couldn't set name %s on clip with id %s", name, asset_id); } } else { GST_ERROR("Couldn't add clip with id %s to layer with priority %d", asset_id, layer_priority); } gst_object_unref (layer); ges_timeline_commit(timeline); beach: g_object_unref(timeline); return res; }
/* A simple timeline with 3 audio/video sources */ int main (int argc, gchar ** argv) { GESAsset *src_asset; GESTimelinePipeline *pipeline; GESTimeline *timeline; GESClip *source; GESTimelineLayer *layer; GMainLoop *mainloop; /* Initialize GStreamer (this will parse environment variables and commandline * arguments. */ gst_init (&argc, &argv); /* Initialize the GStreamer Editing Services */ ges_init (); /* Setup of a A/V timeline */ /* This is our main GESTimeline */ timeline = ges_timeline_new_audio_video (); /* We are only going to be doing one layer of clips */ layer = ges_timeline_layer_new (); /* Add the tracks and the layer to the timeline */ if (!ges_timeline_add_layer (timeline, layer)) return -1; /* We create a simple asset able to extract GESTestClip */ src_asset = ges_asset_request (GES_TYPE_TEST_CLIP, NULL, NULL); /* Add sources to our layer */ ges_timeline_layer_add_asset (layer, src_asset, 0, 0, GST_SECOND, 1, GES_TRACK_TYPE_UNKNOWN); source = ges_timeline_layer_add_asset (layer, src_asset, GST_SECOND, 0, GST_SECOND, 1, GES_TRACK_TYPE_UNKNOWN); g_object_set (source, "freq", 480.0, "vpattern", 2, NULL); ges_timeline_layer_add_asset (layer, src_asset, 2 * GST_SECOND, 0, GST_SECOND, 1, GES_TRACK_TYPE_UNKNOWN); /* In order to view our timeline, let's grab a convenience pipeline to put * our timeline in. */ pipeline = ges_timeline_pipeline_new (); /* Add the timeline to that pipeline */ if (!ges_timeline_pipeline_add_timeline (pipeline, timeline)) return -1; /* The following is standard usage of a GStreamer pipeline (note how you haven't * had to care about GStreamer so far ?). * * We set the pipeline to playing ... */ gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING); /* .. and we start a GMainLoop. GES **REQUIRES** a GMainLoop to be running in * order to function properly ! */ mainloop = g_main_loop_new (NULL, FALSE); /* Simple code to have the mainloop shutdown after 4s */ g_timeout_add_seconds (4, (GSourceFunc) g_main_loop_quit, mainloop); g_main_loop_run (mainloop); return 0; }