asset: fix handling of proxies

Previous usage of the property proxy-target seemed to alternate between
the two definitions:
+ The asset we are the default proxy of
+ The asset we are in the proxy list of
Now, the latter definition is used, which seems more useful to a user
since knowing the latter can easily allow you to find out the former.

The previous behaviour of ges_asset_set_proxy (asset, NULL) was not very
clear. It is now defined so that it clears all the proxies for 'asset'.
This means that after this call, the GESAsset:proxy property will indeed
be NULL.

Also fixed:
+ We can call ges_asset_set_proxy (asset, proxy) when 'proxy' is already
  in the proxy list of 'asset'.
+ Handling of removing the default proxy in ges_asset_unproxy. This was
  sending out the wrong notifies.
+ Prohibiting circular proxying. Before we could only prevent one case,
  we should now be able to prevent all cases. This will prevent a hang
  in ges_asset_request.
This commit is contained in:
Henry Wilkes 2020-03-05 18:15:41 +00:00 committed by Thibault Saunier
parent b03915bc87
commit 7f65b7be0c
2 changed files with 490 additions and 30 deletions

View file

@ -167,6 +167,7 @@ struct _GESAssetPrivate
/* actual list of proxies */
GList *proxies;
/* the asset whose proxies list we belong to */
GESAsset *proxy_target;
/* The error that occurred when an asset has been initialized with error */
@ -502,8 +503,8 @@ ges_asset_class_init (GESAssetClass * klass)
* proxy will act as a substitute for the original asset when the
* original is requested (see ges_asset_request()).
*
* Setting this property will not remove the existing proxy, but will
* replace it as the default (see ges_asset_set_proxy()).
* Setting this property will not usually remove the existing proxy, but
* will replace it as the default (see ges_asset_set_proxy()).
*/
_properties[PROP_PROXY] =
g_param_spec_object ("proxy", "Proxy",
@ -512,8 +513,18 @@ ges_asset_class_init (GESAssetClass * klass)
/**
* GESAsset:proxy-target:
*
* The asset that this asset is a proxy of, or %NULL if it is not a
* The asset that this asset is a proxy for, or %NULL if it is not a
* proxy for another asset.
*
* Note that even if this asset is acting as a proxy for another asset,
* but this asset is not the default #GESAsset:proxy, then @proxy-target
* will *still* point to this other asset. So you should check the
* #GESAsset:proxy property of @target-proxy before assuming it is the
* current default proxy for the target.
*
* Note that the #GObject::notify for this property is emitted after
* the #GESAsset:proxy #GObject::notify for the corresponding (if any)
* asset it is now the proxy of/no longer the proxy of.
*/
_properties[PROP_PROXY_TARGET] =
g_param_spec_object ("proxy-target", "Proxy target",
@ -860,67 +871,89 @@ ges_asset_finish_proxy (GESAsset * proxy)
return ges_asset_set_proxy (proxied_asset, proxy);
}
static gboolean
_contained_in_proxy_tree (GESAsset * node, GESAsset * search)
{
GList *tmp;
if (node == search)
return TRUE;
for (tmp = node->priv->proxies; tmp; tmp = tmp->next) {
if (_contained_in_proxy_tree (tmp->data, search))
return TRUE;
}
return FALSE;
}
/**
* ges_asset_set_proxy:
* @asset: The #GESAsset to proxy
* @proxy: (allow-none): A new default proxy for @asset
*
* Sets one asset as the default #GESAsset:proxy of another (the
* original asset).
* Sets the #GESAsset:proxy for the asset.
*
* If the given proxy is among the existing proxies of the asset (see
* If @proxy is among the existing proxies of the asset (see
* ges_asset_list_proxies()) it will be moved to become the default
* proxy. Otherwise, the proxy will be added to the list of proxies, as
* the new default. The previous default proxy will become 'next in line'
* for if the new one is removed, and so on. As such, this method will
* **not** actually remove the previous default proxy
* (use ges_asset_unproxy() for that).
* proxy. Otherwise, if @proxy is not %NULL, it will be added to the list
* of proxies, as the new default. The previous default proxy will become
* 'next in line' for if the new one is removed, and so on. As such, this
* will **not** actually remove the previous default proxy (use
* ges_asset_unproxy() for that).
*
* Note that an asset can only act as a proxy for one other asset.
*
* As a special case, if @proxy is %NULL, then this method will actually
* remove **all** proxies from the asset.
*
* Returns: %TRUE if @proxy was successfully set as the default for
* @asset.
*/
gboolean
ges_asset_set_proxy (GESAsset * asset, GESAsset * proxy)
{
GESAsset *current_target;
g_return_val_if_fail (GES_IS_ASSET (asset), FALSE);
g_return_val_if_fail (proxy == NULL || GES_IS_ASSET (proxy), FALSE);
g_return_val_if_fail (asset != proxy, FALSE);
if (!proxy) {
GList *tmp, *proxies;
if (asset->priv->error) {
GST_ERROR_OBJECT (asset,
"Proxy was loaded with error (%s), it should not be 'unproxied'",
"Asset was loaded with error (%s), it should not be 'unproxied'",
asset->priv->error->message);
return FALSE;
}
if (asset->priv->proxies) {
GESAsset *old_proxy = GES_ASSET (asset->priv->proxies->data);
GST_DEBUG_OBJECT (asset, "Removing all proxies");
proxies = asset->priv->proxies;
asset->priv->proxies = NULL;
old_proxy->priv->proxy_target = NULL;
g_object_notify_by_pspec (G_OBJECT (old_proxy),
_properties[PROP_PROXY_TARGET]);
for (tmp = proxies; tmp; tmp = tmp->next) {
GESAsset *proxy = tmp->data;
proxy->priv->proxy_target = NULL;
}
GST_DEBUG_OBJECT (asset, "%s not proxied anymore", asset->priv->id);
asset->priv->state = ASSET_INITIALIZED;
g_object_notify_by_pspec (G_OBJECT (asset), _properties[PROP_PROXY]);
g_object_notify_by_pspec (G_OBJECT (asset), _properties[PROP_PROXY]);
for (tmp = proxies; tmp; tmp = tmp->next)
g_object_notify_by_pspec (G_OBJECT (tmp->data),
_properties[PROP_PROXY_TARGET]);
g_list_free (proxies);
return TRUE;
}
current_target = proxy->priv->proxy_target;
if (proxy->priv->proxy_target) {
if (current_target && current_target != asset) {
GST_ERROR_OBJECT (asset,
"Trying to use %s as a proxy, but it is already proxying %s",
proxy->priv->id, proxy->priv->proxy_target->priv->id);
"Trying to use '%s' as a proxy, but it is already proxying '%s'",
proxy->priv->id, current_target->priv->id);
return FALSE;
}
if (g_list_find (proxy->priv->proxies, asset)) {
if (_contained_in_proxy_tree (proxy, asset)) {
GST_ERROR_OBJECT (asset, "Trying to setup a circular proxying dependency!");
return FALSE;
@ -929,17 +962,18 @@ ges_asset_set_proxy (GESAsset * asset, GESAsset * proxy)
if (g_list_find (asset->priv->proxies, proxy)) {
GST_INFO_OBJECT (asset,
"%" GST_PTR_FORMAT " already marked as proxy, moving to first", proxy);
GES_ASSET (asset->priv->proxies->data)->priv->proxy_target = NULL;
asset->priv->proxies = g_list_remove (asset->priv->proxies, proxy);
}
GST_INFO ("%s is now proxied by %s", asset->priv->id, proxy->priv->id);
asset->priv->proxies = g_list_prepend (asset->priv->proxies, proxy);
proxy->priv->proxy_target = asset;
g_object_notify_by_pspec (G_OBJECT (proxy), _properties[PROP_PROXY_TARGET]);
proxy->priv->proxy_target = asset;
asset->priv->state = ASSET_PROXIED;
g_object_notify_by_pspec (G_OBJECT (asset), _properties[PROP_PROXY]);
if (current_target != asset)
g_object_notify_by_pspec (G_OBJECT (proxy), _properties[PROP_PROXY_TARGET]);
/* FIXME: ->inform_proxy is not called. We should figure out what the
* purpose of ->inform_proxy should be generically. Currently, it is
@ -965,21 +999,39 @@ ges_asset_set_proxy (GESAsset * asset, GESAsset * proxy)
gboolean
ges_asset_unproxy (GESAsset * asset, GESAsset * proxy)
{
gboolean removing_default;
gboolean last_proxy;
g_return_val_if_fail (GES_IS_ASSET (asset), FALSE);
g_return_val_if_fail (GES_IS_ASSET (proxy), FALSE);
g_return_val_if_fail (asset != proxy, FALSE);
/* also tests if the list is NULL */
if (!g_list_find (asset->priv->proxies, proxy)) {
GST_INFO_OBJECT (asset, "%s is not a proxy.", proxy->priv->id);
GST_INFO_OBJECT (asset, "'%s' is not a proxy.", proxy->priv->id);
return FALSE;
}
if (asset->priv->proxies->data == proxy)
ges_asset_set_proxy (asset, NULL);
last_proxy = (asset->priv->proxies->next == NULL);
if (last_proxy && asset->priv->error) {
GST_ERROR_OBJECT (asset,
"Asset was loaded with error (%s), its last proxy '%s' should "
"not be removed", asset->priv->error->message, proxy->priv->id);
return FALSE;
}
removing_default = (asset->priv->proxies->data == proxy);
asset->priv->proxies = g_list_remove (asset->priv->proxies, proxy);
if (last_proxy)
asset->priv->state = ASSET_INITIALIZED;
proxy->priv->proxy_target = NULL;
if (removing_default)
g_object_notify_by_pspec (G_OBJECT (asset), _properties[PROP_PROXY]);
g_object_notify_by_pspec (G_OBJECT (proxy), _properties[PROP_PROXY_TARGET]);
return TRUE;
}

View file

@ -327,6 +327,413 @@ GST_START_TEST (test_proxy_asset)
GST_END_TEST;
*/
static void
_count_cb (GObject * obj, GParamSpec * pspec, gpointer key)
{
guint count = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (obj), key));
g_object_set_data (G_OBJECT (obj), key, GUINT_TO_POINTER (count + 1));
}
#define _CONNECT_PROXY_SIGNALS(asset) \
g_signal_connect (asset, "notify::proxy", G_CALLBACK (_count_cb), \
(gchar *)"test-data-proxy-count"); \
g_signal_connect (asset, "notify::proxy-target", G_CALLBACK (_count_cb), \
(gchar *)"test-data-target-count");
/* test that @asset has the properties proxy = @proxy and
* proxy-target = @proxy_target
* Also check that the callback for "notify::proxy" (set up in
* _CONNECT_PROXY_SIGNALS) has been called @p_count times, and the
* callback for "notify::target-proxy" has been called @t_count times.
*/
#define _assert_proxy_state(asset, proxy, proxy_target, p_count, t_count) \
{ \
const gchar *id = ges_asset_get_id (asset); \
guint found_p_count = GPOINTER_TO_UINT (g_object_get_data ( \
G_OBJECT (asset), "test-data-proxy-count")); \
guint found_t_count = GPOINTER_TO_UINT (g_object_get_data ( \
G_OBJECT (asset), "test-data-target-count")); \
GESAsset *found_proxy = ges_asset_get_proxy (asset); \
GESAsset *found_target = ges_asset_get_proxy_target (asset); \
fail_unless (found_proxy == proxy, "Asset '%s' has the proxy '%s' " \
"rather than the expected '%s'", id, \
found_proxy ? ges_asset_get_id (found_proxy) : NULL, \
proxy ? ges_asset_get_id (proxy) : NULL); \
fail_unless (found_target == proxy_target, "Asset '%s' has the proxy " \
"target '%s' rather than the expected '%s'", id, \
found_target ? ges_asset_get_id (found_target) : NULL, \
proxy_target ? ges_asset_get_id (proxy_target) : NULL); \
fail_unless (p_count == found_p_count, "notify::proxy for asset '%s' " \
"was called %u times, rather than the expected %u times", \
id, found_p_count, p_count); \
fail_unless (t_count == found_t_count, "notify::target-proxy for " \
"asset '%s' was called %u times, rather than the expected %u times", \
id, found_t_count, t_count); \
}
#define _assert_proxy_list(asset, cmp_list) \
{ \
const gchar * id = ges_asset_get_id (asset); \
int i; \
GList *tmp; \
for (i = 0, tmp = ges_asset_list_proxies (asset); cmp_list[i] && tmp; \
i++, tmp = tmp->next) { \
GESAsset *proxy = tmp->data; \
fail_unless (proxy == cmp_list[i], "The asset '%s' has '%s' as its " \
"%ith proxy, rather than the expected '%s'", id, \
ges_asset_get_id (proxy), i, ges_asset_get_id (cmp_list[i])); \
} \
fail_unless (tmp == NULL, "Found more proxies for '%s' than expected", \
id); \
fail_unless (cmp_list[i] == NULL, "Found less proxies (%i) for '%s' " \
"than expected", i, id); \
}
#define _assert_effect_asset_request(req_id, expect) \
{ \
GESAsset *requested = ges_asset_request (GES_TYPE_EFFECT, req_id, NULL); \
fail_unless (requested == expect, "Requested asset for id '%s' is " \
"'%s' rather than the expected '%s'", req_id, \
requested ? ges_asset_get_id (requested) : NULL, \
ges_asset_get_id (expect)); \
gst_object_unref (requested); \
}
GST_START_TEST (test_proxy_setters)
{
GESAsset *proxies[] = { NULL, NULL, NULL, NULL };
GESAsset *asset, *alt_asset;
GESAsset *proxy0, *proxy1, *proxy2;
gchar asset_id[] = "video agingtv ! videobalance";
gchar alt_asset_id[] = "video gamma";
gchar proxy0_id[] = "video videobalance contrast=0.0";
gchar proxy1_id[] = "video videobalance contrast=1.0";
gchar proxy2_id[] = "video videobalance contrast=2.0";
ges_init ();
asset = ges_asset_request (GES_TYPE_EFFECT, asset_id, NULL);
alt_asset = ges_asset_request (GES_TYPE_EFFECT, alt_asset_id, NULL);
proxy0 = ges_asset_request (GES_TYPE_EFFECT, proxy0_id, NULL);
proxy1 = ges_asset_request (GES_TYPE_EFFECT, proxy1_id, NULL);
proxy2 = ges_asset_request (GES_TYPE_EFFECT, proxy2_id, NULL);
/* make sure our assets are unique */
fail_unless (asset);
fail_unless (alt_asset);
fail_unless (proxy0);
fail_unless (proxy1);
fail_unless (proxy2);
fail_unless (asset != alt_asset);
fail_unless (asset != proxy0);
fail_unless (asset != proxy1);
fail_unless (asset != proxy2);
fail_unless (alt_asset != proxy0);
fail_unless (alt_asset != proxy1);
fail_unless (alt_asset != proxy2);
fail_unless (proxy0 != proxy1);
fail_unless (proxy0 != proxy1);
fail_unless (proxy0 != proxy2);
fail_unless (proxy1 != proxy2);
_CONNECT_PROXY_SIGNALS (asset);
_CONNECT_PROXY_SIGNALS (alt_asset);
_CONNECT_PROXY_SIGNALS (proxy0);
_CONNECT_PROXY_SIGNALS (proxy1);
_CONNECT_PROXY_SIGNALS (proxy2);
/* no proxies to start with */
_assert_proxy_state (asset, NULL, NULL, 0, 0);
_assert_proxy_state (alt_asset, NULL, NULL, 0, 0);
_assert_proxy_state (proxy0, NULL, NULL, 0, 0);
_assert_proxy_state (proxy1, NULL, NULL, 0, 0);
_assert_proxy_state (proxy2, NULL, NULL, 0, 0);
_assert_proxy_list (asset, proxies);
_assert_proxy_list (alt_asset, proxies);
_assert_proxy_list (proxy0, proxies);
_assert_proxy_list (proxy1, proxies);
_assert_proxy_list (proxy2, proxies);
/* id for an asset with no proxy returns itself */
_assert_effect_asset_request (asset_id, asset);
_assert_effect_asset_request (alt_asset_id, alt_asset);
_assert_effect_asset_request (proxy0_id, proxy0);
_assert_effect_asset_request (proxy1_id, proxy1);
_assert_effect_asset_request (proxy2_id, proxy2);
/* set a proxy */
fail_unless (ges_asset_set_proxy (asset, proxy0));
_assert_proxy_state (asset, proxy0, NULL, 1, 0);
_assert_proxy_state (proxy0, NULL, asset, 0, 1);
_assert_proxy_state (proxy1, NULL, NULL, 0, 0);
_assert_proxy_state (proxy2, NULL, NULL, 0, 0);
proxies[0] = proxy0;
_assert_proxy_list (asset, proxies);
/* requesting the same asset should return the proxy instead */
_assert_effect_asset_request (asset_id, proxy0);
_assert_effect_asset_request (proxy0_id, proxy0);
_assert_effect_asset_request (proxy1_id, proxy1);
_assert_effect_asset_request (proxy2_id, proxy2);
/* can't proxy a different asset */
/* Raises ERROR */
fail_unless (ges_asset_set_proxy (alt_asset, proxy0) == FALSE);
_assert_proxy_state (alt_asset, NULL, NULL, 0, 0);
_assert_proxy_state (asset, proxy0, NULL, 1, 0);
_assert_proxy_state (proxy0, NULL, asset, 0, 1);
_assert_proxy_state (proxy1, NULL, NULL, 0, 0);
_assert_proxy_state (proxy2, NULL, NULL, 0, 0);
_assert_proxy_list (asset, proxies);
_assert_effect_asset_request (asset_id, proxy0);
_assert_effect_asset_request (proxy0_id, proxy0);
/* set the same proxy again is safe */
fail_unless (ges_asset_set_proxy (asset, proxy0));
/* notify::proxy callback count increases, even though we set the same
* proxy. This is the default behaviour for setters. */
_assert_proxy_state (asset, proxy0, NULL, 2, 0);
/* but the notify::target-proxy has not increased for the proxy */
_assert_proxy_state (proxy0, NULL, asset, 0, 1);
_assert_proxy_state (proxy1, NULL, NULL, 0, 0);
_assert_proxy_state (proxy2, NULL, NULL, 0, 0);
_assert_proxy_list (asset, proxies);
_assert_effect_asset_request (asset_id, proxy0);
_assert_effect_asset_request (proxy0_id, proxy0);
/* replace the proxy with a new one */
fail_unless (ges_asset_set_proxy (asset, proxy1));
_assert_proxy_state (asset, proxy1, NULL, 3, 0);
/* first proxy still keeps its target */
_assert_proxy_state (proxy0, NULL, asset, 0, 1);
_assert_proxy_state (proxy1, NULL, asset, 0, 1);
_assert_proxy_state (proxy2, NULL, NULL, 0, 0);
proxies[0] = proxy1;
proxies[1] = proxy0;
_assert_proxy_list (asset, proxies);
_assert_effect_asset_request (asset_id, proxy1);
_assert_effect_asset_request (proxy0_id, proxy0);
_assert_effect_asset_request (proxy1_id, proxy1);
_assert_effect_asset_request (proxy2_id, proxy2);
/* replace again */
fail_unless (ges_asset_set_proxy (asset, proxy2));
_assert_proxy_state (asset, proxy2, NULL, 4, 0);
_assert_proxy_state (proxy0, NULL, asset, 0, 1);
_assert_proxy_state (proxy1, NULL, asset, 0, 1);
_assert_proxy_state (proxy2, NULL, asset, 0, 1);
proxies[0] = proxy2;
proxies[1] = proxy1;
proxies[2] = proxy0;
_assert_proxy_list (asset, proxies);
_assert_effect_asset_request (asset_id, proxy2);
_assert_effect_asset_request (proxy0_id, proxy0);
_assert_effect_asset_request (proxy1_id, proxy1);
_assert_effect_asset_request (proxy2_id, proxy2);
/* move proxy0 back to being the default */
fail_unless (ges_asset_set_proxy (asset, proxy0));
_assert_proxy_state (asset, proxy0, NULL, 5, 0);
_assert_proxy_state (proxy0, NULL, asset, 0, 1);
_assert_proxy_state (proxy1, NULL, asset, 0, 1);
_assert_proxy_state (proxy2, NULL, asset, 0, 1);
proxies[0] = proxy0;
proxies[1] = proxy2;
proxies[2] = proxy1;
_assert_proxy_list (asset, proxies);
_assert_effect_asset_request (asset_id, proxy0);
_assert_effect_asset_request (proxy0_id, proxy0);
_assert_effect_asset_request (proxy1_id, proxy1);
_assert_effect_asset_request (proxy2_id, proxy2);
/* remove proxy2 */
fail_unless (ges_asset_unproxy (asset, proxy2));
/* notify::proxy not released since we have not switched defaults */
_assert_proxy_state (asset, proxy0, NULL, 5, 0);
_assert_proxy_state (proxy0, NULL, asset, 0, 1);
_assert_proxy_state (proxy1, NULL, asset, 0, 1);
_assert_proxy_state (proxy2, NULL, NULL, 0, 2);
proxies[0] = proxy0;
proxies[1] = proxy1;
proxies[2] = NULL;
_assert_proxy_list (asset, proxies);
_assert_effect_asset_request (asset_id, proxy0);
_assert_effect_asset_request (proxy0_id, proxy0);
_assert_effect_asset_request (proxy1_id, proxy1);
_assert_effect_asset_request (proxy2_id, proxy2);
/* make proxy2 a proxy for proxy0 */
fail_unless (ges_asset_set_proxy (proxy0, proxy2));
_assert_proxy_state (asset, proxy0, NULL, 5, 0);
_assert_proxy_state (proxy0, proxy2, asset, 1, 1);
_assert_proxy_state (proxy1, NULL, asset, 0, 1);
_assert_proxy_state (proxy2, NULL, proxy0, 0, 3);
proxies[0] = proxy0;
proxies[1] = proxy1;
proxies[2] = NULL;
_assert_proxy_list (asset, proxies);
proxies[0] = proxy2;
proxies[1] = NULL;
_assert_proxy_list (proxy0, proxies);
/* original id will now follows two proxy links to get proxy2 */
_assert_effect_asset_request (asset_id, proxy2);
_assert_effect_asset_request (proxy0_id, proxy2);
_assert_effect_asset_request (proxy1_id, proxy1);
_assert_effect_asset_request (proxy2_id, proxy2);
/* remove proxy0 from asset, should now default to proxy1 */
fail_unless (ges_asset_unproxy (asset, proxy0));
/* notify::proxy released since we have switched defaults */
_assert_proxy_state (asset, proxy1, NULL, 6, 0);
_assert_proxy_state (proxy0, proxy2, NULL, 1, 2);
_assert_proxy_state (proxy1, NULL, asset, 0, 1);
_assert_proxy_state (proxy2, NULL, proxy0, 0, 3);
proxies[0] = proxy1;
proxies[1] = NULL;
_assert_proxy_list (asset, proxies);
proxies[0] = proxy2;
proxies[1] = NULL;
_assert_proxy_list (proxy0, proxies);
_assert_effect_asset_request (asset_id, proxy1);
_assert_effect_asset_request (proxy0_id, proxy2);
_assert_effect_asset_request (proxy1_id, proxy1);
_assert_effect_asset_request (proxy2_id, proxy2);
/* remove proxy2 from proxy0 */
fail_unless (ges_asset_unproxy (proxy0, proxy2));
_assert_proxy_state (asset, proxy1, NULL, 6, 0);
_assert_proxy_state (proxy0, NULL, NULL, 2, 2);
_assert_proxy_state (proxy1, NULL, asset, 0, 1);
_assert_proxy_state (proxy2, NULL, NULL, 0, 4);
proxies[0] = proxy1;
proxies[1] = NULL;
_assert_proxy_list (asset, proxies);
proxies[0] = NULL;
_assert_proxy_list (proxy0, proxies);
_assert_effect_asset_request (asset_id, proxy1);
_assert_effect_asset_request (proxy0_id, proxy0);
_assert_effect_asset_request (proxy1_id, proxy1);
_assert_effect_asset_request (proxy2_id, proxy2);
/* make both proxy0 and proxy2 proxies of proxy1 */
fail_unless (ges_asset_set_proxy (proxy1, proxy0));
_assert_proxy_state (asset, proxy1, NULL, 6, 0);
_assert_proxy_state (proxy0, NULL, proxy1, 2, 3);
_assert_proxy_state (proxy1, proxy0, asset, 1, 1);
_assert_proxy_state (proxy2, NULL, NULL, 0, 4);
fail_unless (ges_asset_set_proxy (proxy1, proxy2));
_assert_proxy_state (asset, proxy1, NULL, 6, 0);
_assert_proxy_state (proxy0, NULL, proxy1, 2, 3);
_assert_proxy_state (proxy1, proxy2, asset, 2, 1);
_assert_proxy_state (proxy2, NULL, proxy1, 0, 5);
proxies[0] = proxy1;
proxies[1] = NULL;
_assert_proxy_list (asset, proxies);
proxies[0] = proxy2;
proxies[1] = proxy0;
proxies[2] = NULL;
_assert_proxy_list (proxy1, proxies);
_assert_effect_asset_request (asset_id, proxy2);
_assert_effect_asset_request (proxy0_id, proxy0);
_assert_effect_asset_request (proxy1_id, proxy2);
_assert_effect_asset_request (proxy2_id, proxy2);
/* should not be able to set up any circular proxies */
/* Raises ERROR */
fail_unless (ges_asset_set_proxy (proxy1, asset) == FALSE);
_assert_proxy_state (asset, proxy1, NULL, 6, 0);
_assert_proxy_state (proxy0, NULL, proxy1, 2, 3);
_assert_proxy_state (proxy1, proxy2, asset, 2, 1);
_assert_proxy_state (proxy2, NULL, proxy1, 0, 5);
/* Raises ERROR */
fail_unless (ges_asset_set_proxy (proxy0, asset) == FALSE);
_assert_proxy_state (asset, proxy1, NULL, 6, 0);
_assert_proxy_state (proxy0, NULL, proxy1, 2, 3);
_assert_proxy_state (proxy1, proxy2, asset, 2, 1);
_assert_proxy_state (proxy2, NULL, proxy1, 0, 5);
/* Raises ERROR */
fail_unless (ges_asset_set_proxy (proxy2, asset) == FALSE);
_assert_proxy_state (asset, proxy1, NULL, 6, 0);
_assert_proxy_state (proxy0, NULL, proxy1, 2, 3);
_assert_proxy_state (proxy1, proxy2, asset, 2, 1);
_assert_proxy_state (proxy2, NULL, proxy1, 0, 5);
/* remove last proxy from asset, should set its proxy to NULL */
fail_unless (ges_asset_unproxy (asset, proxy1));
_assert_proxy_state (asset, NULL, NULL, 7, 0);
_assert_proxy_state (proxy0, NULL, proxy1, 2, 3);
_assert_proxy_state (proxy1, proxy2, NULL, 2, 2);
_assert_proxy_state (proxy2, NULL, proxy1, 0, 5);
proxies[0] = NULL;
_assert_proxy_list (asset, proxies);
proxies[0] = proxy2;
proxies[1] = proxy0;
proxies[2] = NULL;
_assert_proxy_list (proxy1, proxies);
/* get asset back */
_assert_effect_asset_request (asset_id, asset);
_assert_effect_asset_request (proxy0_id, proxy0);
_assert_effect_asset_request (proxy1_id, proxy2);
_assert_effect_asset_request (proxy2_id, proxy2);
/* set the proxy property to NULL for proxy1, should remove all of
* its proxies */
fail_unless (ges_asset_set_proxy (proxy1, NULL));
_assert_proxy_state (asset, NULL, NULL, 7, 0);
/* only one notify for proxy1, but two separate ones for ex-proxies */
_assert_proxy_state (proxy0, NULL, NULL, 2, 4);
_assert_proxy_state (proxy1, NULL, NULL, 3, 2);
_assert_proxy_state (proxy2, NULL, NULL, 0, 6);
proxies[0] = NULL;
_assert_proxy_list (asset, proxies);
_assert_proxy_list (proxy0, proxies);
_assert_proxy_list (proxy1, proxies);
_assert_proxy_list (proxy2, proxies);
_assert_effect_asset_request (asset_id, asset);
_assert_effect_asset_request (proxy0_id, proxy0);
_assert_effect_asset_request (proxy1_id, proxy1);
_assert_effect_asset_request (proxy2_id, proxy2);
gst_object_unref (asset);
gst_object_unref (alt_asset);
gst_object_unref (proxy0);
gst_object_unref (proxy1);
gst_object_unref (proxy2);
ges_deinit ();
}
GST_END_TEST;
static Suite *
ges_suite (void)
{
@ -340,6 +747,7 @@ ges_suite (void)
tcase_add_test (tc_chain, test_transition_change_asset);
tcase_add_test (tc_chain, test_uri_clip_change_asset);
tcase_add_test (tc_chain, test_list_asset);
tcase_add_test (tc_chain, test_proxy_setters);
return s;
}