project: Fix our asset cache

It was not talking into account the fact that you can have
several assets with a same ID but different exactractable types.
This commit is contained in:
Thibault Saunier 2019-07-07 20:35:14 -04:00
parent b8c897308d
commit 5f3adbc1a3

View file

@ -54,9 +54,6 @@
static GPtrArray *new_paths = NULL; static GPtrArray *new_paths = NULL;
static GHashTable *tried_uris = NULL; static GHashTable *tried_uris = NULL;
/* TODO We should rely on both extractable_type and @id to identify
* a Asset, not only @id
*/
struct _GESProjectPrivate struct _GESProjectPrivate
{ {
GHashTable *assets; GHashTable *assets;
@ -96,6 +93,18 @@ static guint _signals[LAST_SIGNAL] = { 0 };
static guint nb_projects = 0; static guint nb_projects = 0;
/* Find the type that implemented the GESExtractable interface */
static inline const gchar *
_extractable_type_name (GType type)
{
while (1) {
if (g_type_is_a (g_type_parent (type), GES_TYPE_EXTRACTABLE))
type = g_type_parent (type);
else
return g_type_name (type);
}
}
enum enum
{ {
PROP_0, PROP_0,
@ -582,17 +591,34 @@ ges_project_init (GESProject * project)
g_free, NULL); g_free, NULL);
} }
static gchar *
ges_project_internal_extractable_type_id (GType extractable_type,
const gchar * id)
{
return g_strdup_printf ("%s:%s", _extractable_type_name (extractable_type),
id);
}
static gchar *
ges_project_internal_asset_id (GESAsset * asset)
{
return
ges_project_internal_extractable_type_id (ges_asset_get_extractable_type
(asset), ges_asset_get_id (asset));
}
static void static void
_send_error_loading_asset (GESProject * project, GESAsset * asset, _send_error_loading_asset (GESProject * project, GESAsset * asset,
GError * error) GError * error)
{ {
gchar *internal_id = ges_project_internal_asset_id (asset);
const gchar *id = ges_asset_get_id (asset); const gchar *id = ges_asset_get_id (asset);
GST_DEBUG_OBJECT (project, "Sending error loading asset for %s", id); GST_DEBUG_OBJECT (project, "Sending error loading asset for %s", id);
g_hash_table_remove (project->priv->loading_assets, id); g_hash_table_remove (project->priv->loading_assets, internal_id);
g_hash_table_add (project->priv->loaded_with_error, g_strdup (id)); g_hash_table_add (project->priv->loaded_with_error, internal_id);
g_signal_emit (project, _signals[ERROR_LOADING_ASSET], 0, error, id, g_signal_emit (project, _signals[ERROR_LOADING_ASSET], 0, error,
ges_asset_get_extractable_type (asset)); id, ges_asset_get_extractable_type (asset));
} }
gchar * gchar *
@ -601,6 +627,7 @@ ges_project_try_updating_id (GESProject * project, GESAsset * asset,
{ {
gchar *new_id = NULL; gchar *new_id = NULL;
const gchar *id; const gchar *id;
gchar *internal_id;
g_return_val_if_fail (GES_IS_PROJECT (project), NULL); g_return_val_if_fail (GES_IS_PROJECT (project), NULL);
g_return_val_if_fail (GES_IS_ASSET (asset), NULL); g_return_val_if_fail (GES_IS_ASSET (asset), NULL);
@ -632,7 +659,9 @@ ges_project_try_updating_id (GESProject * project, GESAsset * asset,
GST_DEBUG_OBJECT (project, "No new id found for %s", id); GST_DEBUG_OBJECT (project, "No new id found for %s", id);
} }
g_hash_table_remove (project->priv->loading_assets, id); internal_id = ges_project_internal_asset_id (asset);
g_hash_table_remove (project->priv->loading_assets, internal_id);
g_free (internal_id);
if (new_id == NULL) if (new_id == NULL)
_send_error_loading_asset (project, asset, error); _send_error_loading_asset (project, asset, error);
@ -701,8 +730,8 @@ ges_project_add_loading_asset (GESProject * project, GType extractable_type,
GESAsset *asset; GESAsset *asset;
if ((asset = ges_asset_cache_lookup (extractable_type, id))) { if ((asset = ges_asset_cache_lookup (extractable_type, id))) {
if (g_hash_table_insert (project->priv->loading_assets, g_strdup (id), if (g_hash_table_insert (project->priv->loading_assets,
gst_object_ref (asset))) ges_project_internal_asset_id (asset), gst_object_ref (asset)))
g_signal_emit (project, _signals[ASSET_LOADING_SIGNAL], 0, asset); g_signal_emit (project, _signals[ASSET_LOADING_SIGNAL], 0, asset);
} }
} }
@ -730,17 +759,23 @@ gboolean
ges_project_create_asset (GESProject * project, const gchar * id, ges_project_create_asset (GESProject * project, const gchar * id,
GType extractable_type) GType extractable_type)
{ {
gchar *internal_id;
g_return_val_if_fail (GES_IS_PROJECT (project), FALSE); g_return_val_if_fail (GES_IS_PROJECT (project), FALSE);
g_return_val_if_fail (g_type_is_a (extractable_type, GES_TYPE_EXTRACTABLE), g_return_val_if_fail (g_type_is_a (extractable_type, GES_TYPE_EXTRACTABLE),
FALSE); FALSE);
if (id == NULL) if (id == NULL)
id = g_type_name (extractable_type); id = g_type_name (extractable_type);
internal_id = ges_project_internal_extractable_type_id (extractable_type, id);
if (g_hash_table_lookup (project->priv->assets, id) || if (g_hash_table_lookup (project->priv->assets, internal_id) ||
g_hash_table_lookup (project->priv->loading_assets, id) || g_hash_table_lookup (project->priv->loading_assets, internal_id) ||
g_hash_table_lookup (project->priv->loaded_with_error, id)) g_hash_table_lookup (project->priv->loaded_with_error, internal_id)) {
g_free (internal_id);
return FALSE; return FALSE;
}
g_free (internal_id);
/* TODO Add a GCancellable somewhere in our API */ /* TODO Add a GCancellable somewhere in our API */
ges_asset_request_async (extractable_type, id, NULL, ges_asset_request_async (extractable_type, id, NULL,
@ -768,7 +803,7 @@ ges_project_create_asset_sync (GESProject * project, const gchar * id,
GType extractable_type, GError ** error) GType extractable_type, GError ** error)
{ {
GESAsset *asset; GESAsset *asset;
gchar *possible_id = NULL; gchar *possible_id = NULL, *internal_id;
gboolean retry = TRUE; gboolean retry = TRUE;
g_return_val_if_fail (GES_IS_PROJECT (project), FALSE); g_return_val_if_fail (GES_IS_PROJECT (project), FALSE);
@ -778,11 +813,17 @@ ges_project_create_asset_sync (GESProject * project, const gchar * id,
if (id == NULL) if (id == NULL)
id = g_type_name (extractable_type); id = g_type_name (extractable_type);
if ((asset = g_hash_table_lookup (project->priv->assets, id))) internal_id = ges_project_internal_extractable_type_id (extractable_type, id);
if ((asset = g_hash_table_lookup (project->priv->assets, internal_id))) {
g_free (internal_id);
return asset; return asset;
else if (g_hash_table_lookup (project->priv->loading_assets, id) || } else if (g_hash_table_lookup (project->priv->loading_assets, internal_id) ||
g_hash_table_lookup (project->priv->loaded_with_error, id)) g_hash_table_lookup (project->priv->loaded_with_error, internal_id)) {
g_free (internal_id);
return NULL; return NULL;
}
/* TODO Add a GCancellable somewhere in our API */ /* TODO Add a GCancellable somewhere in our API */
while (retry) { while (retry) {
@ -795,10 +836,11 @@ ges_project_create_asset_sync (GESProject * project, const gchar * id,
if (asset) { if (asset) {
retry = FALSE; retry = FALSE;
internal_id =
if ((!g_hash_table_lookup (project->priv->assets, ges_project_internal_extractable_type_id (extractable_type, id);
ges_asset_get_id (asset)))) if ((!g_hash_table_lookup (project->priv->assets, internal_id)))
g_signal_emit (project, _signals[ASSET_LOADING_SIGNAL], 0, asset); g_signal_emit (project, _signals[ASSET_LOADING_SIGNAL], 0, asset);
g_free (internal_id);
if (possible_id) { if (possible_id) {
g_free (possible_id); g_free (possible_id);
@ -848,15 +890,18 @@ ges_project_create_asset_sync (GESProject * project, const gchar * id,
gboolean gboolean
ges_project_add_asset (GESProject * project, GESAsset * asset) ges_project_add_asset (GESProject * project, GESAsset * asset)
{ {
gchar *internal_id;
g_return_val_if_fail (GES_IS_PROJECT (project), FALSE); g_return_val_if_fail (GES_IS_PROJECT (project), FALSE);
if (g_hash_table_lookup (project->priv->assets, ges_asset_get_id (asset))) internal_id = ges_project_internal_asset_id (asset);
if (g_hash_table_lookup (project->priv->assets, internal_id)) {
g_free (internal_id);
return TRUE; return TRUE;
}
g_hash_table_insert (project->priv->assets, g_hash_table_insert (project->priv->assets, internal_id,
g_strdup (ges_asset_get_id (asset)), gst_object_ref (asset)); gst_object_ref (asset));
g_hash_table_remove (project->priv->loading_assets, internal_id);
g_hash_table_remove (project->priv->loading_assets, ges_asset_get_id (asset));
GST_DEBUG_OBJECT (project, "Asset added: %s", ges_asset_get_id (asset)); GST_DEBUG_OBJECT (project, "Asset added: %s", ges_asset_get_id (asset));
g_signal_emit (project, _signals[ASSET_ADDED_SIGNAL], 0, asset); g_signal_emit (project, _signals[ASSET_ADDED_SIGNAL], 0, asset);
@ -876,10 +921,13 @@ gboolean
ges_project_remove_asset (GESProject * project, GESAsset * asset) ges_project_remove_asset (GESProject * project, GESAsset * asset)
{ {
gboolean ret; gboolean ret;
gchar *internal_id;
g_return_val_if_fail (GES_IS_PROJECT (project), FALSE); g_return_val_if_fail (GES_IS_PROJECT (project), FALSE);
ret = g_hash_table_remove (project->priv->assets, ges_asset_get_id (asset)); internal_id = ges_project_internal_asset_id (asset);
ret = g_hash_table_remove (project->priv->assets, internal_id);
g_free (internal_id);
g_signal_emit (project, _signals[ASSET_REMOVED_SIGNAL], 0, asset); g_signal_emit (project, _signals[ASSET_REMOVED_SIGNAL], 0, asset);
return ret; return ret;
@ -900,12 +948,15 @@ ges_project_get_asset (GESProject * project, const gchar * id,
GType extractable_type) GType extractable_type)
{ {
GESAsset *asset; GESAsset *asset;
gchar *internal_id;
g_return_val_if_fail (GES_IS_PROJECT (project), NULL); g_return_val_if_fail (GES_IS_PROJECT (project), NULL);
g_return_val_if_fail (g_type_is_a (extractable_type, GES_TYPE_EXTRACTABLE), g_return_val_if_fail (g_type_is_a (extractable_type, GES_TYPE_EXTRACTABLE),
NULL); NULL);
asset = g_hash_table_lookup (project->priv->assets, id); internal_id = ges_project_internal_extractable_type_id (extractable_type, id);
asset = g_hash_table_lookup (project->priv->assets, internal_id);
g_free (internal_id);
if (asset) if (asset)
return gst_object_ref (asset); return gst_object_ref (asset);