[Telepathy-commits] [telepathy-salut/master] Start the implementation of D-Bus method call set_self_capabilities()

Alban Crequy alban.crequy at collabora.co.uk
Thu Feb 26 11:20:04 PST 2009


---
 src/Makefile.am            |    2 +
 src/salut-connection.c     |  224 +++++++++++++++++++++++++++++++++++++++----
 src/salut-presence-cache.c |  105 +++++++++++++++++++++
 src/salut-presence-cache.h |   46 +++++++++
 4 files changed, 356 insertions(+), 21 deletions(-)
 create mode 100644 src/salut-presence-cache.c
 create mode 100644 src/salut-presence-cache.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 3b6d3ab..26747ab 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -41,6 +41,8 @@ CORE_SOURCES =                                          \
     salut-file-transfer-channel.c                       \
     salut-file-transfer-channel.h                       \
     salut-muc-channel.h                                 \
+    salut-presence-cache.c                              \
+    salut-presence-cache.h                              \
     salut-tubes-manager.c                               \
     salut-tubes-manager.h                               \
     salut-contact.h                                     \
diff --git a/src/salut-connection.c b/src/salut-connection.c
index 14b69ed..fa49b60 100644
--- a/src/salut-connection.c
+++ b/src/salut-connection.c
@@ -30,43 +30,45 @@
 #include <dbus/dbus-glib.h>
 #include <dbus/dbus-glib-lowlevel.h>
 
-#include "salut-connection.h"
+#include <telepathy-glib/channel-manager.h>
+#include <telepathy-glib/dbus.h>
+#include <telepathy-glib/handle-repo-dynamic.h>
+#include <telepathy-glib/handle-repo.h>
+#include <telepathy-glib/handle-repo-static.h>
+#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/svc-generic.h>
+#include <telepathy-glib/util.h>
 
-#include "salut-util.h"
-#include "salut-contact-manager.h"
+#include <gibber/gibber-namespaces.h>
+
+#include "salut-avahi-discovery-client.h"
+#include "salut-caps-channel-manager.h"
+#include "salut-caps-hash.h"
+#include "salut-connection.h"
 #include "salut-contact-channel.h"
+#include "salut-contact.h"
+#include "salut-contact-manager.h"
+#include "salut-direct-bytestream-manager.h"
+#include "salut-discovery-client.h"
 #include "salut-im-manager.h"
 #include "salut-muc-manager.h"
 #include "salut-ft-manager.h"
 #include "salut-contact.h"
 #include "salut-roomlist-manager.h"
+#include "salut-presence.h"
+#include "salut-presence-cache.h"
 #include "salut-self.h"
-#include "salut-xmpp-connection-manager.h"
 #include "salut-si-bytestream-manager.h"
+#include "salut-tubes-manager.h"
+#include "salut-util.h"
+#include "salut-xmpp-connection-manager.h"
 
 #ifdef ENABLE_OLPC
 #include "salut-olpc-activity-manager.h"
 #endif
 
-#include "salut-tubes-manager.h"
-
-#include "salut-presence.h"
-#include "salut-discovery-client.h"
-#include "salut-avahi-discovery-client.h"
-
 #include <extensions/extensions.h>
 
-#include <telepathy-glib/channel-manager.h>
-#include <telepathy-glib/util.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/handle-repo-dynamic.h>
-#include <telepathy-glib/handle-repo-static.h>
-#include <telepathy-glib/handle-repo.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/svc-generic.h>
-
-#include <gibber/gibber-namespaces.h>
-
 #define DEBUG_FLAG DEBUG_CONNECTION
 #include "debug.h"
 
@@ -97,6 +99,9 @@ static void
 salut_connection_avatar_service_iface_init (gpointer g_iface,
     gpointer iface_data);
 
+static void
+salut_conn_contact_caps_iface_init (gpointer, gpointer);
+
 G_DEFINE_TYPE_WITH_CODE(SalutConnection,
     salut_connection,
     TP_TYPE_BASE_CONNECTION,
@@ -112,6 +117,9 @@ G_DEFINE_TYPE_WITH_CODE(SalutConnection,
        tp_presence_mixin_simple_presence_iface_init);
     G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_AVATARS,
        salut_connection_avatar_service_iface_init);
+    G_IMPLEMENT_INTERFACE
+      (SALUT_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_CAPABILITIES,
+      salut_conn_contact_caps_iface_init);
 #ifdef ENABLE_OLPC
     G_IMPLEMENT_INTERFACE (SALUT_TYPE_SVC_OLPC_BUDDY_INFO,
        salut_connection_olpc_buddy_info_iface_init);
@@ -1654,6 +1662,180 @@ salut_connection_avatar_service_iface_init (gpointer g_iface,
 #undef IMPLEMENT
 }
 
+static void
+salut_free_enhanced_contact_capabilities (GPtrArray *caps)
+{
+  guint i;
+
+  for (i = 0; i < caps->len; i++)
+    {
+      GValue monster = {0, };
+
+      g_value_init (&monster, SALUT_STRUCT_TYPE_ENHANCED_CONTACT_CAPABILITY);
+      g_value_take_boxed (&monster, g_ptr_array_index (caps, i));
+      g_value_unset (&monster);
+    }
+
+  g_ptr_array_free (caps, TRUE);
+}
+
+/**
+ * salut_connection_get_handle_contact_capabilities
+ *
+ * Add capabilities of handle to the given GPtrArray
+ */
+static void
+salut_connection_get_handle_contact_capabilities (SalutConnection *self,
+  TpHandle handle, GPtrArray *arr)
+{
+  TpBaseConnection *base_conn = TP_BASE_CONNECTION (self);
+  TpChannelManagerIter iter;
+  TpChannelManager *manager;
+
+  tp_base_connection_channel_manager_iter_init (&iter, base_conn);
+  while (tp_base_connection_channel_manager_iter_next (&iter, &manager))
+    {
+      /* all channel managers must implement the capability interface */
+      g_assert (SALUT_IS_CAPS_CHANNEL_MANAGER (manager));
+
+      salut_caps_channel_manager_get_contact_capabilities (
+          SALUT_CAPS_CHANNEL_MANAGER (manager), self, handle, arr);
+    }
+}
+
+
+static void
+_emit_contact_capabilities_changed (SalutConnection *conn,
+                                    TpHandle handle,
+                                    GHashTable *old_caps,
+                                    GHashTable *new_caps)
+{
+  TpBaseConnection *base_conn = TP_BASE_CONNECTION (conn);
+  TpChannelManagerIter iter;
+  TpChannelManager *manager;
+  GPtrArray *ret;
+  gboolean diff = FALSE;
+
+  tp_base_connection_channel_manager_iter_init (&iter, base_conn);
+  while (tp_base_connection_channel_manager_iter_next (&iter, &manager))
+    {
+      gpointer per_channel_manager_caps_old = NULL;
+      gpointer per_channel_manager_caps_new = NULL;
+
+      /* all channel managers must implement the capability interface */
+      g_assert (SALUT_IS_CAPS_CHANNEL_MANAGER (manager));
+
+      if (old_caps != NULL)
+        per_channel_manager_caps_old = g_hash_table_lookup (old_caps, manager);
+      if (new_caps != NULL)
+        per_channel_manager_caps_new = g_hash_table_lookup (new_caps, manager);
+
+      if (salut_caps_channel_manager_capabilities_diff (
+            SALUT_CAPS_CHANNEL_MANAGER (manager), handle,
+            per_channel_manager_caps_old, per_channel_manager_caps_new))
+        {
+          diff = TRUE;
+          break;
+        }
+    }
+
+  /* Don't emit the D-Bus signal if there is no change */
+  if (! diff)
+    return;
+
+  ret = g_ptr_array_new ();
+
+  salut_connection_get_handle_contact_capabilities (conn, handle, ret);
+  salut_svc_connection_interface_contact_capabilities_emit_contact_capabilities_changed (
+      conn, ret);
+
+  salut_free_enhanced_contact_capabilities (ret);
+}
+
+/**
+ * salut_connection_set_self_capabilities
+ *
+ * Implements D-Bus method SetSelfCapabilities
+ * on interface
+ * org.freedesktop.Telepathy.Connection.Interface.ContactCapabilities
+ *
+ * @error: Used to return a pointer to a GError detailing any error
+ *         that occurred, D-Bus will throw the error only if this
+ *         function returns FALSE.
+ *
+ * Returns: TRUE if successful, FALSE if an error was thrown.
+ */
+static void
+salut_connection_set_self_capabilities (
+    SalutSvcConnectionInterfaceContactCapabilities *iface,
+    const GPtrArray *caps,
+    DBusGMethodInvocation *context)
+{
+  SalutConnection *self = SALUT_CONNECTION (iface);
+  TpBaseConnection *base = (TpBaseConnection *) self;
+  SalutConnectionPrivate *priv = SALUT_CONNECTION_GET_PRIVATE (self);
+  guint i;
+  GHashTable *save_caps;
+  GError *error = NULL;
+
+  TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
+
+  /* reset the caps, and fill with the given parameter but keep a backup for
+   * diffing: we don't want to emit a signal if nothing has changed */
+  save_caps = priv->self->per_channel_manager_caps;
+  priv->self->per_channel_manager_caps = NULL;
+
+  for (i = 0; i < caps->len; i++)
+    {
+      GHashTable *cap_to_add = g_ptr_array_index (caps, i);
+      TpChannelManagerIter iter;
+      TpChannelManager *manager;
+
+      tp_base_connection_channel_manager_iter_init (&iter, base);
+      while (tp_base_connection_channel_manager_iter_next (&iter, &manager))
+        {
+          /* all channel managers must implement the capability interface */
+          g_assert (SALUT_IS_CAPS_CHANNEL_MANAGER (manager));
+
+          salut_caps_channel_manager_add_capability (
+              SALUT_CAPS_CHANNEL_MANAGER (manager), self,
+              base->self_handle, cap_to_add);
+        }
+    }
+
+  if (!salut_self_set_caps (priv->self, "NODE", "HASH", "VER", &error))
+    {
+      salut_presence_cache_free_cache_entry (save_caps);
+      dbus_g_method_return_error (context, error);
+      return;
+    }
+
+  _emit_contact_capabilities_changed (self, base->self_handle,
+                                      save_caps,
+                                      priv->self->per_channel_manager_caps);
+  salut_presence_cache_free_cache_entry (save_caps);
+
+
+  salut_svc_connection_interface_contact_capabilities_return_from_set_self_capabilities
+      (context);
+}
+
+
+static void
+salut_conn_contact_caps_iface_init (gpointer g_iface, gpointer iface_data)
+{
+  SalutSvcConnectionInterfaceContactCapabilitiesClass *klass =
+    (SalutSvcConnectionInterfaceContactCapabilitiesClass *) g_iface;
+
+#define IMPLEMENT(x) \
+    salut_svc_connection_interface_contact_capabilities_implement_##x (\
+    klass, salut_connection_##x)
+  //IMPLEMENT(get_contact_capabilities);
+  IMPLEMENT(set_self_capabilities);
+#undef IMPLEMENT
+}
+
+
 #ifdef ENABLE_OLPC
 static GValue *
 new_gvalue (GType type)
diff --git a/src/salut-presence-cache.c b/src/salut-presence-cache.c
new file mode 100644
index 0000000..c00b269
--- /dev/null
+++ b/src/salut-presence-cache.c
@@ -0,0 +1,105 @@
+/*
+ * salut-presence-cache.c - Salut's contact presence cache
+ * Copyright (C) 2005 Collabora Ltd.
+ * Copyright (C) 2005 Nokia Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "config.h"
+#include "salut-presence-cache.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+
+#define DEBUG_FLAG SALUT_DEBUG_PRESENCE
+
+#include <gibber/gibber-namespaces.h>
+#include <telepathy-glib/channel-manager.h>
+#include <telepathy-glib/intset.h>
+
+#define DEBUG_FLAG SALUT_DEBUG_PRESENCE
+
+#include "salut-caps-channel-manager.h"
+#include "salut-caps-hash.h"
+#include "debug.h"
+
+static void
+free_caps_helper (gpointer key, gpointer value, gpointer user_data)
+{
+  SalutCapsChannelManager *manager = SALUT_CAPS_CHANNEL_MANAGER (key);
+  salut_caps_channel_manager_free_capabilities (manager, value);
+}
+
+void
+salut_presence_cache_free_cache_entry (
+    GHashTable *per_channel_manager_caps)
+{
+  if (per_channel_manager_caps == NULL)
+    return;
+
+  g_hash_table_foreach (per_channel_manager_caps, free_caps_helper,
+      NULL);
+  g_hash_table_destroy (per_channel_manager_caps);
+}
+
+static void
+copy_caps_helper (gpointer key, gpointer value, gpointer user_data)
+{
+  GHashTable *table_out = user_data;
+  SalutCapsChannelManager *manager = SALUT_CAPS_CHANNEL_MANAGER (key);
+  gpointer out;
+  salut_caps_channel_manager_copy_capabilities (manager, &out, value);
+  g_hash_table_insert (table_out, key, out);
+}
+
+void
+salut_presence_cache_copy_cache_entry (
+    GHashTable **out, GHashTable *in)
+{
+  *out = g_hash_table_new (NULL, NULL);
+  if (in != NULL)
+    g_hash_table_foreach (in, copy_caps_helper,
+        *out);
+}
+
+static void
+update_caps_helper (gpointer key, gpointer value, gpointer user_data)
+{
+  GHashTable *table_out = user_data;
+  SalutCapsChannelManager *manager = SALUT_CAPS_CHANNEL_MANAGER (key);
+  gpointer out;
+
+  out = g_hash_table_lookup (table_out, key);
+  if (out == NULL)
+    {
+      salut_caps_channel_manager_copy_capabilities (manager, &out, value);
+      g_hash_table_insert (table_out, key, out);
+    }
+  else
+    {
+      salut_caps_channel_manager_update_capabilities (manager, out, value);
+    }
+}
+
+void
+salut_presence_cache_update_cache_entry (
+    GHashTable *out, GHashTable *in)
+{
+  g_hash_table_foreach (in, update_caps_helper,
+      out);
+}
+
diff --git a/src/salut-presence-cache.h b/src/salut-presence-cache.h
new file mode 100644
index 0000000..40de8cc
--- /dev/null
+++ b/src/salut-presence-cache.h
@@ -0,0 +1,46 @@
+/*
+ * salut-presence-cache.h - Headers for Salut's contact presence cache
+ * Copyright (C) 2005-2008 Collabora Ltd.
+ * Copyright (C) 2005-2008 Nokia Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __SALUT_PRESENCE_CACHE_H__
+#define __SALUT_PRESENCE_CACHE_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+/* loop on CapabilityInfo::per_channel_manager_caps and call
+ * salut_caps_channel_manager_free_capabilities */
+void salut_presence_cache_free_cache_entry (
+    GHashTable *per_channel_manager_caps);
+
+/* loop on CapabilityInfo::per_channel_manager_caps and call
+ * salut_caps_channel_manager_copy_capabilities */
+void salut_presence_cache_copy_cache_entry (GHashTable **out,
+    GHashTable *in);
+
+/* loop on CapabilityInfo::per_channel_manager_caps and call
+ * salut_caps_channel_manager_update_capabilities */
+void salut_presence_cache_update_cache_entry (GHashTable *out,
+    GHashTable *in);
+
+G_END_DECLS
+
+#endif /* __SALUT_PRESENCE_CACHE_H__ */
+
-- 
1.5.6.5




More information about the telepathy-commits mailing list