Esempio n. 1
0
static void
new_asset_cb (GESAsset * source, GAsyncResult * res, GESProject * project)
{
  GError *error = NULL;
  gchar *possible_id = NULL;
  const gchar *id = ges_asset_get_id (source);
  GESAsset *asset = ges_asset_request_finish (res, &error);

  if (error) {
    possible_id = ges_project_try_updating_id (project, source, error);
    if (possible_id == NULL) {
      g_hash_table_remove (project->priv->loading_assets, id);
      g_hash_table_add (project->priv->loaded_with_error, g_strdup (id));
      g_signal_emit (project, _signals[ERROR_LOADING_ASSET], 0, error, id,
          ges_asset_get_extractable_type (source));

      return;
    }

    ges_project_create_asset (project, possible_id,
        ges_asset_get_extractable_type (source));

    g_free (possible_id);
    g_error_free (error);
    return;
  }

  ges_project_add_asset (project, asset);
  if (asset)
    gst_object_unref (asset);
}
static void
new_asset_cb (GESAsset * source, GAsyncResult * res, GESProject * project)
{
  GError *error = NULL;
  gchar *possible_id = NULL;
  GESAsset *asset = ges_asset_request_finish (res, &error);

  if (error) {
    possible_id = ges_project_try_updating_id (project, source, error);

    if (possible_id == NULL)
      return;

    ges_project_create_asset (project, possible_id,
        ges_asset_get_extractable_type (source));

    g_free (possible_id);
    g_error_free (error);
    return;
  }

  ges_project_add_asset (project, asset);
  if (asset)
    gst_object_unref (asset);
}
static void
_send_error_loading_asset (GESProject * project, GESAsset * asset,
    GError * error)
{
  const gchar *id = ges_asset_get_id (asset);

  GST_DEBUG_OBJECT (project, "Sending error loading asset for %s", id);
  g_hash_table_remove (project->priv->loading_assets, id);
  g_hash_table_add (project->priv->loaded_with_error, g_strdup (id));
  g_signal_emit (project, _signals[ERROR_LOADING_ASSET], 0, error, id,
      ges_asset_get_extractable_type (asset));
}
/**
 * ges_project_list_assets:
 * @project: A #GESProject
 * @filter: Type of assets to list, #GES_TYPE_EXTRACTABLE will list
 * all assets
 *
 * List all @asset contained in @project filtering per extractable_type
 * as defined by @filter. It copies the asset and thus will not be updated
 * in time.
 *
 * Returns: (transfer full) (element-type GESAsset): The list of
 * #GESAsset the object contains
 */
GList *
ges_project_list_assets (GESProject * project, GType filter)
{
  GList *ret = NULL;
  GHashTableIter iter;
  gpointer key, value;

  g_return_val_if_fail (GES_IS_PROJECT (project), NULL);

  g_hash_table_iter_init (&iter, project->priv->assets);
  while (g_hash_table_iter_next (&iter, &key, &value)) {
    if (g_type_is_a (ges_asset_get_extractable_type (GES_ASSET (value)),
            filter))
      ret = g_list_append (ret, gst_object_ref (value));
  }

  return ret;
}
static void
new_asset_cb (GESAsset * source, GAsyncResult * res, NewAssetUData * udata)
{
  GError *error = NULL;

  GESAsset *asset = ges_asset_request_finish (res, &error);

  GST_DEBUG_OBJECT (udata->layer, "%" GST_PTR_FORMAT " Asset loaded, "
      "setting its asset", udata->clip);

  if (error) {
    GESProject *project = udata->layer->timeline ?
        GES_PROJECT (ges_extractable_get_asset (GES_EXTRACTABLE
            (udata->layer->timeline))) : NULL;
    if (project) {
      gchar *possible_id;

      possible_id = ges_project_try_updating_id (project, source, error);
      if (possible_id) {
        ges_asset_request_async (ges_asset_get_extractable_type (source),
            possible_id, NULL, (GAsyncReadyCallback) new_asset_cb, udata);
        g_free (possible_id);
        return;
      }
    }

    GST_ERROR ("Asset could not be created for uri %s, error: %s",
        ges_asset_get_id (asset), error->message);

  } else {
    GESProject *project = udata->layer->timeline ?
        GES_PROJECT (ges_extractable_get_asset (GES_EXTRACTABLE
            (udata->layer->timeline))) : NULL;
    ges_extractable_set_asset (GES_EXTRACTABLE (udata->clip), asset);

    ges_project_add_asset (project, asset);
    ges_layer_add_clip (udata->layer, udata->clip);
  }

  gst_object_unref (asset);
  g_slice_free (NewAssetUData, udata);
}
/**
 * ges_layer_add_asset:
 * @layer: a #GESLayer
 * @asset: The asset to add to
 * @start: The start value to set on the new #GESClip
 * @inpoint: The inpoint value to set on the new #GESClip
 * @duration: The duration value to set on the new #GESClip
 * @track_types: The #GESTrackType to set on the the new #GESClip
 *
 * Creates Clip from asset, adds it to layer and
 * returns a reference to it.
 *
 * Returns: (transfer none): Created #GESClip
 */
GESClip *
ges_layer_add_asset (GESLayer * layer,
    GESAsset * asset, GstClockTime start, GstClockTime inpoint,
    GstClockTime duration, GESTrackType track_types)
{
  GESClip *clip;

  g_return_val_if_fail (GES_IS_LAYER (layer), NULL);
  g_return_val_if_fail (GES_IS_ASSET (asset), NULL);
  g_return_val_if_fail (g_type_is_a (ges_asset_get_extractable_type
          (asset), GES_TYPE_CLIP), NULL);

  GST_DEBUG_OBJECT (layer, "Adding asset %s with: start: %" GST_TIME_FORMAT
      " inpoint: %" GST_TIME_FORMAT " duration: %" GST_TIME_FORMAT
      " track types: %d (%s)", ges_asset_get_id (asset), GST_TIME_ARGS (start),
      GST_TIME_ARGS (inpoint), GST_TIME_ARGS (duration), track_types,
      ges_track_type_name (track_types));

  clip = GES_CLIP (ges_asset_extract (asset, NULL));
  _set_start0 (GES_TIMELINE_ELEMENT (clip), start);
  _set_inpoint0 (GES_TIMELINE_ELEMENT (clip), inpoint);
  if (track_types != GES_TRACK_TYPE_UNKNOWN)
    ges_clip_set_supported_formats (clip, track_types);

  if (GST_CLOCK_TIME_IS_VALID (duration)) {
    _set_duration0 (GES_TIMELINE_ELEMENT (clip), duration);
  }

  if (!ges_layer_add_clip (layer, clip)) {
    gst_object_unref (clip);

    return NULL;
  }

  return clip;
}
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);
}
/**
 * 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;
}