#include <telepathy-glib/account-manager.h>
#include <telepathy-glib/enums.h>
#include <telepathy-glib/connection.h>
-#include <telepathy-glib/channel-dispatcher.h>
-#include <telepathy-glib/channel-request.h>
#include <telepathy-glib/util.h>
#include <telepathy-glib/dbus.h>
#include <telepathy-glib/proxy-subclass.h>
#include <telepathy-glib/gtypes.h>
#include <telepathy-glib/defs.h>
-#include <telepathy-glib/svc-client.h>
-#include <telepathy-glib/svc-generic.h>
#include <telepathy-glib/interfaces.h>
#include <extensions/extensions.h>
/* connection to connection data mapping */
GHashTable *connections;
GHashTable *outstanding_classes_requests;
- gpointer token;
- /* channels which the dispatcher is listening "invalidated" */
- GList *channels;
- GPtrArray *array;
-
- GHashTable *request_channel_class_async_ids;
/* reffed (TpAccount *) => gulong
* Signal handler ID of the "status-changed" signal */
GHashTable *status_changed_handlers;
-
- TpChannelDispatcher *channel_dispatcher;
- TpDBusDaemon *dbus;
} EmpathyDispatcherPriv;
G_DEFINE_TYPE (EmpathyDispatcher, empathy_dispatcher, G_TYPE_OBJECT);
typedef struct
{
- /* ObjectPath -> EmpathyDispatchOperations */
- GHashTable *dispatching_channels;
-
/* List of requestable channel classes */
GPtrArray *requestable_channels;
} ConnectionData;
static ConnectionData *
new_connection_data (void)
{
- ConnectionData *cd = g_slice_new0 (ConnectionData);
-
- cd->dispatching_channels = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, g_object_unref);
-
- return cd;
+ return g_slice_new0 (ConnectionData);
}
static void
{
guint i;
- g_hash_table_destroy (cd->dispatching_channels);
-
if (cd->requestable_channels != NULL)
{
for (i = 0 ; i < cd->requestable_channels->len ; i++)
}
static void
-dispatcher_channel_invalidated_cb (TpProxy *proxy,
- guint domain,
- gint code,
- gchar *message,
- EmpathyDispatcher *self)
+got_connection_rcc (EmpathyDispatcher *self,
+ TpConnection *connection)
{
- /* Channel went away... */
EmpathyDispatcherPriv *priv = GET_PRIV (self);
- TpConnection *connection;
+ TpCapabilities *caps;
ConnectionData *cd;
- const gchar *object_path;
-
- connection = tp_channel_borrow_connection (TP_CHANNEL (proxy));
+ GList *requests, *l;
+ FindChannelRequest *request;
+ GList *retval;
- priv->channels = g_list_remove (priv->channels, proxy);
+ caps = tp_connection_get_capabilities (connection);
+ g_assert (caps != NULL);
cd = g_hash_table_lookup (priv->connections, connection);
- /* Connection itself invalidated? */
- if (cd == NULL)
- return;
-
- object_path = tp_proxy_get_object_path (proxy);
+ g_assert (cd != NULL);
- DEBUG ("Channel %s invalidated", object_path);
+ cd->requestable_channels = g_boxed_copy (
+ TP_ARRAY_TYPE_REQUESTABLE_CHANNEL_CLASS_LIST,
+ tp_capabilities_get_channel_classes (caps));
- g_hash_table_remove (cd->dispatching_channels, object_path);
-}
-
-static void
-dispatcher_connection_got_all (TpProxy *proxy,
- GHashTable *properties,
- const GError *error,
- gpointer user_data,
- GObject *object)
-{
- EmpathyDispatcher *self = EMPATHY_DISPATCHER (object);
- EmpathyDispatcherPriv *priv = GET_PRIV (self);
- GPtrArray *requestable_channels;
-
- if (error) {
- DEBUG ("Error: %s", error->message);
- return;
- }
-
- requestable_channels = tp_asv_get_boxed (properties,
- "RequestableChannelClasses", TP_ARRAY_TYPE_REQUESTABLE_CHANNEL_CLASS_LIST);
+ requests = g_hash_table_lookup (priv->outstanding_classes_requests,
+ connection);
- if (requestable_channels == NULL)
- DEBUG ("No RequestableChannelClasses property !?! on connection");
- else
+ for (l = requests; l != NULL; l = l->next)
{
- ConnectionData *cd;
- GList *requests, *l;
- FindChannelRequest *request;
- GList *retval;
-
- cd = g_hash_table_lookup (priv->connections, proxy);
- g_assert (cd != NULL);
-
- cd->requestable_channels = g_boxed_copy (
- TP_ARRAY_TYPE_REQUESTABLE_CHANNEL_CLASS_LIST, requestable_channels);
+ request = l->data;
- requests = g_hash_table_lookup (priv->outstanding_classes_requests,
- proxy);
-
- for (l = requests; l != NULL; l = l->next)
- {
- request = l->data;
-
- retval = empathy_dispatcher_find_channel_classes (self,
- TP_CONNECTION (proxy), request->channel_type,
- request->handle_type, request->properties);
- request->callback (retval, request->user_data);
+ retval = empathy_dispatcher_find_channel_classes (self,
+ connection, request->channel_type,
+ request->handle_type, request->properties);
+ request->callback (retval, request->user_data);
- free_find_channel_request (request);
- g_list_free (retval);
- }
+ free_find_channel_request (request);
+ g_list_free (retval);
+ }
- g_list_free (requests);
+ g_list_free (requests);
- g_hash_table_remove (priv->outstanding_classes_requests, proxy);
- }
+ g_hash_table_remove (priv->outstanding_classes_requests, connection);
}
static void
goto out;
}
- tp_cli_dbus_properties_call_get_all (connection, -1,
- TP_IFACE_CONNECTION_INTERFACE_REQUESTS, dispatcher_connection_got_all,
- NULL, NULL, G_OBJECT (self));
+ got_connection_rcc (self, connection);
out:
g_object_unref (self);
{
EmpathyDispatcherPriv *priv = GET_PRIV (self);
GQuark features[] = { TP_CONNECTION_FEATURE_CORE,
+ TP_CONNECTION_FEATURE_CAPABILITIES,
0 };
if (g_hash_table_lookup (priv->connections, connection) != NULL)
dispatcher_init_connection_if_needed (self, conn);
}
-static void
-remove_idle_handlers (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- guint source_id;
-
- source_id = GPOINTER_TO_UINT (value);
- g_source_remove (source_id);
-}
-
static GObject *
dispatcher_constructor (GType type,
guint n_construct_params,
g_hash_table_destroy (priv->connections);
priv->connections = NULL;
- if (priv->channel_dispatcher != NULL)
- g_object_unref (priv->channel_dispatcher);
- priv->channel_dispatcher = NULL;
-
- if (priv->dbus != NULL)
- g_object_unref (priv->dbus);
- priv->dbus = NULL;
-
G_OBJECT_CLASS (empathy_dispatcher_parent_class)->dispose (object);
}
dispatcher_finalize (GObject *object)
{
EmpathyDispatcherPriv *priv = GET_PRIV (object);
- GList *l;
GHashTableIter iter;
gpointer connection;
GList *list;
gpointer account, id;
- if (priv->request_channel_class_async_ids != NULL)
- {
- g_hash_table_foreach (priv->request_channel_class_async_ids,
- remove_idle_handlers, NULL);
- g_hash_table_destroy (priv->request_channel_class_async_ids);
- }
-
- for (l = priv->channels; l; l = l->next)
- {
- g_signal_handlers_disconnect_by_func (l->data,
- dispatcher_channel_invalidated_cb, object);
- }
-
- g_list_free (priv->channels);
-
g_hash_table_iter_init (&iter, priv->outstanding_classes_requests);
while (g_hash_table_iter_next (&iter, &connection, (gpointer *) &list))
{
priv->outstanding_classes_requests = g_hash_table_new_full (g_direct_hash,
g_direct_equal, g_object_unref, NULL);
- priv->channels = NULL;
-
tp_account_manager_prepare_async (priv->account_manager, NULL,
account_manager_prepared_cb, self);
"account-validity-changed", G_CALLBACK (account_validity_changed_cb),
self, 0);
- priv->request_channel_class_async_ids = g_hash_table_new (g_direct_hash,
- g_direct_equal);
priv->status_changed_handlers = g_hash_table_new_full (NULL, NULL,
(GDestroyNotify) g_object_unref, NULL);
-
- priv->dbus = tp_dbus_daemon_dup (NULL);
- priv->channel_dispatcher = tp_channel_dispatcher_new (priv->dbus);
}
EmpathyDispatcher *
return matching_classes;
}
-static gboolean
-find_channel_class_idle_cb (gpointer user_data)
-{
- GList *retval;
- GList *requests;
- FindChannelRequest *request = user_data;
- ConnectionData *cd;
- gboolean is_ready = TRUE;
- EmpathyDispatcherPriv *priv = GET_PRIV (request->dispatcher);
-
- g_hash_table_remove (priv->request_channel_class_async_ids, request);
-
- cd = g_hash_table_lookup (priv->connections, request->connection);
-
- if (cd == NULL)
- is_ready = FALSE;
- else if (cd->requestable_channels == NULL)
- is_ready = FALSE;
-
- if (is_ready)
- {
- retval = empathy_dispatcher_find_channel_classes (request->dispatcher,
- request->connection, request->channel_type, request->handle_type,
- request->properties);
-
- request->callback (retval, request->user_data);
- free_find_channel_request (request);
- g_list_free (retval);
-
- return FALSE;
- }
-
- requests = g_hash_table_lookup (priv->outstanding_classes_requests,
- request->connection);
- requests = g_list_prepend (requests, request);
-
- g_hash_table_insert (priv->outstanding_classes_requests,
- request->connection, requests);
-
- return FALSE;
-}
-
static GArray *
setup_varargs (va_list var_args,
const char *channel_namespace,
return retval;
}
-
-/**
- * empathy_dispatcher_find_requestable_channel_classes_async:
- * @dispatcher: an #EmpathyDispatcher
- * @connection: a #TpConnection
- * @channel_type: a string identifying the type of the channel to lookup
- * @handle_type: the handle type for the channel
- * @callback: the callback to call when @connection is ready
- * @user_data: the user data to pass to @callback
- * @first_property_name: %NULL, or the name of the first fixed property,
- * followed optionally by more names, followed by %NULL.
- *
- * Please see the documentation of
- * empathy_dispatcher_find_requestable_channel_classes() for a detailed
- * description of this function.
- */
-void
-empathy_dispatcher_find_requestable_channel_classes_async
- (EmpathyDispatcher *self,
- TpConnection *connection,
- const gchar *channel_type,
- guint handle_type,
- EmpathyDispatcherFindChannelClassCb callback,
- gpointer user_data,
- const char *first_property_name,
- ...)
-{
- va_list var_args;
- GArray *properties;
- FindChannelRequest *request;
- EmpathyDispatcherPriv *priv;
- guint source_id;
-
- g_return_if_fail (EMPATHY_IS_DISPATCHER (self));
- g_return_if_fail (TP_IS_CONNECTION (connection));
- g_return_if_fail (channel_type != NULL);
- g_return_if_fail (handle_type != 0);
-
- priv = GET_PRIV (self);
-
- va_start (var_args, first_property_name);
-
- properties = setup_varargs (var_args, channel_type, first_property_name);
-
- va_end (var_args);
-
- /* append another request for this connection */
- request = g_slice_new0 (FindChannelRequest);
- request->dispatcher = g_object_ref (self);
- request->channel_type = g_strdup (channel_type);
- request->handle_type = handle_type;
- request->connection = connection;
- request->callback = callback;
- request->user_data = user_data;
- request->properties = properties;
-
- source_id = g_idle_add (find_channel_class_idle_cb, request);
-
- g_hash_table_insert (priv->request_channel_class_async_ids,
- request, GUINT_TO_POINTER (source_id));
-}