[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