[Telepathy-commits] [telepathy-glib/master] Add TpChannelManager interface

Will Thompson will.thompson at collabora.co.uk
Thu Sep 4 04:32:34 PDT 2008


---
 telepathy-glib/Makefile.am          |    2 +
 telepathy-glib/channel-manager.c    |  418 +++++++++++++++++++++++++++++++++++
 telepathy-glib/channel-manager.h    |  129 +++++++++++
 telepathy-glib/signals-marshal.list |    2 +
 4 files changed, 551 insertions(+), 0 deletions(-)
 create mode 100644 telepathy-glib/channel-manager.c
 create mode 100644 telepathy-glib/channel-manager.h

diff --git a/telepathy-glib/Makefile.am b/telepathy-glib/Makefile.am
index df5639d..e2e60cb 100644
--- a/telepathy-glib/Makefile.am
+++ b/telepathy-glib/Makefile.am
@@ -101,6 +101,7 @@ tpginclude_HEADERS = \
     channel.h \
     channel-iface.h \
     channel-factory-iface.h \
+    channel-manager.h \
     media-interfaces.h \
     connection.h \
     connection-manager.h \
@@ -206,6 +207,7 @@ libtelepathy_glib_internal_la_SOURCES = \
     channel.c \
     channel-group.c \
     channel-internal.h \
+    channel-manager.c \
     connection.c \
     connection-manager.c \
     contacts-mixin.c \
diff --git a/telepathy-glib/channel-manager.c b/telepathy-glib/channel-manager.c
new file mode 100644
index 0000000..612aa90
--- /dev/null
+++ b/telepathy-glib/channel-manager.c
@@ -0,0 +1,418 @@
+/*
+ * channel-manager.c - factory and manager for channels relating to a
+ *  particular protocol feature
+ *
+ * Copyright (C) 2008 Collabora Ltd.
+ * Copyright (C) 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
+ */
+
+#include "config.h"
+#include "channel-manager.h"
+
+#include <telepathy-glib/dbus.h>
+#include <telepathy-glib/exportable-channel.h>
+
+#include "_gen/signals-marshal.h"
+
+enum {
+    S_NEW_CHANNELS,
+    S_REQUEST_ALREADY_SATISFIED,
+    S_REQUEST_FAILED,
+    S_CHANNEL_CLOSED,
+    N_SIGNALS
+};
+
+static guint signals[N_SIGNALS] = {0};
+
+
+static void
+channel_manager_base_init (gpointer klass)
+{
+  static gboolean initialized = FALSE;
+
+  if (!initialized)
+    {
+      initialized = TRUE;
+
+      /* FIXME: should probably have a better GType for @channels */
+      /**
+       * TpChannelManager::new-channels:
+       * @self: the channel manager
+       * @channels: a #GHashTable where the keys are
+       *  #TpExportableChannel instances (hashed and compared
+       *  by g_direct_hash() and g_direct_equal()) and the values are
+       *  linked lists (#GSList) of requests (opaque pointers) satisfied by
+       *  these channels
+       *
+       * Emitted when new channels have been created. The Connection should
+       * generally emit NewChannels (and NewChannel) in response to this
+       * signal, and then return from pending CreateChannel, EnsureChannel
+       * and/or RequestChannel calls if appropriate.
+       */
+      signals[S_NEW_CHANNELS] = g_signal_new ("new-channels",
+          G_OBJECT_CLASS_TYPE (klass),
+          G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+          0,
+          NULL, NULL,
+          g_cclosure_marshal_VOID__POINTER,
+          G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+      /**
+       * TpChannelManager::request-already-satisfied:
+       * @self: the channel manager
+       * @request_token: opaque pointer supplied by the requester,
+       *  representing a request
+       * @channel: the existing #TpExportableChannel that satisfies the
+       *  request
+       *
+       * Emitted when a channel request is satisfied by an existing channel.
+       * The Connection should generally respond to this signal by returning
+       * success from EnsureChannel or RequestChannel.
+       */
+      signals[S_REQUEST_ALREADY_SATISFIED] = g_signal_new (
+          "request-already-satisfied",
+          G_OBJECT_CLASS_TYPE (klass),
+          G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+          0,
+          NULL, NULL,
+          _tp_marshal_VOID__POINTER_OBJECT,
+          G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_OBJECT);
+
+      /**
+       * TpChannelManager::request-failed:
+       * @self: the channel manager
+       * @request_token: opaque pointer supplied by the requester,
+       *  representing a request
+       * @domain: the domain of a #GError indicating why the request
+       *  failed
+       * @code: the error code of a #GError indicating why the request
+       *  failed
+       * @message: the string part of a #GError indicating why the request
+       *  failed
+       *
+       * Emitted when a channel request has failed. The Connection should
+       * generally respond to this signal by returning failure from
+       * CreateChannel, EnsureChannel or RequestChannel.
+       */
+      signals[S_REQUEST_FAILED] = g_signal_new ("request-failed",
+          G_OBJECT_CLASS_TYPE (klass),
+          G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+          0,
+          NULL, NULL,
+          _tp_marshal_VOID__POINTER_UINT_INT_STRING,
+          G_TYPE_NONE, 4, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_INT,
+          G_TYPE_STRING);
+
+      /**
+       * TpChannelManager::channel-closed:
+       * @self: the channel manager
+       * @path: the channel's object-path
+       *
+       * Emitted when a channel has been closed. The Connection should
+       * generally respond to this signal by emitting ChannelClosed.
+       */
+      signals[S_CHANNEL_CLOSED] = g_signal_new ("channel-closed",
+          G_OBJECT_CLASS_TYPE (klass),
+          G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+          0,
+          NULL, NULL,
+          g_cclosure_marshal_VOID__STRING,
+          G_TYPE_NONE, 1, G_TYPE_STRING);
+
+    }
+}
+
+GType
+tp_channel_manager_get_type (void)
+{
+  static GType type = 0;
+
+  if (G_UNLIKELY (type == 0))
+    {
+      static const GTypeInfo info = {
+        sizeof (TpChannelManagerIface),
+        channel_manager_base_init,   /* base_init */
+        NULL,   /* base_finalize */
+        NULL,   /* class_init */
+        NULL,   /* class_finalize */
+        NULL,   /* class_data */
+        0,
+        0,      /* n_preallocs */
+        NULL    /* instance_init */
+      };
+
+      type = g_type_register_static (G_TYPE_INTERFACE,
+          "TpChannelManager", &info, 0);
+    }
+
+  return type;
+}
+
+
+/* Signal emission wrappers */
+
+
+/**
+ * tp_channel_manager_emit_new_channels:
+ * @instance: An object implementing #TpChannelManager
+ * @channels: a #GHashTable where the keys are
+ *  #TpExportableChannel instances (hashed and compared
+ *  by g_direct_hash() and g_direct_equal()) and the values are
+ *  linked lists (#GSList) of requests (opaque pointers) satisfied by
+ *  these channels
+ *
+ * If @channels is non-empty, emit the #TpChannelManager::new-channels
+ * signal indicating that those channels have been created.
+ */
+void
+tp_channel_manager_emit_new_channels (gpointer instance,
+                                      GHashTable *channels)
+{
+  g_return_if_fail (TP_IS_CHANNEL_MANAGER (instance));
+
+  if (g_hash_table_size (channels) == 0)
+    return;
+
+  g_signal_emit (instance, signals[S_NEW_CHANNELS], 0, channels);
+}
+
+
+/**
+ * tp_channel_manager_emit_new_channel:
+ * @instance: An object implementing #TpChannelManager
+ * @channel: A #TpExportableChannel
+ *
+ * Emit the #TpChannelManager::new-channels signal indicating that the
+ * channel has been created. (This is a convenient shortcut for calling
+ * tp_channel_manager_emit_new_channels() with a one-entry hash table.)
+ */
+void
+tp_channel_manager_emit_new_channel (gpointer instance,
+                                     TpExportableChannel *channel,
+                                     GSList *requests)
+{
+  GHashTable *channels;
+
+  g_return_if_fail (TP_IS_CHANNEL_MANAGER (instance));
+  g_return_if_fail (TP_IS_EXPORTABLE_CHANNEL (channel));
+
+  channels = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+      NULL, NULL);
+  g_hash_table_insert (channels, channel, requests);
+  g_signal_emit (instance, signals[S_NEW_CHANNELS], 0, channels);
+  g_hash_table_destroy (channels);
+}
+
+
+/**
+ * tp_channel_manager_emit_channel_closed:
+ * @instance: An object implementing #TpChannelManager
+ * @path: A channel's object-path
+ *
+ * Emit the #TpChannelManager::channel-closed signal indicating that
+ * the channel at the given object path has been closed.
+ */
+void
+tp_channel_manager_emit_channel_closed (gpointer instance,
+                                        const gchar *path)
+{
+  g_return_if_fail (TP_IS_CHANNEL_MANAGER (instance));
+  g_return_if_fail (tp_dbus_check_valid_object_path (path, NULL));
+
+  g_signal_emit (instance, signals[S_CHANNEL_CLOSED], 0, path);
+}
+
+
+/**
+ * tp_channel_manager_emit_channel_closed_for_object:
+ * @instance: An object implementing #TpChannelManager
+ * @channel: A #TpExportableChannel
+ *
+ * Emit the #TpChannelManager::channel-closed signal indicating that
+ * the given channel has been closed. (This is a convenient shortcut for
+ * calling tp_channel_manager_emit_channel_closed() with the
+ * #TpExportableChannel:object-path property of @channel.)
+ */
+void
+tp_channel_manager_emit_channel_closed_for_object (gpointer instance,
+    TpExportableChannel *channel)
+{
+  gchar *path;
+
+  g_return_if_fail (TP_IS_EXPORTABLE_CHANNEL (channel));
+  g_object_get (channel,
+      "object-path", &path,
+      NULL);
+  tp_channel_manager_emit_channel_closed (instance, path);
+  g_free (path);
+}
+
+
+/**
+ * tp_channel_manager_emit_request_already_satisfied:
+ * @instance: An object implementing #TpChannelManager
+ * @request_token: An opaque pointer representing the request that
+ *  succeeded
+ * @channel: The channel that satisfies the request
+ *
+ * Emit the #TpChannelManager::request-already-satisfied signal indicating
+ * that the pre-existing channel @channel satisfies @request_token.
+ */
+void
+tp_channel_manager_emit_request_already_satisfied (gpointer instance,
+    gpointer request_token,
+    TpExportableChannel *channel)
+{
+  g_return_if_fail (TP_IS_EXPORTABLE_CHANNEL (channel));
+  g_return_if_fail (TP_IS_CHANNEL_MANAGER (instance));
+
+  g_signal_emit (instance, signals[S_REQUEST_ALREADY_SATISFIED], 0,
+      request_token, channel);
+}
+
+
+/**
+ * tp_channel_manager_emit_request_failed:
+ * @instance: An object implementing #TpChannelManager
+ * @request_token: An opaque pointer representing the request that failed
+ * @domain: a #GError domain
+ * @code: a #GError code appropriate for @domain
+ * @message: the error message
+ *
+ * Emit the #TpChannelManager::request-failed signal indicating that
+ * the request @request_token failed for the given reason.
+ */
+void
+tp_channel_manager_emit_request_failed (gpointer instance,
+                                        gpointer request_token,
+                                        GQuark domain,
+                                        gint code,
+                                        const gchar *message)
+{
+  g_return_if_fail (TP_IS_CHANNEL_MANAGER (instance));
+
+  g_signal_emit (instance, signals[S_REQUEST_FAILED], 0, request_token,
+      domain, code, message);
+}
+
+
+/**
+ * tp_channel_manager_emit_request_failed_printf:
+ * @instance: An object implementing #TpChannelManager
+ * @request_token: An opaque pointer representing the request that failed
+ * @domain: a #GError domain
+ * @code: a #GError code appropriate for @domain
+ * @format: a printf-style format string for the error message
+ * @...: arguments for the format string
+ *
+ * Emit the #TpChannelManager::request-failed signal indicating that
+ * the request @request_token failed for the given reason.
+ */
+void
+tp_channel_manager_emit_request_failed_printf (gpointer instance,
+                                               gpointer request_token,
+                                               GQuark domain,
+                                               gint code,
+                                               const gchar *format,
+                                               ...)
+{
+  va_list ap;
+  gchar *message;
+
+  va_start (ap, format);
+  message = g_strdup_vprintf (format, ap);
+  va_end (ap);
+
+  tp_channel_manager_emit_request_failed (instance, request_token,
+      domain, code, message);
+
+  g_free (message);
+}
+
+
+/* Virtual-method wrappers */
+
+
+void
+tp_channel_manager_foreach_channel (TpChannelManager *manager,
+                                    TpExportableChannelFunc func,
+                                    gpointer user_data)
+{
+  TpChannelManagerIface *iface = TP_CHANNEL_MANAGER_GET_INTERFACE (
+      manager);
+  TpChannelManagerForeachChannelFunc method = iface->foreach_channel;
+
+  if (method != NULL)
+    {
+      method (manager, func, user_data);
+    }
+  /* ... else assume it has no channels, and do nothing */
+}
+
+
+void
+tp_channel_manager_foreach_channel_class (TpChannelManager *manager,
+    TpChannelManagerChannelClassFunc func,
+    gpointer user_data)
+{
+  TpChannelManagerIface *iface = TP_CHANNEL_MANAGER_GET_INTERFACE (
+      manager);
+  TpChannelManagerForeachChannelClassFunc method =
+      iface->foreach_channel_class;
+
+  if (method != NULL)
+    {
+      method (manager, func, user_data);
+    }
+  /* ... else assume it has no classes of requestable channel */
+}
+
+
+gboolean
+tp_channel_manager_create_channel (TpChannelManager *manager,
+                                   gpointer request_token,
+                                   GHashTable *request_properties)
+{
+  TpChannelManagerIface *iface = TP_CHANNEL_MANAGER_GET_INTERFACE (
+      manager);
+  TpChannelManagerRequestFunc method = iface->create_channel;
+
+  /* A missing implementation is equivalent to one that always returns FALSE,
+   * meaning "can't do that, ask someone else" */
+  if (method != NULL)
+    return method (manager, request_token, request_properties);
+  else
+    return FALSE;
+}
+
+
+gboolean
+tp_channel_manager_request_channel (TpChannelManager *manager,
+                                    gpointer request_token,
+                                    GHashTable *request_properties)
+{
+  TpChannelManagerIface *iface = TP_CHANNEL_MANAGER_GET_INTERFACE (
+      manager);
+  TpChannelManagerRequestFunc method = iface->request_channel;
+
+  /* A missing implementation is equivalent to one that always returns FALSE,
+   * meaning "can't do that, ask someone else" */
+  if (method != NULL)
+    return method (manager, request_token, request_properties);
+  else
+    return FALSE;
+}
diff --git a/telepathy-glib/channel-manager.h b/telepathy-glib/channel-manager.h
new file mode 100644
index 0000000..b4399c7
--- /dev/null
+++ b/telepathy-glib/channel-manager.h
@@ -0,0 +1,129 @@
+/*
+ * channel-manager.h - factory and manager for channels relating to a
+ *  particular protocol feature
+ *
+ * Copyright (C) 2008 Collabora Ltd.
+ * Copyright (C) 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 TP_CHANNEL_MANAGER_H
+#define TP_CHANNEL_MANAGER_H
+
+#include <glib-object.h>
+
+#include <telepathy-glib/exportable-channel.h>
+
+G_BEGIN_DECLS
+
+#define TP_TYPE_CHANNEL_MANAGER (tp_channel_manager_get_type ())
+
+#define TP_CHANNEL_MANAGER(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+  TP_TYPE_CHANNEL_MANAGER, TpChannelManager))
+
+#define TP_IS_CHANNEL_MANAGER(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+  TP_TYPE_CHANNEL_MANAGER))
+
+#define TP_CHANNEL_MANAGER_GET_INTERFACE(obj) \
+  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), \
+  TP_TYPE_CHANNEL_MANAGER, TpChannelManagerIface))
+
+typedef struct _TpChannelManager TpChannelManager;
+typedef struct _TpChannelManagerIface TpChannelManagerIface;
+
+
+/* virtual methods */
+
+typedef void (*TpChannelManagerForeachChannelFunc) (
+    TpChannelManager *manager, TpExportableChannelFunc func,
+    gpointer user_data);
+
+void tp_channel_manager_foreach_channel (TpChannelManager *manager,
+    TpExportableChannelFunc func, gpointer user_data);
+
+
+typedef void (*TpChannelManagerChannelClassFunc) (
+    TpChannelManager *manager,
+    GHashTable *fixed_properties,
+    const gchar * const *allowed_properties,
+    gpointer user_data);
+
+typedef void (*TpChannelManagerForeachChannelClassFunc) (
+    TpChannelManager *manager, TpChannelManagerChannelClassFunc func,
+    gpointer user_data);
+
+void tp_channel_manager_foreach_channel_class (
+    TpChannelManager *manager,
+    TpChannelManagerChannelClassFunc func, gpointer user_data);
+
+
+typedef gboolean (*TpChannelManagerRequestFunc) (
+    TpChannelManager *manager, gpointer request_token,
+    GHashTable *request_properties);
+
+gboolean tp_channel_manager_create_channel (TpChannelManager *manager,
+    gpointer request_token, GHashTable *request_properties);
+
+gboolean tp_channel_manager_request_channel (TpChannelManager *manager,
+    gpointer request_token, GHashTable *request_properties);
+
+
+struct _TpChannelManagerIface {
+    GTypeInterface parent;
+
+    TpChannelManagerForeachChannelFunc foreach_channel;
+
+    TpChannelManagerForeachChannelClassFunc foreach_channel_class;
+
+    TpChannelManagerRequestFunc create_channel;
+    TpChannelManagerRequestFunc request_channel;
+    /* in principle we could have EnsureChannel here too */
+
+    GCallback _future[8];
+    gpointer priv;
+};
+
+
+GType tp_channel_manager_get_type (void);
+
+
+/* signal emission */
+
+void tp_channel_manager_emit_new_channel (gpointer instance,
+    TpExportableChannel *channel, GSList *requests);
+void tp_channel_manager_emit_new_channels (gpointer instance,
+    GHashTable *channels);
+
+void tp_channel_manager_emit_channel_closed (gpointer instance,
+    const gchar *path);
+void tp_channel_manager_emit_channel_closed_for_object (gpointer instance,
+    TpExportableChannel *channel);
+
+void tp_channel_manager_emit_request_already_satisfied (
+    gpointer instance, gpointer request_token,
+    TpExportableChannel *channel);
+
+void tp_channel_manager_emit_request_failed (gpointer instance,
+    gpointer request_token, GQuark domain, gint code, const gchar *message);
+void tp_channel_manager_emit_request_failed_printf (gpointer instance,
+    gpointer request_token, GQuark domain, gint code, const gchar *format,
+    ...) G_GNUC_PRINTF (5, 6);
+
+G_END_DECLS
+
+#endif
diff --git a/telepathy-glib/signals-marshal.list b/telepathy-glib/signals-marshal.list
index d6ef2c2..acfa347 100644
--- a/telepathy-glib/signals-marshal.list
+++ b/telepathy-glib/signals-marshal.list
@@ -3,3 +3,5 @@ VOID:OBJECT,POINTER,POINTER
 VOID:STRING,UINT,UINT,BOXED
 VOID:UINT,INT,STRING
 VOID:UINT,OBJECT
+VOID:POINTER,OBJECT
+VOID:POINTER,UINT,INT,STRING
-- 
1.5.6.5




More information about the Telepathy-commits mailing list