From d96c856f284f48b244382f9411aaf19ee91bb02b Mon Sep 17 00:00:00 2001
From: Julian Bouzas <julian.bouzas@collabora.com>
Date: Mon, 11 Jan 2021 15:08:07 -0500
Subject: [PATCH] m-lua-scripting: handle default endpoints from the metadata

---
 modules/module-lua-scripting/api.c     | 77 ++++++++++++++++++++++++++
 src/config/desktop/policy-endpoint.lua | 23 ++++++--
 2 files changed, 94 insertions(+), 6 deletions(-)

diff --git a/modules/module-lua-scripting/api.c b/modules/module-lua-scripting/api.c
index 4564a0a8..40bf4049 100644
--- a/modules/module-lua-scripting/api.c
+++ b/modules/module-lua-scripting/api.c
@@ -106,6 +106,36 @@ push_wpiterator (lua_State *L, WpIterator *it)
   return 2;
 }
 
+/* Metadata WpIterator */
+
+static int
+metadata_iterator_next (lua_State *L)
+{
+  WpIterator *it = wplua_checkboxed (L, 1, WP_TYPE_ITERATOR);
+  GValue item = G_VALUE_INIT;
+  if (wp_iterator_next (it, &item)) {
+    guint32 s = 0;
+    const gchar *k = NULL, *t = NULL, *v = NULL;
+    wp_metadata_iterator_item_extract (&item, &s, &k, &t, &v);
+    lua_pushinteger (L, s);
+    lua_pushstring (L, k);
+    lua_pushstring (L, t);
+    lua_pushstring (L, v);
+    return 4;
+  } else {
+    lua_pushnil (L);
+    return 1;
+  }
+}
+
+static int
+push_metadata_wpiterator (lua_State *L, WpIterator *it)
+{
+  lua_pushcfunction (L, metadata_iterator_next);
+  wplua_pushboxed (L, WP_TYPE_ITERATOR, it);
+  return 2;
+}
+
 /* WpObjectInterest */
 
 static GVariant *
@@ -314,9 +344,54 @@ object_manager_iterate (lua_State *L)
   return push_wpiterator (L, it);
 }
 
+static int
+object_manager_lookup (lua_State *L)
+{
+  WpObjectManager *om = wplua_checkobject (L, 1, WP_TYPE_OBJECT_MANAGER);
+  WpObject *o = NULL;
+  if (lua_isuserdata (L, 2)) {
+    WpObjectInterest *oi = wplua_checkboxed (L, 2, WP_TYPE_OBJECT_INTEREST);
+    o = wp_object_manager_lookup_full (om, oi);
+  } else {
+    o = wp_object_manager_lookup (om, WP_TYPE_OBJECT, NULL);
+  }
+  wplua_pushobject (L, o);
+  return 1;
+}
+
 static const luaL_Reg object_manager_methods[] = {
   { "activate", object_manager_activate },
   { "iterate", object_manager_iterate },
+  { "lookup", object_manager_lookup },
+  { NULL, NULL }
+};
+
+/* WpMetadata */
+
+static int
+metadata_iterate (lua_State *L)
+{
+  WpMetadata *metadata = wplua_checkobject (L, 1, WP_TYPE_METADATA);
+  lua_Integer subject = luaL_checkinteger (L, 2);
+  g_autoptr (WpIterator) it = wp_metadata_iterate (metadata, subject);
+  return push_metadata_wpiterator (L, it);
+}
+
+static int
+metadata_find (lua_State *L)
+{
+  WpMetadata *metadata = wplua_checkobject (L, 1, WP_TYPE_METADATA);
+  lua_Integer subject = luaL_checkinteger (L, 2);
+  const char *key = luaL_checkstring (L, 3), *v = NULL, *t = NULL;
+  v = wp_metadata_find (metadata, subject, key, &t);
+  lua_pushstring (L, v);
+  lua_pushstring (L, t);
+  return 2;
+}
+
+static const luaL_Reg metadata_methods[] = {
+  { "iterate", metadata_iterate },
+  { "find", metadata_find },
   { NULL, NULL }
 };
 
@@ -433,6 +508,8 @@ wp_lua_scripting_api_init (lua_State *L)
       object_interest_new, NULL);
   wplua_register_type_methods (L, WP_TYPE_OBJECT_MANAGER,
       object_manager_new, object_manager_methods);
+  wplua_register_type_methods (L, WP_TYPE_METADATA,
+      NULL, metadata_methods);
   wplua_register_type_methods (L, WP_TYPE_SESSION,
       NULL, session_methods);
   wplua_register_type_methods (L, WP_TYPE_ENDPOINT,
diff --git a/src/config/desktop/policy-endpoint.lua b/src/config/desktop/policy-endpoint.lua
index 6c71add8..1ad85c1e 100644
--- a/src/config/desktop/policy-endpoint.lua
+++ b/src/config/desktop/policy-endpoint.lua
@@ -17,6 +17,11 @@ reverse_direction = {
   ["output"] = "input",
 }
 
+default_endpoint_key = {
+  ["input"] = "default.session.endpoint.sink",
+  ["output"] = "default.session.endpoint.source",
+}
+
 function findTarget (session, ep)
   local target = nil
 
@@ -39,6 +44,7 @@ function findTarget (session, ep)
 
   -- try to find the best target
   if not target then
+    local metadata = om_metadata:lookup()
     local direction = reverse_direction[ep['direction']]
     local media_class = target_class_assoc[ep['media-class']]
     local highest_prio = -1
@@ -47,13 +53,16 @@ function findTarget (session, ep)
       if candidate_ep['direction'] == direction and
          candidate_ep['media-class'] == media_class
       then
-        --[[
-        if candidate_ep['bound-id'] == session.default_target[direction] then
-          target = candidate_ep
-          Log.debug(session, "choosing default endpoint " .. target['bound-id']);
-          break
+        -- honor default endpoint, if present
+        if metadata then
+          local key = default_endpoint_key[direction]
+          local value = metadata:find(session['bound-id'], key)
+          if candidate_ep['bound-id'] == tonumber(value) then
+            target = candidate_ep
+            Log.debug(session, "choosing default endpoint " .. target['bound-id']);
+            break
+          end
         end
-        ]]
 
         local prio = tonumber(candidate_ep.properties["endpoint.priority"]) or 0
         if highest_prio < prio then
@@ -108,6 +117,7 @@ function handleLink (link)
   end
 end
 
+om_metadata = ObjectManager { Interest { type = "metadata" } }
 om = ObjectManager { Interest { type = "session" } }
 
 om:connect("object-added", function (om, session)
@@ -124,4 +134,5 @@ om:connect("object-added", function (om, session)
   end)
 end)
 
+om_metadata:activate()
 om:activate()
-- 
GitLab