[Telepathy-commits] [telepathy-salut/master] Copy SalutChannelManager and SalutExportableChannel from Gabble.

Will Thompson will.thompson at collabora.co.uk
Thu Oct 23 07:30:32 PDT 2008


---
 src/Makefile.am          |    4 +
 src/channel-manager.c    |  418 ++++++++++++++++++++++++++++++++++++++++++++++
 src/channel-manager.h    |  130 ++++++++++++++
 src/exportable-channel.c |  150 +++++++++++++++++
 src/exportable-channel.h |   61 +++++++
 5 files changed, 763 insertions(+), 0 deletions(-)
 create mode 100644 src/channel-manager.c
 create mode 100644 src/channel-manager.h
 create mode 100644 src/exportable-channel.c
 create mode 100644 src/exportable-channel.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 2eb24b6..3dd06e3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -15,6 +15,10 @@ libexec_PROGRAMS=telepathy-salut
 noinst_PROGRAMS = write-mgr-file
 
 CORE_SOURCES =                                          \
+    channel-manager.c                                   \
+    channel-manager.h                                   \
+    exportable-channel.c                                \
+    exportable-channel.h                                \
     salut-connection-manager.c                          \
     salut-connection-manager.h                          \
     salut-contact-manager.c                             \
diff --git a/src/channel-manager.c b/src/channel-manager.c
new file mode 100644
index 0000000..dfe18e6
--- /dev/null
+++ b/src/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 "exportable-channel.h"
+#include "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 */
+      /**
+       * SalutChannelManager::new-channels:
+       * @self: the channel manager
+       * @channels: a #GHashTable where the keys are
+       *  #SalutExportableChannel 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);
+
+      /**
+       * SalutChannelManager::request-already-satisfied:
+       * @self: the channel manager
+       * @request_token: opaque pointer supplied by the requester,
+       *  representing a request
+       * @channel: the existing #SalutExportableChannel 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,
+          salut_signals_marshal_VOID__POINTER_OBJECT,
+          G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_OBJECT);
+
+      /**
+       * SalutChannelManager::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,
+          salut_signals_marshal_VOID__POINTER_UINT_INT_STRING,
+          G_TYPE_NONE, 4, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_INT,
+          G_TYPE_STRING);
+
+      /**
+       * SalutChannelManager::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
+salut_channel_manager_get_type (void)
+{
+  static GType type = 0;
+
+  if (G_UNLIKELY (type == 0))
+    {
+      static const GTypeInfo info = {
+        sizeof (SalutChannelManagerIface),
+        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,
+          "SalutChannelManager", &info, 0);
+    }
+
+  return type;
+}
+
+
+/* Signal emission wrappers */
+
+
+/**
+ * salut_channel_manager_emit_new_channels:
+ * @instance: An object implementing #SalutChannelManager
+ * @channels: a #GHashTable where the keys are
+ *  #SalutExportableChannel 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 #SalutChannelManager::new-channels
+ * signal indicating that those channels have been created.
+ */
+void
+salut_channel_manager_emit_new_channels (gpointer instance,
+                                         GHashTable *channels)
+{
+  g_return_if_fail (SALUT_IS_CHANNEL_MANAGER (instance));
+
+  if (g_hash_table_size (channels) == 0)
+    return;
+
+  g_signal_emit (instance, signals[S_NEW_CHANNELS], 0, channels);
+}
+
+
+/**
+ * salut_channel_manager_emit_new_channel:
+ * @instance: An object implementing #SalutChannelManager
+ * @channel: A #SalutExportableChannel
+ *
+ * Emit the #SalutChannelManager::new-channels signal indicating that the
+ * channel has been created. (This is a convenient shortcut for calling
+ * salut_channel_manager_emit_new_channels() with a one-entry hash table.)
+ */
+void
+salut_channel_manager_emit_new_channel (gpointer instance,
+                                        SalutExportableChannel *channel,
+                                        GSList *requests)
+{
+  GHashTable *channels;
+
+  g_return_if_fail (SALUT_IS_CHANNEL_MANAGER (instance));
+  g_return_if_fail (SALUT_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);
+}
+
+
+/**
+ * salut_channel_manager_emit_channel_closed:
+ * @instance: An object implementing #SalutChannelManager
+ * @path: A channel's object-path
+ *
+ * Emit the #SalutChannelManager::channel-closed signal indicating that
+ * the channel at the given object path has been closed.
+ */
+void
+salut_channel_manager_emit_channel_closed (gpointer instance,
+                                           const gchar *path)
+{
+  g_return_if_fail (SALUT_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);
+}
+
+
+/**
+ * salut_channel_manager_emit_channel_closed_for_object:
+ * @instance: An object implementing #SalutChannelManager
+ * @channel: A #SalutExportableChannel
+ *
+ * Emit the #SalutChannelManager::channel-closed signal indicating that
+ * the given channel has been closed. (This is a convenient shortcut for
+ * calling salut_channel_manager_emit_channel_closed() with the
+ * #SalutExportableChannel:object-path property of @channel.)
+ */
+void
+salut_channel_manager_emit_channel_closed_for_object (gpointer instance,
+    SalutExportableChannel *channel)
+{
+  gchar *path;
+
+  g_return_if_fail (SALUT_IS_EXPORTABLE_CHANNEL (channel));
+  g_object_get (channel,
+      "object-path", &path,
+      NULL);
+  salut_channel_manager_emit_channel_closed (instance, path);
+  g_free (path);
+}
+
+
+/**
+ * salut_channel_manager_emit_request_already_satisfied:
+ * @instance: An object implementing #SalutChannelManager
+ * @request_token: An opaque pointer representing the request that
+ *  succeeded
+ * @channel: The channel that satisfies the request
+ *
+ * Emit the #SalutChannelManager::request-already-satisfied signal indicating
+ * that the pre-existing channel @channel satisfies @request_token.
+ */
+void
+salut_channel_manager_emit_request_already_satisfied (gpointer instance,
+    gpointer request_token,
+    SalutExportableChannel *channel)
+{
+  g_return_if_fail (SALUT_IS_EXPORTABLE_CHANNEL (channel));
+  g_return_if_fail (SALUT_IS_CHANNEL_MANAGER (instance));
+
+  g_signal_emit (instance, signals[S_REQUEST_ALREADY_SATISFIED], 0,
+      request_token, channel);
+}
+
+
+/**
+ * salut_channel_manager_emit_request_failed:
+ * @instance: An object implementing #SalutChannelManager
+ * @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 #SalutChannelManager::request-failed signal indicating that
+ * the request @request_token failed for the given reason.
+ */
+void
+salut_channel_manager_emit_request_failed (gpointer instance,
+                                           gpointer request_token,
+                                           GQuark domain,
+                                           gint code,
+                                           const gchar *message)
+{
+  g_return_if_fail (SALUT_IS_CHANNEL_MANAGER (instance));
+
+  g_signal_emit (instance, signals[S_REQUEST_FAILED], 0, request_token,
+      domain, code, message);
+}
+
+
+/**
+ * salut_channel_manager_emit_request_failed_printf:
+ * @instance: An object implementing #SalutChannelManager
+ * @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 #SalutChannelManager::request-failed signal indicating that
+ * the request @request_token failed for the given reason.
+ */
+void
+salut_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);
+
+  salut_channel_manager_emit_request_failed (instance, request_token,
+      domain, code, message);
+
+  g_free (message);
+}
+
+
+/* Virtual-method wrappers */
+
+
+void
+salut_channel_manager_foreach_channel (SalutChannelManager *manager,
+                                       SalutExportableChannelFunc func,
+                                       gpointer user_data)
+{
+  SalutChannelManagerIface *iface = SALUT_CHANNEL_MANAGER_GET_INTERFACE (
+      manager);
+  SalutChannelManagerForeachChannelFunc method = iface->foreach_channel;
+
+  if (method != NULL)
+    {
+      method (manager, func, user_data);
+    }
+  /* ... else assume it has no channels, and do nothing */
+}
+
+
+void
+salut_channel_manager_foreach_channel_class (SalutChannelManager *manager,
+    SalutChannelManagerChannelClassFunc func,
+    gpointer user_data)
+{
+  SalutChannelManagerIface *iface = SALUT_CHANNEL_MANAGER_GET_INTERFACE (
+      manager);
+  SalutChannelManagerForeachChannelClassFunc method =
+      iface->foreach_channel_class;
+
+  if (method != NULL)
+    {
+      method (manager, func, user_data);
+    }
+  /* ... else assume it has no classes of requestable channel */
+}
+
+
+gboolean
+salut_channel_manager_create_channel (SalutChannelManager *manager,
+                                      gpointer request_token,
+                                      GHashTable *request_properties)
+{
+  SalutChannelManagerIface *iface = SALUT_CHANNEL_MANAGER_GET_INTERFACE (
+      manager);
+  SalutChannelManagerRequestFunc 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
+salut_channel_manager_request_channel (SalutChannelManager *manager,
+                                       gpointer request_token,
+                                       GHashTable *request_properties)
+{
+  SalutChannelManagerIface *iface = SALUT_CHANNEL_MANAGER_GET_INTERFACE (
+      manager);
+  SalutChannelManagerRequestFunc 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/src/channel-manager.h b/src/channel-manager.h
new file mode 100644
index 0000000..6b61a6b
--- /dev/null
+++ b/src/channel-manager.h
@@ -0,0 +1,130 @@
+/*
+ * 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 SALUT_CHANNEL_MANAGER_H
+#define SALUT_CHANNEL_MANAGER_H
+
+#include <glib-object.h>
+
+#include "exportable-channel.h"
+
+G_BEGIN_DECLS
+
+#define SALUT_TYPE_CHANNEL_MANAGER (salut_channel_manager_get_type ())
+
+#define SALUT_CHANNEL_MANAGER(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+  SALUT_TYPE_CHANNEL_MANAGER, SalutChannelManager))
+
+#define SALUT_IS_CHANNEL_MANAGER(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+  SALUT_TYPE_CHANNEL_MANAGER))
+
+#define SALUT_CHANNEL_MANAGER_GET_INTERFACE(obj) \
+  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), \
+  SALUT_TYPE_CHANNEL_MANAGER, SalutChannelManagerIface))
+
+typedef struct _SalutChannelManager SalutChannelManager;
+typedef struct _SalutChannelManagerIface SalutChannelManagerIface;
+
+
+/* virtual methods */
+
+typedef void (*SalutChannelManagerForeachChannelFunc) (
+    SalutChannelManager *manager, SalutExportableChannelFunc func,
+    gpointer user_data);
+
+void salut_channel_manager_foreach_channel (SalutChannelManager *manager,
+    SalutExportableChannelFunc func, gpointer user_data);
+
+
+typedef void (*SalutChannelManagerChannelClassFunc) (
+    SalutChannelManager *manager,
+    GHashTable *fixed_properties,
+    const gchar * const *required_properties,
+    const gchar * const *optional_properties,
+    gpointer user_data);
+
+typedef void (*SalutChannelManagerForeachChannelClassFunc) (
+    SalutChannelManager *manager, SalutChannelManagerChannelClassFunc func,
+    gpointer user_data);
+
+void salut_channel_manager_foreach_channel_class (
+    SalutChannelManager *manager,
+    SalutChannelManagerChannelClassFunc func, gpointer user_data);
+
+
+typedef gboolean (*SalutChannelManagerRequestFunc) (
+    SalutChannelManager *manager, gpointer request_token,
+    GHashTable *request_properties);
+
+gboolean salut_channel_manager_create_channel (SalutChannelManager *manager,
+    gpointer request_token, GHashTable *request_properties);
+
+gboolean salut_channel_manager_request_channel (SalutChannelManager *manager,
+    gpointer request_token, GHashTable *request_properties);
+
+
+struct _SalutChannelManagerIface {
+    GTypeInterface parent;
+
+    SalutChannelManagerForeachChannelFunc foreach_channel;
+
+    SalutChannelManagerForeachChannelClassFunc foreach_channel_class;
+
+    SalutChannelManagerRequestFunc create_channel;
+    SalutChannelManagerRequestFunc request_channel;
+    /* in principle we could have EnsureChannel here too */
+
+    GCallback _future[8];
+    gpointer priv;
+};
+
+
+GType salut_channel_manager_get_type (void);
+
+
+/* signal emission */
+
+void salut_channel_manager_emit_new_channel (gpointer instance,
+    SalutExportableChannel *channel, GSList *requests);
+void salut_channel_manager_emit_new_channels (gpointer instance,
+    GHashTable *channels);
+
+void salut_channel_manager_emit_channel_closed (gpointer instance,
+    const gchar *path);
+void salut_channel_manager_emit_channel_closed_for_object (gpointer instance,
+    SalutExportableChannel *channel);
+
+void salut_channel_manager_emit_request_already_satisfied (
+    gpointer instance, gpointer request_token,
+    SalutExportableChannel *channel);
+
+void salut_channel_manager_emit_request_failed (gpointer instance,
+    gpointer request_token, GQuark domain, gint code, const gchar *message);
+void salut_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/src/exportable-channel.c b/src/exportable-channel.c
new file mode 100644
index 0000000..e4e812c
--- /dev/null
+++ b/src/exportable-channel.c
@@ -0,0 +1,150 @@
+/*
+ * exportable-channel.c - A channel usable with the Channel Manager
+ *
+ * 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 "exportable-channel.h"
+
+#include <telepathy-glib/gtypes.h>
+#include <telepathy-glib/svc-channel.h>
+#include <telepathy-glib/util.h>
+
+
+static void
+exportable_channel_base_init (gpointer klass)
+{
+  static gboolean initialized = FALSE;
+
+  if (!initialized)
+    {
+      GParamSpec *param_spec;
+
+      initialized = TRUE;
+
+      /**
+       * SalutExportableChannel:object-path:
+       *
+       * The D-Bus object path used for this object on the bus. Read-only
+       * except during construction.
+       */
+      param_spec = g_param_spec_string ("object-path", "D-Bus object path",
+          "The D-Bus object path used for this object on the bus.", NULL,
+          G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE |
+          G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK);
+      g_object_interface_install_property (klass, param_spec);
+
+      /**
+       * SalutExportableChannel:channel-properties:
+       *
+       * The D-Bus properties to be announced in the NewChannels signal
+       * and in the Channels property, as a map from
+       * inter.face.name.propertyname to GValue.
+       *
+       * This can only change when the closed signal is emitted.
+       */
+      param_spec = g_param_spec_boxed ("channel-properties",
+          "Channel properties",
+          "The channel properties",
+          TP_HASH_TYPE_QUALIFIED_PROPERTY_VALUE_MAP,
+          G_PARAM_READABLE |
+          G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK);
+      g_object_interface_install_property (klass, param_spec);
+
+      /**
+       * SalutExportableChannel:channel-destroyed:
+       *
+       * If true, the closed signal on the Channel interface indicates that
+       * the channel can go away.
+       *
+       * If false, the closed signal indicates that the channel should
+       * appear to go away and be re-created.
+       */
+      param_spec = g_param_spec_boolean ("channel-destroyed",
+          "Destroyed?",
+          "If true, the channel has *really* closed, rather than just "
+          "appearing to do so",
+          FALSE,
+          G_PARAM_READABLE |
+          G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK);
+      g_object_interface_install_property (klass, param_spec);
+    }
+}
+
+GType
+salut_exportable_channel_get_type (void)
+{
+  static GType type = 0;
+
+  if (G_UNLIKELY (type == 0))
+    {
+      static const GTypeInfo info = {
+        sizeof (SalutExportableChannelIface),
+        exportable_channel_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,
+          "SalutExportableChannel", &info, 0);
+
+      g_type_interface_add_prerequisite (type, TP_TYPE_SVC_CHANNEL);
+    }
+
+  return type;
+}
+
+GHashTable *
+salut_tp_dbus_properties_mixin_make_properties_hash (
+    GObject *object,
+    const gchar *first_interface,
+    const gchar *first_property,
+    ...)
+{
+  va_list ap;
+  GHashTable *table;
+  const gchar *interface, *property;
+
+  table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
+      (GDestroyNotify) tp_g_value_slice_free);
+
+  va_start (ap, first_property);
+
+  for (interface = first_interface, property = first_property;
+       interface != NULL;
+       interface = va_arg (ap, gchar *), property = va_arg (ap, gchar *))
+    {
+      GValue *value = g_slice_new0 (GValue);
+
+      tp_dbus_properties_mixin_get (object, interface, property,
+            value, NULL);
+      /* Fetching our immutable properties had better not fail... */
+      g_assert (G_IS_VALUE (value));
+
+      g_hash_table_insert (table,
+          g_strdup_printf ("%s.%s", interface, property), value);
+    }
+
+  return table;
+}
diff --git a/src/exportable-channel.h b/src/exportable-channel.h
new file mode 100644
index 0000000..d4f0325
--- /dev/null
+++ b/src/exportable-channel.h
@@ -0,0 +1,61 @@
+/*
+ * exportable-channel.h - A channel usable with the Channel Manager
+ *
+ * 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 SALUT_EXPORTABLE_CHANNEL_H
+#define SALUT_EXPORTABLE_CHANNEL_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define SALUT_TYPE_EXPORTABLE_CHANNEL (salut_exportable_channel_get_type ())
+
+#define SALUT_EXPORTABLE_CHANNEL(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+  SALUT_TYPE_EXPORTABLE_CHANNEL, SalutExportableChannel))
+
+#define SALUT_IS_EXPORTABLE_CHANNEL(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+  SALUT_TYPE_EXPORTABLE_CHANNEL))
+
+#define SALUT_EXPORTABLE_CHANNEL_GET_INTERFACE(obj) \
+  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), \
+  SALUT_TYPE_EXPORTABLE_CHANNEL, SalutExportableChannelIface))
+
+typedef struct _SalutExportableChannel SalutExportableChannel;
+typedef struct _SalutExportableChannelIface SalutExportableChannelIface;
+
+typedef void (*SalutExportableChannelFunc) (SalutExportableChannel *channel,
+    gpointer user_data);
+
+struct _SalutExportableChannelIface {
+    GTypeInterface parent;
+};
+
+GType salut_exportable_channel_get_type (void);
+
+GHashTable *salut_tp_dbus_properties_mixin_make_properties_hash (
+    GObject *object, const gchar *first_interface,
+    const gchar *first_property, ...) G_GNUC_NULL_TERMINATED;
+
+G_END_DECLS
+
+#endif
-- 
1.5.6.5




More information about the Telepathy-commits mailing list