[telepathy-idle/master] Initial transition from IdleIMFactory to IdleIMManager
Jonathon Jongsma
jjongsma at gnome.org
Thu Sep 10 16:07:38 PDT 2009
using new TpChannelManager interface instead of old TpChannelFactory interface
---
src/Makefile.am | 8 +-
src/idle-connection.c | 27 +-
src/idle-im-factory.c | 260 --------------
src/idle-im-manager.c | 489 ++++++++++++++++++++++++++
src/{idle-im-factory.h => idle-im-manager.h} | 28 +-
5 files changed, 521 insertions(+), 291 deletions(-)
delete mode 100644 src/idle-im-factory.c
create mode 100644 src/idle-im-manager.c
rename src/{idle-im-factory.h => idle-im-manager.h} (51%)
diff --git a/src/Makefile.am b/src/Makefile.am
index 6b979f8..0795300 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -22,12 +22,12 @@ libidle_convenience_la_SOURCES = \
idle-handles.h \
idle-im-channel.c \
idle-im-channel.h \
- idle-im-factory.c \
- idle-im-factory.h \
+ idle-im-manager.c \
+ idle-im-manager.h \
idle-muc-channel.c \
idle-muc-channel.h \
- idle-muc-factory.c \
- idle-muc-factory.h \
+ idle-muc-manager.c \
+ idle-muc-manager.h \
idle-parser.c \
idle-parser.h \
idle-server-connection.c \
diff --git a/src/idle-connection.c b/src/idle-connection.c
index 6c2d645..1664c91 100644
--- a/src/idle-connection.c
+++ b/src/idle-connection.c
@@ -34,14 +34,14 @@
#include <telepathy-glib/errors.h>
#include <telepathy-glib/interfaces.h>
#include <telepathy-glib/svc-connection.h>
-#include <telepathy-glib/channel-factory-iface.h>
+#include <telepathy-glib/channel-manager.h>
#define IDLE_DEBUG_FLAG IDLE_DEBUG_CONNECTION
#include "idle-ctcp.h"
#include "idle-debug.h"
#include "idle-handles.h"
-#include "idle-im-factory.h"
-#include "idle-muc-factory.h"
+#include "idle-im-manager.h"
+#include "idle-muc-manager.h"
#include "idle-parser.h"
#include "idle-server-connection.h"
#include "idle-server-connection-iface.h"
@@ -164,7 +164,7 @@ struct _IdleConnectionPrivate {
#define IDLE_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), IDLE_TYPE_CONNECTION, IdleConnectionPrivate))
static void _iface_create_handle_repos(TpBaseConnection *self, TpHandleRepoIface **repos);
-static GPtrArray *_iface_create_channel_factories(TpBaseConnection *self);
+static GPtrArray *_iface_create_channel_managers(TpBaseConnection *self);
static gchar *_iface_get_unique_connection_name(TpBaseConnection *self);
static void _iface_disconnected(TpBaseConnection *self);
static void _iface_shut_down(TpBaseConnection *self);
@@ -359,7 +359,8 @@ static void idle_connection_class_init(IdleConnectionClass *klass) {
parent_class->create_handle_repos = _iface_create_handle_repos;
parent_class->get_unique_connection_name = _iface_get_unique_connection_name;
- parent_class->create_channel_factories = _iface_create_channel_factories;
+ parent_class->create_channel_factories = NULL;
+ parent_class->create_channel_managers = _iface_create_channel_managers;
parent_class->connecting = NULL;
parent_class->connected = NULL;
parent_class->disconnected = _iface_disconnected;
@@ -392,17 +393,17 @@ static void idle_connection_class_init(IdleConnectionClass *klass) {
g_object_class_install_property(object_class, PROP_USE_SSL, param_spec);
}
-static GPtrArray *_iface_create_channel_factories(TpBaseConnection *self) {
- GPtrArray *factories = g_ptr_array_sized_new(1);
- GObject *factory;
+static GPtrArray *_iface_create_channel_managers(TpBaseConnection *self) {
+ GPtrArray *managers = g_ptr_array_sized_new(1);
+ GObject *manager;
- factory = g_object_new(IDLE_TYPE_IM_FACTORY, "connection", self, NULL);
- g_ptr_array_add(factories, factory);
+ manager = g_object_new(IDLE_TYPE_IM_MANAGER, "connection", self, NULL);
+ g_ptr_array_add(managers, manager);
- factory = g_object_new(IDLE_TYPE_MUC_FACTORY, "connection", self, NULL);
- g_ptr_array_add(factories, factory);
+ manager = g_object_new(IDLE_TYPE_MUC_MANAGER, "connection", self, NULL);
+ g_ptr_array_add(managers, manager);
- return factories;
+ return managers;
}
static void _iface_create_handle_repos(TpBaseConnection *self, TpHandleRepoIface **repos) {
diff --git a/src/idle-im-factory.c b/src/idle-im-factory.c
deleted file mode 100644
index 972c8e3..0000000
--- a/src/idle-im-factory.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * This file is part of telepathy-idle
- *
- * Copyright (C) 2006-2007 Collabora Limited
- * Copyright (C) 2006-2007 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
- * version 2.1 as published by the Free Software Foundation.
- *
- * 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 "idle-im-factory.h"
-
-#include <telepathy-glib/channel-factory-iface.h>
-#include <telepathy-glib/interfaces.h>
-
-#define IDLE_DEBUG_FLAG IDLE_DEBUG_IM
-#include "idle-connection.h"
-#include "idle-ctcp.h"
-#include "idle-debug.h"
-#include "idle-im-channel.h"
-#include "idle-parser.h"
-#include "idle-text.h"
-
-static void _factory_iface_init(gpointer g_iface, gpointer iface_data);
-
-G_DEFINE_TYPE_WITH_CODE(IdleIMFactory, idle_im_factory, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE(TP_TYPE_CHANNEL_FACTORY_IFACE, _factory_iface_init));
-
-/* properties */
-enum {
- PROP_CONNECTION = 1,
- LAST_PROPERTY_ENUM
-};
-
-typedef struct _IdleIMFactoryPrivate IdleIMFactoryPrivate;
-struct _IdleIMFactoryPrivate {
- IdleConnection *conn;
- GHashTable *channels;
-
- gboolean dispose_has_run;
-};
-
-#define IDLE_IM_FACTORY_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), IDLE_TYPE_IM_FACTORY, IdleIMFactoryPrivate))
-
-static IdleParserHandlerResult _notice_privmsg_handler(IdleParser *parser, IdleParserMessageCode code, GValueArray *args, gpointer user_data);
-
-static void _iface_close_all(TpChannelFactoryIface *iface);
-static void _iface_connecting(TpChannelFactoryIface *iface);
-static void _iface_disconnected(TpChannelFactoryIface *iface);
-static void _iface_foreach(TpChannelFactoryIface *iface, TpChannelFunc func, gpointer user_data);
-static TpChannelFactoryRequestStatus _iface_request(TpChannelFactoryIface *iface, const gchar *chan_type, TpHandleType handle_type, guint handle, gpointer request, TpChannelIface **new_chan, GError **error);
-
-static IdleIMChannel *_create_channel(IdleIMFactory *factory, TpHandle handle, gpointer context);
-static void _channel_closed_cb(IdleIMChannel *chan, gpointer user_data);
-
-static void idle_im_factory_init(IdleIMFactory *obj) {
- IdleIMFactoryPrivate *priv = IDLE_IM_FACTORY_GET_PRIVATE(obj);
-
- priv->channels = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref);
-}
-
-static void idle_im_factory_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) {
- IdleIMFactory *fac = IDLE_IM_FACTORY(object);
- IdleIMFactoryPrivate *priv = IDLE_IM_FACTORY_GET_PRIVATE(fac);
-
- switch (property_id) {
- case PROP_CONNECTION:
- g_value_set_object(value, priv->conn);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
- break;
- }
-}
-
-static void idle_im_factory_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) {
- IdleIMFactory *fac = IDLE_IM_FACTORY(object);
- IdleIMFactoryPrivate *priv = IDLE_IM_FACTORY_GET_PRIVATE(fac);
-
- switch (property_id) {
- case PROP_CONNECTION:
- priv->conn = g_value_get_object(value);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
- break;
- }
-}
-
-static void idle_im_factory_class_init(IdleIMFactoryClass *klass) {
- GObjectClass *object_class = G_OBJECT_CLASS(klass);
- GParamSpec *param_spec;
-
- g_type_class_add_private(klass, sizeof(IdleIMFactoryPrivate));
-
- object_class->get_property = idle_im_factory_get_property;
- object_class->set_property = idle_im_factory_set_property;
-
- param_spec = g_param_spec_object("connection", "IdleConnection object", "The IdleConnection object that owns this IM channel factory object.", IDLE_TYPE_CONNECTION, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB);
- g_object_class_install_property(object_class, PROP_CONNECTION, param_spec);
-}
-
-static IdleParserHandlerResult _notice_privmsg_handler(IdleParser *parser, IdleParserMessageCode code, GValueArray *args, gpointer user_data) {
- IdleIMFactory *factory = IDLE_IM_FACTORY(user_data);
- IdleIMFactoryPrivate *priv = IDLE_IM_FACTORY_GET_PRIVATE(factory);
- TpHandle handle = (TpHandle) g_value_get_uint(g_value_array_get_nth(args, 0));
- IdleIMChannel *chan;
- TpChannelTextMessageType type;
- gchar *body;
-
- if (code == IDLE_PARSER_PREFIXCMD_NOTICE_USER) {
- type = TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE;
- body = idle_ctcp_kill_blingbling(g_value_get_string(g_value_array_get_nth(args, 2)));
- } else {
- gboolean decoded = idle_text_decode(g_value_get_string(g_value_array_get_nth(args, 2)), &type, &body);
- if (!decoded)
- return IDLE_PARSER_HANDLER_RESULT_NOT_HANDLED;
- }
-
- idle_connection_emit_queued_aliases_changed(priv->conn);
-
- if (!priv->channels) {
- IDLE_DEBUG("Channels hash table missing, ignoring...");
- return IDLE_PARSER_HANDLER_RESULT_NOT_HANDLED;
- }
-
- if (!(chan = g_hash_table_lookup(priv->channels, GUINT_TO_POINTER(handle))))
- chan = _create_channel(factory, handle, NULL);
-
- idle_im_channel_receive(chan, type, handle, body);
-
- g_free(body);
-
- return IDLE_PARSER_HANDLER_RESULT_HANDLED;
-}
-
-static void _iface_close_all(TpChannelFactoryIface *iface) {
- IdleIMFactoryPrivate *priv = IDLE_IM_FACTORY_GET_PRIVATE(iface);
-
- if (!priv->channels) {
- IDLE_DEBUG("Channels already closed, ignoring...");
- return;
- }
-
- GHashTable *tmp = priv->channels;
- priv->channels = NULL;
- g_hash_table_destroy(tmp);
-}
-
-static void _iface_connecting(TpChannelFactoryIface *iface) {
- IdleIMFactoryPrivate *priv = IDLE_IM_FACTORY_GET_PRIVATE(iface);
-
- idle_parser_add_handler(priv->conn->parser, IDLE_PARSER_PREFIXCMD_NOTICE_USER, _notice_privmsg_handler, iface);
- idle_parser_add_handler(priv->conn->parser, IDLE_PARSER_PREFIXCMD_PRIVMSG_USER, _notice_privmsg_handler, iface);
-}
-
-static void _iface_disconnected(TpChannelFactoryIface *iface) {
- IdleIMFactoryPrivate *priv = IDLE_IM_FACTORY_GET_PRIVATE(iface);
-
- idle_parser_remove_handlers_by_data(priv->conn->parser, iface);
-}
-
-struct _ForeachHelperData {
- TpChannelFunc func;
- gpointer user_data;
-};
-
-static void _foreach_helper(gpointer key, gpointer value, gpointer user_data) {
- struct _ForeachHelperData *data = user_data;
- data->func(value, data->user_data);
-}
-
-static void _iface_foreach(TpChannelFactoryIface *iface, TpChannelFunc func, gpointer user_data) {
- IdleIMFactoryPrivate *priv = IDLE_IM_FACTORY_GET_PRIVATE(iface);
- struct _ForeachHelperData data = {func, user_data};
-
- if (!priv->channels) {
- IDLE_DEBUG("Channels hash table missing, ignoring...");
- return;
- }
-
- g_hash_table_foreach(priv->channels, _foreach_helper, &data);
-}
-
-static TpChannelFactoryRequestStatus _iface_request(TpChannelFactoryIface *iface, const gchar *chan_type, TpHandleType handle_type, guint handle, gpointer request, TpChannelIface **new_chan, GError **error) {
- IdleIMFactory *factory = IDLE_IM_FACTORY(iface);
- IdleIMFactoryPrivate *priv = IDLE_IM_FACTORY_GET_PRIVATE(factory);
-
- if (!g_str_equal(chan_type, TP_IFACE_CHANNEL_TYPE_TEXT))
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_NOT_IMPLEMENTED;
-
- if (handle_type != TP_HANDLE_TYPE_CONTACT)
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_NOT_AVAILABLE;
-
- if (!tp_handle_is_valid(tp_base_connection_get_handles(TP_BASE_CONNECTION(priv->conn), TP_HANDLE_TYPE_CONTACT), handle, error))
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_INVALID_HANDLE;
-
- if (!priv->channels) {
- IDLE_DEBUG("Channels hash table missing, failing request...");
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_ERROR;
- }
-
- if ((*new_chan = g_hash_table_lookup(priv->channels, GUINT_TO_POINTER(handle)))) {
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_EXISTING;
- } else {
- *new_chan = (TpChannelIface *) _create_channel(factory, handle, request);
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_CREATED;
- }
-}
-
-static IdleIMChannel *_create_channel(IdleIMFactory *factory, TpHandle handle, gpointer context) {
- IdleIMFactoryPrivate *priv = IDLE_IM_FACTORY_GET_PRIVATE(factory);
- IdleIMChannel *chan;
- gchar *object_path;
-
- object_path = g_strdup_printf("%s/ImChannel%u", priv->conn->parent.object_path, handle);
- chan = g_object_new(IDLE_TYPE_IM_CHANNEL, "connection", priv->conn, "object-path", object_path, "handle", handle, NULL);
-
- g_signal_connect(chan, "closed", (GCallback) _channel_closed_cb, factory);
- g_hash_table_insert(priv->channels, GUINT_TO_POINTER(handle), chan);
- tp_channel_factory_iface_emit_new_channel(factory, (TpChannelIface *) chan, context);
-
- g_free(object_path);
-
- return chan;
-}
-
-static void _channel_closed_cb(IdleIMChannel *chan, gpointer user_data) {
- IdleIMFactoryPrivate *priv = IDLE_IM_FACTORY_GET_PRIVATE(user_data);
- TpHandle handle;
-
- if (priv->channels) {
- g_object_get(chan, "handle", &handle, NULL);
- g_hash_table_remove(priv->channels, GUINT_TO_POINTER(handle));
- }
-}
-
-static void _factory_iface_init(gpointer g_iface, gpointer iface_data) {
- TpChannelFactoryIfaceClass *klass = (TpChannelFactoryIfaceClass *) g_iface;
-
- klass->close_all = _iface_close_all;
- klass->connected = NULL;
- klass->connecting = _iface_connecting;
- klass->disconnected = _iface_disconnected;
- klass->foreach = _iface_foreach;
- klass->request = _iface_request;
-}
-
diff --git a/src/idle-im-manager.c b/src/idle-im-manager.c
new file mode 100644
index 0000000..972445f
--- /dev/null
+++ b/src/idle-im-manager.c
@@ -0,0 +1,489 @@
+/*
+ * This file is part of telepathy-idle
+ *
+ * Copyright (C) 2006-2007 Collabora Limited
+ * Copyright (C) 2006-2007 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
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * 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 "idle-im-manager.h"
+
+#include <telepathy-glib/channel-manager.h>
+#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/dbus.h>
+
+#define IDLE_DEBUG_FLAG IDLE_DEBUG_IM
+#include "idle-connection.h"
+#include "idle-ctcp.h"
+#include "idle-debug.h"
+#include "idle-im-channel.h"
+#include "idle-parser.h"
+#include "idle-text.h"
+
+static void _im_manager_iface_init(gpointer g_iface, gpointer iface_data);
+static GObject * _im_manager_constructor (GType type, guint n_props, GObjectConstructParam *props);
+static void _im_manager_dispose (GObject *object);
+
+G_DEFINE_TYPE_WITH_CODE(IdleIMManager, idle_im_manager, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE(TP_TYPE_CHANNEL_MANAGER, _im_manager_iface_init));
+
+/* properties */
+enum {
+ PROP_CONNECTION = 1,
+ LAST_PROPERTY_ENUM
+};
+
+static const gchar * const im_channel_fixed_properties[] = {
+ TP_IFACE_CHANNEL ".ChannelType",
+ TP_IFACE_CHANNEL ".TargetHandleType",
+ NULL
+};
+
+static const gchar * const im_channel_allowed_properties[] = {
+ TP_IFACE_CHANNEL ".TargetHandle",
+ TP_IFACE_CHANNEL ".TargetID",
+ NULL
+};
+
+typedef struct _IdleIMManagerPrivate IdleIMManagerPrivate;
+struct _IdleIMManagerPrivate {
+ IdleConnection *conn;
+ GHashTable *channels;
+ int status_changed_id;
+ gboolean dispose_has_run;
+};
+
+#define IDLE_IM_MANAGER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), IDLE_TYPE_IM_MANAGER, IdleIMManagerPrivate))
+
+static IdleParserHandlerResult _notice_privmsg_handler(IdleParser *parser, IdleParserMessageCode code, GValueArray *args, gpointer user_data);
+
+static void _im_manager_close_all(IdleIMManager *manager);
+static void connection_status_changed_cb (IdleConnection* conn, guint status, guint reason, IdleIMManager *self);
+
+static void _im_manager_foreach(TpChannelManager *manager, TpExportableChannelFunc func, gpointer user_data);
+static void _im_manager_foreach_class (TpChannelManager* manager, TpChannelManagerChannelClassFunc func, gpointer user_data);
+
+//static TpChannelManagerRequestStatus _iface_request(TpChannelFactoryIface *iface, const gchar *chan_type, TpHandleType handle_type, guint handle, gpointer request, TpChannelIface **new_chan, GError **error);
+
+static gboolean _im_manager_create_channel(TpChannelManager *manager, gpointer request_token, GHashTable *request_properties);
+static gboolean _im_manager_request_channel(TpChannelManager *manager, gpointer request_token, GHashTable *request_properties);
+static gboolean _im_manager_ensure_channel(TpChannelManager *manager, gpointer request_token, GHashTable *request_properties);
+static gboolean _im_manager_requestotron (IdleIMManager *self, gpointer request_token, GHashTable *request_properties, gboolean require_new);
+static IdleIMChannel *_im_manager_new_channel (IdleIMManager *mgr, TpHandle handle, gpointer request);
+
+static void _im_channel_closed_cb (IdleIMChannel *chan, gpointer user_data);
+
+static void idle_im_manager_init(IdleIMManager *obj) {
+ IdleIMManagerPrivate *priv = IDLE_IM_MANAGER_GET_PRIVATE(obj);
+ priv->channels = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref);
+ priv->status_changed_id = 0;
+ priv->dispose_has_run = FALSE;
+}
+
+static void idle_im_manager_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) {
+ IdleIMManager *mgr = IDLE_IM_MANAGER(object);
+ IdleIMManagerPrivate *priv = IDLE_IM_MANAGER_GET_PRIVATE(mgr);
+
+ switch (property_id) {
+ case PROP_CONNECTION:
+ g_value_set_object(value, priv->conn);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+ break;
+ }
+}
+
+static void idle_im_manager_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) {
+ IdleIMManager *manager = IDLE_IM_MANAGER(object);
+ IdleIMManagerPrivate *priv = IDLE_IM_MANAGER_GET_PRIVATE(manager);
+
+ switch (property_id) {
+ case PROP_CONNECTION:
+ priv->conn = g_value_get_object(value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+ break;
+ }
+}
+
+static void idle_im_manager_class_init(IdleIMManagerClass *klass) {
+ GObjectClass *object_class = G_OBJECT_CLASS(klass);
+ GParamSpec *param_spec;
+
+ g_type_class_add_private(klass, sizeof(IdleIMManagerPrivate));
+
+ object_class->constructor = _im_manager_constructor;
+ object_class->dispose = _im_manager_dispose;
+ object_class->get_property = idle_im_manager_get_property;
+ object_class->set_property = idle_im_manager_set_property;
+
+ param_spec = g_param_spec_object("connection", "IdleConnection object", "The IdleConnection object that owns this IM channel manager object.", IDLE_TYPE_CONNECTION, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB);
+ g_object_class_install_property(object_class, PROP_CONNECTION, param_spec);
+}
+
+static GObject *
+_im_manager_constructor (GType type,
+ guint n_props,
+ GObjectConstructParam *props)
+{
+ GObject *obj;
+ IdleIMManager *self;
+ IdleIMManagerPrivate *priv;
+
+ obj = G_OBJECT_CLASS (idle_im_manager_parent_class)->constructor (type,
+ n_props,
+ props);
+
+ self = IDLE_IM_MANAGER (obj);
+ priv = IDLE_IM_MANAGER_GET_PRIVATE (self);
+
+ g_return_val_if_fail (priv->conn, obj);
+
+ priv->status_changed_id = g_signal_connect (priv->conn,
+ "status-changed", (GCallback)
+ connection_status_changed_cb,
+ self);
+
+ return obj;
+}
+
+
+static IdleParserHandlerResult _notice_privmsg_handler(IdleParser *parser, IdleParserMessageCode code, GValueArray *args, gpointer user_data) {
+ IdleIMManager *manager = IDLE_IM_MANAGER(user_data);
+ IdleIMManagerPrivate *priv = IDLE_IM_MANAGER_GET_PRIVATE(manager);
+ TpHandle handle = (TpHandle) g_value_get_uint(g_value_array_get_nth(args, 0));
+ IdleIMChannel *chan;
+ TpChannelTextMessageType type;
+ gchar *body;
+
+ if (code == IDLE_PARSER_PREFIXCMD_NOTICE_USER) {
+ type = TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE;
+ body = idle_ctcp_kill_blingbling(g_value_get_string(g_value_array_get_nth(args, 2)));
+ } else {
+ gboolean decoded = idle_text_decode(g_value_get_string(g_value_array_get_nth(args, 2)), &type, &body);
+ if (!decoded)
+ return IDLE_PARSER_HANDLER_RESULT_NOT_HANDLED;
+ }
+
+ idle_connection_emit_queued_aliases_changed(priv->conn);
+
+ if (!priv->channels) {
+ IDLE_DEBUG("Channels hash table missing, ignoring...");
+ return IDLE_PARSER_HANDLER_RESULT_NOT_HANDLED;
+ }
+
+ if (!(chan = g_hash_table_lookup(priv->channels, GUINT_TO_POINTER(handle))))
+ chan = _im_manager_new_channel(manager, handle, NULL);
+
+ idle_im_channel_receive(chan, type, handle, body);
+
+ g_free(body);
+
+ return IDLE_PARSER_HANDLER_RESULT_HANDLED;
+}
+
+static void _im_manager_close_all(IdleIMManager *manager) {
+ IdleIMManagerPrivate *priv = IDLE_IM_MANAGER_GET_PRIVATE(manager);
+
+ if (priv->channels) {
+ GHashTable *tmp = priv->channels;
+ priv->channels = NULL;
+ g_hash_table_destroy(tmp);
+ }
+ if (priv->status_changed_id != 0) {
+ g_signal_handler_disconnect (priv->conn, priv->status_changed_id);
+ priv->status_changed_id = 0;
+ }
+}
+
+static void connection_status_changed_cb (IdleConnection* conn,
+ guint status,
+ guint reason,
+ IdleIMManager *self)
+{
+ IdleIMManagerPrivate *priv = IDLE_IM_MANAGER_GET_PRIVATE(self);
+
+ if (status == TP_CONNECTION_STATUS_DISCONNECTED) {
+ idle_parser_remove_handlers_by_data(priv->conn->parser, self);
+ _im_manager_close_all (self);
+ } else if (status == TP_CONNECTION_STATUS_CONNECTED) {
+ idle_parser_add_handler(priv->conn->parser, IDLE_PARSER_PREFIXCMD_NOTICE_USER, _notice_privmsg_handler, self);
+ idle_parser_add_handler(priv->conn->parser, IDLE_PARSER_PREFIXCMD_PRIVMSG_USER, _notice_privmsg_handler, self);
+ }
+}
+
+/*
+static void _iface_connecting(TpChannelFactoryIface *iface) {
+ IdleIMFactoryPrivate *priv = IDLE_IM_FACTORY_GET_PRIVATE(iface);
+
+ idle_parser_add_handler(priv->conn->parser, IDLE_PARSER_PREFIXCMD_NOTICE_USER, _notice_privmsg_handler, iface);
+ idle_parser_add_handler(priv->conn->parser, IDLE_PARSER_PREFIXCMD_PRIVMSG_USER, _notice_privmsg_handler, iface);
+}
+
+static void _iface_disconnected(TpChannelFactoryIface *iface) {
+ IdleIMFactoryPrivate *priv = IDLE_IM_FACTORY_GET_PRIVATE(iface);
+
+ idle_parser_remove_handlers_by_data(priv->conn->parser, iface);
+}
+*/
+
+struct _ForeachHelperData {
+ TpExportableChannelFunc func;
+ gpointer user_data;
+};
+
+static void _foreach_helper(gpointer key, gpointer value, gpointer user_data) {
+ struct _ForeachHelperData *data = user_data;
+ data->func(value, data->user_data);
+}
+
+static void _im_manager_foreach(TpChannelManager *manager, TpExportableChannelFunc func, gpointer user_data) {
+ IdleIMManagerPrivate *priv = IDLE_IM_MANAGER_GET_PRIVATE(manager);
+ struct _ForeachHelperData data = {func, user_data};
+
+ if (!priv->channels) {
+ IDLE_DEBUG("Channels hash table missing, ignoring...");
+ return;
+ }
+
+ g_hash_table_foreach(priv->channels, _foreach_helper, &data);
+}
+
+
+static void _im_manager_foreach_class (TpChannelManager* manager,
+ TpChannelManagerChannelClassFunc func,
+ gpointer user_data)
+{
+ GHashTable *table;
+ GValue *value;
+
+ table = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, (GDestroyNotify) tp_g_value_slice_free);
+
+ value = tp_g_value_slice_new (G_TYPE_STRING);
+ g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_TEXT);
+ g_hash_table_insert (table, (gpointer) im_channel_fixed_properties[0], value);
+
+ value = tp_g_value_slice_new (G_TYPE_UINT);
+ g_value_set_uint (value, TP_HANDLE_TYPE_CONTACT);
+ g_hash_table_insert (table, (gpointer) im_channel_fixed_properties[1], value);
+
+ func (manager, table, im_channel_allowed_properties, user_data);
+
+ g_hash_table_destroy (table);
+}
+
+
+static gboolean
+_im_manager_create_channel(TpChannelManager *manager,
+ gpointer request_token,
+ GHashTable *request_properties)
+{
+ IdleIMManager *self = IDLE_IM_MANAGER (manager);
+
+ return _im_manager_requestotron (self, request_token, request_properties,
+ TRUE);
+}
+
+
+static gboolean
+_im_manager_request_channel(TpChannelManager *manager,
+ gpointer request_token,
+ GHashTable *request_properties)
+{
+ IdleIMManager *self = IDLE_IM_MANAGER (manager);
+
+ return _im_manager_requestotron (self, request_token, request_properties,
+ FALSE);
+}
+
+
+static gboolean
+_im_manager_ensure_channel(TpChannelManager *manager,
+ gpointer request_token,
+ GHashTable *request_properties)
+{
+ IdleIMManager *self = IDLE_IM_MANAGER (manager);
+
+ return _im_manager_requestotron (self, request_token, request_properties,
+ FALSE);
+}
+
+
+static gboolean
+_im_manager_requestotron (IdleIMManager *self,
+ gpointer request_token,
+ GHashTable *request_properties,
+ gboolean require_new)
+{
+ IdleIMManagerPrivate *priv = IDLE_IM_MANAGER_GET_PRIVATE (self);
+ TpBaseConnection *base_conn = (TpBaseConnection *) priv->conn;
+ TpHandleRepoIface *contact_repo =
+ tp_base_connection_get_handles (base_conn, TP_HANDLE_TYPE_CONTACT);
+ TpHandle handle;
+ GError *error = NULL;
+ TpExportableChannel *channel;
+
+ if (tp_strdiff (tp_asv_get_string (request_properties,
+ TP_IFACE_CHANNEL ".ChannelType"), TP_IFACE_CHANNEL_TYPE_TEXT))
+ return FALSE;
+
+ if (tp_asv_get_uint32 (request_properties,
+ TP_IFACE_CHANNEL ".TargetHandleType", NULL) != TP_HANDLE_TYPE_CONTACT)
+ return FALSE;
+
+ handle = tp_asv_get_uint32 (request_properties,
+ TP_IFACE_CHANNEL ".TargetHandle", NULL);
+
+ if (!tp_handle_is_valid (contact_repo, handle, &error))
+ goto error;
+
+ /* Check if there are any other properties that we don't understand */
+ if (tp_channel_manager_asv_has_unknown_properties (request_properties,
+ im_channel_fixed_properties,
+ im_channel_allowed_properties,
+ &error))
+ {
+ goto error;
+ }
+
+ /* Don't support opening a channel to our self handle */
+ if (handle == base_conn->self_handle)
+ {
+ g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ "Can't open a text channel to yourself");
+ goto error;
+ }
+
+ channel = g_hash_table_lookup (priv->channels, GUINT_TO_POINTER (handle));
+
+ if (channel == NULL)
+ {
+ _im_manager_new_channel (self, handle, request_token);
+ return TRUE;
+ }
+
+ if (require_new)
+ {
+ g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ "Already chatting with contact #%u in another channel", handle);
+ goto error;
+ }
+
+ tp_channel_manager_emit_request_already_satisfied (self, request_token,
+ channel);
+ return TRUE;
+
+error:
+ tp_channel_manager_emit_request_failed (self, request_token,
+ error->domain, error->code, error->message);
+ g_error_free (error);
+ return TRUE;
+}
+
+
+static void
+_im_channel_closed_cb (IdleIMChannel *chan,
+ gpointer user_data)
+{
+ IdleIMManager *self = IDLE_IM_MANAGER (user_data);
+ IdleIMManagerPrivate *priv = IDLE_IM_MANAGER_GET_PRIVATE (self);
+ TpHandle handle;
+
+ tp_channel_manager_emit_channel_closed_for_object (self,
+ TP_EXPORTABLE_CHANNEL (chan));
+
+ if (priv->channels)
+ {
+ g_object_get (chan, "handle", &handle, NULL);
+ IDLE_DEBUG ("Removing channel with handle %u", handle);
+ g_hash_table_remove (priv->channels, GUINT_TO_POINTER (handle));
+ }
+}
+
+
+static IdleIMChannel *
+_im_manager_new_channel (IdleIMManager *mgr,
+ TpHandle handle,
+ gpointer request)
+{
+ IdleIMManagerPrivate *priv = IDLE_IM_MANAGER_GET_PRIVATE (mgr);
+ TpBaseConnection *base_connection = TP_BASE_CONNECTION (priv->conn);
+ TpHandleRepoIface *handle_repo =
+ tp_base_connection_get_handles (base_connection, TP_HANDLE_TYPE_CONTACT);
+ IdleIMChannel *chan;
+ const gchar *name;
+ gchar *object_path = NULL;
+ GSList *requests = NULL;
+
+ g_assert (g_hash_table_lookup (priv->channels, GUINT_TO_POINTER (handle))
+ == NULL);
+
+ name = tp_handle_inspect (handle_repo, handle);
+ IDLE_DEBUG ("Requested channel for handle: %u (%s)", handle, name);
+
+ object_path = g_strdup_printf("%s/ImChannel%u", priv->conn->parent.object_path, handle);
+ chan = g_object_new (IDLE_TYPE_IM_CHANNEL,
+ "connection", priv->conn,
+ "object-path", object_path,
+ "handle", handle,
+ NULL);
+ g_free (object_path);
+ g_hash_table_insert (priv->channels, GUINT_TO_POINTER (handle), chan);
+
+ if (request != NULL)
+ requests = g_slist_prepend (requests, request);
+
+ tp_channel_manager_emit_new_channel (mgr, TP_EXPORTABLE_CHANNEL (chan),
+ requests);
+
+ g_slist_free (requests);
+
+ g_signal_connect (chan, "closed", G_CALLBACK (_im_channel_closed_cb), mgr);
+
+ return chan;
+}
+
+static void _im_manager_iface_init(gpointer g_iface, gpointer iface_data) {
+ TpChannelManagerIface *iface = g_iface;
+
+ iface->foreach_channel = _im_manager_foreach;
+ iface->foreach_channel_class = _im_manager_foreach_class;
+ iface->request_channel = _im_manager_request_channel;
+ iface->create_channel = _im_manager_create_channel;
+ iface->ensure_channel = _im_manager_ensure_channel;
+}
+
+static void
+_im_manager_dispose (GObject *object)
+{
+ IdleIMManager *self = IDLE_IM_MANAGER (object);
+ IdleIMManagerPrivate *priv = IDLE_IM_MANAGER_GET_PRIVATE (self);
+
+ if (priv->dispose_has_run)
+ return;
+
+ priv->dispose_has_run = TRUE;
+
+ _im_manager_close_all (self);
+
+ if (G_OBJECT_CLASS (idle_im_manager_parent_class)->dispose)
+ G_OBJECT_CLASS (idle_im_manager_parent_class)->dispose (object);
+}
+
diff --git a/src/idle-im-factory.h b/src/idle-im-manager.h
similarity index 51%
rename from src/idle-im-factory.h
rename to src/idle-im-manager.h
index 2816e41..1967a29 100644
--- a/src/idle-im-factory.h
+++ b/src/idle-im-manager.h
@@ -18,34 +18,34 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef __IDLE_IM_FACTORY_H__
-#define __IDLE_IM_FACTORY_H__
+#ifndef __IDLE_IM_MANAGER_H__
+#define __IDLE_IM_MANAGER_H__
#include <glib-object.h>
G_BEGIN_DECLS
-typedef struct _IdleIMFactory IdleIMFactory;
-typedef struct _IdleIMFactoryClass IdleIMFactoryClass;
+typedef struct _IdleIMManager IdleIMManager;
+typedef struct _IdleIMManagerClass IdleIMManagerClass;
-struct _IdleIMFactoryClass {
+struct _IdleIMManagerClass {
GObjectClass parent_class;
};
-struct _IdleIMFactory {
+struct _IdleIMManager {
GObject parent;
};
-GType idle_im_factory_get_type();
+GType idle_im_manager_get_type();
-#define IDLE_TYPE_IM_FACTORY (idle_im_factory_get_type())
-#define IDLE_IM_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), IDLE_TYPE_IM_FACTORY, IdleIMFactory))
-#define IDLE_IM_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), IDLE_TYPE_IM_FACTORY, IdleIMFactoryClass))
-#define IDLE_IS_IM_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), IDLE_TYPE_IM_FACTORY))
-#define IDLE_IS_IM_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), IDLE_TYPE_IM_FACTORY))
-#define IDLE_IM_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), IDLE_TYPE_IM_FACTORY, IdleIMFactoryClass))
+#define IDLE_TYPE_IM_MANAGER (idle_im_manager_get_type())
+#define IDLE_IM_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), IDLE_TYPE_IM_MANAGER, IdleIMManager))
+#define IDLE_IM_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), IDLE_TYPE_IM_MANAGER, IdleIMManagerClass))
+#define IDLE_IS_IM_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), IDLE_TYPE_IM_MANAGER))
+#define IDLE_IS_IM_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), IDLE_TYPE_IM_MANAGER))
+#define IDLE_IM_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), IDLE_TYPE_IM_MANAGER, IdleIMManagerClass))
G_END_DECLS
-#endif /* #ifndef __IDLE_IM_FACTORY_H__ */
+#endif /* #ifndef __IDLE_IM_MANAGER_H__ */
--
1.5.6.5
More information about the telepathy-commits
mailing list