From ca1453febd9052b8308746e7442f94d023e37454 Mon Sep 17 00:00:00 2001
From: George Kiagiadakis <george.kiagiadakis@collabora.com>
Date: Tue, 18 Jun 2019 17:42:06 +0300
Subject: [PATCH] endpoint: add some useful API for querying info about streams
 & controls

---
 lib/wp/endpoint.c | 113 ++++++++++++++++++++++++++++++++++++++++++++--
 lib/wp/endpoint.h |   8 ++++
 2 files changed, 118 insertions(+), 3 deletions(-)

diff --git a/lib/wp/endpoint.c b/lib/wp/endpoint.c
index f971aef3..8a30c5e8 100644
--- a/lib/wp/endpoint.c
+++ b/lib/wp/endpoint.c
@@ -425,6 +425,26 @@ wp_endpoint_register_stream (WpEndpoint * self, GVariant * stream)
   g_ptr_array_add (priv->streams, g_variant_ref_sink (stream));
 }
 
+GVariant *
+wp_endpoint_get_stream (WpEndpoint * self, guint32 stream_id)
+{
+  WpEndpointPrivate *priv;
+  guint32 id;
+  gint i;
+
+  g_return_val_if_fail (WP_IS_ENDPOINT (self), NULL);
+
+  priv = wp_endpoint_get_instance_private (self);
+  for (i = 0; i < priv->streams->len; i++) {
+    GVariant *v = g_ptr_array_index (priv->streams, i);
+    if (g_variant_lookup (v, "id", "u", &id) && id == stream_id) {
+      return g_variant_ref (v);
+    }
+  }
+
+  return NULL;
+}
+
 /**
  * wp_endpoint_list_streams:
  * @self: the endpoint
@@ -445,6 +465,30 @@ wp_endpoint_list_streams (WpEndpoint * self)
       (GVariant * const *) priv->streams->pdata, priv->streams->len);
 }
 
+guint32
+wp_endpoint_find_stream (WpEndpoint * self, const gchar * name)
+{
+  WpEndpointPrivate *priv;
+  const gchar *tmp = NULL;
+  guint32 id = WP_STREAM_ID_NONE;
+  gint i;
+
+  g_return_val_if_fail (WP_IS_ENDPOINT (self), WP_STREAM_ID_NONE);
+  g_return_val_if_fail (name != NULL, WP_STREAM_ID_NONE);
+
+  priv = wp_endpoint_get_instance_private (self);
+  for (i = 0; i < priv->streams->len; i++) {
+    GVariant *v = g_ptr_array_index (priv->streams, i);
+    if (g_variant_lookup (v, "name", "&s", &tmp) && !g_strcmp0 (tmp, name)) {
+      /* found, return the id */
+      g_variant_lookup (v, "id", "u", &id);
+      break;
+    }
+  }
+
+  return id;
+}
+
 /**
  * wp_endpoint_register_control:
  * @self: the endpoint
@@ -462,6 +506,26 @@ wp_endpoint_register_control (WpEndpoint * self, GVariant * control)
   g_ptr_array_add (priv->controls, g_variant_ref_sink (control));
 }
 
+GVariant *
+wp_endpoint_get_control (WpEndpoint * self, guint32 control_id)
+{
+  WpEndpointPrivate *priv;
+  guint32 id;
+  gint i;
+
+  g_return_val_if_fail (WP_IS_ENDPOINT (self), NULL);
+
+  priv = wp_endpoint_get_instance_private (self);
+  for (i = 0; i < priv->controls->len; i++) {
+    GVariant *v = g_ptr_array_index (priv->controls, i);
+    if (g_variant_lookup (v, "id", "u", &id) && id == control_id) {
+      return g_variant_ref (v);
+    }
+  }
+
+  return NULL;
+}
+
 /**
  * wp_endpoint_list_controls:
  * @self: the endpoint
@@ -482,6 +546,44 @@ wp_endpoint_list_controls (WpEndpoint * self)
       (GVariant * const *) priv->controls->pdata, priv->controls->len);
 }
 
+guint32
+wp_endpoint_find_control (WpEndpoint * self, guint32 stream_id,
+    const gchar * name)
+{
+  WpEndpointPrivate *priv;
+  const gchar *tmp = NULL;
+  guint32 tmp_id = WP_STREAM_ID_NONE;
+  guint32 id = WP_CONTROL_ID_NONE;
+  gint i;
+
+  g_return_val_if_fail (WP_IS_ENDPOINT (self), WP_CONTROL_ID_NONE);
+  g_return_val_if_fail (name != NULL, WP_CONTROL_ID_NONE);
+
+  priv = wp_endpoint_get_instance_private (self);
+  for (i = 0; i < priv->controls->len; i++) {
+    GVariant *v = g_ptr_array_index (priv->controls, i);
+
+    /*
+     * if the stream-id exists, it must match @stream_id
+     * if it doesn't exist, then @stream_id must be NONE
+     */
+    if (g_variant_lookup (v, "stream-id", "u", &tmp_id)) {
+      if (stream_id != tmp_id)
+        continue;
+    } else if (stream_id != WP_STREAM_ID_NONE) {
+      continue;
+    }
+
+    if (g_variant_lookup (v, "name", "&s", &tmp) && !g_strcmp0 (tmp, name)) {
+      /* found, return the id */
+      g_variant_lookup (v, "id", "u", &id);
+      break;
+    }
+  }
+
+  return id;
+}
+
 /**
  * wp_endpoint_get_control_value: (virtual get_control_value)
  * @self: the endpoint
@@ -522,13 +624,18 @@ gboolean
 wp_endpoint_set_control_value (WpEndpoint * self, guint32 control_id,
     GVariant * value)
 {
+  gboolean ret = FALSE;
+
   g_return_val_if_fail (WP_IS_ENDPOINT (self), FALSE);
 
   if (WP_ENDPOINT_GET_CLASS (self)->set_control_value)
-    return WP_ENDPOINT_GET_CLASS (self)->set_control_value (self, control_id,
+    ret = WP_ENDPOINT_GET_CLASS (self)->set_control_value (self, control_id,
         value);
-  else
-    return FALSE;
+
+  if (g_variant_is_floating (value))
+    g_variant_unref (value);
+
+  return ret;
 }
 
 /**
diff --git a/lib/wp/endpoint.h b/lib/wp/endpoint.h
index 8f6358b8..1364b776 100644
--- a/lib/wp/endpoint.h
+++ b/lib/wp/endpoint.h
@@ -13,6 +13,9 @@
 
 G_BEGIN_DECLS
 
+static const guint32 WP_STREAM_ID_NONE = 0xffffffff;
+static const guint32 WP_CONTROL_ID_NONE = 0xffffffff;
+
 #define WP_TYPE_ENDPOINT (wp_endpoint_get_type ())
 G_DECLARE_DERIVABLE_TYPE (WpEndpoint, wp_endpoint, WP, ENDPOINT, GObject)
 
@@ -43,10 +46,15 @@ const gchar * wp_endpoint_get_name (WpEndpoint * self);
 const gchar * wp_endpoint_get_media_class (WpEndpoint * self);
 
 void wp_endpoint_register_stream (WpEndpoint * self, GVariant * stream);
+GVariant * wp_endpoint_get_stream (WpEndpoint * self, guint32 stream_id);
 GVariant * wp_endpoint_list_streams (WpEndpoint * self);
+guint32 wp_endpoint_find_stream (WpEndpoint * self, const gchar * name);
 
 void wp_endpoint_register_control (WpEndpoint * self, GVariant * control);
+GVariant * wp_endpoint_get_control (WpEndpoint * self, guint32 control_id);
 GVariant * wp_endpoint_list_controls (WpEndpoint * self);
+guint32 wp_endpoint_find_control (WpEndpoint * self, guint32 stream_id,
+    const gchar * name);
 
 GVariant * wp_endpoint_get_control_value (WpEndpoint * self,
     guint32 control_id);
-- 
GitLab