diff options
Diffstat (limited to 'libempathy/empathy-dispatcher.c')
-rw-r--r-- | libempathy/empathy-dispatcher.c | 290 |
1 files changed, 174 insertions, 116 deletions
diff --git a/libempathy/empathy-dispatcher.c b/libempathy/empathy-dispatcher.c index 8618be6e0..721d398d9 100644 --- a/libempathy/empathy-dispatcher.c +++ b/libempathy/empathy-dispatcher.c @@ -19,6 +19,9 @@ * Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> */ +#define DISPATCHER_BUS_NAME TP_CLIENT_BUS_NAME_BASE "Empathy" +#define DISPATCHER_OBJECT_PATH TP_CLIENT_OBJECT_PATH_BASE "Empathy" + #include <config.h> #include <string.h> @@ -31,6 +34,9 @@ #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 <extensions/extensions.h> @@ -62,7 +68,29 @@ typedef struct GHashTable *request_channel_class_async_ids; } EmpathyDispatcherPriv; -G_DEFINE_TYPE (EmpathyDispatcher, empathy_dispatcher, G_TYPE_OBJECT); +static void empathy_dispatcher_client_handler_iface_init (gpointer g_iface, + gpointer g_iface_data); + +G_DEFINE_TYPE_WITH_CODE (EmpathyDispatcher, + empathy_dispatcher, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, + tp_dbus_properties_mixin_iface_init); + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CLIENT, NULL); + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CLIENT_HANDLER, + empathy_dispatcher_client_handler_iface_init); + ); + +static const gchar *empathy_displatcher_interfaces[] = { + TP_IFACE_CLIENT_HANDLER, + NULL +}; + +enum +{ + PROP_INTERFACES = 1, + PROP_CHANNEL_FILTER, +}; enum { @@ -636,30 +664,11 @@ dispatcher_connection_new_channel (EmpathyDispatcher *dispatcher, } static void -dispatcher_connection_new_channel_cb (TpConnection *connection, - const gchar *object_path, - const gchar *channel_type, - guint handle_type, - guint handle, - gboolean suppress_handler, - gpointer user_data, - GObject *object) -{ - EmpathyDispatcher *dispatcher = EMPATHY_DISPATCHER (object); - - /* Empathy heavily abuses surpress handler (don't try this at home), if - * surpress handler is true then it is an outgoing channel, which is - * requested either by us or some other party (like the megaphone applet). - * Otherwise it's an incoming channel */ - dispatcher_connection_new_channel (dispatcher, connection, - object_path, channel_type, handle_type, handle, NULL, !suppress_handler); -} - -static void -dispatcher_connection_new_channel_with_properties (EmpathyDispatcher *dispatcher, - TpConnection *connection, - const gchar *object_path, - GHashTable *properties) +dispatcher_connection_new_channel_with_properties ( + EmpathyDispatcher *dispatcher, + TpConnection *connection, + const gchar *object_path, + GHashTable *properties) { const gchar *channel_type; guint handle_type; @@ -707,29 +716,6 @@ dispatcher_connection_new_channel_with_properties (EmpathyDispatcher *dispatcher } static void -dispatcher_connection_new_channels_cb (TpConnection *connection, - const GPtrArray *channels, - gpointer user_data, - GObject *object) -{ - EmpathyDispatcher *dispatcher = EMPATHY_DISPATCHER (object); - int i; - - for (i = 0; i < channels->len ; i++) - { - GValueArray *arr = g_ptr_array_index (channels, i); - const gchar *object_path; - GHashTable *properties; - - object_path = g_value_get_boxed (g_value_array_get_nth (arr, 0)); - properties = g_value_get_boxed (g_value_array_get_nth (arr, 1)); - - dispatcher_connection_new_channel_with_properties (dispatcher, - connection, object_path, properties); - } -} - -static void dispatcher_connection_got_all (TpProxy *proxy, GHashTable *properties, const GError *error, @@ -738,7 +724,6 @@ dispatcher_connection_got_all (TpProxy *proxy, { EmpathyDispatcher *dispatcher = EMPATHY_DISPATCHER (object); EmpathyDispatcherPriv *priv = GET_PRIV (dispatcher); - GPtrArray *channels; GPtrArray *requestable_channels; if (error) { @@ -746,15 +731,6 @@ dispatcher_connection_got_all (TpProxy *proxy, return; } - channels = tp_asv_get_boxed (properties, "Channels", - TP_ARRAY_TYPE_CHANNEL_DETAILS_LIST); - - if (channels == NULL) - DEBUG ("No Channels property !?! on connection"); - else - dispatcher_connection_new_channels_cb (TP_CONNECTION (proxy), - channels, NULL, object); - requestable_channels = tp_asv_get_boxed (properties, "RequestableChannelClasses", TP_ARRAY_TYPE_REQUESTABLE_CHANNEL_CLASS_LIST); @@ -796,38 +772,6 @@ dispatcher_connection_got_all (TpProxy *proxy, } static void -dispatcher_connection_list_channels_cb (TpConnection *connection, - const GPtrArray *channels, - const GError *error, - gpointer user_data, - GObject *dispatcher) -{ - int i; - - if (error) - { - DEBUG ("Error: %s", error->message); - return; - } - - for (i = 0; i < channels->len; i++) - { - GValueArray *values; - - values = g_ptr_array_index (channels, i); - /* We don't have any extra info, so assume already existing channels are - * incoming... */ - dispatcher_connection_new_channel (EMPATHY_DISPATCHER (dispatcher), - connection, - g_value_get_boxed (g_value_array_get_nth (values, 0)), - g_value_get_string (g_value_array_get_nth (values, 1)), - g_value_get_uint (g_value_array_get_nth (values, 2)), - g_value_get_uint (g_value_array_get_nth (values, 3)), - NULL, TRUE); - } -} - -static void dispatcher_connection_advertise_capabilities_cb (TpConnection *connection, const GPtrArray *capabilities, const GError *error, @@ -861,26 +805,11 @@ dispatcher_new_connection_cb (EmpathyAccountManager *manager, if (tp_proxy_has_interface_by_id (TP_PROXY (connection), TP_IFACE_QUARK_CONNECTION_INTERFACE_REQUESTS)) { - tp_cli_connection_interface_requests_connect_to_new_channels (connection, - dispatcher_connection_new_channels_cb, - NULL, NULL, G_OBJECT (dispatcher), NULL); - tp_cli_dbus_properties_call_get_all (connection, -1, TP_IFACE_CONNECTION_INTERFACE_REQUESTS, dispatcher_connection_got_all, NULL, NULL, G_OBJECT (dispatcher)); } - else - { - tp_cli_connection_connect_to_new_channel (connection, - dispatcher_connection_new_channel_cb, - NULL, NULL, G_OBJECT (dispatcher), NULL); - - tp_cli_connection_call_list_channels (connection, -1, - dispatcher_connection_list_channels_cb, NULL, NULL, - G_OBJECT (dispatcher)); - - } /* Advertise VoIP capabilities */ capabilities = g_ptr_array_sized_new (1); @@ -922,19 +851,25 @@ dispatcher_constructor (GType type, GObjectConstructParam *construct_params) { GObject *retval; + TpDBusDaemon *dbus; - if (dispatcher == NULL) - { - retval = G_OBJECT_CLASS (empathy_dispatcher_parent_class)->constructor - (type, n_construct_params, construct_params); + if (dispatcher != NULL) + return g_object_ref (dispatcher); - dispatcher = EMPATHY_DISPATCHER (retval); - g_object_add_weak_pointer (retval, (gpointer) &dispatcher); - } - else - { - retval = g_object_ref (dispatcher); - } + retval = G_OBJECT_CLASS (empathy_dispatcher_parent_class)->constructor + (type, n_construct_params, construct_params); + + dispatcher = EMPATHY_DISPATCHER (retval); + g_object_add_weak_pointer (retval, (gpointer) &dispatcher); + + dbus = tp_dbus_daemon_dup (NULL); + + g_assert (tp_dbus_daemon_request_name (dbus, + DISPATCHER_BUS_NAME, TRUE, NULL)); + dbus_g_connection_register_g_object (tp_get_bus (), + DISPATCHER_OBJECT_PATH, retval); + + DEBUG ("Registering at '%s'", DISPATCHER_OBJECT_PATH); return retval; } @@ -988,13 +923,78 @@ dispatcher_finalize (GObject *object) } static void +dispatcher_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) + { + case PROP_INTERFACES: + g_value_set_boxed (value, empathy_displatcher_interfaces); + break; + case PROP_CHANNEL_FILTER: + { + GPtrArray *filters = g_ptr_array_new (); + GHashTable *filter = g_hash_table_new (NULL, NULL); + + g_ptr_array_add (filters, filter); + + g_value_set_boxed (value, filters); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void empathy_dispatcher_class_init (EmpathyDispatcherClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); + GParamSpec *param_spec; + + static TpDBusPropertiesMixinPropImpl client_props[] = { + { "Interfaces", "interfaces", NULL }, + { NULL } + }; + static TpDBusPropertiesMixinPropImpl client_handler_props[] = { + { "HandlerChannelFilter", "channel-filter", NULL }, + { NULL } + }; + static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { + { TP_IFACE_CLIENT, + tp_dbus_properties_mixin_getter_gobject_properties, + NULL, + client_props + }, + { TP_IFACE_CLIENT_HANDLER, + tp_dbus_properties_mixin_getter_gobject_properties, + NULL, + client_handler_props + }, + { NULL } + }; object_class->finalize = dispatcher_finalize; object_class->constructor = dispatcher_constructor; + object_class->get_property = dispatcher_get_property; + + param_spec = g_param_spec_boxed ("interfaces", "interfaces", + "Available D-Bus interfaces", + G_TYPE_STRV, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_INTERFACES, param_spec); + + param_spec = g_param_spec_boxed ("channel-filter", "channel-filter", + "Filter for channels this handles", + TP_ARRAY_TYPE_CHANNEL_CLASS_LIST, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, + PROP_CHANNEL_FILTER, param_spec); + signals[OBSERVE] = g_signal_new ("observe", G_TYPE_FROM_CLASS (klass), @@ -1025,8 +1025,13 @@ empathy_dispatcher_class_init (EmpathyDispatcherClass *klass) G_TYPE_NONE, 1, EMPATHY_TYPE_DISPATCH_OPERATION); + g_type_class_add_private (object_class, sizeof (EmpathyDispatcherPriv)); + + klass->dbus_props_class.interfaces = prop_interfaces; + tp_dbus_properties_mixin_class_init (object_class, + G_STRUCT_OFFSET (EmpathyDispatcherClass, dbus_props_class)); } static void @@ -1751,3 +1756,56 @@ empathy_dispatcher_find_requestable_channel_classes_async g_hash_table_insert (priv->request_channel_class_async_ids, request, GUINT_TO_POINTER (source_id)); } + +static void +empathy_dispatcher_handle_channels (TpSvcClientHandler *self, + const gchar *account_path, + const gchar *connection_path, + const GPtrArray *channels, + const GPtrArray *requests_satisfied, + guint64 timestamp, + GHashTable *handler_info, + DBusGMethodInvocation *context) +{ + EmpathyDispatcher *dispatcher = EMPATHY_DISPATCHER (self); + EmpathyDispatcherPriv *priv = GET_PRIV (dispatcher); + int i; + EmpathyAccount *account; + TpConnection *connection; + + account = empathy_account_manager_lookup (priv->account_manager, + account_path); + /* FIXME */ + g_assert (account != NULL); + + connection = empathy_account_get_connection (account); + /* FIXME */ + g_assert (connection != NULL); + + for (i = 0; i < channels->len ; i++) + { + GValueArray *arr = g_ptr_array_index (channels, i); + const gchar *object_path; + GHashTable *properties; + + object_path = g_value_get_boxed (g_value_array_get_nth (arr, 0)); + properties = g_value_get_boxed (g_value_array_get_nth (arr, 1)); + + dispatcher_connection_new_channel_with_properties (dispatcher, + connection, object_path, properties); + } + + tp_svc_client_handler_return_from_handle_channels (context); + + g_object_unref (account); +} + +static void +empathy_dispatcher_client_handler_iface_init (gpointer g_iface, + gpointer g_iface_data) +{ + TpSvcClientHandlerClass *klass = (TpSvcClientHandlerClass *) g_iface; + + tp_svc_client_handler_implement_handle_channels (klass, + empathy_dispatcher_handle_channels); +} |