[Telepathy-commits] [telepathy-salut/master] Split SalutMucManager to SalutMucManager and SalutRoomlistManager
Alban Crequy
alban.crequy at collabora.co.uk
Thu Nov 27 10:07:57 PST 2008
---
src/Makefile.am | 4 +
src/salut-avahi-muc-manager.c | 245 ---------------
src/salut-avahi-roomlist-manager.c | 383 +++++++++++++++++++++++
src/salut-avahi-roomlist-manager.h | 71 +++++
src/salut-connection.c | 25 ++-
src/salut-muc-manager.c | 592 +++++++++++++++++++----------------
src/salut-muc-manager.h | 19 --
src/salut-roomlist-manager.c | 440 ++++++++++++++++++++++++++
src/salut-roomlist-manager.h | 99 ++++++
9 files changed, 1342 insertions(+), 536 deletions(-)
create mode 100644 src/salut-avahi-roomlist-manager.c
create mode 100644 src/salut-avahi-roomlist-manager.h
create mode 100644 src/salut-roomlist-manager.c
create mode 100644 src/salut-roomlist-manager.h
diff --git a/src/Makefile.am b/src/Makefile.am
index f094b18..34d88d5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -25,6 +25,8 @@ CORE_SOURCES = \
salut-im-channel.h \
salut-muc-manager.c \
salut-muc-manager.h \
+ salut-roomlist-manager.c \
+ salut-roomlist-manager.h \
salut-muc-channel.c \
salut-ft-manager.c \
salut-ft-manager.h \
@@ -77,6 +79,8 @@ AVAHI_BACKEND_SOURCES = \
salut-avahi-discovery-client.c \
salut-avahi-muc-manager.h \
salut-avahi-muc-manager.c \
+ salut-avahi-roomlist-manager.h \
+ salut-avahi-roomlist-manager.c \
salut-avahi-muc-channel.h \
salut-avahi-muc-channel.c \
salut-avahi-contact-manager.h \
diff --git a/src/salut-avahi-muc-manager.c b/src/salut-avahi-muc-manager.c
index 02d06bf..8c64d14 100644
--- a/src/salut-avahi-muc-manager.c
+++ b/src/salut-avahi-muc-manager.c
@@ -60,10 +60,6 @@ typedef struct _SalutAvahiMucManagerPrivate SalutAvahiMucManagerPrivate;
struct _SalutAvahiMucManagerPrivate
{
SalutAvahiDiscoveryClient *discovery_client;
- GaServiceBrowser *browser;
-
- /* room name => (GaServiceResolver *) */
- GHashTable *room_resolvers;
gboolean dispose_has_run;
};
@@ -72,28 +68,12 @@ struct _SalutAvahiMucManagerPrivate
((SalutAvahiMucManagerPrivate *) ((SalutAvahiMucManager *)obj)->priv)
static void
-room_resolver_removed (gpointer data)
-{
- GArray *arr = (GArray *) data;
- int i;
- for (i = 0; i < arr->len; i++)
- {
- g_object_unref (g_array_index (arr, GObject *, i));
- }
- g_array_free (arr, TRUE);
-}
-
-static void
salut_avahi_muc_manager_init (SalutAvahiMucManager *self)
{
SalutAvahiMucManagerPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
SALUT_TYPE_AVAHI_MUC_MANAGER, SalutAvahiMucManagerPrivate);
self->priv = priv;
- priv->browser = ga_service_browser_new (SALUT_DNSSD_CLIQUE);
-
- priv->room_resolvers = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, room_resolver_removed);
}
static void
@@ -139,215 +119,6 @@ salut_avahi_muc_manager_set_property (GObject *object,
static void salut_avahi_muc_manager_dispose (GObject *object);
-static void
-browser_found (GaServiceBrowser *browser,
- AvahiIfIndex interface,
- AvahiProtocol protocol,
- const char *name,
- const char *type,
- const char *domain,
- GaLookupResultFlags flags,
- SalutAvahiMucManager *self)
-{
- SalutAvahiMucManagerPrivate *priv = SALUT_AVAHI_MUC_MANAGER_GET_PRIVATE (self);
- GArray *arr;
- GaServiceResolver *resolver;
- GError *error = NULL;
-
- DEBUG ("found room: %s.%s.%s", name, type, domain);
- resolver = ga_service_resolver_new (interface, protocol,
- name, type, domain, protocol, 0);
-
- if (!ga_service_resolver_attach (resolver,
- priv->discovery_client->avahi_client, &error))
- {
- DEBUG ("resolver attach failed: %s", error->message);
- g_object_unref (resolver);
- g_error_free (error);
- return;
- }
-
- arr = g_hash_table_lookup (priv->room_resolvers, name);
- if (arr == NULL)
- {
- arr = g_array_new (FALSE, FALSE, sizeof (GObject *));
- g_hash_table_insert (priv->room_resolvers, g_strdup (name), arr);
- salut_muc_manager_room_discovered (SALUT_MUC_MANAGER (self),
- name);
- }
- g_array_append_val (arr, resolver);
-}
-
-static void
-browser_removed (GaServiceBrowser *browser,
- AvahiIfIndex interface,
- AvahiProtocol protocol,
- const char *name,
- const char *type,
- const char *domain,
- GaLookupResultFlags flags,
- SalutAvahiMucManager *self)
-{
- SalutAvahiMucManagerPrivate *priv = SALUT_AVAHI_MUC_MANAGER_GET_PRIVATE (self);
- GArray *arr;
- int i;
-
- arr = g_hash_table_lookup (priv->room_resolvers, name);
-
- if (arr == NULL) {
- DEBUG ("Browser removed for %s, but didn't have any resolvers", name);
- return;
- }
-
- for (i = 0; i < arr->len; i++)
- {
- GaServiceResolver *resolver;
- AvahiIfIndex r_interface;
- AvahiProtocol r_protocol;
- gchar *r_name;
- gchar *r_type;
- gchar *r_domain;
-
- resolver = g_array_index (arr, GaServiceResolver *, i);
- g_object_get ((gpointer) resolver,
- "interface", &r_interface,
- "protocol", &r_protocol,
- "name", &r_name,
- "type", &r_type,
- "domain", &r_domain,
- NULL);
- if (interface == r_interface
- && protocol == r_protocol
- && !tp_strdiff (name, r_name)
- && !tp_strdiff (type, r_type)
- && !tp_strdiff (domain, r_domain))
- {
- g_free (r_name);
- g_free (r_type);
- g_free (r_domain);
- g_object_unref (resolver);
- g_array_remove_index_fast (arr, i);
- break;
- }
-
- g_free (r_name);
- g_free (r_type);
- g_free (r_domain);
- }
-
- if (arr->len > 0)
- return;
-
- DEBUG ("remove room: %s.%s.%s", name, type, domain);
-
- g_hash_table_remove (priv->room_resolvers, name);
-
- salut_muc_manager_room_removed (SALUT_MUC_MANAGER (self), name);
-}
-
-static void
-browser_failed (GaServiceBrowser *browser,
- GError *error,
- SalutAvahiMucManager *self)
-{
- /* FIXME proper error handling */
- DEBUG ("browser failed -> %s", error->message);
-}
-
-static gboolean
-salut_avahi_muc_manager_start (SalutMucManager *mgr,
- GError **error)
-{
- SalutAvahiMucManager *self = SALUT_AVAHI_MUC_MANAGER (mgr);
- SalutAvahiMucManagerPrivate *priv = SALUT_AVAHI_MUC_MANAGER_GET_PRIVATE (self);
-
- g_signal_connect (priv->browser, "new-service",
- G_CALLBACK (browser_found), self);
- g_signal_connect (priv->browser, "removed-service",
- G_CALLBACK (browser_removed), self);
- g_signal_connect (priv->browser, "failure",
- G_CALLBACK (browser_failed), self);
-
- if (!ga_service_browser_attach (priv->browser,
- priv->discovery_client->avahi_client, error))
- {
- DEBUG ("browser attach failed");
- return FALSE;
- }
-
- return TRUE;
-}
-
-static gchar *
-_avahi_address_to_string_address (const AvahiAddress *address)
-{
- gchar str[AVAHI_ADDRESS_STR_MAX];
-
- if (avahi_address_snprint (str, sizeof (str), address) == NULL)
- {
- DEBUG ("Failed to convert AvahiAddress to string");
- return NULL;
- }
- return g_strdup (str);
-}
-
-static gboolean
-salut_avahi_muc_manager_find_muc_address (SalutMucManager *mgr,
- const gchar *name,
- gchar **address,
- guint16 *port)
-{
- SalutAvahiMucManager *self = SALUT_AVAHI_MUC_MANAGER (mgr);
- SalutAvahiMucManagerPrivate *priv = SALUT_AVAHI_MUC_MANAGER_GET_PRIVATE (self);
- GArray *arr;
- AvahiAddress avahi_address;
- guint i;
-
- arr = g_hash_table_lookup (priv->room_resolvers, name);
- if (arr == NULL || arr->len == 0)
- return FALSE;
-
- for (i = 0; i < arr->len; i++)
- {
- GaServiceResolver *resolver;
- resolver = g_array_index (arr, GaServiceResolver *, i);
-
- if (!ga_service_resolver_get_address (resolver, &avahi_address, port))
- {
- DEBUG ("..._get_address failed: creating a new MUC room instead");
- return FALSE;
- }
- else
- {
- *address = _avahi_address_to_string_address (&avahi_address);
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-static void
-add_room_to_list (const gchar *room,
- GaServiceResolver *resolver,
- GSList **list)
-{
- *list = g_slist_prepend (*list, (gchar *) room);
-}
-
-static GSList *
-salut_avahi_muc_manager_get_rooms (SalutMucManager *mgr)
-{
- SalutAvahiMucManager *self = SALUT_AVAHI_MUC_MANAGER (mgr);
- SalutAvahiMucManagerPrivate *priv = SALUT_AVAHI_MUC_MANAGER_GET_PRIVATE (self);
- GSList *rooms = NULL;
-
- g_hash_table_foreach (priv->room_resolvers, (GHFunc) add_room_to_list,
- &rooms);
-
- return rooms;
-}
-
static SalutMucChannel *
salut_avahi_muc_manager_create_muc_channel (
SalutMucManager *mgr,
@@ -385,10 +156,6 @@ salut_avahi_muc_manager_class_init (
object_class->dispose = salut_avahi_muc_manager_dispose;
- muc_manager_class->start = salut_avahi_muc_manager_start;
- muc_manager_class->find_muc_address =
- salut_avahi_muc_manager_find_muc_address;
- muc_manager_class->get_rooms = salut_avahi_muc_manager_get_rooms;
muc_manager_class->create_muc_channel =
salut_avahi_muc_manager_create_muc_channel;
@@ -414,18 +181,6 @@ salut_avahi_muc_manager_dispose (GObject *object)
priv->dispose_has_run = TRUE;
- if (priv->room_resolvers != NULL)
- {
- g_hash_table_destroy (priv->room_resolvers);
- priv->room_resolvers = NULL;
- }
-
- if (priv->browser != NULL)
- {
- g_object_unref (priv->browser);
- priv->browser = NULL;
- }
-
if (priv->discovery_client != NULL)
{
g_object_unref (priv->discovery_client);
diff --git a/src/salut-avahi-roomlist-manager.c b/src/salut-avahi-roomlist-manager.c
new file mode 100644
index 0000000..b21aeda
--- /dev/null
+++ b/src/salut-avahi-roomlist-manager.c
@@ -0,0 +1,383 @@
+/*
+ * salut-avahi-roomlist-manager.c - Source for SalutAvahiRoomlistManager
+ * Copyright (C) 2006 Collabora Ltd.
+ *
+ * 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 <dbus/dbus-glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <arpa/inet.h>
+
+#include "salut-avahi-roomlist-manager.h"
+
+#include <avahi-gobject/ga-service-browser.h>
+#include <avahi-gobject/ga-service-resolver.h>
+
+#include <gibber/gibber-muc-connection.h>
+#include <gibber/gibber-namespaces.h>
+#include <gibber/gibber-xmpp-error.h>
+
+#include "salut-contact-manager.h"
+#include "salut-tubes-channel.h"
+#include "salut-roomlist-channel.h"
+#include "salut-xmpp-connection-manager.h"
+
+#include <telepathy-glib/channel-factory-iface.h>
+#include <telepathy-glib/interfaces.h>
+
+#define DEBUG_FLAG DEBUG_MUC
+#include "debug.h"
+
+G_DEFINE_TYPE (SalutAvahiRoomlistManager, salut_avahi_roomlist_manager,
+ SALUT_TYPE_ROOMLIST_MANAGER);
+
+/* properties */
+enum {
+ PROP_CLIENT = 1,
+ LAST_PROP
+};
+
+/* private structure */
+typedef struct _SalutAvahiRoomlistManagerPrivate
+ SalutAvahiRoomlistManagerPrivate;
+
+struct _SalutAvahiRoomlistManagerPrivate
+{
+ SalutAvahiDiscoveryClient *discovery_client;
+ GaServiceBrowser *browser;
+
+ /* room name => (GaServiceResolver *) */
+ GHashTable *room_resolvers;
+
+ gboolean dispose_has_run;
+};
+
+#define SALUT_AVAHI_ROOMLIST_MANAGER_GET_PRIVATE(obj) \
+ ((SalutAvahiRoomlistManagerPrivate *) \
+ ((SalutAvahiRoomlistManager *)obj)->priv)
+
+static void
+room_resolver_removed (gpointer data)
+{
+ GArray *arr = (GArray *) data;
+ int i;
+ for (i = 0; i < arr->len; i++)
+ {
+ g_object_unref (g_array_index (arr, GObject *, i));
+ }
+ g_array_free (arr, TRUE);
+}
+
+static void
+salut_avahi_roomlist_manager_init (SalutAvahiRoomlistManager *self)
+{
+ SalutAvahiRoomlistManagerPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ SALUT_TYPE_AVAHI_ROOMLIST_MANAGER, SalutAvahiRoomlistManagerPrivate);
+
+ self->priv = priv;
+ priv->browser = ga_service_browser_new (SALUT_DNSSD_CLIQUE);
+
+ priv->room_resolvers = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, room_resolver_removed);
+}
+
+static void
+salut_avahi_roomlist_manager_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ SalutAvahiRoomlistManager *self = SALUT_AVAHI_ROOMLIST_MANAGER (object);
+ SalutAvahiRoomlistManagerPrivate *priv = SALUT_AVAHI_ROOMLIST_MANAGER_GET_PRIVATE (self);
+
+ switch (property_id)
+ {
+ case PROP_CLIENT:
+ g_value_set_object (value, priv->discovery_client);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+salut_avahi_roomlist_manager_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ SalutAvahiRoomlistManager *self = SALUT_AVAHI_ROOMLIST_MANAGER (object);
+ SalutAvahiRoomlistManagerPrivate *priv = SALUT_AVAHI_ROOMLIST_MANAGER_GET_PRIVATE (self);
+
+ switch (property_id)
+ {
+ case PROP_CLIENT:
+ priv->discovery_client = g_value_get_object (value);
+ g_object_ref (priv->discovery_client);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void salut_avahi_roomlist_manager_dispose (GObject *object);
+
+static void
+browser_found (GaServiceBrowser *browser,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ const char *name,
+ const char *type,
+ const char *domain,
+ GaLookupResultFlags flags,
+ SalutAvahiRoomlistManager *self)
+{
+ SalutAvahiRoomlistManagerPrivate *priv = SALUT_AVAHI_ROOMLIST_MANAGER_GET_PRIVATE (self);
+ GArray *arr;
+ GaServiceResolver *resolver;
+ GError *error = NULL;
+
+ DEBUG ("found room: %s.%s.%s", name, type, domain);
+ resolver = ga_service_resolver_new (interface, protocol,
+ name, type, domain, protocol, 0);
+
+ if (!ga_service_resolver_attach (resolver,
+ priv->discovery_client->avahi_client, &error))
+ {
+ DEBUG ("resolver attach failed: %s", error->message);
+ g_object_unref (resolver);
+ g_error_free (error);
+ return;
+ }
+
+ arr = g_hash_table_lookup (priv->room_resolvers, name);
+ if (arr == NULL)
+ {
+ arr = g_array_new (FALSE, FALSE, sizeof (GObject *));
+ g_hash_table_insert (priv->room_resolvers, g_strdup (name), arr);
+ salut_roomlist_manager_room_discovered (SALUT_ROOMLIST_MANAGER (self),
+ name);
+ }
+ g_array_append_val (arr, resolver);
+}
+
+static void
+browser_removed (GaServiceBrowser *browser,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ const char *name,
+ const char *type,
+ const char *domain,
+ GaLookupResultFlags flags,
+ SalutAvahiRoomlistManager *self)
+{
+ SalutAvahiRoomlistManagerPrivate *priv = SALUT_AVAHI_ROOMLIST_MANAGER_GET_PRIVATE (self);
+ GArray *arr;
+ int i;
+
+ arr = g_hash_table_lookup (priv->room_resolvers, name);
+
+ if (arr == NULL) {
+ DEBUG ("Browser removed for %s, but didn't have any resolvers", name);
+ return;
+ }
+
+ for (i = 0; i < arr->len; i++)
+ {
+ GaServiceResolver *resolver;
+ AvahiIfIndex r_interface;
+ AvahiProtocol r_protocol;
+ gchar *r_name;
+ gchar *r_type;
+ gchar *r_domain;
+
+ resolver = g_array_index (arr, GaServiceResolver *, i);
+ g_object_get ((gpointer) resolver,
+ "interface", &r_interface,
+ "protocol", &r_protocol,
+ "name", &r_name,
+ "type", &r_type,
+ "domain", &r_domain,
+ NULL);
+ if (interface == r_interface
+ && protocol == r_protocol
+ && !tp_strdiff (name, r_name)
+ && !tp_strdiff (type, r_type)
+ && !tp_strdiff (domain, r_domain))
+ {
+ g_free (r_name);
+ g_free (r_type);
+ g_free (r_domain);
+ g_object_unref (resolver);
+ g_array_remove_index_fast (arr, i);
+ break;
+ }
+
+ g_free (r_name);
+ g_free (r_type);
+ g_free (r_domain);
+ }
+
+ if (arr->len > 0)
+ return;
+
+ DEBUG ("remove room: %s.%s.%s", name, type, domain);
+
+ g_hash_table_remove (priv->room_resolvers, name);
+
+ salut_roomlist_manager_room_removed (SALUT_ROOMLIST_MANAGER (self), name);
+}
+
+static void
+browser_failed (GaServiceBrowser *browser,
+ GError *error,
+ SalutAvahiRoomlistManager *self)
+{
+ /* FIXME proper error handling */
+ DEBUG ("browser failed -> %s", error->message);
+}
+
+static gboolean
+salut_avahi_roomlist_manager_start (SalutRoomlistManager *mgr,
+ GError **error)
+{
+ SalutAvahiRoomlistManager *self = SALUT_AVAHI_ROOMLIST_MANAGER (mgr);
+ SalutAvahiRoomlistManagerPrivate *priv = SALUT_AVAHI_ROOMLIST_MANAGER_GET_PRIVATE (self);
+
+ g_signal_connect (priv->browser, "new-service",
+ G_CALLBACK (browser_found), self);
+ g_signal_connect (priv->browser, "removed-service",
+ G_CALLBACK (browser_removed), self);
+ g_signal_connect (priv->browser, "failure",
+ G_CALLBACK (browser_failed), self);
+
+ if (!ga_service_browser_attach (priv->browser,
+ priv->discovery_client->avahi_client, error))
+ {
+ DEBUG ("browser attach failed");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+add_room_to_list (const gchar *room,
+ GaServiceResolver *resolver,
+ GSList **list)
+{
+ *list = g_slist_prepend (*list, (gchar *) room);
+}
+
+static GSList *
+salut_avahi_roomlist_manager_get_rooms (SalutRoomlistManager *mgr)
+{
+ SalutAvahiRoomlistManager *self = SALUT_AVAHI_ROOMLIST_MANAGER (mgr);
+ SalutAvahiRoomlistManagerPrivate *priv = SALUT_AVAHI_ROOMLIST_MANAGER_GET_PRIVATE (self);
+ GSList *rooms = NULL;
+
+ g_hash_table_foreach (priv->room_resolvers, (GHFunc) add_room_to_list,
+ &rooms);
+
+ return rooms;
+}
+
+static void
+salut_avahi_roomlist_manager_class_init (
+ SalutAvahiRoomlistManagerClass *salut_avahi_roomlist_manager_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (salut_avahi_roomlist_manager_class);
+ SalutRoomlistManagerClass *roomlist_manager_class = SALUT_ROOMLIST_MANAGER_CLASS (
+ salut_avahi_roomlist_manager_class);
+ GParamSpec *param_spec;
+
+ g_type_class_add_private (salut_avahi_roomlist_manager_class,
+ sizeof (SalutAvahiRoomlistManagerPrivate));
+
+ object_class->get_property = salut_avahi_roomlist_manager_get_property;
+ object_class->set_property = salut_avahi_roomlist_manager_set_property;
+
+ object_class->dispose = salut_avahi_roomlist_manager_dispose;
+
+ roomlist_manager_class->start = salut_avahi_roomlist_manager_start;
+ roomlist_manager_class->get_rooms = salut_avahi_roomlist_manager_get_rooms;
+
+ param_spec = g_param_spec_object (
+ "discovery-client",
+ "SalutAvahiDiscoveryClient object",
+ "The Salut Avahi Discovery client associated with this roomlist manager",
+ SALUT_TYPE_AVAHI_DISCOVERY_CLIENT,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_CLIENT,
+ param_spec);
+}
+
+static void
+salut_avahi_roomlist_manager_dispose (GObject *object)
+{
+ SalutAvahiRoomlistManager *self = SALUT_AVAHI_ROOMLIST_MANAGER (object);
+ SalutAvahiRoomlistManagerPrivate *priv = SALUT_AVAHI_ROOMLIST_MANAGER_GET_PRIVATE (self);
+
+ if (priv->dispose_has_run)
+ return;
+
+ priv->dispose_has_run = TRUE;
+
+ if (priv->room_resolvers != NULL)
+ {
+ g_hash_table_destroy (priv->room_resolvers);
+ priv->room_resolvers = NULL;
+ }
+
+ if (priv->browser != NULL)
+ {
+ g_object_unref (priv->browser);
+ priv->browser = NULL;
+ }
+
+ if (priv->discovery_client != NULL)
+ {
+ g_object_unref (priv->discovery_client);
+ priv->discovery_client = NULL;
+ }
+
+ /* release any references held by the object here */
+
+ if (G_OBJECT_CLASS (salut_avahi_roomlist_manager_parent_class)->dispose)
+ G_OBJECT_CLASS (salut_avahi_roomlist_manager_parent_class)->dispose (object);
+}
+
+/* public functions */
+SalutAvahiRoomlistManager *
+salut_avahi_roomlist_manager_new (SalutConnection *connection,
+ SalutXmppConnectionManager *xmpp_connection_manager,
+ SalutAvahiDiscoveryClient *discovery_client)
+{
+ g_assert (connection != NULL);
+ g_assert (xmpp_connection_manager != NULL);
+ g_assert (discovery_client != NULL);
+
+ return g_object_new (SALUT_TYPE_AVAHI_ROOMLIST_MANAGER,
+ "connection", connection,
+ "xmpp-connection-manager", xmpp_connection_manager,
+ "discovery-client", discovery_client,
+ NULL);
+}
diff --git a/src/salut-avahi-roomlist-manager.h b/src/salut-avahi-roomlist-manager.h
new file mode 100644
index 0000000..542f695
--- /dev/null
+++ b/src/salut-avahi-roomlist-manager.h
@@ -0,0 +1,71 @@
+/*
+ * salut-avahi-roomlist-manager.h - Header for SalutAvahiRoomlistManager
+ * Copyright (C) 2006 Collabora Ltd.
+ *
+ * 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_AVAHI_ROOMLIST_MANAGER_H__
+#define __SALUT_AVAHI_ROOMLIST_MANAGER_H__
+
+#include <glib-object.h>
+
+#include "salut-roomlist-manager.h"
+#include "salut-connection.h"
+#include "salut-xmpp-connection-manager.h"
+#include "salut-avahi-discovery-client.h"
+
+G_BEGIN_DECLS
+
+typedef struct _SalutAvahiRoomlistManager SalutAvahiRoomlistManager;
+typedef struct _SalutAvahiRoomlistManagerClass SalutAvahiRoomlistManagerClass;
+
+struct _SalutAvahiRoomlistManagerClass {
+ SalutRoomlistManagerClass parent_class;
+};
+
+struct _SalutAvahiRoomlistManager {
+ SalutRoomlistManager parent;
+
+ gpointer priv;
+};
+
+GType salut_avahi_roomlist_manager_get_type (void);
+
+/* TYPE MACROS */
+#define SALUT_TYPE_AVAHI_ROOMLIST_MANAGER \
+ (salut_avahi_roomlist_manager_get_type ())
+#define SALUT_AVAHI_ROOMLIST_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), SALUT_TYPE_AVAHI_ROOMLIST_MANAGER, \
+ SalutAvahiRoomlistManager))
+#define SALUT_AVAHI_ROOMLIST_MANAGER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), SALUT_TYPE_AVAHI_ROOMLIST_MANAGER, \
+ SalutAvahiRoomlistManagerClass))
+#define SALUT_IS_AVAHI_ROOMLIST_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), SALUT_TYPE_AVAHI_ROOMLIST_MANAGER))
+#define SALUT_IS_AVAHI_ROOMLIST_MANAGER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), SALUT_TYPE_AVAHI_ROOMLIST_MANAGER))
+#define SALUT_AVAHI_ROOMLIST_MANAGER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), SALUT_TYPE_AVAHI_ROOMLIST_MANAGER, \
+ SalutAvahiRoomlistManagerClass))
+
+SalutAvahiRoomlistManager *
+salut_avahi_roomlist_manager_new (SalutConnection *connection,
+ SalutXmppConnectionManager *xmpp_connection_manager,
+ SalutAvahiDiscoveryClient *discovery_client);
+
+G_END_DECLS
+
+#endif /* #ifndef __SALUT_AVAHI_ROOMLIST_MANAGER_H__*/
diff --git a/src/salut-connection.c b/src/salut-connection.c
index 74434cd..8457fe6 100644
--- a/src/salut-connection.c
+++ b/src/salut-connection.c
@@ -39,6 +39,7 @@
#include "salut-muc-manager.h"
#include "salut-ft-manager.h"
#include "salut-contact.h"
+#include "salut-roomlist-manager.h"
#include "salut-self.h"
#include "salut-xmpp-connection-manager.h"
#include "salut-si-bytestream-manager.h"
@@ -140,6 +141,7 @@ enum {
PROP_IM_MANAGER,
PROP_MUC_MANAGER,
PROP_TUBES_MANAGER,
+ PROP_ROOMLIST_MANAGER,
PROP_CONTACT_MANAGER,
PROP_SELF,
PROP_XCM,
@@ -190,6 +192,9 @@ struct _SalutConnectionPrivate
/* FT channel manager */
SalutFtManager *ft_manager;
+ /* MUC channel manager */
+ SalutRoomlistManager *roomlist_manager;
+
/* Tubes channel manager */
SalutTubesManager *tubes_manager;
@@ -342,6 +347,9 @@ salut_connection_get_property (GObject *object,
case PROP_TUBES_MANAGER:
g_value_set_object (value, priv->tubes_manager);
break;
+ case PROP_ROOMLIST_MANAGER:
+ g_value_set_object (value, priv->roomlist_manager);
+ break;
case PROP_CONTACT_MANAGER:
g_value_set_object (value, priv->contact_manager);
break;
@@ -710,6 +718,17 @@ salut_connection_class_init (SalutConnectionClass *salut_connection_class)
param_spec);
param_spec = g_param_spec_object (
+ "roomlist-manager",
+ "SalutRoomlistManager object",
+ "The Salut Roomlist Manager associated with this Salut Connection",
+ SALUT_TYPE_ROOMLIST_MANAGER,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB);
+ g_object_class_install_property (object_class, PROP_ROOMLIST_MANAGER,
+ param_spec);
+
+ param_spec = g_param_spec_object (
"contact-manager",
"SalutContactManager object",
"The Salut Contact Manager associated with this Salut Connection",
@@ -887,7 +906,7 @@ _self_established_cb (SalutSelf *s, gpointer data)
return;
}
- if (!salut_muc_manager_start (priv->muc_manager, NULL))
+ if (!salut_roomlist_manager_start (priv->roomlist_manager, NULL))
{
/* XXX handle error */
return;
@@ -2845,9 +2864,13 @@ salut_connection_create_channel_managers (TpBaseConnection *base)
priv->ft_manager = salut_ft_manager_new (self, priv->contact_manager,
priv->xmpp_connection_manager);
+ priv->muc_manager = salut_discovery_client_create_muc_manager (
+ priv->discovery_client, self, priv->xmpp_connection_manager);
+
g_ptr_array_add (managers, priv->im_manager);
g_ptr_array_add (managers, priv->contact_manager);
g_ptr_array_add (managers, priv->ft_manager);
+ g_ptr_array_add (managers, priv->muc_manager);
return managers;
}
diff --git a/src/salut-muc-manager.c b/src/salut-muc-manager.c
index 6359066..d105e6b 100644
--- a/src/salut-muc-manager.c
+++ b/src/salut-muc-manager.c
@@ -33,11 +33,14 @@
#include "salut-contact-manager.h"
#include "salut-tubes-channel.h"
#include "salut-roomlist-channel.h"
+#include "salut-roomlist-manager.h"
#include "salut-xmpp-connection-manager.h"
#include "salut-discovery-client.h"
-#include <telepathy-glib/channel-factory-iface.h>
+#include <telepathy-glib/channel-manager.h>
+#include <telepathy-glib/dbus.h>
#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/util.h>
#define DEBUG_FLAG DEBUG_MUC
#include "debug.h"
@@ -53,13 +56,13 @@ invite_stanza_callback (SalutXmppConnectionManager *mgr,
SalutContact *contact, gpointer user_data);
-static void salut_muc_manager_factory_iface_init (gpointer g_iface,
+static void salut_muc_manager_iface_init (gpointer g_iface,
gpointer iface_data);
G_DEFINE_TYPE_WITH_CODE(SalutMucManager, salut_muc_manager,
G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_FACTORY_IFACE,
- salut_muc_manager_factory_iface_init));
+ G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_MANAGER,
+ salut_muc_manager_iface_init));
/* properties */
enum {
@@ -74,6 +77,7 @@ typedef struct _SalutMucManagerPrivate SalutMucManagerPrivate;
struct _SalutMucManagerPrivate
{
SalutConnection *connection;
+ gulong status_changed_id;
SalutXmppConnectionManager *xmpp_connection_manager;
/* GUINT_TO_POINTER (room_handle) => (SalutMucChannel *) */
@@ -82,7 +86,11 @@ struct _SalutMucManagerPrivate
/* GUINT_TO_POINTER(room_handle) => (SalutTubesChannel *) */
GHashTable *tubes_channels;
#endif
- GSList *roomlist_channels;
+
+ /* Map from channels to the request-tokens of requests that they will
+ * satisfy when they're ready.
+ * Borrowed TpExportableChannel => GSList of gpointer */
+ GHashTable *queued_requests;
gboolean dispose_has_run;
};
@@ -103,8 +111,6 @@ salut_muc_manager_init (SalutMucManager *obj)
priv->tubes_channels = g_hash_table_new_full (g_direct_hash, g_direct_equal,
NULL, g_object_unref);
#endif
-
- priv->roomlist_channels = NULL;
}
static void
@@ -152,6 +158,59 @@ salut_muc_manager_set_property (GObject *object,
}
}
+static void
+closed_channel_foreach (TpHandle handle,
+ SalutMucChannel *channel,
+ SalutMucManager *self)
+{
+ salut_muc_channel_emit_closed (channel);
+}
+
+static void
+salut_muc_manager_close_all (SalutMucManager *self)
+{
+ SalutMucManagerPrivate *priv = SALUT_MUC_MANAGER_GET_PRIVATE (self);
+
+ DEBUG ("closing channels");
+
+ if (priv->status_changed_id != 0)
+ {
+ g_signal_handler_disconnect (priv->connection, priv->status_changed_id);
+ priv->status_changed_id = 0;
+ }
+
+ if (priv->text_channels)
+ {
+ GHashTable *tmp = priv->text_channels;
+ priv->text_channels = NULL;
+ g_hash_table_foreach (tmp, (GHFunc) closed_channel_foreach, self);
+ g_hash_table_destroy (tmp);
+ }
+
+#ifdef ENABLE_DBUS_TUBES
+ if (priv->tubes_channels != NULL)
+ {
+ GHashTable *tmp = priv->tubes_channels;
+ priv->tubes_channels = NULL;
+ g_hash_table_destroy (tmp);
+ }
+#endif
+}
+
+static void
+connection_status_changed_cb (SalutConnection *conn,
+ guint status,
+ guint reason,
+ SalutMucManager *self)
+{
+ switch (status)
+ {
+ case TP_CONNECTION_STATUS_DISCONNECTED:
+ salut_muc_manager_close_all (self);
+ break;
+ }
+}
+
static GObject *
salut_muc_manager_constructor (GType type,
guint n_props,
@@ -169,6 +228,9 @@ salut_muc_manager_constructor (GType type,
priv->xmpp_connection_manager, NULL,
invite_stanza_filter, invite_stanza_callback, obj);
+ priv->status_changed_id = g_signal_connect (priv->connection,
+ "status-changed", (GCallback) connection_status_changed_cb, obj);
+
return obj;
}
@@ -228,7 +290,7 @@ salut_muc_manager_dispose (GObject *object)
priv->xmpp_connection_manager, NULL,
invite_stanza_filter, invite_stanza_callback, self);
- tp_channel_factory_iface_close_all (TP_CHANNEL_FACTORY_IFACE (object));
+ salut_muc_manager_close_all (self);
g_assert (priv->text_channels == NULL);
#ifdef ENABLE_DBUS_TUBES
g_assert (priv->tubes_channels == NULL);
@@ -257,108 +319,95 @@ salut_muc_manager_finalize (GObject *object)
G_OBJECT_CLASS (salut_muc_manager_parent_class)->finalize (object);
}
-static void
-closed_channel_foreach (TpHandle handle,
- SalutMucChannel *channel,
- SalutMucManager *self)
-{
- salut_muc_channel_emit_closed (channel);
-}
-
/* Channel Factory interface */
-static void
-salut_muc_manager_factory_iface_close_all (TpChannelFactoryIface *iface) {
- SalutMucManager *mgr = SALUT_MUC_MANAGER (iface);
- SalutMucManagerPrivate *priv = SALUT_MUC_MANAGER_GET_PRIVATE (mgr);
-
- if (priv->text_channels)
- {
- GHashTable *tmp = priv->text_channels;
- priv->text_channels = NULL;
- g_hash_table_foreach (tmp, (GHFunc) closed_channel_foreach, mgr);
- g_hash_table_destroy (tmp);
- }
-
-#ifdef ENABLE_DBUS_TUBES
- if (priv->tubes_channels != NULL)
- {
- GHashTable *tmp = priv->tubes_channels;
- priv->tubes_channels = NULL;
- g_hash_table_destroy (tmp);
- }
-#endif
+struct _ForeachData
+{
+ TpExportableChannelFunc foreach;
+ gpointer user_data;
+};
- if (priv->roomlist_channels != NULL)
- {
- GSList *l = priv->roomlist_channels;
- priv->roomlist_channels = NULL;
- g_slist_foreach (l, (GFunc) g_object_unref, NULL);
- g_slist_free (l);
- }
-}
static void
-salut_muc_manager_factory_iface_connecting (TpChannelFactoryIface *iface)
+_foreach_slave (gpointer key, gpointer value, gpointer user_data)
{
-}
+ struct _ForeachData *data = (struct _ForeachData *) user_data;
+ TpExportableChannel *channel = TP_EXPORTABLE_CHANNEL (value);
-static void
-salut_muc_manager_factory_iface_connected (TpChannelFactoryIface *iface)
-{
+ data->foreach (channel, data->user_data);
}
static void
-salut_muc_manager_factory_iface_disconnected (TpChannelFactoryIface *iface)
+salut_muc_manager_foreach_channel (TpChannelManager *iface,
+ TpExportableChannelFunc foreach,
+ gpointer user_data)
{
- /* FIMXE close all channels ? */
+ SalutMucManager *fac = SALUT_MUC_MANAGER (iface);
+ SalutMucManagerPrivate *priv = SALUT_MUC_MANAGER_GET_PRIVATE (fac);
+ struct _ForeachData data;
+
+ data.user_data = user_data;
+ data.foreach = foreach;
+
+
+ g_hash_table_foreach (priv->text_channels, _foreach_slave, &data);
+#ifdef ENABLE_DBUS_TUBES
+ g_hash_table_foreach (priv->tubes_channels, _foreach_slave, &data);
+#endif
}
-struct foreach_data {
- TpChannelFunc func;
- gpointer data;
+static const gchar * const muc_channel_fixed_properties[] = {
+ TP_IFACE_CHANNEL ".ChannelType",
+ TP_IFACE_CHANNEL ".TargetHandleType",
+ NULL
};
-static void
-salut_muc_manager_iface_foreach_one (gpointer key,
- gpointer value,
- gpointer data)
-{
- TpChannelIface *chan = TP_CHANNEL_IFACE (value);
- struct foreach_data *f = (struct foreach_data *) data;
+static const gchar * const * muc_tubes_channel_fixed_properties =
+ muc_channel_fixed_properties;
+
+static const gchar * const muc_channel_allowed_properties[] = {
+ TP_IFACE_CHANNEL ".TargetHandle",
+ TP_IFACE_CHANNEL ".TargetID",
+ NULL
+};
+
+static const gchar * const * muc_tubes_channel_allowed_properties =
+ muc_channel_allowed_properties;
- f->func (chan, f->data);
-}
static void
-salut_muc_manager_iface_foreach_one_list (TpChannelIface *chan,
- gpointer data)
+salut_muc_manager_foreach_channel_class (TpChannelManager *manager,
+ TpChannelManagerChannelClassFunc func,
+ gpointer user_data)
{
- struct foreach_data *f = (struct foreach_data *) data;
+ GHashTable *table = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, (GDestroyNotify) tp_g_value_slice_free);
+ GValue *channel_type_value, *handle_type_value;
- f->func (chan, f->data);
-}
+ channel_type_value = tp_g_value_slice_new (G_TYPE_STRING);
+ /* no string value yet - we'll change it for each channel class */
+ g_hash_table_insert (table, TP_IFACE_CHANNEL ".ChannelType",
+ channel_type_value);
-static void
-salut_muc_manager_factory_iface_foreach (TpChannelFactoryIface *iface,
- TpChannelFunc func, gpointer data) {
- SalutMucManager *mgr = SALUT_MUC_MANAGER(iface);
- SalutMucManagerPrivate *priv = SALUT_MUC_MANAGER_GET_PRIVATE(mgr);
- struct foreach_data f;
- f.func = func;
- f.data = data;
+ handle_type_value = tp_g_value_slice_new (G_TYPE_UINT);
+ g_value_set_uint (handle_type_value, TP_HANDLE_TYPE_ROOM);
+ g_hash_table_insert (table, TP_IFACE_CHANNEL ".TargetHandleType",
+ handle_type_value);
- g_hash_table_foreach (priv->text_channels,
- salut_muc_manager_iface_foreach_one, &f);
-#ifdef ENABLE_DBUS_TUBES
- g_hash_table_foreach (priv->tubes_channels,
- salut_muc_manager_iface_foreach_one, &f);
-#endif
+ g_value_set_static_string (channel_type_value, TP_IFACE_CHANNEL_TYPE_TEXT);
+ func (manager, table, muc_channel_allowed_properties,
+ user_data);
- g_slist_foreach (priv->roomlist_channels,
- (GFunc) salut_muc_manager_iface_foreach_one_list, &f);
+ g_value_set_static_string (channel_type_value, TP_IFACE_CHANNEL_TYPE_TUBES);
+ func (manager, table, muc_tubes_channel_allowed_properties,
+ user_data);
+
+ /* FIXME: add roomlist channels */
+
+ g_hash_table_destroy (table);
}
+
static void
muc_channel_closed_cb (SalutMucChannel *chan,
gpointer user_data)
@@ -367,6 +416,9 @@ muc_channel_closed_cb (SalutMucChannel *chan,
SalutMucManagerPrivate *priv = SALUT_MUC_MANAGER_GET_PRIVATE (self);
TpHandle handle;
+ tp_channel_manager_emit_channel_closed_for_object (self,
+ TP_EXPORTABLE_CHANNEL (chan));
+
if (priv->text_channels)
{
g_object_get (chan, "handle", &handle, NULL);
@@ -402,6 +454,9 @@ tubes_channel_closed_cb (SalutTubesChannel *chan, gpointer user_data)
SalutMucManagerPrivate *priv = SALUT_MUC_MANAGER_GET_PRIVATE (fac);
TpHandle room_handle;
+ tp_channel_manager_emit_channel_closed_for_object (fac,
+ TP_EXPORTABLE_CHANNEL (chan));
+
if (priv->tubes_channels != NULL)
{
g_object_get (chan, "handle", &room_handle, NULL);
@@ -430,6 +485,20 @@ _get_connection (SalutMucManager *mgr,
protocol, parameters, error);
}
+static void
+salut_muc_manager_emit_new_channel (SalutMucManager *self,
+ TpExportableChannel *channel)
+{
+ SalutMucManagerPrivate *priv = SALUT_MUC_MANAGER_GET_PRIVATE (self);
+ GSList *requests_satisfied;
+
+ requests_satisfied = g_hash_table_lookup (priv->queued_requests, channel);
+ g_hash_table_steal (priv->queued_requests, channel);
+ requests_satisfied = g_slist_reverse (requests_satisfied);
+ tp_channel_manager_emit_new_channel (self, channel, requests_satisfied);
+ g_slist_free (requests_satisfied);
+}
+
static SalutMucChannel *
salut_muc_manager_new_muc_channel (SalutMucManager *mgr,
@@ -462,8 +531,7 @@ salut_muc_manager_new_muc_channel (SalutMucManager *mgr,
g_free (path);
g_signal_connect (chan, "closed", G_CALLBACK (muc_channel_closed_cb), mgr);
- tp_channel_factory_iface_emit_new_channel (mgr, TP_CHANNEL_IFACE (chan),
- NULL);
+ salut_muc_manager_emit_new_channel (mgr, TP_EXPORTABLE_CHANNEL (chan));
g_hash_table_insert (priv->text_channels, GUINT_TO_POINTER (handle), chan);
@@ -505,8 +573,7 @@ new_tubes_channel (SalutMucManager *self,
NULL);
g_signal_connect (chan, "closed", (GCallback) tubes_channel_closed_cb, self);
- tp_channel_factory_iface_emit_new_channel (self,
- TP_CHANNEL_IFACE (chan), NULL);
+ salut_muc_manager_emit_new_channel (self, TP_EXPORTABLE_CHANNEL (chan));
g_hash_table_insert (priv->tubes_channels, GUINT_TO_POINTER (room), chan);
@@ -533,11 +600,14 @@ salut_muc_manager_request_new_muc_channel (SalutMucManager *mgr,
gchar *address;
guint16 p;
gboolean r;
+ SalutRoomlistManager *roomlist_manager;
+
+ g_object_get (priv->connection, "roomlist-manager", &roomlist_manager, NULL);
room_name = tp_handle_inspect (room_repo, handle);
- if (SALUT_MUC_MANAGER_GET_CLASS (mgr)->find_muc_address (mgr, room_name,
- &address, &p))
+ if (SALUT_ROOMLIST_MANAGER_GET_CLASS (roomlist_manager)->find_muc_address
+ (roomlist_manager, room_name, &address, &p))
{
/* This MUC already exists on the network, so we reuse its
* address */
@@ -594,58 +664,6 @@ salut_muc_manager_request_new_muc_channel (SalutMucManager *mgr,
return text_chan;
}
-static void
-roomlist_channel_closed_cb (SalutRoomlistChannel *chan,
- gpointer data)
-{
- SalutMucManager *self = SALUT_MUC_MANAGER (data);
- SalutMucManagerPrivate *priv = SALUT_MUC_MANAGER_GET_PRIVATE (self);
-
- if (priv->roomlist_channels != NULL)
- {
- g_object_unref (chan);
- priv->roomlist_channels = g_slist_remove (priv->roomlist_channels, chan);
- }
-}
-
-static SalutRoomlistChannel *
-make_roomlist_channel (SalutMucManager *self,
- gpointer request)
-{
- SalutMucManagerPrivate *priv = SALUT_MUC_MANAGER_GET_PRIVATE (self);
- TpBaseConnection *conn = (TpBaseConnection *) priv->connection;
- SalutRoomlistChannel *roomlist_channel;
- gchar *object_path;
- static guint cpt = 0;
- GSList *rooms, *l;
-
- object_path = g_strdup_printf ("%s/RoomlistChannel%u",
- conn->object_path, cpt++);
-
- roomlist_channel = salut_roomlist_channel_new (priv->connection,
- object_path);
-
- rooms = SALUT_MUC_MANAGER_GET_CLASS (self)->get_rooms (self);
- for (l = rooms; l != NULL; l = g_slist_next (l))
- {
- const gchar *room_name = l->data;
-
- salut_roomlist_channel_add_room (roomlist_channel, room_name);
- }
-
- priv->roomlist_channels = g_slist_prepend (priv->roomlist_channels,
- roomlist_channel);
-
- g_signal_connect (roomlist_channel, "closed",
- (GCallback) roomlist_channel_closed_cb, self);
-
- tp_channel_factory_iface_emit_new_channel (self,
- (TpChannelIface *) roomlist_channel, request);
-
- g_free (object_path);
- return roomlist_channel;
-}
-
static SalutTubesChannel *
create_tubes_channel (SalutMucManager *self,
TpHandle handle,
@@ -675,112 +693,201 @@ create_tubes_channel (SalutMucManager *self,
return tubes_chan;
}
-static TpChannelFactoryRequestStatus
-salut_muc_manager_factory_iface_request (TpChannelFactoryIface *iface,
- const gchar *chan_type,
- TpHandleType handle_type,
- guint handle,
- gpointer request,
- TpChannelIface **ret,
- GError **error)
+/**
+ * ensure_muc_channel:
+ *
+ * Create a MUC channel in response to RequestChannel.
+ *
+ * Return TRUE if it already existed, or return FALSE
+ * if it needed to be created (so isn't ready yet).
+ */
+static gboolean
+ensure_muc_channel (SalutMucManager *fac,
+ SalutMucManagerPrivate *priv,
+ TpHandle handle,
+ SalutMucChannel **ret)
{
- SalutMucManager *mgr = SALUT_MUC_MANAGER (iface);
- SalutMucManagerPrivate *priv = SALUT_MUC_MANAGER_GET_PRIVATE (mgr);
- TpBaseConnection *base_connection = (TpBaseConnection *) (priv->connection);
- TpHandleRepoIface *room_repo =
- tp_base_connection_get_handles (base_connection, TP_HANDLE_TYPE_ROOM);
- SalutMucChannel *text_chan;
- TpChannelFactoryRequestStatus status;
+ *ret = g_hash_table_lookup (priv->text_channels, GINT_TO_POINTER (handle));
- DEBUG ("MUC request: ctype=%s htype=%u handle=%u", chan_type, handle_type,
- handle);
-
- if (!tp_strdiff (chan_type, TP_IFACE_CHANNEL_TYPE_ROOM_LIST))
+ if (*ret == NULL)
{
- SalutRoomlistChannel *roomlist_channel;
-
- roomlist_channel = make_roomlist_channel (mgr, request);
- *ret = TP_CHANNEL_IFACE (roomlist_channel);
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_CREATED;
+ *ret = salut_muc_manager_request_new_muc_channel (fac, handle, NULL);
+ return FALSE;
}
- if (handle_type != TP_HANDLE_TYPE_ROOM)
- {
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_NOT_AVAILABLE;
- }
+ return TRUE;
+}
- /* Most be a valid room handle */
- if (!tp_handle_is_valid (room_repo, handle, NULL))
- {
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_INVALID_HANDLE;
- }
+static void
+salut_muc_manager_associate_request (SalutMucManager *self,
+ gpointer channel,
+ gpointer request)
+{
+ SalutMucManagerPrivate *priv = SALUT_MUC_MANAGER_GET_PRIVATE (self);
+ GSList *list = g_hash_table_lookup (priv->queued_requests, channel);
+
+ g_assert (TP_IS_EXPORTABLE_CHANNEL (channel));
+
+ g_hash_table_steal (priv->queued_requests, channel);
+ list = g_slist_prepend (list, request);
+ g_hash_table_insert (priv->queued_requests, channel, list);
+}
+
+
+static gboolean
+salut_muc_manager_request (SalutMucManager *self,
+ gpointer request_token,
+ GHashTable *request_properties,
+ gboolean require_new)
+{
+ SalutMucManagerPrivate *priv = SALUT_MUC_MANAGER_GET_PRIVATE (self);
+ TpBaseConnection *base_conn = (TpBaseConnection *) priv->connection;
+ TpHandleRepoIface *room_repo = tp_base_connection_get_handles (base_conn,
+ TP_HANDLE_TYPE_ROOM);
+ GError *error = NULL;
+ TpHandle handle;
+ const gchar *channel_type;
+ SalutMucChannel *text_chan;
+ SalutTubesChannel *tubes_chan;
+
+ if (tp_asv_get_uint32 (request_properties,
+ TP_IFACE_CHANNEL ".TargetHandleType", NULL) != TP_HANDLE_TYPE_ROOM)
+ return FALSE;
- if (!tp_strdiff (chan_type, TP_IFACE_CHANNEL_TYPE_TEXT))
+ handle = tp_asv_get_uint32 (request_properties,
+ TP_IFACE_CHANNEL ".TargetHandle", NULL);
+
+ if (!tp_handle_is_valid (room_repo, handle, &error))
+ goto error;
+
+ channel_type = tp_asv_get_string (request_properties,
+ TP_IFACE_CHANNEL ".ChannelType");
+
+ if (!tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TEXT))
{
- text_chan = g_hash_table_lookup (priv->text_channels,
- GUINT_TO_POINTER (handle));
+ if (tp_channel_manager_asv_has_unknown_properties (request_properties,
+ muc_channel_fixed_properties, muc_channel_allowed_properties,
+ &error))
+ goto error;
- if (text_chan != NULL)
+ if (ensure_muc_channel (self, priv, handle, &text_chan))
{
- status = TP_CHANNEL_FACTORY_REQUEST_STATUS_EXISTING;
+ if (require_new)
+ {
+ g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ "That channel has already been created (or requested)");
+ goto error;
+ }
+ else
+ {
+ tp_channel_manager_emit_request_already_satisfied (self,
+ request_token, TP_EXPORTABLE_CHANNEL (text_chan));
+ }
}
else
{
- text_chan = salut_muc_manager_request_new_muc_channel (mgr,
- handle, error);
- if (text_chan == NULL)
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_ERROR;
-
- status = TP_CHANNEL_FACTORY_REQUEST_STATUS_CREATED;
+ salut_muc_manager_associate_request (self, text_chan,
+ request_token);
}
- g_assert (text_chan != NULL);
- *ret = TP_CHANNEL_IFACE (text_chan);
+ return TRUE;
}
-#ifdef ENABLE_DBUS_TUBES
- else if (!tp_strdiff (chan_type, TP_IFACE_CHANNEL_TYPE_TUBES))
+ else if (!tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TUBES))
{
- SalutTubesChannel *tubes_chan;
+ if (tp_channel_manager_asv_has_unknown_properties (request_properties,
+ muc_tubes_channel_fixed_properties,
+ muc_tubes_channel_allowed_properties,
+ &error))
+ goto error;
tubes_chan = g_hash_table_lookup (priv->tubes_channels,
GUINT_TO_POINTER (handle));
if (tubes_chan != NULL)
{
- status = TP_CHANNEL_FACTORY_REQUEST_STATUS_EXISTING;
- *ret = TP_CHANNEL_IFACE (tubes_chan);
+ if (require_new)
+ {
+ g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ "That channel has already been created (or requested)");
+ goto error;
+ }
+ else
+ {
+ tp_channel_manager_emit_request_already_satisfied (self,
+ request_token, TP_EXPORTABLE_CHANNEL (tubes_chan));
+ }
}
else
{
- tubes_chan = create_tubes_channel (mgr, handle,
- base_connection->self_handle, error);
- if (tubes_chan == NULL)
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_ERROR;
-
- *ret = TP_CHANNEL_IFACE (tubes_chan);
-
- status = TP_CHANNEL_FACTORY_REQUEST_STATUS_CREATED;
+ ensure_muc_channel (self, priv, handle, &text_chan);
+ tubes_chan = new_tubes_channel (self, handle, text_chan,
+ base_conn->self_handle);
+ salut_muc_manager_associate_request (self, tubes_chan,
+ request_token);
+ salut_muc_manager_emit_new_channel (self,
+ TP_EXPORTABLE_CHANNEL (tubes_chan));
}
+
+ return TRUE;
}
-#endif
else
{
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_NOT_IMPLEMENTED;
+ return FALSE;
}
- return status;
+error:
+ tp_channel_manager_emit_request_failed (self, request_token,
+ error->domain, error->code, error->message);
+ g_error_free (error);
+ return TRUE;
+}
+
+static gboolean
+salut_muc_manager_create_channel (TpChannelManager *manager,
+ gpointer request_token,
+ GHashTable *request_properties)
+{
+ SalutMucManager *self = SALUT_MUC_MANAGER (manager);
+
+ return salut_muc_manager_request (self, request_token, request_properties,
+ TRUE);
+}
+
+
+static gboolean
+salut_muc_manager_request_channel (TpChannelManager *manager,
+ gpointer request_token,
+ GHashTable *request_properties)
+{
+ SalutMucManager *self = SALUT_MUC_MANAGER (manager);
+
+ return salut_muc_manager_request (self, request_token, request_properties,
+ FALSE);
}
-static void salut_muc_manager_factory_iface_init (gpointer g_iface,
- gpointer iface_data) {
- TpChannelFactoryIfaceClass *klass = (TpChannelFactoryIfaceClass *)g_iface;
- klass->close_all = salut_muc_manager_factory_iface_close_all;
- klass->connecting = salut_muc_manager_factory_iface_connecting;
- klass->connected = salut_muc_manager_factory_iface_connected;
- klass->disconnected = salut_muc_manager_factory_iface_disconnected;
- klass->foreach = salut_muc_manager_factory_iface_foreach;
- klass->request = salut_muc_manager_factory_iface_request;
+static gboolean
+salut_muc_manager_ensure_channel (TpChannelManager *manager,
+ gpointer request_token,
+ GHashTable *request_properties)
+{
+ SalutMucManager *self = SALUT_MUC_MANAGER (manager);
+
+ return salut_muc_manager_request (self, request_token, request_properties,
+ FALSE);
+}
+
+
+static void salut_muc_manager_iface_init (gpointer g_iface,
+ gpointer iface_data)
+{
+ TpChannelManagerIface *iface = g_iface;
+
+ iface->foreach_channel = salut_muc_manager_foreach_channel;
+ iface->foreach_channel_class = salut_muc_manager_foreach_channel_class;
+ iface->request_channel = salut_muc_manager_request_channel;
+ iface->create_channel = salut_muc_manager_create_channel;
+ iface->ensure_channel = salut_muc_manager_ensure_channel;
}
static gboolean
@@ -921,13 +1028,6 @@ discard:
/* public functions */
-gboolean
-salut_muc_manager_start (SalutMucManager *self,
- GError **error)
-{
- return SALUT_MUC_MANAGER_GET_CLASS (self)->start (self, error);
-}
-
SalutMucChannel *
salut_muc_manager_get_text_channel (SalutMucManager *self,
TpHandle handle)
@@ -997,53 +1097,3 @@ salut_muc_manager_ensure_tubes_channel (SalutMucManager *self,
return tubes_chan;
}
-static void
-add_room_foreach (SalutRoomlistChannel *roomlist_channel,
- const gchar *room)
-{
- salut_roomlist_channel_add_room (roomlist_channel, room);
-}
-
-void
-salut_muc_manager_room_discovered (SalutMucManager *self,
- const gchar *room)
-{
- SalutMucManagerPrivate *priv = SALUT_MUC_MANAGER_GET_PRIVATE (self);
-
- g_slist_foreach (priv->roomlist_channels, (GFunc) add_room_foreach,
- (gchar *) room);
-}
-
-static void
-remove_room_foreach (SalutRoomlistChannel *roomlist_channel,
- const gchar *room)
-{
- salut_roomlist_channel_remove_room (roomlist_channel, room);
-}
-
-void
-salut_muc_manager_room_removed (SalutMucManager *self,
- const gchar *room)
-{
- SalutMucManagerPrivate *priv = SALUT_MUC_MANAGER_GET_PRIVATE (self);
- TpBaseConnection *base_connection = TP_BASE_CONNECTION (priv->connection);
- TpHandleRepoIface *room_repo =
- tp_base_connection_get_handles (base_connection, TP_HANDLE_TYPE_ROOM);
- TpHandle handle;
- SalutMucChannel *muc;
-
- g_slist_foreach (priv->roomlist_channels, (GFunc) remove_room_foreach,
- (gchar *) room);
-
- /* Do we have to re-announce this room ? */
- handle = tp_handle_lookup (room_repo, room, NULL, NULL);
- if (handle == 0)
- return;
-
- muc = g_hash_table_lookup (priv->text_channels, GUINT_TO_POINTER (handle));
- if (muc == NULL)
- return;
-
- DEBUG ("We know this room %s. Try to re-announce it", room);
- salut_muc_channel_publish_service (muc);
-}
diff --git a/src/salut-muc-manager.h b/src/salut-muc-manager.h
index 8bffb24..3b3e07a 100644
--- a/src/salut-muc-manager.h
+++ b/src/salut-muc-manager.h
@@ -38,15 +38,6 @@ typedef struct _SalutMucManagerClass SalutMucManagerClass;
struct _SalutMucManagerClass {
GObjectClass parent_class;
- /* public abstract methods */
- gboolean (*start) (SalutMucManager *self, GError **error);
-
- /* private abstract methods */
- gboolean (*find_muc_address) (SalutMucManager *self, const gchar *name,
- gchar **address, guint16 *port);
-
- GSList * (*get_rooms) (SalutMucManager *self);
-
SalutMucChannel * (*create_muc_channel) (SalutMucManager *self,
SalutConnection *connection, const gchar *path,
GibberMucConnection *muc_connection, TpHandle handle,
@@ -74,9 +65,6 @@ GType salut_muc_manager_get_type (void);
#define SALUT_MUC_MANAGER_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), SALUT_TYPE_MUC_MANAGER, SalutMucManagerClass))
-gboolean
-salut_muc_manager_start (SalutMucManager *muc_manager, GError **error);
-
SalutMucChannel *
salut_muc_manager_get_text_channel (SalutMucManager *muc_manager,
TpHandle handle);
@@ -89,13 +77,6 @@ SalutTubesChannel * salut_muc_manager_ensure_tubes_channel (
SalutMucManager *muc_manager, TpHandle handle, TpHandle actor);
-/* "protected" methods */
-void salut_muc_manager_room_discovered (SalutMucManager *muc_manager,
- const gchar *room);
-
-void salut_muc_manager_room_removed (SalutMucManager *muc_manager,
- const gchar *room);
-
G_END_DECLS
#endif /* #ifndef __SALUT_MUC_MANAGER_H__*/
diff --git a/src/salut-roomlist-manager.c b/src/salut-roomlist-manager.c
new file mode 100644
index 0000000..64d2c34
--- /dev/null
+++ b/src/salut-roomlist-manager.c
@@ -0,0 +1,440 @@
+/*
+ * salut-roomlist-manager.c - Source for SalutRoomlistManager
+ * Copyright (C) 2006 Collabora Ltd.
+ *
+ * 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 <dbus/dbus-glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <arpa/inet.h>
+
+#include "salut-roomlist-manager.h"
+
+#include <gibber/gibber-muc-connection.h>
+#include <gibber/gibber-namespaces.h>
+#include <gibber/gibber-xmpp-error.h>
+
+#include "salut-roomlist-channel.h"
+#include "salut-contact-manager.h"
+#include "salut-muc-manager.h"
+#include "salut-tubes-channel.h"
+#include "salut-roomlist-channel.h"
+#include "salut-xmpp-connection-manager.h"
+#include "salut-discovery-client.h"
+
+#include <telepathy-glib/channel-manager.h>
+#include <telepathy-glib/dbus.h>
+#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/util.h>
+
+#define DEBUG_FLAG DEBUG_MUC
+#include "debug.h"
+
+static void salut_roomlist_manager_iface_init (gpointer g_iface,
+ gpointer iface_data);
+
+G_DEFINE_TYPE_WITH_CODE(SalutRoomlistManager, salut_roomlist_manager,
+ G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_MANAGER,
+ salut_roomlist_manager_iface_init));
+
+/* properties */
+enum {
+ PROP_CONNECTION = 1,
+ LAST_PROP
+};
+
+/* private structure */
+typedef struct _SalutRoomlistManagerPrivate SalutRoomlistManagerPrivate;
+
+struct _SalutRoomlistManagerPrivate
+{
+ SalutConnection *connection;
+ gulong status_changed_id;
+
+ GSList *roomlist_channels;
+
+ /* Map from channels to the request-tokens of requests that they will
+ * satisfy when they're ready.
+ * Borrowed TpExportableChannel => GSList of gpointer */
+ GHashTable *queued_requests;
+
+ gboolean dispose_has_run;
+};
+
+#define SALUT_ROOMLIST_MANAGER_GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), SALUT_TYPE_ROOMLIST_MANAGER, \
+ SalutRoomlistManagerPrivate))
+
+static void
+salut_roomlist_manager_init (SalutRoomlistManager *obj)
+{
+ SalutRoomlistManagerPrivate *priv = SALUT_ROOMLIST_MANAGER_GET_PRIVATE (obj);
+ priv->connection = NULL;
+}
+
+static void
+salut_roomlist_manager_get_property (GObject *object,
+ guint property_id, GValue *value, GParamSpec *pspec)
+{
+ SalutRoomlistManager *self = SALUT_ROOMLIST_MANAGER (object);
+ SalutRoomlistManagerPrivate *priv = SALUT_ROOMLIST_MANAGER_GET_PRIVATE (self);
+
+ switch (property_id)
+ {
+ case PROP_CONNECTION:
+ g_value_set_object (value, priv->connection);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+salut_roomlist_manager_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ SalutRoomlistManager *self = SALUT_ROOMLIST_MANAGER (object);
+ SalutRoomlistManagerPrivate *priv = SALUT_ROOMLIST_MANAGER_GET_PRIVATE (self);
+
+ switch (property_id)
+ {
+ case PROP_CONNECTION:
+ priv->connection = g_value_get_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+salut_roomlist_manager_close_all (SalutRoomlistManager *self)
+{
+ SalutRoomlistManagerPrivate *priv = SALUT_ROOMLIST_MANAGER_GET_PRIVATE (self);
+
+ DEBUG ("closing channels");
+
+ if (priv->status_changed_id != 0)
+ {
+ g_signal_handler_disconnect (priv->connection, priv->status_changed_id);
+ priv->status_changed_id = 0;
+ }
+
+ /* FIXME: close roomlist channels */
+}
+
+static void
+connection_status_changed_cb (SalutConnection *conn,
+ guint status,
+ guint reason,
+ SalutRoomlistManager *self)
+{
+ switch (status)
+ {
+ case TP_CONNECTION_STATUS_DISCONNECTED:
+ salut_roomlist_manager_close_all (self);
+ break;
+ }
+}
+
+static GObject *
+salut_roomlist_manager_constructor (GType type,
+ guint n_props,
+ GObjectConstructParam *props)
+{
+ GObject *obj;
+ SalutRoomlistManagerPrivate *priv;
+
+ obj = G_OBJECT_CLASS (salut_roomlist_manager_parent_class)->
+ constructor (type, n_props, props);
+
+ priv = SALUT_ROOMLIST_MANAGER_GET_PRIVATE (obj);
+
+ priv->status_changed_id = g_signal_connect (priv->connection,
+ "status-changed", (GCallback) connection_status_changed_cb, obj);
+
+ return obj;
+}
+
+static void salut_roomlist_manager_dispose (GObject *object);
+static void salut_roomlist_manager_finalize (GObject *object);
+
+static void
+salut_roomlist_manager_class_init (
+ SalutRoomlistManagerClass *salut_roomlist_manager_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (salut_roomlist_manager_class);
+ GParamSpec *param_spec;
+
+ g_type_class_add_private (salut_roomlist_manager_class,
+ sizeof (SalutRoomlistManagerPrivate));
+
+ object_class->get_property = salut_roomlist_manager_get_property;
+ object_class->set_property = salut_roomlist_manager_set_property;
+
+ object_class->constructor = salut_roomlist_manager_constructor;
+ object_class->dispose = salut_roomlist_manager_dispose;
+ object_class->finalize = salut_roomlist_manager_finalize;
+
+ param_spec = g_param_spec_object (
+ "connection",
+ "SalutConnection object",
+ "The Salut Connection associated with this roomlist manager",
+ SALUT_TYPE_CONNECTION,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_CONNECTION,
+ param_spec);
+}
+
+void
+salut_roomlist_manager_dispose (GObject *object)
+{
+ SalutRoomlistManager *self = SALUT_ROOMLIST_MANAGER (object);
+ SalutRoomlistManagerPrivate *priv = SALUT_ROOMLIST_MANAGER_GET_PRIVATE (self);
+
+ if (priv->dispose_has_run)
+ return;
+
+ priv->dispose_has_run = TRUE;
+
+ salut_roomlist_manager_close_all (self);
+
+ /* release any references held by the object here */
+
+ if (G_OBJECT_CLASS (salut_roomlist_manager_parent_class)->dispose)
+ G_OBJECT_CLASS (salut_roomlist_manager_parent_class)->dispose (object);
+}
+
+void
+salut_roomlist_manager_finalize (GObject *object)
+{
+ /*SalutRoomlistManager *self = SALUT_ROOMLIST_MANAGER (object);*/
+ /*SalutRoomlistManagerPrivate *priv = SALUT_ROOMLIST_MANAGER_GET_PRIVATE (self);*/
+
+ /* free any data held directly by the object here */
+
+ G_OBJECT_CLASS (salut_roomlist_manager_parent_class)->finalize (object);
+}
+
+/* Channel Factory interface */
+
+struct _ForeachData
+{
+ TpExportableChannelFunc foreach;
+ gpointer user_data;
+};
+
+
+static void
+salut_roomlist_manager_foreach_one_list (TpChannelManager *chan,
+ gpointer user_data)
+{
+ struct _ForeachData *data = (struct _ForeachData *) user_data;
+ TpExportableChannel *channel = TP_EXPORTABLE_CHANNEL (chan);
+
+ data->foreach (channel, data->user_data);
+}
+
+
+static void
+salut_roomlist_manager_foreach_channel (TpChannelManager *iface,
+ TpExportableChannelFunc foreach,
+ gpointer user_data)
+{
+ SalutRoomlistManager *fac = SALUT_ROOMLIST_MANAGER (iface);
+ SalutRoomlistManagerPrivate *priv = SALUT_ROOMLIST_MANAGER_GET_PRIVATE (fac);
+ struct _ForeachData data;
+
+ data.user_data = user_data;
+ data.foreach = foreach;
+
+ g_slist_foreach (priv->roomlist_channels,
+ (GFunc) salut_roomlist_manager_foreach_one_list, &data);
+}
+
+static const gchar * const roomlist_channel_fixed_properties[] = {
+ TP_IFACE_CHANNEL ".ChannelType",
+ TP_IFACE_CHANNEL ".TargetHandleType",
+ NULL
+};
+
+static const gchar * const roomlist_channel_allowed_properties[] = {
+ TP_IFACE_CHANNEL ".TargetHandle",
+ TP_IFACE_CHANNEL ".TargetID",
+ NULL
+};
+
+
+static void
+salut_roomlist_manager_foreach_channel_class (
+ TpChannelManager *manager,
+ TpChannelManagerChannelClassFunc func,
+ gpointer user_data)
+{
+ GHashTable *table = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, (GDestroyNotify) tp_g_value_slice_free);
+ GValue *channel_type_value, *handle_type_value;
+
+ channel_type_value = tp_g_value_slice_new (G_TYPE_STRING);
+ /* no string value yet - we'll change it for each channel class */
+ g_hash_table_insert (table, TP_IFACE_CHANNEL ".ChannelType",
+ channel_type_value);
+
+ handle_type_value = tp_g_value_slice_new (G_TYPE_UINT);
+ g_value_set_uint (handle_type_value, TP_HANDLE_TYPE_ROOM);
+ g_hash_table_insert (table, TP_IFACE_CHANNEL ".TargetHandleType",
+ handle_type_value);
+
+ g_value_set_static_string (channel_type_value,
+ TP_IFACE_CHANNEL_TYPE_ROOM_LIST);
+ func (manager, table, roomlist_channel_allowed_properties,
+ user_data);
+
+
+ g_hash_table_destroy (table);
+}
+
+
+static gboolean
+salut_roomlist_manager_request (SalutRoomlistManager *self,
+ gpointer request_token,
+ GHashTable *request_properties,
+ gboolean require_new)
+{
+ return FALSE;
+}
+
+
+static gboolean
+salut_roomlist_manager_create_channel (TpChannelManager *manager,
+ gpointer request_token,
+ GHashTable *request_properties)
+{
+ SalutRoomlistManager *self = SALUT_ROOMLIST_MANAGER (manager);
+
+ return salut_roomlist_manager_request (self, request_token, request_properties,
+ TRUE);
+}
+
+
+static gboolean
+salut_roomlist_manager_request_channel (TpChannelManager *manager,
+ gpointer request_token,
+ GHashTable *request_properties)
+{
+ SalutRoomlistManager *self = SALUT_ROOMLIST_MANAGER (manager);
+
+ return salut_roomlist_manager_request (self, request_token, request_properties,
+ FALSE);
+}
+
+
+static gboolean
+salut_roomlist_manager_ensure_channel (TpChannelManager *manager,
+ gpointer request_token,
+ GHashTable *request_properties)
+{
+ SalutRoomlistManager *self = SALUT_ROOMLIST_MANAGER (manager);
+
+ return salut_roomlist_manager_request (self, request_token, request_properties,
+ FALSE);
+}
+
+
+static void salut_roomlist_manager_iface_init (gpointer g_iface,
+ gpointer iface_data)
+{
+ TpChannelManagerIface *iface = g_iface;
+
+ iface->foreach_channel = salut_roomlist_manager_foreach_channel;
+ iface->foreach_channel_class = salut_roomlist_manager_foreach_channel_class;
+ iface->request_channel = salut_roomlist_manager_request_channel;
+ iface->create_channel = salut_roomlist_manager_create_channel;
+ iface->ensure_channel = salut_roomlist_manager_ensure_channel;
+}
+
+/* public functions */
+
+gboolean
+salut_roomlist_manager_start (SalutRoomlistManager *self,
+ GError **error)
+{
+ return SALUT_ROOMLIST_MANAGER_GET_CLASS (self)->start (self, error);
+}
+
+static void
+add_room_foreach (SalutRoomlistChannel *roomlist_channel,
+ const gchar *room)
+{
+ salut_roomlist_channel_add_room (roomlist_channel, room);
+}
+
+void
+salut_roomlist_manager_room_discovered (SalutRoomlistManager *self,
+ const gchar *room)
+{
+ SalutRoomlistManagerPrivate *priv =
+ SALUT_ROOMLIST_MANAGER_GET_PRIVATE (self);
+
+ g_slist_foreach (priv->roomlist_channels, (GFunc) add_room_foreach,
+ (gchar *) room);
+}
+
+static void
+remove_room_foreach (SalutRoomlistChannel *roomlist_channel,
+ const gchar *room)
+{
+ salut_roomlist_channel_remove_room (roomlist_channel, room);
+}
+
+void
+salut_roomlist_manager_room_removed (SalutRoomlistManager *self,
+ const gchar *room)
+{
+ SalutRoomlistManagerPrivate *priv = SALUT_ROOMLIST_MANAGER_GET_PRIVATE (self);
+ TpBaseConnection *base_connection = TP_BASE_CONNECTION (priv->connection);
+ TpHandleRepoIface *room_repo =
+ tp_base_connection_get_handles (base_connection, TP_HANDLE_TYPE_ROOM);
+ TpHandle handle;
+ SalutMucChannel *muc;
+ SalutMucManager *muc_manager;
+
+ g_slist_foreach (priv->roomlist_channels, (GFunc) remove_room_foreach,
+ (gchar *) room);
+
+ /* Do we have to re-announce this room ? */
+ handle = tp_handle_lookup (room_repo, room, NULL, NULL);
+ if (handle == 0)
+ return;
+
+ g_object_get (priv->connection, "muc-manager", &muc_manager, NULL);
+ g_assert (muc_manager != NULL);
+
+ muc = salut_muc_manager_get_text_channel (muc_manager, handle);
+ if (muc == NULL)
+ return;
+
+ DEBUG ("We know this room %s. Try to re-announce it", room);
+ salut_muc_channel_publish_service (muc);
+ g_object_unref (muc);
+}
diff --git a/src/salut-roomlist-manager.h b/src/salut-roomlist-manager.h
new file mode 100644
index 0000000..dab7b11
--- /dev/null
+++ b/src/salut-roomlist-manager.h
@@ -0,0 +1,99 @@
+/*
+ * salut-roomlist-manager.h - Header for SalutRoomlistManager
+ * Copyright (C) 2006 Collabora Ltd.
+ *
+ * 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_ROOMLIST_MANAGER_H__
+#define __SALUT_ROOMLIST_MANAGER_H__
+
+#include <glib-object.h>
+
+#include <gibber/gibber-bytestream-iface.h>
+
+#include <salut-connection.h>
+#include "salut-xmpp-connection-manager.h"
+#include "salut-tubes-channel.h"
+#include "salut-roomlist-channel.h"
+
+G_BEGIN_DECLS
+
+typedef struct _SalutRoomlistManager SalutRoomlistManager;
+typedef struct _SalutRoomlistManagerClass SalutRoomlistManagerClass;
+
+struct _SalutRoomlistManagerClass {
+ GObjectClass parent_class;
+
+ /* public abstract methods */
+ gboolean (*start) (SalutRoomlistManager *self, GError **error);
+
+ /* private abstract methods */
+ gboolean (*find_muc_address) (SalutRoomlistManager *self, const gchar *name,
+ gchar **address, guint16 *port);
+
+ GSList * (*get_rooms) (SalutRoomlistManager *self);
+};
+
+struct _SalutRoomlistManager {
+ GObject parent;
+};
+
+GType salut_roomlist_manager_get_type (void);
+
+/* TYPE MACROS */
+#define SALUT_TYPE_ROOMLIST_MANAGER \
+ (salut_roomlist_manager_get_type ())
+#define SALUT_ROOMLIST_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), SALUT_TYPE_ROOMLIST_MANAGER, \
+ SalutRoomlistManager))
+#define SALUT_ROOMLIST_MANAGER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), SALUT_TYPE_ROOMLIST_MANAGER, \
+ SalutRoomlistManagerClass))
+#define SALUT_IS_ROOMLIST_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), SALUT_TYPE_ROOMLIST_MANAGER))
+#define SALUT_IS_ROOMLIST_MANAGER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), SALUT_TYPE_ROOMLIST_MANAGER))
+#define SALUT_ROOMLIST_MANAGER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), SALUT_TYPE_ROOMLIST_MANAGER, \
+ SalutRoomlistManagerClass))
+
+gboolean
+salut_roomlist_manager_start (SalutRoomlistManager *roomlist_manager,
+ GError **error);
+
+SalutRoomlistChannel *
+salut_roomlist_manager_get_text_channel (SalutRoomlistManager *roomlist_manager,
+ TpHandle handle);
+
+void salut_roomlist_manager_handle_si_stream_request (
+ SalutRoomlistManager *roomlist_manager,
+ GibberBytestreamIface *bytestream, TpHandle room_handle,
+ const gchar *stream_id, GibberXmppStanza *msg);
+
+SalutTubesChannel * salut_roomlist_manager_ensure_tubes_channel (
+ SalutRoomlistManager *roomlist_manager, TpHandle handle, TpHandle actor);
+
+/* "protected" methods */
+void salut_roomlist_manager_room_discovered (
+ SalutRoomlistManager *roomlist_manager, const gchar *room);
+
+void salut_roomlist_manager_room_removed (
+ SalutRoomlistManager *roomlist_manager, const gchar *room);
+
+
+G_END_DECLS
+
+#endif /* #ifndef __SALUT_ROOMLIST_MANAGER_H__*/
--
1.5.6.5
More information about the Telepathy-commits
mailing list