From 3617ca07ae390c80cdf9115a58af9b7344a4ffd1 Mon Sep 17 00:00:00 2001
From: George Kiagiadakis <george.kiagiadakis@collabora.com>
Date: Sun, 3 May 2020 19:42:42 +0300
Subject: [PATCH] lib: align node/endpoint/session features
 ports/streams/endpoints,links

- Use similar code for consistency
- Add changed signals everywhere
- Port to the new object-manager API
---
 lib/wp/endpoint.c | 144 +++++++++++++-----------
 lib/wp/node.c     |  29 ++---
 lib/wp/session.c  | 280 +++++++++++++++++++++++-----------------------
 3 files changed, 234 insertions(+), 219 deletions(-)

diff --git a/lib/wp/endpoint.c b/lib/wp/endpoint.c
index a8ccad0c..017db5db 100644
--- a/lib/wp/endpoint.c
+++ b/lib/wp/endpoint.c
@@ -35,9 +35,15 @@
 #include <spa/pod/parser.h>
 #include <spa/pod/filter.h>
 
-
 /* WpEndpoint */
 
+enum {
+  SIGNAL_STREAMS_CHANGED,
+  N_SIGNALS,
+};
+
+static guint32 signals[N_SIGNALS] = {0};
+
 typedef struct _WpEndpointPrivate WpEndpointPrivate;
 struct _WpEndpointPrivate
 {
@@ -46,6 +52,7 @@ struct _WpEndpointPrivate
   struct pw_endpoint *iface;
   struct spa_hook listener;
   WpObjectManager *streams_om;
+  gboolean ft_streams_requested;
 };
 
 G_DEFINE_TYPE_WITH_PRIVATE (WpEndpoint, wp_endpoint, WP_TYPE_PROXY)
@@ -69,51 +76,65 @@ wp_endpoint_finalize (GObject * object)
 }
 
 static void
-wp_endpoint_enable_feature_streams (WpEndpoint * self, guint32 bound_id)
+wp_endpoint_on_streams_om_installed (WpObjectManager *streams_om,
+    WpEndpoint * self)
 {
-  WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self);
-  g_autoptr (WpCore) core = wp_proxy_get_core (WP_PROXY (self));
-  GVariantBuilder b;
-
-  /* proxy endpoint stream -> check for endpoint.id in global properties */
-  g_variant_builder_init (&b, G_VARIANT_TYPE ("aa{sv}"));
-  g_variant_builder_open (&b, G_VARIANT_TYPE_VARDICT);
-  g_variant_builder_add (&b, "{sv}", "type",
-      g_variant_new_int32 (WP_OBJECT_MANAGER_CONSTRAINT_PW_GLOBAL_PROPERTY));
-  g_variant_builder_add (&b, "{sv}", "name",
-      g_variant_new_string (PW_KEY_ENDPOINT_ID));
-  g_variant_builder_add (&b, "{sv}", "value",
-      g_variant_new_take_string (g_strdup_printf ("%u", bound_id)));
-  g_variant_builder_close (&b);
-
-  wp_object_manager_add_interest (priv->streams_om,
-      WP_TYPE_ENDPOINT_STREAM,
-      g_variant_builder_end (&b),
-      WP_PROXY_FEATURES_STANDARD);
-
-  /* impl endpoint stream -> check for endpoint.id in standard properties */
-  g_variant_builder_init (&b, G_VARIANT_TYPE ("aa{sv}"));
-  g_variant_builder_open (&b, G_VARIANT_TYPE_VARDICT);
-  g_variant_builder_add (&b, "{sv}", "type",
-      g_variant_new_int32 (WP_OBJECT_MANAGER_CONSTRAINT_PW_PROPERTY));
-  g_variant_builder_add (&b, "{sv}", "name",
-      g_variant_new_string (PW_KEY_ENDPOINT_ID));
-  g_variant_builder_add (&b, "{sv}", "value",
-      g_variant_new_take_string (g_strdup_printf ("%u", bound_id)));
-  g_variant_builder_close (&b);
-
-  wp_object_manager_add_interest (priv->streams_om,
-      WP_TYPE_IMPL_ENDPOINT_STREAM,
-      g_variant_builder_end (&b),
-      WP_PROXY_FEATURES_STANDARD);
-
-  wp_core_install_object_manager (core, priv->streams_om);
   wp_proxy_set_feature_ready (WP_PROXY (self), WP_ENDPOINT_FEATURE_STREAMS);
 }
 
+static void
+wp_endpoint_emit_streams_changed (WpObjectManager *streams_om,
+    WpEndpoint * self)
+{
+  g_signal_emit (self, signals[SIGNAL_STREAMS_CHANGED], 0);
+}
+
+static void
+wp_endpoint_ensure_feature_streams (WpEndpoint * self, guint32 bound_id)
+{
+  WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self);
+  WpProxyFeatures ft = wp_proxy_get_features (WP_PROXY (self));
+
+  if (priv->ft_streams_requested && !priv->streams_om &&
+      (ft & WP_PROXY_FEATURE_BOUND))
+  {
+    g_autoptr (WpCore) core = wp_proxy_get_core (WP_PROXY (self));
+
+    if (!bound_id)
+      bound_id = wp_proxy_get_bound_id (WP_PROXY (self));
+
+    wp_debug_object (self, "enabling WP_ENDPOINT_FEATURE_STREAMS, bound_id:%u",
+        bound_id);
+
+    priv->streams_om = wp_object_manager_new ();
+    /* proxy endpoint stream -> check for endpoint.id in global properties */
+    wp_object_manager_add_interest_1 (priv->streams_om,
+        WP_TYPE_ENDPOINT_STREAM,
+        WP_CONSTRAINT_TYPE_PW_GLOBAL_PROPERTY, PW_KEY_ENDPOINT_ID, "=u", bound_id,
+        NULL);
+    /* impl endpoint stream -> check for endpoint.id in standard properties */
+    wp_object_manager_add_interest_1 (priv->streams_om,
+        WP_TYPE_IMPL_ENDPOINT_STREAM,
+        WP_CONSTRAINT_TYPE_PW_PROPERTY, PW_KEY_ENDPOINT_ID, "=u", bound_id,
+        NULL);
+    wp_object_manager_request_proxy_features (priv->streams_om,
+        WP_TYPE_ENDPOINT_STREAM, WP_PROXY_FEATURES_STANDARD);
+
+    g_signal_connect_object (priv->streams_om, "installed",
+        G_CALLBACK (wp_endpoint_on_streams_om_installed), self, 0);
+    g_signal_connect_object (priv->streams_om, "objects-changed",
+        G_CALLBACK (wp_endpoint_emit_streams_changed), self, 0);
+
+    wp_core_install_object_manager (core, priv->streams_om);
+  }
+}
+
 static void
 wp_endpoint_augment (WpProxy * proxy, WpProxyFeatures features)
 {
+  WpEndpoint *self = WP_ENDPOINT (proxy);
+  WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self);
+
   /* call the parent impl first to ensure we have a pw proxy if necessary */
   WP_PROXY_CLASS (wp_endpoint_parent_class)->augment (proxy, features);
 
@@ -130,17 +151,8 @@ wp_endpoint_augment (WpProxy * proxy, WpProxyFeatures features)
   }
 
   if (features & WP_ENDPOINT_FEATURE_STREAMS) {
-    WpEndpointPrivate *priv =
-        wp_endpoint_get_instance_private (WP_ENDPOINT (proxy));
-
-    priv->streams_om = wp_object_manager_new ();
-
-    /* if we are already bound, enable right away;
-       else, continue in the bound() event */
-    if (wp_proxy_get_features (proxy) & WP_PROXY_FEATURE_BOUND) {
-      wp_endpoint_enable_feature_streams (WP_ENDPOINT (proxy),
-          wp_proxy_get_bound_id (proxy));
-    }
+    priv->ft_streams_requested = TRUE;
+    wp_endpoint_ensure_feature_streams (self, 0);
   }
 }
 
@@ -247,10 +259,7 @@ static void
 wp_endpoint_bound (WpProxy * proxy, guint32 id)
 {
   WpEndpoint *self = WP_ENDPOINT (proxy);
-  WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self);
-
-  if (priv->streams_om)
-    wp_endpoint_enable_feature_streams (self, id);
+  wp_endpoint_ensure_feature_streams (self, id);
 }
 
 static const gchar *
@@ -298,6 +307,17 @@ wp_endpoint_class_init (WpEndpointClass * klass)
   klass->get_name = get_name;
   klass->get_media_class = get_media_class;
   klass->get_direction = get_direction;
+
+  /**
+   * WpEndpoint::streams-changed:
+   * @self: the endpoint
+   *
+   * Emitted when the endpoints's streams change. This is only emitted
+   * when %WP_ENDPOINT_FEATURE_STREAMS is enabled.
+   */
+  signals[SIGNAL_STREAMS_CHANGED] = g_signal_new (
+      "streams-changed", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
 }
 
 /**
@@ -378,8 +398,10 @@ wp_endpoint_find_stream (WpEndpoint * self, guint32 bound_id)
           WP_ENDPOINT_FEATURE_STREAMS, NULL);
 
   WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self);
-  return (WpEndpointStream *)
-      wp_object_manager_find_proxy (priv->streams_om, bound_id);
+  return (WpEndpointStream *) wp_object_manager_lookup (priv->streams_om,
+      WP_TYPE_ENDPOINT_STREAM,
+      WP_CONSTRAINT_TYPE_G_PROPERTY, "bound-id", "=u", bound_id,
+      NULL);
 }
 
 /**
@@ -899,14 +921,8 @@ wp_impl_endpoint_augment (WpProxy * proxy, WpProxyFeatures features)
   }
 
   if (features & WP_ENDPOINT_FEATURE_STREAMS) {
-    priv->streams_om = wp_object_manager_new ();
-
-    /* if we are already bound, enable right away;
-       else, continue in the bound() event */
-    if (wp_proxy_get_features (proxy) & WP_PROXY_FEATURE_BOUND) {
-      wp_endpoint_enable_feature_streams (WP_ENDPOINT (proxy),
-          wp_proxy_get_bound_id (proxy));
-    }
+    priv->ft_streams_requested = TRUE;
+    wp_endpoint_ensure_feature_streams (WP_ENDPOINT (self), 0);
   }
 }
 
diff --git a/lib/wp/node.c b/lib/wp/node.c
index 4174813d..02131221 100644
--- a/lib/wp/node.c
+++ b/lib/wp/node.c
@@ -94,27 +94,20 @@ wp_node_ensure_feature_ports (WpNode * self, guint32 bound_id)
       (ft & WP_PROXY_FEATURES_STANDARD) == WP_PROXY_FEATURES_STANDARD)
   {
     g_autoptr (WpCore) core = wp_proxy_get_core (WP_PROXY (self));
-    GVariantBuilder b;
 
     if (!bound_id)
       bound_id = wp_proxy_get_bound_id (WP_PROXY (self));
 
-    /* proxy node port -> check for node.id in global properties */
-    g_variant_builder_init (&b, G_VARIANT_TYPE ("aa{sv}"));
-    g_variant_builder_open (&b, G_VARIANT_TYPE_VARDICT);
-    g_variant_builder_add (&b, "{sv}", "type",
-        g_variant_new_int32 (WP_OBJECT_MANAGER_CONSTRAINT_PW_GLOBAL_PROPERTY));
-    g_variant_builder_add (&b, "{sv}", "name",
-        g_variant_new_string (PW_KEY_NODE_ID));
-    g_variant_builder_add (&b, "{sv}", "value",
-        g_variant_new_take_string (g_strdup_printf ("%u", bound_id)));
-    g_variant_builder_close (&b);
+    wp_debug_object (self, "enabling WP_NODE_FEATURE_PORTS, bound_id:%u",
+        bound_id);
 
     priv->ports_om = wp_object_manager_new ();
-    wp_object_manager_add_interest (priv->ports_om,
+    wp_object_manager_add_interest_1 (priv->ports_om,
         WP_TYPE_PORT,
-        g_variant_builder_end (&b),
-        WP_PROXY_FEATURES_STANDARD);
+        WP_CONSTRAINT_TYPE_PW_GLOBAL_PROPERTY, PW_KEY_NODE_ID, "=u", bound_id,
+        NULL);
+    wp_object_manager_request_proxy_features (priv->ports_om,
+        WP_TYPE_PORT, WP_PROXY_FEATURES_STANDARD);
 
     g_signal_connect_object (priv->ports_om, "installed",
         G_CALLBACK (wp_node_on_ports_om_installed), self, 0);
@@ -426,8 +419,10 @@ wp_node_find_port (WpNode * self, guint32 bound_id)
           WP_NODE_FEATURE_PORTS, NULL);
 
   WpNodePrivate *priv = wp_node_get_instance_private (self);
-  return (WpPort *)
-      wp_object_manager_find_proxy (priv->ports_om, bound_id);
+  return (WpPort *) wp_object_manager_lookup (priv->ports_om,
+      WP_TYPE_PORT,
+      WP_CONSTRAINT_TYPE_G_PROPERTY, "bound-id", "=u", bound_id,
+      NULL);
 }
 
 /**
@@ -518,7 +513,7 @@ wp_impl_node_augment (WpProxy * proxy, WpProxyFeatures features)
 
   /* if any of the default features is requested, make sure BOUND
      is also requested, as they all depend on binding the pw_impl_node */
-  if (features & WP_NODE_FEATURES_STANDARD)
+  if (features & WP_PROXY_FEATURES_STANDARD)
     features |= WP_PROXY_FEATURE_BOUND;
 
   if (features & WP_PROXY_FEATURE_BOUND) {
diff --git a/lib/wp/session.c b/lib/wp/session.c
index 40cc53f3..36dd6359 100644
--- a/lib/wp/session.c
+++ b/lib/wp/session.c
@@ -22,9 +22,10 @@
 
 #define G_LOG_DOMAIN "wp-session"
 
+#include "session.h"
 #include "spa-type.h"
 #include "spa-pod.h"
-#include "session.h"
+#include "debug.h"
 #include "private.h"
 #include "error.h"
 #include "wpenums.h"
@@ -39,6 +40,8 @@
 
 enum {
   SIGNAL_DEFAULT_ENDPOINT_CHANGED,
+  SIGNAL_ENDPOINTS_CHANGED,
+  SIGNAL_LINKS_CHANGED,
   N_SIGNALS,
 };
 
@@ -55,6 +58,8 @@ struct _WpSessionPrivate
   struct spa_hook listener;
   WpObjectManager *endpoints_om;
   WpObjectManager *links_om;
+  gboolean ft_endpoints_requested;
+  gboolean ft_links_requested;
 };
 
 G_DEFINE_TYPE_WITH_PRIVATE (WpSession, wp_session, WP_TYPE_PROXY)
@@ -78,6 +83,101 @@ wp_session_finalize (GObject * object)
   G_OBJECT_CLASS (wp_session_parent_class)->finalize (object);
 }
 
+static void
+wp_session_on_endpoints_om_installed (WpObjectManager *endpoints_om,
+    WpSession * self)
+{
+  wp_proxy_set_feature_ready (WP_PROXY (self), WP_SESSION_FEATURE_ENDPOINTS);
+}
+
+static void
+wp_session_emit_endpoints_changed (WpObjectManager *endpoints_om,
+    WpSession * self)
+{
+  g_signal_emit (self, signals[SIGNAL_ENDPOINTS_CHANGED], 0);
+}
+
+static void
+wp_session_on_links_om_installed (WpObjectManager *links_om, WpSession * self)
+{
+  wp_proxy_set_feature_ready (WP_PROXY (self), WP_SESSION_FEATURE_LINKS);
+}
+
+static void
+wp_session_emit_links_changed (WpObjectManager *links_om, WpSession * self)
+{
+  g_signal_emit (self, signals[SIGNAL_LINKS_CHANGED], 0);
+}
+
+static void
+wp_session_ensure_features_endpoints_links (WpSession * self, guint32 bound_id)
+{
+  WpSessionPrivate *priv = wp_session_get_instance_private (self);
+  WpProxyFeatures ft = wp_proxy_get_features (WP_PROXY (self));
+  g_autoptr (WpCore) core = NULL;
+
+  if (!(ft & WP_PROXY_FEATURE_BOUND))
+    return;
+
+  core = wp_proxy_get_core (WP_PROXY (self));
+  if (!bound_id)
+    bound_id = wp_proxy_get_bound_id (WP_PROXY (self));
+
+  if (priv->ft_endpoints_requested && !priv->endpoints_om) {
+    wp_debug_object (self, "enabling WP_SESSION_FEATURE_ENDPOINTS, bound_id:%u",
+        bound_id);
+
+    priv->endpoints_om = wp_object_manager_new ();
+    /* proxy endpoint -> check for session.id in global properties */
+    wp_object_manager_add_interest_1 (priv->endpoints_om,
+        WP_TYPE_ENDPOINT,
+        WP_CONSTRAINT_TYPE_PW_GLOBAL_PROPERTY, PW_KEY_SESSION_ID, "=u", bound_id,
+        NULL);
+    /* impl endpoint -> check for session.id in standard properties */
+    wp_object_manager_add_interest_1 (priv->endpoints_om,
+        WP_TYPE_IMPL_ENDPOINT,
+        WP_CONSTRAINT_TYPE_PW_PROPERTY, PW_KEY_SESSION_ID, "=u", bound_id,
+        NULL);
+
+    wp_object_manager_request_proxy_features (priv->endpoints_om,
+        WP_TYPE_ENDPOINT, WP_ENDPOINT_FEATURES_STANDARD);
+
+    g_signal_connect_object (priv->endpoints_om, "installed",
+        G_CALLBACK (wp_session_on_endpoints_om_installed), self, 0);
+    g_signal_connect_object (priv->endpoints_om, "objects-changed",
+        G_CALLBACK (wp_session_emit_endpoints_changed), self, 0);
+
+    wp_core_install_object_manager (core, priv->endpoints_om);
+  }
+
+  if (priv->ft_links_requested && !priv->links_om) {
+    wp_debug_object (self, "enabling WP_SESSION_FEATURE_LINKS, bound_id:%u",
+        bound_id);
+
+    priv->links_om = wp_object_manager_new ();
+    /* proxy link -> check for session.id in global properties */
+    wp_object_manager_add_interest_1 (priv->links_om,
+        WP_TYPE_ENDPOINT_LINK,
+        WP_CONSTRAINT_TYPE_PW_GLOBAL_PROPERTY, PW_KEY_SESSION_ID, "=u", bound_id,
+        NULL);
+    /* impl link -> check for session.id in standard properties */
+    wp_object_manager_add_interest_1 (priv->links_om,
+        WP_TYPE_IMPL_ENDPOINT_LINK,
+        WP_CONSTRAINT_TYPE_PW_PROPERTY, PW_KEY_SESSION_ID, "=u", bound_id,
+        NULL);
+
+    wp_object_manager_request_proxy_features (priv->links_om,
+        WP_TYPE_ENDPOINT_LINK, WP_PROXY_FEATURES_STANDARD);
+
+    g_signal_connect_object (priv->links_om, "installed",
+        G_CALLBACK (wp_session_on_links_om_installed), self, 0);
+    g_signal_connect_object (priv->links_om, "objects-changed",
+        G_CALLBACK (wp_session_emit_links_changed), self, 0);
+
+    wp_core_install_object_manager (core, priv->links_om);
+  }
+}
+
 static gconstpointer
 wp_session_get_info (WpProxy * proxy)
 {
@@ -173,102 +273,11 @@ wp_session_pw_proxy_created (WpProxy * proxy, struct pw_proxy * pw_proxy)
   pw_session_add_listener (priv->iface, &priv->listener, &session_events, self);
 }
 
-static void
-wp_session_enable_feature_endpoints (WpSession * self, guint32 bound_id)
-{
-  WpSessionPrivate *priv = wp_session_get_instance_private (self);
-  g_autoptr (WpCore) core = wp_proxy_get_core (WP_PROXY (self));
-  GVariantBuilder b;
-
-  /* proxy endpoint -> check for session.id in global properties */
-  g_variant_builder_init (&b, G_VARIANT_TYPE ("aa{sv}"));
-  g_variant_builder_open (&b, G_VARIANT_TYPE_VARDICT);
-  g_variant_builder_add (&b, "{sv}", "type",
-      g_variant_new_int32 (WP_OBJECT_MANAGER_CONSTRAINT_PW_GLOBAL_PROPERTY));
-  g_variant_builder_add (&b, "{sv}", "name",
-      g_variant_new_string (PW_KEY_SESSION_ID));
-  g_variant_builder_add (&b, "{sv}", "value",
-      g_variant_new_take_string (g_strdup_printf ("%u", bound_id)));
-  g_variant_builder_close (&b);
-
-  wp_object_manager_add_interest (priv->endpoints_om,
-      WP_TYPE_ENDPOINT,
-      g_variant_builder_end (&b),
-      WP_ENDPOINT_FEATURES_STANDARD);
-
-  /* impl endpoint -> check for session.id in standard properties */
-  g_variant_builder_init (&b, G_VARIANT_TYPE ("aa{sv}"));
-  g_variant_builder_open (&b, G_VARIANT_TYPE_VARDICT);
-  g_variant_builder_add (&b, "{sv}", "type",
-      g_variant_new_int32 (WP_OBJECT_MANAGER_CONSTRAINT_PW_PROPERTY));
-  g_variant_builder_add (&b, "{sv}", "name",
-      g_variant_new_string (PW_KEY_SESSION_ID));
-  g_variant_builder_add (&b, "{sv}", "value",
-      g_variant_new_take_string (g_strdup_printf ("%u", bound_id)));
-  g_variant_builder_close (&b);
-
-  wp_object_manager_add_interest (priv->endpoints_om,
-      WP_TYPE_IMPL_ENDPOINT,
-      g_variant_builder_end (&b),
-      WP_ENDPOINT_FEATURES_STANDARD);
-
-  wp_core_install_object_manager (core, priv->endpoints_om);
-  wp_proxy_set_feature_ready (WP_PROXY (self), WP_SESSION_FEATURE_ENDPOINTS);
-}
-
-static void
-wp_session_enable_feature_links (WpSession * self, guint32 bound_id)
-{
-  WpSessionPrivate *priv = wp_session_get_instance_private (self);
-  g_autoptr (WpCore) core = wp_proxy_get_core (WP_PROXY (self));
-  GVariantBuilder b;
-
-  /* proxy link -> check for session.id in global properties */
-  g_variant_builder_init (&b, G_VARIANT_TYPE ("aa{sv}"));
-  g_variant_builder_open (&b, G_VARIANT_TYPE_VARDICT);
-  g_variant_builder_add (&b, "{sv}", "type",
-      g_variant_new_int32 (WP_OBJECT_MANAGER_CONSTRAINT_PW_GLOBAL_PROPERTY));
-  g_variant_builder_add (&b, "{sv}", "name",
-      g_variant_new_string (PW_KEY_SESSION_ID));
-  g_variant_builder_add (&b, "{sv}", "value",
-      g_variant_new_take_string (g_strdup_printf ("%u", bound_id)));
-  g_variant_builder_close (&b);
-
-  wp_object_manager_add_interest (priv->links_om,
-      WP_TYPE_ENDPOINT_LINK,
-      g_variant_builder_end (&b),
-      WP_PROXY_FEATURES_STANDARD);
-
-  /* impl link -> check for session.id in standard properties */
-  g_variant_builder_init (&b, G_VARIANT_TYPE ("aa{sv}"));
-  g_variant_builder_open (&b, G_VARIANT_TYPE_VARDICT);
-  g_variant_builder_add (&b, "{sv}", "type",
-      g_variant_new_int32 (WP_OBJECT_MANAGER_CONSTRAINT_PW_PROPERTY));
-  g_variant_builder_add (&b, "{sv}", "name",
-      g_variant_new_string (PW_KEY_SESSION_ID));
-  g_variant_builder_add (&b, "{sv}", "value",
-      g_variant_new_take_string (g_strdup_printf ("%u", bound_id)));
-  g_variant_builder_close (&b);
-
-  wp_object_manager_add_interest (priv->links_om,
-      WP_TYPE_IMPL_ENDPOINT_LINK,
-      g_variant_builder_end (&b),
-      WP_PROXY_FEATURES_STANDARD);
-
-  wp_core_install_object_manager (core, priv->links_om);
-  wp_proxy_set_feature_ready (WP_PROXY (self), WP_SESSION_FEATURE_LINKS);
-}
-
 static void
 wp_session_bound (WpProxy * proxy, guint32 id)
 {
   WpSession *self = WP_SESSION (proxy);
-  WpSessionPrivate *priv = wp_session_get_instance_private (self);
-
-  if (priv->endpoints_om)
-    wp_session_enable_feature_endpoints (self, id);
-  if (priv->links_om)
-    wp_session_enable_feature_links (self, id);
+  wp_session_ensure_features_endpoints_links (self, id);
 }
 
 static void
@@ -286,7 +295,8 @@ wp_session_control_changed (WpProxy * proxy, const char * id_name)
 static void
 wp_session_augment (WpProxy * proxy, WpProxyFeatures features)
 {
-  WpSessionPrivate *priv = wp_session_get_instance_private (WP_SESSION (proxy));
+  WpSession *self = WP_SESSION (proxy);
+  WpSessionPrivate *priv = wp_session_get_instance_private (self);
 
   /* call the parent impl first to ensure we have a pw proxy if necessary */
   WP_PROXY_CLASS (wp_session_parent_class)->augment (proxy, features);
@@ -303,26 +313,10 @@ wp_session_augment (WpProxy * proxy, WpProxyFeatures features)
     pw_session_subscribe_params (pw_proxy, ids, SPA_N_ELEMENTS (ids));
   }
 
-  if (features & WP_SESSION_FEATURE_ENDPOINTS) {
-    priv->endpoints_om = wp_object_manager_new ();
-
-    /* if we are already bound, enable right away;
-       else, continue in the bound() event */
-    if (wp_proxy_get_features (proxy) & WP_PROXY_FEATURE_BOUND) {
-      wp_session_enable_feature_endpoints (WP_SESSION (proxy),
-          wp_proxy_get_bound_id (proxy));
-    }
-  }
-
-  if (features & WP_SESSION_FEATURE_LINKS) {
-    priv->links_om = wp_object_manager_new ();
-
-    /* if we are already bound, enable right away;
-       else, continue in the bound() event */
-    if (wp_proxy_get_features (proxy) & WP_PROXY_FEATURE_BOUND) {
-      wp_session_enable_feature_links (WP_SESSION (proxy),
-          wp_proxy_get_bound_id (proxy));
-    }
+  if (features & (WP_SESSION_FEATURE_ENDPOINTS | WP_SESSION_FEATURE_LINKS)) {
+    priv->ft_endpoints_requested = (features & WP_SESSION_FEATURE_ENDPOINTS);
+    priv->ft_links_requested = (features & WP_SESSION_FEATURE_LINKS);
+    wp_session_ensure_features_endpoints_links (self, 0);
   }
 }
 
@@ -394,6 +388,28 @@ wp_session_class_init (WpSessionClass * klass)
       "default-endpoint-changed", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 2,
       G_TYPE_STRING, G_TYPE_UINT);
+
+  /**
+   * WpSession::endpoints-changed:
+   * @self: the session
+   *
+   * Emitted when the sessions's endpoints change. This is only emitted
+   * when %WP_SESSION_FEATURE_ENDPOINTS is enabled.
+   */
+  signals[SIGNAL_ENDPOINTS_CHANGED] = g_signal_new (
+      "endpoints-changed", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
+
+  /**
+   * WpSession::links-changed:
+   * @self: the session
+   *
+   * Emitted when the session's links change. This is only emitted
+   * when %WP_SESSION_FEATURE_LINKS is enabled.
+   */
+  signals[SIGNAL_LINKS_CHANGED] = g_signal_new (
+      "links-changed", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
 }
 
 /**
@@ -465,8 +481,10 @@ wp_session_find_endpoint (WpSession * self, guint32 bound_id)
           WP_SESSION_FEATURE_ENDPOINTS, NULL);
 
   WpSessionPrivate *priv = wp_session_get_instance_private (self);
-  return (WpEndpoint *)
-      wp_object_manager_find_proxy (priv->endpoints_om, bound_id);
+  return (WpEndpoint *) wp_object_manager_lookup (priv->endpoints_om,
+      WP_TYPE_ENDPOINT,
+      WP_CONSTRAINT_TYPE_G_PROPERTY, "bound-id", "=u", bound_id,
+      NULL);
 }
 
 /**
@@ -520,8 +538,10 @@ wp_session_find_link (WpSession * self, guint32 bound_id)
           WP_SESSION_FEATURE_LINKS, NULL);
 
   WpSessionPrivate *priv = wp_session_get_instance_private (self);
-  return (WpEndpointLink *)
-      wp_object_manager_find_proxy (priv->links_om, bound_id);
+  return (WpEndpointLink *) wp_object_manager_lookup (priv->links_om,
+      WP_TYPE_ENDPOINT_LINK,
+      WP_CONSTRAINT_TYPE_G_PROPERTY, "bound-id", "=u", bound_id,
+      NULL);
 }
 
 /**
@@ -769,26 +789,10 @@ wp_impl_session_augment (WpProxy * proxy, WpProxyFeatures features)
             priv->iface, 0));
   }
 
-  if (features & WP_SESSION_FEATURE_ENDPOINTS) {
-    priv->endpoints_om = wp_object_manager_new ();
-
-    /* if we are already bound, enable right away;
-       else, continue in the bound() event */
-    if (wp_proxy_get_features (proxy) & WP_PROXY_FEATURE_BOUND) {
-      wp_session_enable_feature_endpoints (WP_SESSION (proxy),
-          wp_proxy_get_bound_id (proxy));
-    }
-  }
-
-  if (features & WP_SESSION_FEATURE_LINKS) {
-    priv->links_om = wp_object_manager_new ();
-
-    /* if we are already bound, enable right away;
-       else, continue in the bound() event */
-    if (wp_proxy_get_features (proxy) & WP_PROXY_FEATURE_BOUND) {
-      wp_session_enable_feature_links (WP_SESSION (proxy),
-          wp_proxy_get_bound_id (proxy));
-    }
+  if (features & (WP_SESSION_FEATURE_ENDPOINTS | WP_SESSION_FEATURE_LINKS)) {
+    priv->ft_endpoints_requested = (features & WP_SESSION_FEATURE_ENDPOINTS);
+    priv->ft_links_requested = (features & WP_SESSION_FEATURE_LINKS);
+    wp_session_ensure_features_endpoints_links (WP_SESSION (self), 0);
   }
 }
 
-- 
GitLab